Handle non-standard baud rates in sport_open().

This should allow the use of the Olimex MSP430-JTAG-ISO on Windows (and
other platforms, if handling is implemented).
This commit is contained in:
Daniel Beer 2012-02-29 16:58:11 +13:00
parent 68f968a637
commit cf5b7f3399
2 changed files with 46 additions and 42 deletions

View File

@ -28,11 +28,6 @@
#include "output.h" #include "output.h"
#include "sport.h" #include "sport.h"
#if defined(__linux__)
#include <linux/serial.h>
#include <fcntl.h>
#endif
struct uif_transport { struct uif_transport {
struct transport base; struct transport base;
@ -80,37 +75,6 @@ static void serial_destroy(transport_t tr_base)
free(tr); 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) transport_t uif_open(const char *device, uif_type_t type)
{ {
struct uif_transport *tr = malloc(sizeof(*tr)); struct uif_transport *tr = malloc(sizeof(*tr));
@ -144,13 +108,8 @@ transport_t uif_open(const char *device, uif_type_t type)
break; break;
case UIF_TYPE_OLIMEX_ISO: case UIF_TYPE_OLIMEX_ISO:
#if defined(__linux__)
printc("Trying to open Olimex (ISO) on %s...\n", device); printc("Trying to open Olimex (ISO) on %s...\n", device);
tr->serial_fd = open_olimex_iso(device); tr->serial_fd = sport_open(device, 200000, 0);
#else
printc_err("uif_open: ioctl TIOCSSERIAL not supported "
"on this platform\n");
#endif
break; break;
} }

View File

@ -23,6 +23,11 @@
#include "sport.h" #include "sport.h"
#include "util.h" #include "util.h"
#include "output.h"
#ifdef __linux__
#include <linux/serial.h>
#endif
#ifndef WIN32 #ifndef WIN32
@ -57,6 +62,35 @@ static int rate_to_code(int rate)
return -1; 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) sport_t sport_open(const char *device, int rate, int flags)
{ {
int fd = open(device, O_RDWR | O_NOCTTY); 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) { if (rate_code >= 0) {
cfsetispeed(&attr, rate_code); cfsetispeed(&attr, rate_code);
cfsetospeed(&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) if (flags & SPORT_EVEN_PARITY)