Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Custom baud rates #19

Open
wants to merge 1 commit into
base: v2.x
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 8 additions & 4 deletions dll/serialunix/libnserial/baudrate.c
Original file line number Diff line number Diff line change
Expand Up @@ -177,16 +177,20 @@ NSERIAL_EXPORT int WINAPI serial_setbaud(struct serialhandle *handle, int baud)
if (baud == baudrates[i].baud) {
handle->baudrate = baudrates[i].baud;
handle->cbaud = baudrates[i].cbaud;

handle->custombaud = 0;
// TODO: Update the serial port baud rate if already opened.
return 0;
}
i++;
}

// Nope? set custom baud config
// Derived from https://github.com/torvalds/linux/blob/master/drivers/usb/serial/ftdi_sio.c line 1262
handle->cbaud = B38400;
handle->baudrate = baud;
handle->custombaud = 1;

serial_seterror(handle, ERRMSG_UNSUPPORTEDBAUDRATE);
errno = EINVAL;
return -1;
return 0;
}

NSERIAL_EXPORT int WINAPI serial_getbaud(struct serialhandle *handle, int *baud)
Expand Down
85 changes: 64 additions & 21 deletions dll/serialunix/libnserial/openserial.c
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
#include <errno.h>
#include <fcntl.h>
#include <termios.h>
#include <linux/serial.h>
#include <sys/ioctl.h>
#include <unistd.h>

Expand Down Expand Up @@ -187,18 +188,31 @@ NSERIAL_EXPORT int WINAPI serial_getproperties(struct serialhandle *handle)
}

// Get the baud rate
handle->cbaud = cfgetispeed(&tio);
handle->baudrate = 0;
int i = 0;
while (baudrates[i].baud && handle->baudrate == 0) {
if (baudrates[i].cbaud == handle->cbaud) {
handle->baudrate = baudrates[i].baud;
if(handle->custombaud == 0) {
handle->cbaud = cfgetispeed(&tio);
handle->baudrate = 0;
int i = 0;
while (baudrates[i].baud && handle->baudrate == 0) {
if (baudrates[i].cbaud == handle->cbaud) {
handle->baudrate = baudrates[i].baud;
}
i++;
}
i++;
}
if (handle->baudrate == 0) {
// This baudrate is not known, so we set the default
serial_setdefaultbaud(handle);
if (handle->baudrate == 0) {
// This baudrate is not known, so we set the default
serial_setdefaultbaud(handle);
}
} else {
struct serial_struct serstruct;

handle->cbaud = cfgetispeed(&tio);
//TODO: Should be B38400
if (ioctl(handle->fd, TIOCGSERIAL, &serstruct) != 0) {
serial_seterror(handle, ERRMSG_SERIALTCGETATTR);
return -1;
}

handle->baudrate = serstruct.baud_base / serstruct.custom_divisor;
}

return 0;
Expand Down Expand Up @@ -367,16 +381,44 @@ NSERIAL_EXPORT int WINAPI serial_setproperties(struct serialhandle *handle)
return -1;
}

// Set baudrate. Here we assume first no custom baudrate
if (cfsetospeed(&newtio, handle->cbaud) < 0 ||
cfsetispeed(&newtio, handle->cbaud) < 0) {
serial_seterror(handle, ERRMSG_INVALIDBAUD);
errno = EINVAL;
return -1;
if(handle->custombaud == 0) {
// Set baudrate. Here we assume first no custom baudrate
if (cfsetospeed(&newtio, handle->cbaud) < 0 ||
cfsetispeed(&newtio, handle->cbaud) < 0) {
serial_seterror(handle, ERRMSG_INVALIDBAUD);
errno = EINVAL;
return -1;
}
} else {
struct serial_struct serstruct;

//Set speed to B38400
if (cfsetospeed(&newtio, B38400) < 0 ||
cfsetispeed(&newtio, B38400) < 0) {
serial_seterror(handle, ERRMSG_INVALIDBAUD);
errno = EINVAL;
return -1;
}

//Extract serial_struct
if (ioctl(handle->fd, TIOCGSERIAL, &serstruct) != 0) {
serial_seterror(handle, ERRMSG_SERIALTCGETATTR);
return -1;
}

//Calculate divisor and set custom flags
serstruct.custom_divisor = serstruct.baud_base / handle->baudrate;
if (serstruct.custom_divisor == 0)
serstruct.custom_divisor = 1;
serstruct.flags &= ~ASYNC_SPD_MASK;
serstruct.flags |= ASYNC_SPD_CUST;

if (ioctl(handle->fd, TIOCSSERIAL, &serstruct) != 0) {
serial_seterror(handle, ERRMSG_SERIALTCSETATTR);
return -1;
}
}

// TODO: Custom baudrates are not currently supported

// Turn off delays in the system. Read only the data in the serial port.
newtio.c_cc[VMIN] = 0;
newtio.c_cc[VTIME] = 0;
Expand All @@ -395,8 +437,9 @@ NSERIAL_EXPORT int WINAPI serial_setproperties(struct serialhandle *handle)

// Get the baudrate and compare with what we set
tcgetattr(handle->fd, &newtio);
if (cfgetispeed(&newtio) != handle->cbaud ||
cfgetospeed(&newtio) != handle->cbaud) {
if (handle->custombaud == 0 &&
(cfgetispeed(&newtio) != handle->cbaud ||
cfgetospeed(&newtio) != handle->cbaud)) {
nslog(handle, NSLOG_WARNING, "setproperties: baudrate mismatch. "
"ispeed ret=%d set=%d; ospeed ret=%d set=%d",
cfgetispeed(&newtio), handle->cbaud,
Expand Down
1 change: 1 addition & 0 deletions dll/serialunix/libnserial/serialhandle.h
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@ struct serialhandle {
int fd; // File descriptor for the serial port
int baudrate; // Integer value of the baudrate
int cbaud; // Converted cbaud value
int custombaud; // Flag to indicate that there is no supported cbaud value and a custom trick has to be performed
int databits; // Databits: 5..8
serialparity_t parity; // Parity: N, E, O, S, M
serialstopbits_t stopbits; // Stopbits: 1, 1.5, 2
Expand Down