diff --git a/drivers/uif.c b/drivers/uif.c index 39a0af9..c9390a9 100644 --- a/drivers/uif.c +++ b/drivers/uif.c @@ -28,11 +28,6 @@ #include "output.h" #include "sport.h" -#if defined(__linux__) -#include -#include -#endif - struct uif_transport { struct transport base; @@ -80,37 +75,6 @@ static void serial_destroy(transport_t tr_base) free(tr); } -#if defined(__linux__) -static int open_olimex_iso(const char *device) -{ - int fd = open(device, O_RDWR | O_NOCTTY); - struct termios attr; - struct serial_struct serial_info; - - if (fd < 0) - return -1; - - tcgetattr(fd, &attr); - cfmakeraw(&attr); - cfsetispeed(&attr, B38400); - cfsetospeed(&attr, B38400); - - serial_info.flags = ASYNC_SPD_CUST; - serial_info.custom_divisor = 120; - if (ioctl(fd, TIOCSSERIAL, &serial_info) < 0) { - printc_err("open_olimex_iso: can't do " - "ioctl TIOCSSERIAL: %s\n", - last_error()); - return -1; - } - - if (tcsetattr(fd, TCSAFLUSH, &attr) < 0) - return -1; - - return fd; -} -#endif - transport_t uif_open(const char *device, uif_type_t type) { struct uif_transport *tr = malloc(sizeof(*tr)); @@ -144,13 +108,8 @@ transport_t uif_open(const char *device, uif_type_t type) break; case UIF_TYPE_OLIMEX_ISO: -#if defined(__linux__) printc("Trying to open Olimex (ISO) on %s...\n", device); - tr->serial_fd = open_olimex_iso(device); -#else - printc_err("uif_open: ioctl TIOCSSERIAL not supported " - "on this platform\n"); -#endif + tr->serial_fd = sport_open(device, 200000, 0); break; } diff --git a/util/sport.c b/util/sport.c index 79634c6..2b6ef84 100644 --- a/util/sport.c +++ b/util/sport.c @@ -23,6 +23,11 @@ #include "sport.h" #include "util.h" +#include "output.h" + +#ifdef __linux__ +#include +#endif #ifndef WIN32 @@ -57,6 +62,35 @@ static int rate_to_code(int rate) return -1; } +#ifdef __linux__ +static int set_nonstandard_rate(int fd, int rate) +{ + struct serial_struct ss; + + if (ioctl(fd, TIOCGSERIAL, &ss) < 0) { + pr_error("sport: TIOCGSERIAL failed"); + return -1; + } + + ss.custom_divisor = ss.baud_base / rate; + ss.flags = ASYNC_SPD_CUST; + + if (ioctl(fd, TIOCSSERIAL, &ss) < 0) { + pr_error("sport: TIOCSSERIAL failed"); + return -1; + } + + return 0; +} +#else +static int set_nonstandard_rate(int fd, int rate) +{ + printc_err("sport: Can't set non-standard baud rate %d on " + "this platform\n", rate); + return -1; +} +#endif + sport_t sport_open(const char *device, int rate, int flags) { int fd = open(device, O_RDWR | O_NOCTTY); @@ -72,6 +106,17 @@ sport_t sport_open(const char *device, int rate, int flags) if (rate_code >= 0) { cfsetispeed(&attr, rate_code); cfsetospeed(&attr, rate_code); + } else { + if (set_nonstandard_rate(fd, rate) < 0) { + close(fd); + return -1; + } + + /* We need to set the rate code to B38400 on Linux for + * the non-standard rate to take effect. + */ + cfsetispeed(&attr, B38400); + cfsetospeed(&attr, B38400); } if (flags & SPORT_EVEN_PARITY)