Add support for non standard baudrates.

This commit is contained in:
Jef Driesen 2011-08-11 20:35:00 +02:00
parent d3e522b070
commit 088ea6d054
3 changed files with 87 additions and 19 deletions

View File

@ -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])

View File

@ -19,6 +19,10 @@
* MA 02110-1301 USA
*/
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#include <stdlib.h> // malloc, free
#include <string.h> // strerror
#include <errno.h> // errno
@ -28,6 +32,12 @@
#include <sys/ioctl.h> // ioctl
#include <sys/time.h> // gettimeofday
#include <time.h> // nanosleep
#ifdef HAVE_LINUX_SERIAL_H
#include <linux/serial.h>
#endif
#ifdef HAVE_IOKIT_SERIAL_IOSS_H
#include <IOKit/serial/ioss.h>
#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;
}

View File

@ -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)