core: update some serial port settings

1) use cfsetispeed/cfsetospeed like the TTY manpage suggests
2) ignore parity/framing errors since we're not using parity anyway
3) double-check that all our TTY settings were successfully set
This commit is contained in:
Dan Williams
2011-07-06 13:08:18 -05:00
parent 50e9d6fc54
commit 2ca045f178

View File

@@ -324,7 +324,7 @@ static gboolean
real_config_fd (MMSerialPort *self, int fd, GError **error) real_config_fd (MMSerialPort *self, int fd, GError **error)
{ {
MMSerialPortPrivate *priv = MM_SERIAL_PORT_GET_PRIVATE (self); MMSerialPortPrivate *priv = MM_SERIAL_PORT_GET_PRIVATE (self);
struct termios stbuf; struct termios stbuf, other;
int speed; int speed;
int bits; int bits;
int parity; int parity;
@@ -343,7 +343,7 @@ real_config_fd (MMSerialPort *self, int fd, GError **error)
errno); errno);
} }
stbuf.c_iflag &= ~(IGNCR | ICRNL | IUCLC | INPCK | IXON | IXANY | IGNPAR ); stbuf.c_iflag &= ~(IGNCR | ICRNL | IUCLC | INPCK | IXON | IXANY );
stbuf.c_oflag &= ~(OPOST | OLCUC | OCRNL | ONLCR | ONLRET); stbuf.c_oflag &= ~(OPOST | OLCUC | OCRNL | ONLCR | ONLRET);
stbuf.c_lflag &= ~(ICANON | XCASE | ECHO | ECHOE | ECHONL); stbuf.c_lflag &= ~(ICANON | XCASE | ECHO | ECHOE | ECHONL);
stbuf.c_lflag &= ~(ECHO | ECHOE); stbuf.c_lflag &= ~(ECHO | ECHOE);
@@ -351,14 +351,34 @@ real_config_fd (MMSerialPort *self, int fd, GError **error)
stbuf.c_cc[VTIME] = 0; stbuf.c_cc[VTIME] = 0;
stbuf.c_cc[VEOF] = 1; stbuf.c_cc[VEOF] = 1;
/* Use software handshaking */ /* Use software handshaking and ignore parity/framing errors */
stbuf.c_iflag |= (IXON | IXOFF | IXANY); stbuf.c_iflag |= (IXON | IXOFF | IXANY | IGNPAR);
/* Set up port speed and serial attributes; also ignore modem control /* Set up port speed and serial attributes; also ignore modem control
* lines since most drivers don't implement RTS/CTS anyway. * lines since most drivers don't implement RTS/CTS anyway.
*/ */
stbuf.c_cflag &= ~(CBAUD | CSIZE | CSTOPB | PARENB | CRTSCTS); stbuf.c_cflag &= ~(CBAUD | CSIZE | CSTOPB | PARENB | CRTSCTS);
stbuf.c_cflag |= (speed | bits | CREAD | 0 | parity | stopbits | CLOCAL); stbuf.c_cflag |= (bits | CREAD | 0 | parity | stopbits | CLOCAL);
errno = 0;
if (cfsetispeed (&stbuf, speed) != 0) {
g_set_error (error,
MM_MODEM_ERROR,
MM_MODEM_ERROR_GENERAL,
"%s: failed to set serial port input speed; errno %d",
__func__, errno);
return FALSE;
}
errno = 0;
if (cfsetospeed (&stbuf, speed) != 0) {
g_set_error (error,
MM_MODEM_ERROR,
MM_MODEM_ERROR_GENERAL,
"%s: failed to set serial port output speed; errno %d",
__func__, errno);
return FALSE;
}
if (tcsetattr (fd, TCSANOW, &stbuf) < 0) { if (tcsetattr (fd, TCSANOW, &stbuf) < 0) {
g_set_error (error, g_set_error (error,
@@ -369,6 +389,22 @@ real_config_fd (MMSerialPort *self, int fd, GError **error)
return FALSE; return FALSE;
} }
/* tcsetattr() returns 0 if any of the requested attributes could be set,
* so we should double-check that all were set and log a warning if not.
*/
memset (&other, 0, sizeof (struct termios));
errno = 0;
if (tcgetattr (fd, &other) != 0) {
mm_warn ("(%s): tcgetattr() error: %d",
mm_port_get_device (MM_PORT (self)),
errno);
}
if (memcmp (&stbuf, &other, sizeof (other)) != 0) {
mm_warn ("(%s): port attributes not fully set",
mm_port_get_device (MM_PORT (self)));
}
return TRUE; return TRUE;
} }