2
* Copyright (c) 2013, Joyent, Inc.
3
* See LICENSE file for copyright and license details.
11
#include <sys/types.h>
18
#include <sys/socket.h>
21
#include <sys/epoll.h>
26
#include "plat/unix_common.h"
28
#define SERIAL_DEVICE "/dev/ttyS1"
30
typedef struct mdata_plat {
36
raw_mode(int fd, char **errmsg)
40
if (tcgetattr(fd, &tios) == -1) {
41
*errmsg = "could not set raw mode on serial device";
45
tios.c_iflag &= ~(BRKINT | ICRNL | INPCK | ISTRIP | IXON);
46
tios.c_oflag &= ~(OPOST);
47
tios.c_cflag |= (CS8);
48
tios.c_lflag &= ~(ECHO | ICANON | IEXTEN | ISIG);
51
* As described in "Case C: MIN = 0, TIME > 0" of termio(7I), this
52
* configuration will block waiting for at least one character, or
53
* the expiry of a 100 millisecond timeout:
58
if (tcsetattr(fd, TCSAFLUSH, &tios) == -1) {
59
*errmsg = "could not get attributes from serial device";
67
open_md(int *outfd, char **errmsg, int *permfail)
74
if ((fd = open(SERIAL_DEVICE, O_RDWR | O_EXCL |
76
*errmsg = "Could not open serial device.";
77
if (errno != EAGAIN && errno != EBUSY && errno != EINTR)
83
* Lock the serial port for exclusive access:
86
l.l_whence = SEEK_SET;
87
l.l_start = l.l_len = 0;
88
if (fcntl(fd, F_SETLKW, &l) == -1) {
89
fprintf(stderr, "could not lock: %s\n", strerror(errno));
94
* Set raw mode on the serial port:
96
if (raw_mode(fd, errmsg) == -1) {
103
* Because this is a shared serial line, we may be part way through
104
* a response from the remote peer. Read (and discard) data until we
105
* cannot do so anymore:
108
sz = read(fd, &scrap, sizeof (scrap));
110
if (sz == -1 && errno != EAGAIN) {
111
*errmsg = "Failed to flush serial port before use.";
125
plat_send(mdata_plat_t *mpl, string_t *data)
127
int len = dynstr_len(data);
129
if (write(mpl->mpl_conn, dynstr_cstr(data), len) != len)
136
plat_recv(mdata_plat_t *mpl, string_t *data, int timeout_ms)
139
struct epoll_event event;
141
if (epoll_wait(mpl->mpl_epoll, &event, 1, timeout_ms) == -1) {
142
fprintf(stderr, "epoll error: %d\n", errno);
143
if (errno == EINTR) {
146
err(1, "EPOLL_WAIT ERROR");
149
if (event.data.fd == 0 || event.events == 0) {
150
fprintf(stderr, "plat_recv timeout\n");
154
if (event.events & EPOLLIN) {
158
sz = read(mpl->mpl_conn, buf, 1);
160
fprintf(stderr, "WHAT, NO DATA?!\n");
164
if (buf[0] == '\n') {
168
dynstr_append(data, buf);
171
if (event.events & EPOLLERR) {
172
fprintf(stderr, "POLLERR\n");
175
if (event.events & EPOLLHUP) {
176
fprintf(stderr, "POLLHUP\n");
185
plat_fini(mdata_plat_t *mpl __UNUSED)
188
if (mpl->mpl_epoll != -1)
189
(void) close(mpl->mpl_epoll);
190
if (mpl->mpl_conn != -1)
191
(void) close(mpl->mpl_conn);
197
plat_send_reset(mdata_plat_t *mpl)
200
string_t *str = dynstr_new();
202
dynstr_append(str, "\n");
203
if (plat_send(mpl, str) != 0)
207
if (plat_recv(mpl, str, 2000) != 0)
210
if (strcmp(dynstr_cstr(str), "invalid command") != 0)
221
plat_is_interactive(void)
223
return (unix_is_interactive());
227
plat_init(mdata_plat_t **mplout, char **errmsg, int *permfail)
229
mdata_plat_t *mpl = NULL;
230
struct epoll_event event;
232
if ((mpl = calloc(1, sizeof (*mpl))) == NULL) {
233
*errmsg = "Could not allocate memory.";
240
if ((mpl->mpl_epoll = epoll_create(1)) == -1) {
241
*errmsg = "Could not create epoll fd.";
246
if (open_md(&mpl->mpl_conn, errmsg, permfail) != 0) {
250
event.data.fd = mpl->mpl_conn;
251
event.events = EPOLLIN | EPOLLERR | EPOLLHUP;
253
if (epoll_ctl(mpl->mpl_epoll, EPOLL_CTL_ADD, mpl->mpl_conn,
255
*errmsg = "Could not add conn to epoll context.";
260
if (plat_send_reset(mpl) == -1) {
261
*errmsg = "Could not do active reset.";