diff options
author | Miguel de Icaza <miguel@gnome.org> | 2007-08-12 20:11:08 +0400 |
---|---|---|
committer | Miguel de Icaza <miguel@gnome.org> | 2007-08-12 20:11:08 +0400 |
commit | c1618ae78e6db3dff3bb11153bd8e3ab1955fa8b (patch) | |
tree | 1e98e11384f1ef4b85f55511701aa0f0f1bd58d7 /support | |
parent | 598606f78ead551938e993e3f8753c2f9e1bcf6e (diff) |
First part of patch for bug #81967,
2007-08-12 Lukasz Byczynski <lukaszb@forcom.com.pl>
* serial.c:
- all changes are based on Windows .Net SerialPort behavior and
this
document: http://www.easysw.com/~mike/serial/serial.html
- removed wrong default values from open_serial
- added timeout detection in write_serial
- added proper parameters setting in set_attributes
svn path=/trunk/mono/; revision=83921
Diffstat (limited to 'support')
-rw-r--r-- | support/ChangeLog | 11 | ||||
-rw-r--r-- | support/serial.c | 212 |
2 files changed, 152 insertions, 71 deletions
diff --git a/support/ChangeLog b/support/ChangeLog index 202109c55ee..1e67a66f8c4 100644 --- a/support/ChangeLog +++ b/support/ChangeLog @@ -1,3 +1,14 @@ +2007-08-12 Lukasz Byczynski <lukaszb@forcom.com.pl> + + * serial.c: + + - all changes are based on Windows .Net SerialPort behavior and + this + document: http://www.easysw.com/~mike/serial/serial.html + - removed wrong default values from open_serial + - added timeout detection in write_serial + - added proper parameters setting in set_attributes + 2007-06-29 Jonathan Pryor <jonpryor@vt.edu> * dirent.c, grp.c, pwd.c, stdio.c, syslog.c, unistd.c: Following in the diff --git a/support/serial.c b/support/serial.c index f7746c41a86..a5acb738f97 100644 --- a/support/serial.c +++ b/support/serial.c @@ -59,21 +59,11 @@ int open_serial (char* devfile) { int fd; - struct termios newtio; - - fd = open (devfile, O_RDWR); + fd = open (devfile, O_RDWR | O_NOCTTY | O_NONBLOCK); if (fd == -1) return -1; - newtio.c_cflag = CLOCAL | CREAD; - newtio.c_iflag = 0; - newtio.c_oflag = 0; - newtio.c_lflag = 0; - - tcflush(fd, TCIOFLUSH); - tcsetattr(fd,TCSANOW,&newtio); - return fd; } @@ -93,25 +83,46 @@ read_serial (int fd, guchar *buffer, int offset, int count) return (guint32) n; } -void +int write_serial (int fd, guchar *buffer, int offset, int count, int timeout) { + struct timeval tmval; + fd_set writefs; guint32 n; - struct pollfd ufd; - - ufd.fd = fd; - ufd.events = POLLHUP | POLLOUT | POLLERR; + n = count - offset; - while (poll (&ufd, 1, timeout) == -1 && errno == EINTR){ + FD_SET(fd, &writefs); + tmval.tv_sec = timeout / 1000; + tmval.tv_usec = (timeout - tmval.tv_sec) * 1000; + + while (n > 0) + { + size_t t; + + if (timeout > 0) + { + if (select(fd+1, NULL, &writefs, NULL, &tmval) <= 0 && errno != EINTR) + { + return -1; + } + } + + t = write(fd, buffer + offset, count); + if (timeout > 0) + { + if (select(fd+1, NULL, &writefs, NULL, &tmval) <= 0 && errno != EINTR) + { + return -1; + } } - if ((ufd.revents & POLLOUT) != POLLOUT) { - return; + offset += t; + n -= t; } - n = write (fd, buffer + offset, count); + return 0; } void @@ -138,71 +149,100 @@ set_attributes (int fd, int baud_rate, MonoParity parity, int dataBits, MonoStop struct termios newtio; tcgetattr (fd, &newtio); - - switch (baud_rate) { - case 230400: baud_rate = B230400; break; - case 115200: baud_rate = B115200; break; - case 57600: baud_rate = B57600; break; - case 38400: baud_rate = B38400; break; - case 19200: baud_rate = B19200; break; - case 9600: baud_rate = B9600; break; - case 4800: baud_rate = B4800; break; - case 2400: baud_rate = B2400; break; - case 1800: baud_rate = B1800; break; - case 1200: baud_rate = B1200; break; - case 600: baud_rate = B600; break; - case 300: baud_rate = B300; break; - case 200: baud_rate = B200; break; - case 150: baud_rate = B150; break; - case 134: baud_rate = B134; break; - case 110: baud_rate = B110; break; - case 75: baud_rate = B75; break; - case 50: - case 0: - default: + newtio.c_cflag |= (CLOCAL | CREAD); + newtio.c_lflag &= ~(ICANON | ECHO | ECHOE | ECHOK | ECHONL | ISIG | IEXTEN ); + newtio.c_oflag &= ~(OPOST); + newtio.c_iflag = IGNBRK; + + /* setup baudrate */ + switch (baud_rate) + { + case 230400: + baud_rate = B230400; + break; + case 115200: + baud_rate = B115200; + break; + case 57600: + baud_rate = B57600; + break; + case 38400: + baud_rate = B38400; + break; + case 19200: + baud_rate = B19200; + break; + case 9600: baud_rate = B9600; break; - } - - switch (parity) { - case NoneParity: /* None */ - newtio.c_iflag |= IGNPAR; - newtio.c_cflag &= ~(PARENB | PARODD); + case 4800: + baud_rate = B4800; break; - case Odd: /* Odd */ - newtio.c_iflag &= ~IGNPAR; - newtio.c_cflag |= PARENB | PARODD; + case 2400: + baud_rate = B2400; break; - case Even: /* Even */ - newtio.c_iflag &= ~(IGNPAR | PARODD); - newtio.c_cflag |= PARENB; + case 1800: + baud_rate = B1800; break; - case Mark: /* Mark */ - /* XXX unhandled */ + case 1200: + baud_rate = B1200; break; - case Space: /* Space */ - /* XXX unhandled */ + case 600: + baud_rate = B600; + break; + case 300: + baud_rate = B300; + break; + case 200: + baud_rate = B200; + break; + case 150: + baud_rate = B150; + break; + case 134: + baud_rate = B134; + break; + case 110: + baud_rate = B110; + break; + case 75: + baud_rate = B75; + break; + case 50: + case 0: + default: + baud_rate = B9600; break; } + /* char lenght */ newtio.c_cflag &= ~CSIZE; - switch (dataBits) { - case 5: newtio.c_cflag |= CS5; break; - case 6: newtio.c_cflag |= CS6; break; - case 7: newtio.c_cflag |= CS7; break; + switch (dataBits) + { + case 5: + newtio.c_cflag |= CS5; + break; + case 6: + newtio.c_cflag |= CS6; + break; + case 7: + newtio.c_cflag |= CS7; + break; case 8: default: newtio.c_cflag |= CS8; break; } - newtio.c_cflag &= ~CSTOPB; - switch (stopBits) { + /* stopbits */ + switch (stopBits) + { case NoneStopBits: /* Unhandled */ break; case One: /* One */ /* do nothing, the default is one stop bit */ + newtio.c_cflag &= ~CSTOPB; break; case Two: /* Two */ newtio.c_cflag |= CSTOPB; @@ -212,12 +252,38 @@ set_attributes (int fd, int baud_rate, MonoParity parity, int dataBits, MonoStop break; } - newtio.c_iflag &= ~IXOFF; - newtio.c_oflag &= ~IXON; + /* parity */ + newtio.c_iflag &= ~(INPCK | ISTRIP ); + + switch (parity) + { + case NoneParity: /* None */ + newtio.c_cflag &= ~(PARENB | PARODD); + break; + + case Odd: /* Odd */ + newtio.c_cflag |= PARENB | PARODD; + break; + + case Even: /* Even */ + newtio.c_cflag &= ~(PARODD); + break; + + case Mark: /* Mark */ + /* XXX unhandled */ + break; + case Space: /* Space */ + /* XXX unhandled */ + break; + } + + newtio.c_iflag &= ~(IXOFF | IXON); #ifdef CRTSCTS newtio.c_cflag &= ~CRTSCTS; #endif /* def CRTSCTS */ - switch (handshake) { + + switch (handshake) + { case NoneHandshake: /* None */ /* do nothing */ break; @@ -232,18 +298,22 @@ set_attributes (int fd, int baud_rate, MonoParity parity, int dataBits, MonoStop #endif /* def CRTSCTS */ /* fall through */ case XOnXOff: /* XOnXOff */ - newtio.c_iflag |= IXOFF; - // newtio.c_oflag |= IXON; + newtio.c_iflag |= IXOFF | IXON; break; } if (cfsetospeed (&newtio, baud_rate) < 0 || cfsetispeed (&newtio, baud_rate) < 0 || - tcsetattr (fd, TCSADRAIN, &newtio) < 0) + tcsetattr (fd, TCSANOW, &newtio) < 0) + { return FALSE; - + } + else + { return TRUE; + } } + static gint32 get_signal_code (MonoSerialSignal signal) { |