aboutsummaryrefslogtreecommitdiff
path: root/lib/stream/builtin/unix.c
diff options
context:
space:
mode:
Diffstat (limited to 'lib/stream/builtin/unix.c')
-rw-r--r--lib/stream/builtin/unix.c271
1 files changed, 161 insertions, 110 deletions
diff --git a/lib/stream/builtin/unix.c b/lib/stream/builtin/unix.c
index 6ea5309..d625a35 100644
--- a/lib/stream/builtin/unix.c
+++ b/lib/stream/builtin/unix.c
@@ -14,6 +14,10 @@
attrs->tio_serial_attrs_flags &= ~(MASK); \
attrs->tio_serial_attrs_flags |= (VALUE); \
}
+# define SET_CHAR(CAR, VALUE) \
+ { \
+ attrs->tio_serial_attrs_cc[(CAR)] = (VALUE); \
+ }
TIO_LOCAL(int) unix_get_attrs(tio_serial_attrs_t *attrs, int fd)
{
@@ -55,6 +59,11 @@ TIO_LOCAL(int) unix_get_attrs(tio_serial_attrs_t *attrs, int fd)
SET_MASK(TIO_XINMASK, term.c_iflag & IXON ? TIO_XINENB : TIO_XINDIS)
SET_MASK(TIO_XOUTMASK, term.c_iflag & IXOFF ? TIO_XOUTENB : TIO_XOUTDIS)
+ /* Characters. */
+
+ SET_CHAR(TIO_XON, term.c_cc[VSTART])
+ SET_CHAR(TIO_XOFF, term.c_cc[VSTOP])
+
/* Get DTR/RTS status. */
if (ioctl(fd, TIOCMGET, &status) >= 0)
@@ -82,13 +91,14 @@ struct cookie {
/* File descriptor, a boolean to know if we ought to close the
* file descriptor at stream closing, and the timeout. */
- int _fd, _cl;
- unsigned int _to;
+ int fd, cl;
+ unsigned int to;
/* Buffer [control] */
- ssize_t _str, _end;
- unsigned char _buf[BUFSIZE];
+ ssize_t str;
+ ssize_t end;
+ unsigned char buf[BUFSIZE];
};
/* `unix_read()`: read from a UNIX stream. */
@@ -96,19 +106,19 @@ struct cookie {
TIO_HOOK(int) unix_read(cookie_t *cookie, unsigned char *dest,
size_t size)
{
- int fd = cookie->_fd;
+ int fd = cookie->fd;
/* Transmit what's already in the buffer. */
- if (cookie->_str <= cookie->_end) {
+ if (cookie->str <= cookie->end) {
size_t tocopy;
- tocopy = cookie->_end - cookie->_start + 1;
+ tocopy = cookie->end - cookie->str + 1;
if (tocopy > size)
tocopy = size;
- memcpy(dest, &cookie->_buf[cookie->_start], tocopy);
- cookie->_str += tocopy;
+ memcpy(dest, &cookie->buf[cookie->str], tocopy);
+ cookie->str += tocopy;
dest += tocopy;
size -= tocopy;
@@ -124,7 +134,7 @@ TIO_HOOK(int) unix_read(cookie_t *cookie, unsigned char *dest,
/* Receive. */
- recv = read(fd, cookie->_buf, BUFSIZE);
+ recv = read(fd, cookie->buf, BUFSIZE);
if (!recv)
continue;
@@ -148,14 +158,14 @@ TIO_HOOK(int) unix_read(cookie_t *cookie, unsigned char *dest,
/* Copy to destination. */
- memcpy(dest, cookie->_buf, tocopy);
+ memcpy(dest, cookie->buf, tocopy);
dest += tocopy;
size -= tocopy;
/* Correct start and end points. */
- cookie->_str = tocopy;
- cookie->_end = (size_t)recv - 1;
+ cookie->str = tocopy;
+ cookie->end = (size_t)recv - 1;
}
return (tio_error_ok);
@@ -166,7 +176,7 @@ TIO_HOOK(int) unix_read(cookie_t *cookie, unsigned char *dest,
TIO_HOOK(int) unix_write(cookie_t *cookie,
unsigned char const *data, size_t size)
{
- int fd = cookie->_fd;
+ int fd = cookie->fd;
/* Send. */
@@ -198,14 +208,14 @@ TIO_HOOK(int) unix_write(cookie_t *cookie,
TIO_HOOK(int) unix_seek(cookie_t *cookie, tio_off_t *offp,
tio_whence_t whence)
{
- int fd = cookie->_fd;
+ int fd = cookie->fd;
off_t off;
int wh;
/* Check parameters. */
if (offp == NULL)
- return (tio_error_invalid);
+ return (tio_error_arg);
off = (off_t)*offp;
switch (whence) {
@@ -221,12 +231,12 @@ TIO_HOOK(int) unix_seek(cookie_t *cookie, tio_off_t *offp,
# endif
default:
- return (tio_error_invalid);
+ return (tio_error_arg);
}
/* Do the seek. */
- if (lseek(fd, (off_t)*off, wh) == (off_t)-1) switch (errno) {
+ if (lseek(fd, (off_t)*offp, wh) == (off_t)-1) switch (errno) {
default:
msg((ll_error, "errno was %d: %s", errno, strerror(errno)));
break;
@@ -243,88 +253,137 @@ TIO_HOOK(int) unix_seek(cookie_t *cookie, tio_off_t *offp,
# define SPEED(TIO, NATIVE) case TIO: speed = NATIVE; break;
TIO_HOOK(int) unix_set_attrs(cookie_t *cookie,
- tio_serial_attrs_t const *settings)
+ tio_serial_attrs_t const *settings, unsigned long flags)
{
- struct termios term;
- unsigned int status, dtrflags, rtsflags;
- int fd = cookie->_fd;
- speed_t speed;
+ int fd = cookie->fd;
- /* Get the speed. */
+ if (flags & (TIO_SERIALFLAG_SPEED | TIO_SERIALFLAG_XINOUT
+ | TIO_SERIALFLAG_STOP | TIO_SERIALFLAG_PARITY)) {
+ struct termios term;
+ speed_t speed;
+
+ /* Get the speed. */
+
+ if (flags & TIO_SERIALFLAG_SPEED) {
+ switch (settings->tio_serial_attrs_speed) {
+ SPEED(TIO_B1200, B1200)
+ SPEED(TIO_B2400, B2400)
+ SPEED(TIO_B4800, B4800)
+ SPEED(TIO_B9600, B9600)
+ SPEED(TIO_B19200, B19200)
+ SPEED(TIO_B38400, B38400)
+ SPEED(TIO_B57600, B57600)
+ SPEED(TIO_B115200, B115200)
+
+ default:
+ msg((ll_error, "Speed was unsupported by termios: %u",
+ settings->tio_serial_attrs_speed));
+ return (tio_error_op);
+ }
+ }
- switch (settings->tio_serial_attrs_speed) {
- SPEED(TIO_B1200, B1200)
- SPEED(TIO_B2400, B2400)
- SPEED(TIO_B4800, B4800)
- SPEED(TIO_B9600, B9600)
- SPEED(TIO_B19200, B19200)
- SPEED(TIO_B38400, B38400)
- SPEED(TIO_B57600, B57600)
- SPEED(TIO_B115200, B115200)
+ /* Get the current configuration. */
- default:
- msg((ll_error, "Speed was unsupported by termios: %u",
- settings->tio_serial_attrs_speed));
- return (tio_error_op);
- }
+ if (tcgetattr(fd, &term) < 0)
+ return (tio_error_unknown);
- /* Get the current configuration. */
+ /* Set the speed. */
- if (tcgetattr(fd, &term) < 0)
- return (tio_error_unknown);
+ if (flags & TIO_SERIALFLAG_SPEED) {
+ cfsetispeed(&term, speed);
+ cfsetospeed(&term, speed);
+ }
+
+ /* Input flags. */
- /* Set the speed. */
+ term.c_iflag &= ~(IGNBRK | IGNCR | BRKINT | PARMRK | ISTRIP | INLCR
+ | ICRNL | IGNPAR);
+ if (flags & TIO_SERIALFLAG_XIN) {
+ term.c_iflag &= ~IXON;
- cfsetispeed(&term, speed);
- cfsetospeed(&term, speed);
+ if ((settings->tio_serial_attrs_flags & TIO_XINMASK)
+ == TIO_XINENB)
+ term.c_iflag &= ~IXON;
+ }
- /* Input flags. */
+ if (flags & TIO_SERIALFLAG_XOUT) {
+ term.c_iflag &= ~IXOFF;
- term.c_iflag &= ~(IGNBRK | IGNCR | BRKINT | PARMRK | ISTRIP | INLCR
- | ICRNL | IGNPAR | IXON | IXOFF);
- if (settings->tio_serial_attrs_flags & TIO_XONMASK)
- term.c_iflag |= IXON;
- if (settings->tio_serial_attrs_flags & TIO_XOFFMASK)
- term.c_iflag |= IXOFF;
+ if ((settings->tio_serial_attrs_flags & TIO_XOUTMASK)
+ == TIO_XOUTENB)
+ term.c_iflag |= IXOFF;
+ }
- /* Output flags, local modes. */
+ /* Output flags, local modes. */
- term.c_oflag = 0;
- term.c_lflag &= ~(ECHO | ECHONL | ICANON | ISIG | IEXTEN);
+ term.c_oflag = 0;
+ term.c_lflag &= ~(ECHO | ECHONL | ICANON | ISIG | IEXTEN);
- /* Control flags. */
+ /* Control flags. */
- term.c_cflag &= ~(PARENB | PARODD | CREAD | CSTOPB | CSIZE);
- term.c_cflag |= CREAD | CS8;
- if (settings->tio_serial_attrs_flags & TIO_STOTWO)
- term.c_cflag |= CSTOPB;
- if (settings->tio_serial_attrs_flags & TIO_PARENB)
- term.c_cflag |= PARENB;
- if (settings->tio_serial_attrs_flags & TIO_PARODD)
- term.c_cflag |= PARODD;
+ term.c_cflag &= ~(CREAD | CSIZE);
+ term.c_cflag |= CREAD | CS8;
- /* Update the termios settings! */
+ if (flags & TIO_SERIALFLAG_STOP) {
+ term.c_cflag &= ~CSTOPB;
- if (tcsetattr(fd, TCSANOW, &term))
- return (tio_error_unknown);
+ if (settings->tio_serial_attrs_flags & TIO_STOTWO)
+ term.c_cflag |= CSTOPB;
+ }
- /* Get line status. */
+ if (flags & TIO_SERIALFLAG_PARITY) {
+ term.c_cflag &= ~(PARENB | PARODD);
- if (ioctl(fd, TIOCMGET, &status) >= 0)
- status = 0;
- status &= ~(TIOCM_DTR | TIOCM_RTS);
-
- /* Activate DTR and RTS.
- * TODO: use the 'X' versions if available? */
-
- dtrflags = settings->tio_serial_attrs_flags & TIO_DTRMASK;
- rtsflags = settings->tio_serial_attrs_flags & TIO_RTSMASK;
- if (dtrflags & TIO_DTRENB)
- status |= TIOCM_DTR;
- if (rtsflags & TIO_RTSENB)
- status |= TIOCM_RTS;
- if (ioctl(fd, TIOCMSET, &status) < 0)
- return (tio_error_unknown);
+ if (settings->tio_serial_attrs_flags & TIO_PARENB) {
+ term.c_cflag |= PARENB;
+
+ if (settings->tio_serial_attrs_flags & TIO_PARODD)
+ term.c_cflag |= PARODD;
+ }
+ }
+
+ /* Update the termios settings! */
+
+ if (tcsetattr(fd, TCSANOW, &term))
+ return (tio_error_unknown);
+ }
+
+ if (flags & TIO_SERIALFLAG_DTRRTS) {
+ unsigned int status;
+
+ /* Get line status. */
+
+ if (ioctl(fd, TIOCMGET, &status) >= 0)
+ status = 0;
+
+ /* Enable DTR and RTS.
+ * TODO: use the 'X' versions if available? */
+
+ if (flags & TIO_SERIALFLAG_DTR) {
+ status &= ~TIOCM_DTR;
+
+ switch (settings->tio_serial_attrs_flags & TIO_DTRMASK) {
+ case TIO_DTRENB | TIO_DTRHAND:
+ case TIO_DTRENB | TIO_DTRNOHAND:
+ status |= TIOCM_DTR;
+ break;
+ }
+ }
+
+ if (flags & TIO_SERIALFLAG_RTS) {
+ status &= ~TIOCM_RTS;
+
+ switch (settings->tio_serial_attrs_flags & TIO_RTSMASK) {
+ case TIO_RTSENB | TIO_RTSHAND:
+ case TIO_RTSENB | TIO_RTSNOHAND:
+ status |= TIOCM_RTS;
+ break;
+ }
+ }
+
+ if (ioctl(fd, TIOCMSET, &status) < 0)
+ return (tio_error_unknown);
+ }
/* We're good! */
@@ -337,8 +396,8 @@ TIO_HOOK(void) unix_close(cookie_t *cookie)
{
/* Close the file descriptors if necessary. */
- if (cookie->_fd >= 0 && cookie->_cl)
- close(cookie->_fd);
+ if (cookie->fd >= 0 && cookie->cl)
+ close(cookie->fd);
/* Free the cookie and exit. */
@@ -362,7 +421,7 @@ TIO_LOCAL_DATA(tio_serial_functions_t const) unix_serial_functions = {
(tio_read_t *)unix_read,
(tio_write_t *)unix_write,
- (tio_setattrs_t *)unix_set_attrs,
+ (tio_set_serial_attrs_t *)unix_set_attrs,
NULL,
NULL,
@@ -385,7 +444,7 @@ TIO_EXTERN(int) tio_open_unix_file(tio_stream_t **streamp, int fd, int cl)
/* Check if the device is valid. */
if (fd < 0) {
- err = tio_error_invalid;
+ err = tio_error_arg;
goto fail;
}
@@ -394,7 +453,7 @@ TIO_EXTERN(int) tio_open_unix_file(tio_stream_t **streamp, int fd, int cl)
if (write(fd, NULL, 0) < 0)
mode &= ~TIO_OPENFLAG_WRITE;
if (!(mode & (TIO_OPENFLAG_READ | TIO_OPENFLAG_WRITE))) {
- err = tio_error_invalid;
+ err = tio_error_arg;
goto fail;
}
@@ -405,20 +464,11 @@ TIO_EXTERN(int) tio_open_unix_file(tio_stream_t **streamp, int fd, int cl)
goto fail;
}
- cookie->_fd = fd;
- cookie->_cl = cl;
- cookie->_to = -1;
- cookie->_str = 0;
- cookie->_end = -1;
-
- /* Get the read and write timeouts. */
-
- {
- struct termios term;
-
- if (tcgetattr(rfd, &term))
- cookie->_to = term.c_cc[VTIME] * 100;
- }
+ cookie->fd = fd;
+ cookie->cl = cl;
+ cookie->to = -1;
+ cookie->str = 0;
+ cookie->end = -1;
/* Initialize for real. */
@@ -426,7 +476,7 @@ TIO_EXTERN(int) tio_open_unix_file(tio_stream_t **streamp, int fd, int cl)
/* Final call. */
- return (tio_open(streamp, mode, cookie, &unix_functions, 0));
+ return (tio_open(streamp, NULL, cookie, mode, &unix_functions, 0));
fail:
if (fd >= 0 && cl)
close(fd);
@@ -440,6 +490,7 @@ TIO_EXTERN(int) tio_open_unix_serial(tio_stream_t **streamp,
int fd, int cl)
{
cookie_t *cookie = NULL;
+ tio_serial_attrs_t attrs;
int err;
/* Check if the device is valid. */
@@ -469,11 +520,11 @@ TIO_EXTERN(int) tio_open_unix_serial(tio_stream_t **streamp,
goto fail;
}
- cookie->_fd = fd;
- cookie->_cl = cl;
- cookie->_to = -1;
- cookie->_str = 0;
- cookie->_end = -1;
+ cookie->fd = fd;
+ cookie->cl = cl;
+ cookie->to = -1;
+ cookie->str = 0;
+ cookie->end = -1;
/* Initialize for real. */
@@ -481,9 +532,9 @@ TIO_EXTERN(int) tio_open_unix_serial(tio_stream_t **streamp,
/* Final call. */
- return (tio_open(streamp, TIO_OPENFLAG_SERIAL_READ
+ return (tio_open_serial(streamp, NULL, cookie, TIO_OPENFLAG_SERIAL_READ
| TIO_OPENFLAG_SERIAL_WRITE | TIO_OPENFLAG_SERIAL_SETATTRS,
- cookie, &unix_serial_functions, 0));
+ &unix_serial_functions, &attrs, TIO_SERIALFLAG_ALL));
fail:
if (fd >= 0 && cl)
close(fd);
@@ -516,7 +567,7 @@ TIO_EXTERN(int) tio_open_unix_serial_port(tio_stream_t **streamp,
return (tio_error_unknown);
}
- return (tio_open_unix_serial(streamp, fd));
+ return (tio_open_unix_serial(streamp, fd, 1));
}
#endif