/* evlist/serial.c * * Serial port functions. * * Copyright (C) 2003, 2004 * Andy Goth * * This code is available under the GNU General Public License; see COPYING. */ #include #include #include #include #include #include #include #include #include "evlist/evlist.h" typedef struct termios termios_t; typedef struct serial { int data_bits; int stop_bits; int parity; int baud_rate; int sw_flow_ctrl; int hw_flow_ctrl; termios_t saved_termios; } serial_t; static int serial_cleanup(device_t* dev); static int serial_open (device_t* dev); static int serial_close (device_t* dev); int serial_init(device_t* dev, char* path, int data_bits, int stop_bits, int parity, int baud_rate, int sw_flow_ctrl, int hw_flow_ctrl) { char* path_dup; serial_t* serial; path_dup = strdup(path); if (path_dup == NULL) { errno = ENOMEM; return -1; } serial = malloc(sizeof(serial_t)); if (serial == NULL) { free(path_dup); errno = ENOMEM; return -1; } serial->data_bits = data_bits ; serial->stop_bits = stop_bits ; serial->parity = parity ; serial->baud_rate = baud_rate ; serial->sw_flow_ctrl = sw_flow_ctrl; serial->hw_flow_ctrl = hw_flow_ctrl; dev->path = path_dup ; dev->hw_cleanup = serial_cleanup ; dev->hw_state = serial ; dev->hw_open = serial_open ; dev->hw_close = serial_close ; dev->hw_readable = device_readable; dev->hw_writable = device_writable; return 0; } static int serial_cleanup(device_t* dev) { free(dev->path); free(dev->hw_state); dev->path = NULL; dev->hw_state = NULL; dev->hw_open = NULL; dev->hw_close = NULL; dev->hw_cleanup = NULL; dev->hw_readable = NULL; dev->hw_writable = NULL; return 0; } static int serial_open(device_t* dev) { termios_t current; serial_t* serial = dev->hw_state; int fd; if ((fd = open(dev->path, O_RDWR)) == -1) return -1; if (tcgetattr(fd, ¤t) != 0) { close(fd); return -1; } serial->saved_termios = current; current.c_iflag &= ~(IXON | IXANY | IXOFF | ISTRIP | INLCR | ICRNL | IGNCR | IUCLC ); current.c_oflag &= ~(OLCUC | ONLCR | OCRNL | ONOCR | ONLRET); current.c_lflag &= ~(ICANON | ECHO | ECHOE | ECHONL | ISIG ); current.c_cflag &= ~(PARENB | PARODD); current.c_iflag |= serial->sw_flow_ctrl; current.c_cflag |= serial->parity | serial->data_bits | serial->stop_bits | serial->hw_flow_ctrl | CLOCAL; current.c_cc[VTIME] = 0; current.c_cc[VMIN ] = 1; cfsetispeed(¤t, serial->baud_rate); cfsetospeed(¤t, serial->baud_rate); if (tcsetattr(fd, TCSANOW, ¤t) != 0) { close(fd); return -1; } device_attach_fd(dev, fd, O_RDWR); return 0; } static int serial_close(device_t* dev) { serial_t* serial = dev->hw_state; tcsetattr(dev->pollfd_in->fd, TCSANOW, &serial->saved_termios); if (close(dev->pollfd_in->fd) == -1) return -1; device_detatch_fd(dev, O_RDWR); return 0; } /* vim: set ts=4 sts=4 sw=4 tw=80 et: */