From 088ea6d054aad3934118adace2fc9f51b2c31cba Mon Sep 17 00:00:00 2001 From: Jef Driesen Date: Thu, 11 Aug 2011 20:35:00 +0200 Subject: [PATCH] Add support for non standard baudrates. --- configure.ac | 4 +++ src/serial_posix.c | 83 +++++++++++++++++++++++++++++++++++++++++++++- src/serial_win32.c | 19 +---------- 3 files changed, 87 insertions(+), 19 deletions(-) diff --git a/configure.ac b/configure.ac index 049d286..71d1468 100644 --- a/configure.ac +++ b/configure.ac @@ -67,6 +67,10 @@ AC_CHECK_HEADERS([sys/socket.h linux/types.h linux/irda.h], [irda_linux=yes], [i AM_CONDITIONAL([IRDA], [test "$irda_win32" = "yes" || test "$irda_linux" = "yes"]) +# Checks for header files. +AC_CHECK_HEADERS([linux/serial.h]) +AC_CHECK_HEADERS([IOKit/serial/ioss.h]) + # Checks for library functions. AC_CHECK_FUNCS([localtime_r gmtime_r]) diff --git a/src/serial_posix.c b/src/serial_posix.c index 3c4bff2..2064c22 100644 --- a/src/serial_posix.c +++ b/src/serial_posix.c @@ -19,6 +19,10 @@ * MA 02110-1301 USA */ +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + #include // malloc, free #include // strerror #include // errno @@ -28,6 +32,12 @@ #include // ioctl #include // gettimeofday #include // nanosleep +#ifdef HAVE_LINUX_SERIAL_H +#include +#endif +#ifdef HAVE_IOKIT_SERIAL_IOSS_H +#include +#endif #ifndef TIOCINQ #define TIOCINQ FIONREAD @@ -187,6 +197,7 @@ serial_configure (serial_t *device, int baudrate, int databits, int parity, int tty.c_cc[VTIME] = 0; // Set the baud rate. + int custom = 0; speed_t baud = 0; switch (baudrate) { case 0: baud = B0; break; @@ -213,9 +224,47 @@ serial_configure (serial_t *device, int baudrate, int databits, int parity, int #endif #ifdef B230400 case 230400: baud = B230400; break; +#endif +#ifdef B460800 + case 460800: baud = B460800; break; +#endif +#ifdef B500000 + case 500000: baud = B500000; break; +#endif +#ifdef B576000 + case 576000: baud = B576000; break; +#endif +#ifdef B921600 + case 921600: baud = B921600; break; +#endif +#ifdef B1000000 + case 1000000: baud = B1000000; break; +#endif +#ifdef B1152000 + case 1152000: baud = B1152000; break; +#endif +#ifdef B1500000 + case 1500000: baud = B1500000; break; +#endif +#ifdef B2000000 + case 2000000: baud = B2000000; break; +#endif +#ifdef B2500000 + case 2500000: baud = B2500000; break; +#endif +#ifdef B3000000 + case 3000000: baud = B3000000; break; +#endif +#ifdef B3500000 + case 3500000: baud = B3500000; break; +#endif +#ifdef B4000000 + case 4000000: baud = B4000000; break; #endif default: - return -1; + baud = B38400; /* Required for custom baudrates on linux. */ + custom = 1; + break; } if (cfsetispeed (&tty, baud) != 0 || cfsetospeed (&tty, baud) != 0) { @@ -320,6 +369,38 @@ serial_configure (serial_t *device, int baudrate, int databits, int parity, int return -1; } + // Configure a custom baudrate if necessary. + if (custom) { +#if defined(TIOCGSERIAL) && defined(TIOCSSERIAL) + // Get the current settings. + struct serial_struct ss; + if (ioctl (device->fd, TIOCGSERIAL, &ss) != 0) { + TRACE ("ioctl"); + return -1; + } + + // Set the custom divisor. + ss.custom_divisor = ss.baud_base / baudrate; + ss.flags &= ~ASYNC_SPD_MASK; + ss.flags |= ASYNC_SPD_CUST; + + // Apply the new settings. + if (ioctl (device->fd, TIOCSSERIAL, &ss) != 0) { + TRACE ("ioctl"); + return -1; + } +#elif defined(IOSSIOSPEED) + speed_t speed = baudrate; + if (ioctl (device->fd, IOSSIOSPEED, &speed) != 0) { + TRACE ("ioctl"); + return -1; + } +#else + // Custom baudrates are not supported. + return -1; +#endif + } + return 0; } diff --git a/src/serial_win32.c b/src/serial_win32.c index 9ec432d..8a9c619 100644 --- a/src/serial_win32.c +++ b/src/serial_win32.c @@ -194,24 +194,7 @@ serial_configure (serial_t *device, int baudrate, int databits, int parity, int dcb.fAbortOnError = FALSE; // Baudrate. - switch (baudrate) { - case 110: dcb.BaudRate = CBR_110; break; - case 300: dcb.BaudRate = CBR_300; break; - case 600: dcb.BaudRate = CBR_600; break; - case 1200: dcb.BaudRate = CBR_1200; break; - case 2400: dcb.BaudRate = CBR_2400; break; - case 4800: dcb.BaudRate = CBR_4800; break; - case 9600: dcb.BaudRate = CBR_9600; break; - case 14400: dcb.BaudRate = CBR_14400; break; - case 19200: dcb.BaudRate = CBR_19200; break; - case 38400: dcb.BaudRate = CBR_38400; break; - case 57600: dcb.BaudRate = CBR_57600; break; - case 115200: dcb.BaudRate = CBR_115200; break; - case 128000: dcb.BaudRate = CBR_128000; break; - case 256000: dcb.BaudRate = CBR_256000; break; - default: - return -1; - } + dcb.BaudRate = baudrate; // Character size. if (databits >= 5 && databits <= 8)