| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182 | #include <string.h>#include <stdlib.h>#include <stdarg.h>#include <errno.h>#include <unistd.h>#include <termios.h>#include <fcntl.h>#include <sys/ioctl.h>#include <sys/time.h>#include <sys/select.h>#include <serial.h>#include <sprog.h>int serial_setbaud_termios(struct termios *t, int baud);int serial_select(int nfds, fd_set *readfds, fd_set *writefds, fd_set *exceptfds, struct timeval *timeout);/* supported baud codes to use with cfsetispeed, cfsetospeed - keep sorted! */const struct baud_code baud_codes[] = {  {50, B50},  {75, B75},  {110, B110},  {134, B134},  {150, B150},  {200, B200},  {300, B300},  {600, B600},  {1200, B1200},  {1800, B1800},  {2400, B2400},  {4800, B4800},  {9600, B9600},  {19200, B19200},  {38400, B38400},  {57600, B57600},  {115200, B115200},  {230400, B230400},  {-1, 0}};int serial_open(struct serial_device *port, const char *path, int baud) {  struct termios attr;  int fd;  fd = open(path, O_RDWR);  if(fd<0) {    sprog_error("Unable to open serial port %s: %s\n", path, strerror(errno));    exit(1);  }    tcgetattr(fd, &attr);  /* 8 data bits, 1 stop bit, no parity */  attr.c_iflag = IGNBRK;  attr.c_oflag &= ~(OPOST | OLCUC | ONOCR | ONLRET | ONLCR);   attr.c_cflag = CS8 | CREAD | CLOCAL;  attr.c_lflag = ICANON;  serial_setbaud_termios(&attr, baud);  tcsetattr(fd, TCSANOW, &attr);  port->fd = fd;  port->f = fdopen(fd, "r+");  return fd;}void serial_close(struct serial_device *port) {  close(port->fd);}int serial_setbaud(struct serial_device *port, int baud) {  struct termios attr;  tcgetattr(port->fd, &attr);  baud = serial_setbaud_termios(&attr, baud);  tcsetattr(port->fd, TCSANOW, &attr);  return baud;}int serial_setbaud_termios(struct termios *t, int baud) {  int i;  int baudcode;    /* find the corresponding baud code */    for(i=0; baud_codes[i].baud>0; i++) {    if(baud_codes[i].baud == baud)      break;    if(baud_codes[i].baud > baud) {      if(i>0) i--;      break;    }  }    /* if the selected baud rate is greater than any of available rates, set the highest one */  if(baud_codes[i].baud<=0) i--;    if(baud_codes[i].baud != baud)    sprog_error("Unsupported baud rate %d, using the nearest value %d\n", baud, baud_codes[i].baud);    baudcode = baud_codes[i].code;  cfsetispeed(t, baudcode);  cfsetospeed(t, baudcode);  return baud_codes[i].baud;}void serial_setline(struct serial_device *port, int line, int state) {  int bits;  int mask;  if(line==SERIAL_DTR)    mask = TIOCM_DTR;  else    mask = TIOCM_RTS;    ioctl(port->fd, TIOCMGET, &bits);  if(state)    bits |= mask;  else    bits &= ~mask;  ioctl(port->fd, TIOCMSET, &bits);}void serial_write(struct serial_device *port, const char *text) {  int i;  int b;  int bytes;  bytes = strlen(text);  i = 0;//  sprog_info("<-- %s\n", text);    while(bytes-i>0) {    b = write(port->fd, &text[i], bytes-i);    if(b<0) {      sprog_error("Error while writing to the serial port: %s\n", strerror(errno));      break;    }    i += b;  }}int serial_read(struct serial_device *port, char *buf, int len, int timeout) {  int bytes;  fd_set readset;  struct timeval tval;  FD_ZERO(&readset);  FD_SET(port->fd, &readset);    tval.tv_sec = timeout/1000;  tval.tv_usec = (timeout % 1000) * 1000;    bytes = 0;  while((serial_select(port->fd+1, &readset, NULL, NULL, &tval)>0) && (len-bytes)>0) {    if(FD_ISSET(port->fd, &readset))      bytes += read(port->fd, &buf[bytes], len-bytes);  }//  buf[bytes]=0; sprog_info("--> %s\n", buf);  return bytes;}int serial_select(int nfds, fd_set *readfds, fd_set *writefds, fd_set *exceptfds, struct timeval *timeout) {  int res;     /* Linux automatically subtracts the time elapsed on awaiting   * for an event when calling select(), The following code unifices   * the behaviour under different implementations of UNIX.   */#ifndef __linux__  struct timeval start_time  struct timeval cur_time;  long int remaining;    gettimeofday(&start_time, NULL);  res = pselect(nfds, readfds, writefds, exceptfds, timeout, NULL)  gettimeofday(&cur_time, NULL);  remaining = (timeout->tv_sec - (cur_time.tv_sec - start_time.tv_sec))*1000000 + timeout->tv_usec - (cur_time.tv_usec - start_time.tv_usec);  if(remaining<0) remaining = 0;    timeout.tv_sec = remaining/1000000;  timeout.tv_usec = remmaining%1000000;#else  res = select(nfds, readfds, writefds, exceptfds, timeout);#endif   return res;}
 |