diff options
Diffstat (limited to 'serial.c')
-rw-r--r-- | serial.c | 59 |
1 files changed, 43 insertions, 16 deletions
@@ -15,8 +15,6 @@ * GNU General Public License for more details. */ -#include "platform.h" - #include <stdio.h> #include <stdlib.h> #include <unistd.h> @@ -49,6 +47,10 @@ fdtype sp_fd = SER_INV_FD; * On Linux there is a non-standard way to use arbitrary baud rates that we use if there is no * matching standard rate, see custom_baud.c * + * On Darwin there is also a non-standard ioctl() to set arbitrary baud rates + * and any above 230400, see custom_baud_darwin.c and + * https://opensource.apple.com/source/IOSerialFamily/IOSerialFamily-91/tests/IOSerialTestLib.c.auto.html + * * On Windows there exist similar macros (starting with CBR_ instead of B) but they are only defined for * backwards compatibility and the API supports arbitrary baud rates in the same manner as the macros, see * http://msdn.microsoft.com/en-us/library/windows/desktop/aa363214(v=vs.85).aspx @@ -181,6 +183,7 @@ int serialport_config(fdtype fd, int baud) } msg_pdbg("Baud rate is %ld.\n", dcb.BaudRate); #else + int custom_baud = (baud >= 0 && use_custom_baud(baud, sp_baudtable)); struct termios wanted, observed; if (tcgetattr(fd, &observed) != 0) { msg_perr_strerror("Could not fetch original serial port configuration: "); @@ -188,8 +191,8 @@ int serialport_config(fdtype fd, int baud) } wanted = observed; if (baud >= 0) { - if (use_custom_baud(baud, sp_baudtable)) { - if (set_custom_baudrate(fd, baud)) { + if (custom_baud) { + if (set_custom_baudrate(fd, baud, BEFORE_FLAGS, NULL)) { msg_perr_strerror("Could not set custom baudrate: "); return 1; } @@ -200,7 +203,6 @@ int serialport_config(fdtype fd, int baud) msg_perr_strerror("Could not fetch serial port configuration: "); return 1; } - msg_pdbg("Using custom baud rate.\n"); } else { const struct baudentry *entry = round_baud(baud); if (cfsetispeed(&wanted, entry->flag) != 0 || cfsetospeed(&wanted, entry->flag) != 0) { @@ -214,6 +216,10 @@ int serialport_config(fdtype fd, int baud) wanted.c_lflag &= ~(ICANON | ECHO | ECHOE | ISIG | IEXTEN); wanted.c_iflag &= ~(IXON | IXOFF | IXANY | ICRNL | IGNCR | INLCR); wanted.c_oflag &= ~OPOST; + if (custom_baud && set_custom_baudrate(fd, baud, WITH_FLAGS, &wanted)) { + msg_perr_strerror("Could not set custom baudrate: "); + return 1; + } if (tcsetattr(fd, TCSANOW, &wanted) != 0) { msg_perr_strerror("Could not change serial port configuration: "); return 1; @@ -238,6 +244,13 @@ int serialport_config(fdtype fd, int baud) (long)observed.c_oflag, (long)wanted.c_oflag ); } + if (custom_baud) { + if (set_custom_baudrate(fd, baud, AFTER_FLAGS, &wanted)) { + msg_perr_strerror("Could not set custom baudrate: "); + return 1; + } + msg_pdbg("Using custom baud rate.\n"); + } if (cfgetispeed(&observed) != cfgetispeed(&wanted) || cfgetospeed(&observed) != cfgetospeed(&wanted)) { msg_pwarn("Could not set baud rates exactly.\n"); @@ -391,18 +404,21 @@ int serialport_write(const unsigned char *buf, unsigned int writecnt) while (writecnt > 0) { #if IS_WINDOWS - WriteFile(sp_fd, buf, writecnt, &tmp, NULL); + if (!WriteFile(sp_fd, buf, writecnt, &tmp, NULL)) { + msg_perr("Serial port write error!\n"); + return 1; + } #else tmp = write(sp_fd, buf, writecnt); -#endif if (tmp == -1) { msg_perr("Serial port write error!\n"); return 1; } +#endif if (!tmp) { msg_pdbg2("Empty write\n"); empty_writes--; - internal_delay(500); + default_delay(500); if (empty_writes == 0) { msg_perr("Serial port is unresponsive!\n"); return 1; @@ -425,14 +441,17 @@ int serialport_read(unsigned char *buf, unsigned int readcnt) while (readcnt > 0) { #if IS_WINDOWS - ReadFile(sp_fd, buf, readcnt, &tmp, NULL); + if (!ReadFile(sp_fd, buf, readcnt, &tmp, NULL)) { + msg_perr("Serial port read error!\n"); + return 1; + } #else tmp = read(sp_fd, buf, readcnt); -#endif if (tmp == -1) { msg_perr("Serial port read error!\n"); return 1; } +#endif if (!tmp) msg_pdbg2("Empty read\n"); readcnt -= tmp; @@ -485,24 +504,28 @@ int serialport_read_nonblock(unsigned char *c, unsigned int readcnt, unsigned in for (i = 0; i < timeout; i++) { msg_pspew("readcnt %u rd_bytes %u\n", readcnt, rd_bytes); #if IS_WINDOWS - ReadFile(sp_fd, c + rd_bytes, readcnt - rd_bytes, &rv, NULL); + if (!ReadFile(sp_fd, c + rd_bytes, readcnt - rd_bytes, &rv, NULL)) { + msg_perr_strerror("Serial port read error: "); + ret = -1; + break; + } msg_pspew("read %lu bytes\n", rv); #else rv = read(sp_fd, c + rd_bytes, readcnt - rd_bytes); msg_pspew("read %zd bytes\n", rv); -#endif if ((rv == -1) && (errno != EAGAIN)) { msg_perr_strerror("Serial port read error: "); ret = -1; break; } +#endif if (rv > 0) rd_bytes += rv; if (rd_bytes == readcnt) { ret = 0; break; } - internal_delay(1000); /* 1ms units */ + default_delay(1000); /* 1ms units */ } if (really_read != NULL) *really_read = rd_bytes; @@ -565,17 +588,21 @@ int serialport_write_nonblock(const unsigned char *buf, unsigned int writecnt, u for (i = 0; i < timeout; i++) { msg_pspew("writecnt %u wr_bytes %u\n", writecnt, wr_bytes); #if IS_WINDOWS - WriteFile(sp_fd, buf + wr_bytes, writecnt - wr_bytes, &rv, NULL); + if (!WriteFile(sp_fd, buf + wr_bytes, writecnt - wr_bytes, &rv, NULL)) { + msg_perr_strerror("Serial port write error: "); + ret = -1; + break; + } msg_pspew("wrote %lu bytes\n", rv); #else rv = write(sp_fd, buf + wr_bytes, writecnt - wr_bytes); msg_pspew("wrote %zd bytes\n", rv); -#endif if ((rv == -1) && (errno != EAGAIN)) { msg_perr_strerror("Serial port write error: "); ret = -1; break; } +#endif if (rv > 0) { wr_bytes += rv; if (wr_bytes == writecnt) { @@ -584,7 +611,7 @@ int serialport_write_nonblock(const unsigned char *buf, unsigned int writecnt, u break; } } - internal_delay(1000); /* 1ms units */ + default_delay(1000); /* 1ms units */ } if (really_wrote != NULL) *really_wrote = wr_bytes; |