aboutsummaryrefslogtreecommitdiff
path: root/src/mm-serial-port.c
diff options
context:
space:
mode:
authorDan Williams <dcbw@redhat.com>2011-07-06 13:08:18 -0500
committerDan Williams <dcbw@redhat.com>2011-07-06 15:49:02 -0500
commit2ca045f1781095ed652bc01d0f47cdbe6b0b9775 (patch)
tree5196722f39196ef45f4bf403e5c65e64229a8013 /src/mm-serial-port.c
parent50e9d6fc54da6900796cc6af957465120dc530d7 (diff)
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
Diffstat (limited to 'src/mm-serial-port.c')
-rw-r--r--src/mm-serial-port.c46
1 files changed, 41 insertions, 5 deletions
diff --git a/src/mm-serial-port.c b/src/mm-serial-port.c
index 617da5a3..116eb611 100644
--- a/src/mm-serial-port.c
+++ b/src/mm-serial-port.c
@@ -324,7 +324,7 @@ static gboolean
real_config_fd (MMSerialPort *self, int fd, GError **error)
{
MMSerialPortPrivate *priv = MM_SERIAL_PORT_GET_PRIVATE (self);
- struct termios stbuf;
+ struct termios stbuf, other;
int speed;
int bits;
int parity;
@@ -343,7 +343,7 @@ real_config_fd (MMSerialPort *self, int fd, GError **error)
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_lflag &= ~(ICANON | XCASE | ECHO | ECHOE | ECHONL);
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[VEOF] = 1;
- /* Use software handshaking */
- stbuf.c_iflag |= (IXON | IXOFF | IXANY);
+ /* Use software handshaking and ignore parity/framing errors */
+ stbuf.c_iflag |= (IXON | IXOFF | IXANY | IGNPAR);
/* Set up port speed and serial attributes; also ignore modem control
* lines since most drivers don't implement RTS/CTS anyway.
*/
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) {
g_set_error (error,
@@ -369,6 +389,22 @@ real_config_fd (MMSerialPort *self, int fd, GError **error)
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;
}