2 * This file is part of the libserialport project.
4 * Copyright (C) 2010-2012 Bert Vermeulen <bert@biot.com>
5 * Copyright (C) 2010-2012 Uwe Hermann <uwe@hermann-uwe.de>
6 * Copyright (C) 2013 Martin Ling <martin-libserialport@earth.li>
7 * Copyright (C) 2013 Matthias Heidbrink <m-sigrok@heidbrink.biz>
9 * This program is free software: you can redistribute it and/or modify
10 * it under the terms of the GNU Lesser General Public License as
11 * published by the Free Software Foundation, either version 3 of the
12 * License, or (at your option) any later version.
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU General Public License for more details.
19 * You should have received a copy of the GNU Lesser General Public License
20 * along with this program. If not, see <http://www.gnu.org/licenses/>.
24 #include <sys/types.h>
39 #include <sys/ioctl.h>
44 #include <IOKit/IOKitLib.h>
45 #include <IOKit/serial/IOSerialKeys.h>
46 #include <IOKit/serial/ioss.h>
47 #include <sys/syslimits.h>
54 #include "linux/serial.h"
56 #include "linux_termios.h"
58 /* TCGETX/TCSETX is not available everywhere. */
59 #if defined(TCGETX) && defined(TCSETX) && defined(HAVE_TERMIOX)
64 /* TIOCINQ/TIOCOUTQ is not available everywhere. */
65 #if !defined(TIOCINQ) && defined(FIONREAD)
66 #define TIOCINQ FIONREAD
68 #if !defined(TIOCOUTQ) && defined(FIONWRITE)
69 #define TIOCOUTQ FIONWRITE
73 #include "linux_termios.h"
76 #include "libserialport.h"
82 COMMTIMEOUTS timeouts;
92 struct sp_port_config {
95 enum sp_parity parity;
101 enum sp_xonxoff xon_xoff;
110 int termiox_supported;
115 /* Standard baud rates. */
117 #define BAUD_TYPE DWORD
118 #define BAUD(n) {CBR_##n, n}
120 #define BAUD_TYPE speed_t
121 #define BAUD(n) {B##n, n}
124 struct std_baudrate {
129 const struct std_baudrate std_baudrates[] = {
132 * The baudrates 50/75/134/150/200/1800/230400/460800 do not seem to
133 * have documented CBR_* macros.
135 BAUD(110), BAUD(300), BAUD(600), BAUD(1200), BAUD(2400), BAUD(4800),
136 BAUD(9600), BAUD(14400), BAUD(19200), BAUD(38400), BAUD(57600),
137 BAUD(115200), BAUD(128000), BAUD(256000),
139 BAUD(50), BAUD(75), BAUD(110), BAUD(134), BAUD(150), BAUD(200),
140 BAUD(300), BAUD(600), BAUD(1200), BAUD(1800), BAUD(2400), BAUD(4800),
141 BAUD(9600), BAUD(19200), BAUD(38400), BAUD(57600), BAUD(115200),
143 #if !defined(__APPLE__) && !defined(__OpenBSD__)
149 void (*sp_debug_handler)(const char *format, ...) = sp_default_debug_handler;
151 #define ARRAY_SIZE(x) (sizeof(x) / sizeof(x[0]))
152 #define NUM_STD_BAUDRATES ARRAY_SIZE(std_baudrates)
154 /* Debug output macros. */
155 #define DEBUG(fmt, ...) do { if (sp_debug_handler) sp_debug_handler(fmt ".\n", ##__VA_ARGS__); } while (0)
156 #define DEBUG_ERROR(err, msg) DEBUG("%s returning " #err ": " msg, __func__)
157 #define DEBUG_FAIL(msg) do { \
158 char *errmsg = sp_last_error_message(); \
159 DEBUG("%s returning SP_ERR_FAIL: " msg ": %s", __func__, errmsg); \
160 sp_free_error_message(errmsg); \
162 #define RETURN() do { DEBUG("%s returning", __func__); return; } while(0)
163 #define RETURN_CODE(x) do { DEBUG("%s returning " #x, __func__); return x; } while (0)
164 #define RETURN_CODEVAL(x) do { \
166 case SP_OK: RETURN_CODE(SP_OK); \
167 case SP_ERR_ARG: RETURN_CODE(SP_ERR_ARG); \
168 case SP_ERR_FAIL: RETURN_CODE(SP_ERR_FAIL); \
169 case SP_ERR_MEM: RETURN_CODE(SP_ERR_MEM); \
170 case SP_ERR_SUPP: RETURN_CODE(SP_ERR_SUPP); \
173 #define RETURN_OK() RETURN_CODE(SP_OK);
174 #define RETURN_ERROR(err, msg) do { DEBUG_ERROR(err, msg); return err; } while (0)
175 #define RETURN_FAIL(msg) do { DEBUG_FAIL(msg); return SP_ERR_FAIL; } while (0)
176 #define RETURN_VALUE(fmt, x) do { \
178 DEBUG("%s returning " fmt, __func__, _x); \
181 #define SET_ERROR(val, err, msg) do { DEBUG_ERROR(err, msg); val = err; } while (0)
182 #define SET_FAIL(val, msg) do { DEBUG_FAIL(msg); val = SP_ERR_FAIL; } while (0)
183 #define TRACE(fmt, ...) DEBUG("%s(" fmt ") called", __func__, ##__VA_ARGS__)
185 #define TRY(x) do { int ret = x; if (ret != SP_OK) RETURN_CODEVAL(ret); } while (0)
187 /* Helper functions. */
188 static struct sp_port **list_append(struct sp_port **list, const char *portname);
189 static enum sp_return get_config(struct sp_port *port, struct port_data *data,
190 struct sp_port_config *config);
191 static enum sp_return set_config(struct sp_port *port, struct port_data *data,
192 const struct sp_port_config *config);
194 enum sp_return sp_get_port_by_name(const char *portname, struct sp_port **port_ptr)
196 struct sp_port *port;
199 TRACE("%s, %p", portname, port_ptr);
202 RETURN_ERROR(SP_ERR_ARG, "Null result pointer");
207 RETURN_ERROR(SP_ERR_ARG, "Null port name");
209 DEBUG("Building structure for port %s", portname);
211 if (!(port = malloc(sizeof(struct sp_port))))
212 RETURN_ERROR(SP_ERR_MEM, "Port structure malloc failed");
214 len = strlen(portname) + 1;
216 if (!(port->name = malloc(len))) {
218 RETURN_ERROR(SP_ERR_MEM, "Port name malloc failed");
221 memcpy(port->name, portname, len);
224 port->hdl = INVALID_HANDLE_VALUE;
234 char *sp_get_port_name(const struct sp_port *port)
241 RETURN_VALUE("%s", port->name);
244 enum sp_return sp_get_port_handle(const struct sp_port *port, void *result_ptr)
246 TRACE("%p, %p", port, result_ptr);
249 RETURN_ERROR(SP_ERR_ARG, "Null port");
252 HANDLE *handle_ptr = result_ptr;
253 *handle_ptr = port->hdl;
255 int *fd_ptr = result_ptr;
262 enum sp_return sp_copy_port(const struct sp_port *port, struct sp_port **copy_ptr)
264 TRACE("%p, %p", port, copy_ptr);
267 RETURN_ERROR(SP_ERR_ARG, "Null result pointer");
272 RETURN_ERROR(SP_ERR_ARG, "Null port");
275 RETURN_ERROR(SP_ERR_ARG, "Null port name");
277 DEBUG("Copying port structure");
279 RETURN_VALUE("%p", sp_get_port_by_name(port->name, copy_ptr));
282 void sp_free_port(struct sp_port *port)
291 DEBUG("Freeing port structure");
301 static struct sp_port **list_append(struct sp_port **list, const char *portname)
306 for (count = 0; list[count]; count++);
307 if (!(tmp = realloc(list, sizeof(struct sp_port *) * (count + 2))))
310 if (sp_get_port_by_name(portname, &list[count]) != SP_OK)
312 list[count + 1] = NULL;
316 sp_free_port_list(list);
320 enum sp_return sp_list_ports(struct sp_port ***list_ptr)
322 struct sp_port **list;
323 int ret = SP_ERR_SUPP;
325 TRACE("%p", list_ptr);
328 RETURN_ERROR(SP_ERR_ARG, "Null result pointer");
330 DEBUG("Enumerating ports");
332 if (!(list = malloc(sizeof(struct sp_port **))))
333 RETURN_ERROR(SP_ERR_MEM, "Port list malloc failed");
340 DWORD max_value_len, max_data_size, max_data_len;
341 DWORD value_len, data_size, data_len;
342 DWORD type, index = 0;
348 DEBUG("Opening registry key");
349 if (RegOpenKeyEx(HKEY_LOCAL_MACHINE, _T("HARDWARE\\DEVICEMAP\\SERIALCOMM"),
350 0, KEY_QUERY_VALUE, &key) != ERROR_SUCCESS) {
351 SET_FAIL(ret, "RegOpenKeyEx() failed");
354 DEBUG("Querying registry key value and data sizes");
355 if (RegQueryInfoKey(key, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
356 &max_value_len, &max_data_size, NULL, NULL) != ERROR_SUCCESS) {
357 SET_FAIL(ret, "RegQueryInfoKey() failed");
360 max_data_len = max_data_size / sizeof(TCHAR);
361 if (!(value = malloc((max_value_len + 1) * sizeof(TCHAR)))) {
362 SET_ERROR(ret, SP_ERR_MEM, "registry value malloc failed");
365 if (!(data = malloc((max_data_len + 1) * sizeof(TCHAR)))) {
366 SET_ERROR(ret, SP_ERR_MEM, "registry data malloc failed");
369 DEBUG("Iterating over values");
371 value_len = max_value_len + 1,
372 data_size = max_data_size,
373 RegEnumValue(key, index, value, &value_len,
374 NULL, &type, (LPBYTE)data, &data_size) == ERROR_SUCCESS)
376 data_len = data_size / sizeof(TCHAR);
377 data[data_len] = '\0';
379 name_len = WideCharToMultiByte(CP_ACP, 0, data, -1, NULL, 0, NULL, NULL)
381 name_len = data_len + 1;
383 if (!(name = malloc(name_len))) {
384 SET_ERROR(ret, SP_ERR_MEM, "registry port name malloc failed");
388 WideCharToMultiByte(CP_ACP, 0, data, -1, name, name_len, NULL, NULL);
392 if (type == REG_SZ) {
393 DEBUG("Found port %s", name);
394 if (!(list = list_append(list, name))) {
395 SET_ERROR(ret, SP_ERR_MEM, "list append failed");
411 CFMutableDictionaryRef classes;
420 DEBUG("Getting IOKit master port");
421 if (IOMasterPort(MACH_PORT_NULL, &master) != KERN_SUCCESS) {
422 SET_FAIL(ret, "IOMasterPort() failed");
426 DEBUG("Creating matching dictionary");
427 if (!(classes = IOServiceMatching(kIOSerialBSDServiceValue))) {
428 SET_FAIL(ret, "IOServiceMatching() failed");
432 CFDictionarySetValue(classes,
433 CFSTR(kIOSerialBSDTypeKey), CFSTR(kIOSerialBSDAllTypes));
435 DEBUG("Getting matching services");
436 if (IOServiceGetMatchingServices(master, classes, &iter) != KERN_SUCCESS) {
437 SET_FAIL(ret, "IOServiceGetMatchingServices() failed");
441 if (!(path = malloc(PATH_MAX))) {
442 SET_ERROR(ret, SP_ERR_MEM, "device path malloc failed");
446 DEBUG("Iterating over results");
447 while ((port = IOIteratorNext(iter))) {
448 cf_path = IORegistryEntryCreateCFProperty(port,
449 CFSTR(kIOCalloutDeviceKey), kCFAllocatorDefault, 0);
451 result = CFStringGetCString(cf_path,
452 path, PATH_MAX, kCFStringEncodingASCII);
455 DEBUG("Found port %s", path);
456 if (!(list = list_append(list, path))) {
457 SET_ERROR(ret, SP_ERR_MEM, "list append failed");
458 IOObjectRelease(port);
463 IOObjectRelease(port);
468 IOObjectRelease(iter);
471 #if defined(__linux__) && defined(HAVE_LIBUDEV)
473 struct udev_enumerate *ud_enumerate;
474 struct udev_list_entry *ud_list;
475 struct udev_list_entry *ud_entry;
477 struct udev_device *ud_dev, *ud_parent;
480 int fd, ioctl_result;
481 struct serial_struct serial_info;
485 DEBUG("Enumerating tty devices");
487 ud_enumerate = udev_enumerate_new(ud);
488 udev_enumerate_add_match_subsystem(ud_enumerate, "tty");
489 udev_enumerate_scan_devices(ud_enumerate);
490 ud_list = udev_enumerate_get_list_entry(ud_enumerate);
491 DEBUG("Iterating over results");
492 udev_list_entry_foreach(ud_entry, ud_list) {
493 path = udev_list_entry_get_name(ud_entry);
494 DEBUG("Found device %s", path);
495 ud_dev = udev_device_new_from_syspath(ud, path);
496 /* If there is no parent device, this is a virtual tty. */
497 ud_parent = udev_device_get_parent(ud_dev);
498 if (ud_parent == NULL) {
499 DEBUG("No parent device, assuming virtual tty");
500 udev_device_unref(ud_dev);
503 name = udev_device_get_devnode(ud_dev);
504 /* The serial8250 driver has a hardcoded number of ports.
505 * The only way to tell which actually exist on a given system
506 * is to try to open them and make an ioctl call. */
507 driver = udev_device_get_driver(ud_parent);
508 if (driver && !strcmp(driver, "serial8250")) {
509 DEBUG("serial8250 device, attempting to open");
510 if ((fd = open(name, O_RDWR | O_NONBLOCK | O_NOCTTY)) < 0) {
511 DEBUG("open failed, skipping");
514 ioctl_result = ioctl(fd, TIOCGSERIAL, &serial_info);
516 if (ioctl_result != 0) {
517 DEBUG("ioctl failed, skipping");
520 if (serial_info.type == PORT_UNKNOWN) {
521 DEBUG("port type is unknown, skipping");
525 DEBUG("Found port %s", name);
526 list = list_append(list, name);
528 udev_device_unref(ud_dev);
530 SET_ERROR(ret, SP_ERR_MEM, "list append failed");
535 udev_enumerate_unref(ud_enumerate);
544 DEBUG_ERROR(SP_ERR_SUPP, "Enumeration not supported on this platform");
547 sp_free_port_list(list);
553 void sp_free_port_list(struct sp_port **list)
564 DEBUG("Freeing port list");
566 for (i = 0; list[i]; i++)
567 sp_free_port(list[i]);
573 #define CHECK_PORT() do { \
575 RETURN_ERROR(SP_ERR_ARG, "Null port"); \
576 if (port->name == NULL) \
577 RETURN_ERROR(SP_ERR_ARG, "Null port name"); \
580 #define CHECK_PORT_HANDLE() do { \
581 if (port->hdl == INVALID_HANDLE_VALUE) \
582 RETURN_ERROR(SP_ERR_ARG, "Invalid port handle"); \
585 #define CHECK_PORT_HANDLE() do { \
587 RETURN_ERROR(SP_ERR_ARG, "Invalid port fd"); \
590 #define CHECK_OPEN_PORT() do { \
592 CHECK_PORT_HANDLE(); \
595 enum sp_return sp_open(struct sp_port *port, enum sp_mode flags)
597 struct port_data data;
598 struct sp_port_config config;
601 TRACE("%p, 0x%x", port, flags);
605 if (flags > (SP_MODE_READ | SP_MODE_WRITE))
606 RETURN_ERROR(SP_ERR_ARG, "Invalid flags");
608 DEBUG("Opening port %s", port->name);
611 DWORD desired_access = 0, flags_and_attributes = 0, errors;
612 char *escaped_port_name;
615 /* Prefix port name with '\\.\' to work with ports above COM9. */
616 if (!(escaped_port_name = malloc(strlen(port->name + 5))))
617 RETURN_ERROR(SP_ERR_MEM, "Escaped port name malloc failed");
618 sprintf(escaped_port_name, "\\\\.\\%s", port->name);
620 /* Map 'flags' to the OS-specific settings. */
621 flags_and_attributes = FILE_ATTRIBUTE_NORMAL | FILE_FLAG_OVERLAPPED;
622 if (flags & SP_MODE_READ)
623 desired_access |= GENERIC_READ;
624 if (flags & SP_MODE_WRITE)
625 desired_access |= GENERIC_WRITE;
627 port->hdl = CreateFile(escaped_port_name, desired_access, 0, 0,
628 OPEN_EXISTING, flags_and_attributes, 0);
630 free(escaped_port_name);
632 if (port->hdl == INVALID_HANDLE_VALUE)
633 RETURN_FAIL("port CreateFile() failed");
635 /* All timeouts initially disabled. */
636 port->timeouts.ReadIntervalTimeout = 0;
637 port->timeouts.ReadTotalTimeoutMultiplier = 0;
638 port->timeouts.ReadTotalTimeoutConstant = 0;
639 port->timeouts.WriteTotalTimeoutMultiplier = 0;
640 port->timeouts.WriteTotalTimeoutConstant = 0;
642 if (SetCommTimeouts(port->hdl, &port->timeouts) == 0) {
644 RETURN_FAIL("SetCommTimeouts() failed");
647 /* Prepare OVERLAPPED structures. */
648 memset(&port->read_ovl, 0, sizeof(port->read_ovl));
649 memset(&port->write_ovl, 0, sizeof(port->write_ovl));
650 port->read_ovl.hEvent = INVALID_HANDLE_VALUE;
651 port->write_ovl.hEvent = INVALID_HANDLE_VALUE;
652 if ((port->read_ovl.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL)) == INVALID_HANDLE_VALUE) {
654 RETURN_FAIL("read event CreateEvent() failed");
656 if ((port->write_ovl.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL)) == INVALID_HANDLE_VALUE) {
658 RETURN_FAIL("write event CreateEvent() failed");
661 port->writing = FALSE;
664 int flags_local = O_NONBLOCK | O_NOCTTY;
666 /* Map 'flags' to the OS-specific settings. */
667 if (flags & (SP_MODE_READ | SP_MODE_WRITE))
668 flags_local |= O_RDWR;
669 else if (flags & SP_MODE_READ)
670 flags_local |= O_RDONLY;
671 else if (flags & SP_MODE_WRITE)
672 flags_local |= O_WRONLY;
674 if ((port->fd = open(port->name, flags_local)) < 0)
675 RETURN_FAIL("open() failed");
678 ret = get_config(port, &data, &config);
685 /* Set sane port settings. */
687 data.dcb.fBinary = TRUE;
688 data.dcb.fDsrSensitivity = FALSE;
689 data.dcb.fErrorChar = FALSE;
690 data.dcb.fNull = FALSE;
691 data.dcb.fAbortOnError = TRUE;
693 /* Turn off all fancy termios tricks, give us a raw channel. */
694 data.term.c_iflag &= ~(IGNBRK | BRKINT | PARMRK | ISTRIP | INLCR | IGNCR | ICRNL | IMAXBEL);
696 data.term.c_iflag &= ~IUCLC;
698 data.term.c_oflag &= ~(OPOST | ONLCR | OCRNL | ONOCR | ONLRET);
700 data.term.c_oflag &= ~OLCUC;
703 data.term.c_oflag &= ~NLDLY;
706 data.term.c_oflag &= ~CRDLY;
709 data.term.c_oflag &= ~TABDLY;
712 data.term.c_oflag &= ~BSDLY;
715 data.term.c_oflag &= ~VTDLY;
718 data.term.c_oflag &= ~FFDLY;
721 data.term.c_oflag &= ~OFILL;
723 data.term.c_lflag &= ~(ISIG | ICANON | ECHO | IEXTEN);
724 data.term.c_cc[VMIN] = 0;
725 data.term.c_cc[VTIME] = 0;
727 /* Ignore modem status lines; enable receiver; leave control lines alone on close. */
728 data.term.c_cflag |= (CLOCAL | CREAD | HUPCL);
732 ClearCommError(port->hdl, &errors, &status);
735 ret = set_config(port, &data, &config);
745 enum sp_return sp_close(struct sp_port *port)
751 DEBUG("Closing port %s", port->name);
754 /* Returns non-zero upon success, 0 upon failure. */
755 if (CloseHandle(port->hdl) == 0)
756 RETURN_FAIL("port CloseHandle() failed");
757 port->hdl = INVALID_HANDLE_VALUE;
758 /* Close event handle created for overlapped reads. */
759 if (port->read_ovl.hEvent != INVALID_HANDLE_VALUE && CloseHandle(port->read_ovl.hEvent) == 0)
760 RETURN_FAIL("read event CloseHandle() failed");
761 /* Close event handle created for overlapped writes. */
762 if (port->write_ovl.hEvent != INVALID_HANDLE_VALUE && CloseHandle(port->write_ovl.hEvent) == 0)
763 RETURN_FAIL("write event CloseHandle() failed");
765 /* Returns 0 upon success, -1 upon failure. */
766 if (close(port->fd) == -1)
767 RETURN_FAIL("close() failed");
774 enum sp_return sp_flush(struct sp_port *port, enum sp_buffer buffers)
776 TRACE("%p, 0x%x", port, buffers);
780 if (buffers > SP_BUF_BOTH)
781 RETURN_ERROR(SP_ERR_ARG, "Invalid buffer selection");
783 const char *buffer_names[] = {"no", "input", "output", "both"};
785 DEBUG("Flushing %s buffers on port %s", buffer_names[buffers], port->name);
789 if (buffers & SP_BUF_INPUT)
790 flags |= PURGE_RXCLEAR;
791 if (buffers & SP_BUF_OUTPUT)
792 flags |= PURGE_TXCLEAR;
794 /* Returns non-zero upon success, 0 upon failure. */
795 if (PurgeComm(port->hdl, flags) == 0)
796 RETURN_FAIL("PurgeComm() failed");
799 if (buffers & SP_BUF_BOTH)
801 else if (buffers & SP_BUF_INPUT)
803 else if (buffers & SP_BUF_OUTPUT)
806 /* Returns 0 upon success, -1 upon failure. */
807 if (tcflush(port->fd, flags) < 0)
808 RETURN_FAIL("tcflush() failed");
813 enum sp_return sp_drain(struct sp_port *port)
819 DEBUG("Draining port %s", port->name);
822 /* Returns non-zero upon success, 0 upon failure. */
823 if (FlushFileBuffers(port->hdl) == 0)
824 RETURN_FAIL("FlushFileBuffers() failed");
831 result = ioctl(port->fd, TCSBRK, &arg);
833 result = tcdrain(port->fd);
836 if (errno == EINTR) {
837 DEBUG("tcdrain() was interrupted");
840 RETURN_FAIL("tcdrain() failed");
849 enum sp_return sp_blocking_write(struct sp_port *port, const void *buf, size_t count, unsigned int timeout)
851 TRACE("%p, %p, %d, %d", port, buf, count, timeout);
856 RETURN_ERROR(SP_ERR_ARG, "Null buffer");
859 DEBUG("Writing %d bytes to port %s, timeout %d ms", count, port->name, timeout);
861 DEBUG("Writing %d bytes to port %s, no timeout", count, port->name);
864 RETURN_VALUE("0", 0);
867 DWORD bytes_written = 0;
870 /* Wait for previous non-blocking write to complete, if any. */
872 DEBUG("Waiting for previous write to complete");
873 result = GetOverlappedResult(port->hdl, &port->write_ovl, &bytes_written, TRUE);
876 RETURN_FAIL("Previous write failed to complete");
877 DEBUG("Previous write completed");
881 port->timeouts.WriteTotalTimeoutConstant = timeout;
882 if (SetCommTimeouts(port->hdl, &port->timeouts) == 0)
883 RETURN_FAIL("SetCommTimeouts() failed");
886 if (WriteFile(port->hdl, buf, count, NULL, &port->write_ovl) == 0) {
887 if (GetLastError() == ERROR_IO_PENDING) {
888 DEBUG("Waiting for write to complete");
889 GetOverlappedResult(port->hdl, &port->write_ovl, &bytes_written, TRUE);
890 DEBUG("Write completed, %d/%d bytes written", bytes_written, count);
891 RETURN_VALUE("%d", bytes_written);
893 RETURN_FAIL("WriteFile() failed");
896 DEBUG("Write completed immediately");
897 RETURN_VALUE("%d", count);
900 size_t bytes_written = 0;
901 unsigned char *ptr = (unsigned char *) buf;
902 struct timeval start, delta, now, end = {0, 0};
907 /* Get time at start of operation. */
908 gettimeofday(&start, NULL);
909 /* Define duration of timeout. */
910 delta.tv_sec = timeout / 1000;
911 delta.tv_usec = (timeout % 1000) * 1000;
912 /* Calculate time at which we should give up. */
913 timeradd(&start, &delta, &end);
916 /* Loop until we have written the requested number of bytes. */
917 while (bytes_written < count)
919 /* Wait until space is available. */
921 FD_SET(port->fd, &fds);
923 gettimeofday(&now, NULL);
924 if (timercmp(&now, &end, >)) {
925 DEBUG("write timed out");
926 RETURN_VALUE("%d", bytes_written);
928 timersub(&end, &now, &delta);
930 result = select(port->fd + 1, NULL, &fds, NULL, timeout ? &delta : NULL);
932 if (errno == EINTR) {
933 DEBUG("select() call was interrupted, repeating");
936 RETURN_FAIL("select() failed");
938 } else if (result == 0) {
939 DEBUG("write timed out");
940 RETURN_VALUE("%d", bytes_written);
944 result = write(port->fd, ptr, count - bytes_written);
948 /* This shouldn't happen because we did a select() first, but handle anyway. */
951 /* This is an actual failure. */
952 RETURN_FAIL("write() failed");
955 bytes_written += result;
959 RETURN_VALUE("%d", bytes_written);
963 enum sp_return sp_nonblocking_write(struct sp_port *port, const void *buf, size_t count)
965 TRACE("%p, %p, %d", port, buf, count);
970 RETURN_ERROR(SP_ERR_ARG, "Null buffer");
972 DEBUG("Writing up to %d bytes to port %s", count, port->name);
975 RETURN_VALUE("0", 0);
979 BYTE *ptr = (BYTE *) buf;
981 /* Check whether previous write is complete. */
983 if (HasOverlappedIoCompleted(&port->write_ovl)) {
984 DEBUG("Previous write completed");
987 DEBUG("Previous write not complete");
988 /* Can't take a new write until the previous one finishes. */
989 RETURN_VALUE("0", 0);
994 port->timeouts.WriteTotalTimeoutConstant = 0;
995 if (SetCommTimeouts(port->hdl, &port->timeouts) == 0)
996 RETURN_FAIL("SetCommTimeouts() failed");
998 /* Keep writing data until the OS has to actually start an async IO for it.
999 * At that point we know the buffer is full. */
1000 while (written < count)
1002 /* Copy first byte of user buffer. */
1003 port->pending_byte = *ptr++;
1005 /* Start asynchronous write. */
1006 if (WriteFile(port->hdl, &port->pending_byte, 1, NULL, &port->write_ovl) == 0) {
1007 if (GetLastError() == ERROR_IO_PENDING) {
1008 if (HasOverlappedIoCompleted(&port->write_ovl)) {
1009 DEBUG("Asynchronous write completed immediately");
1014 DEBUG("Asynchronous write running");
1016 RETURN_VALUE("%d", ++written);
1019 /* Actual failure of some kind. */
1020 RETURN_FAIL("WriteFile() failed");
1023 DEBUG("Single byte written immediately");
1028 DEBUG("All bytes written immediately");
1030 RETURN_VALUE("%d", written);
1032 /* Returns the number of bytes written, or -1 upon failure. */
1033 ssize_t written = write(port->fd, buf, count);
1036 RETURN_FAIL("write() failed");
1038 RETURN_VALUE("%d", written);
1042 enum sp_return sp_blocking_read(struct sp_port *port, void *buf, size_t count, unsigned int timeout)
1044 TRACE("%p, %p, %d, %d", port, buf, count, timeout);
1049 RETURN_ERROR(SP_ERR_ARG, "Null buffer");
1052 DEBUG("Reading %d bytes from port %s, timeout %d ms", count, port->name, timeout);
1054 DEBUG("Reading %d bytes from port %s, no timeout", count, port->name);
1057 RETURN_VALUE("0", 0);
1060 DWORD bytes_read = 0;
1063 port->timeouts.ReadIntervalTimeout = 0;
1064 port->timeouts.ReadTotalTimeoutConstant = timeout;
1065 if (SetCommTimeouts(port->hdl, &port->timeouts) == 0)
1066 RETURN_FAIL("SetCommTimeouts() failed");
1069 if (ReadFile(port->hdl, buf, count, NULL, &port->read_ovl) == 0) {
1070 if (GetLastError() == ERROR_IO_PENDING) {
1071 DEBUG("Waiting for read to complete");
1072 GetOverlappedResult(port->hdl, &port->read_ovl, &bytes_read, TRUE);
1073 DEBUG("Read completed, %d/%d bytes read", bytes_read, count);
1074 RETURN_VALUE("%d", bytes_read);
1076 RETURN_FAIL("ReadFile() failed");
1079 DEBUG("Read completed immediately");
1080 RETURN_VALUE("%d", count);
1083 size_t bytes_read = 0;
1084 unsigned char *ptr = (unsigned char *) buf;
1085 struct timeval start, delta, now, end = {0, 0};
1090 /* Get time at start of operation. */
1091 gettimeofday(&start, NULL);
1092 /* Define duration of timeout. */
1093 delta.tv_sec = timeout / 1000;
1094 delta.tv_usec = (timeout % 1000) * 1000;
1095 /* Calculate time at which we should give up. */
1096 timeradd(&start, &delta, &end);
1099 /* Loop until we have the requested number of bytes. */
1100 while (bytes_read < count)
1102 /* Wait until data is available. */
1104 FD_SET(port->fd, &fds);
1106 gettimeofday(&now, NULL);
1107 if (timercmp(&now, &end, >))
1108 /* Timeout has expired. */
1109 RETURN_VALUE("%d", bytes_read);
1110 timersub(&end, &now, &delta);
1112 result = select(port->fd + 1, &fds, NULL, NULL, timeout ? &delta : NULL);
1114 if (errno == EINTR) {
1115 DEBUG("select() call was interrupted, repeating");
1118 RETURN_FAIL("select() failed");
1120 } else if (result == 0) {
1121 DEBUG("read timed out");
1122 RETURN_VALUE("%d", bytes_read);
1126 result = read(port->fd, ptr, count - bytes_read);
1129 if (errno == EAGAIN)
1130 /* This shouldn't happen because we did a select() first, but handle anyway. */
1133 /* This is an actual failure. */
1134 RETURN_FAIL("read() failed");
1137 bytes_read += result;
1141 RETURN_VALUE("%d", bytes_read);
1145 enum sp_return sp_nonblocking_read(struct sp_port *port, void *buf, size_t count)
1147 TRACE("%p, %p, %d", port, buf, count);
1152 RETURN_ERROR(SP_ERR_ARG, "Null buffer");
1154 DEBUG("Reading up to %d bytes from port %s", count, port->name);
1160 port->timeouts.ReadIntervalTimeout = MAXDWORD;
1161 port->timeouts.ReadTotalTimeoutConstant = 0;
1162 if (SetCommTimeouts(port->hdl, &port->timeouts) == 0)
1163 RETURN_FAIL("SetCommTimeouts() failed");
1166 if (ReadFile(port->hdl, buf, count, NULL, &port->read_ovl) == 0)
1167 RETURN_FAIL("ReadFile() failed");
1169 /* Get number of bytes read. */
1170 if (GetOverlappedResult(port->hdl, &port->read_ovl, &bytes_read, TRUE) == 0)
1171 RETURN_FAIL("GetOverlappedResult() failed");
1173 RETURN_VALUE("%d", bytes_read);
1177 /* Returns the number of bytes read, or -1 upon failure. */
1178 if ((bytes_read = read(port->fd, buf, count)) < 0) {
1179 if (errno == EAGAIN)
1180 /* No bytes available. */
1183 /* This is an actual failure. */
1184 RETURN_FAIL("read() failed");
1186 RETURN_VALUE("%d", bytes_read);
1190 enum sp_return sp_input_waiting(struct sp_port *port)
1196 DEBUG("Checking input bytes waiting on port %s", port->name);
1202 if (ClearCommError(port->hdl, &errors, &comstat) == 0)
1203 RETURN_FAIL("ClearComError() failed");
1204 RETURN_VALUE("%d", comstat.cbInQue);
1207 if (ioctl(port->fd, TIOCINQ, &bytes_waiting) < 0)
1208 RETURN_FAIL("TIOCINQ ioctl failed");
1209 RETURN_VALUE("%d", bytes_waiting);
1213 enum sp_return sp_output_waiting(struct sp_port *port)
1219 DEBUG("Checking output bytes waiting on port %s", port->name);
1225 if (ClearCommError(port->hdl, &errors, &comstat) == 0)
1226 RETURN_FAIL("ClearComError() failed");
1227 RETURN_VALUE("%d", comstat.cbOutQue);
1230 if (ioctl(port->fd, TIOCOUTQ, &bytes_waiting) < 0)
1231 RETURN_FAIL("TIOCOUTQ ioctl failed");
1232 RETURN_VALUE("%d", bytes_waiting);
1237 static enum sp_return get_baudrate(int fd, int *baudrate)
1241 TRACE("%d, %p", fd, baudrate);
1243 DEBUG("Getting baud rate");
1245 if (!(data = malloc(get_termios_size())))
1246 RETURN_ERROR(SP_ERR_MEM, "termios malloc failed");
1248 if (ioctl(fd, get_termios_get_ioctl(), data) < 0) {
1250 RETURN_FAIL("getting termios failed");
1253 *baudrate = get_termios_speed(data);
1260 static enum sp_return set_baudrate(int fd, int baudrate)
1264 TRACE("%d, %d", fd, baudrate);
1266 DEBUG("Getting baud rate");
1268 if (!(data = malloc(get_termios_size())))
1269 RETURN_ERROR(SP_ERR_MEM, "termios malloc failed");
1271 if (ioctl(fd, get_termios_get_ioctl(), data) < 0) {
1273 RETURN_FAIL("getting termios failed");
1276 DEBUG("Setting baud rate");
1278 set_termios_speed(data, baudrate);
1280 if (ioctl(fd, get_termios_set_ioctl(), data) < 0) {
1282 RETURN_FAIL("setting termios failed");
1291 static enum sp_return get_flow(int fd, int *flow)
1295 TRACE("%d, %p", fd, flow);
1297 DEBUG("Getting advanced flow control");
1299 if (!(data = malloc(get_termiox_size())))
1300 RETURN_ERROR(SP_ERR_MEM, "termiox malloc failed");
1302 if (ioctl(fd, TCGETX, data) < 0) {
1304 RETURN_FAIL("getting termiox failed");
1307 *flow = get_termiox_flow(data);
1314 static enum sp_return set_flow(int fd, int flow)
1318 TRACE("%d, %d", fd, flow);
1320 DEBUG("Getting advanced flow control");
1322 if (!(data = malloc(get_termiox_size())))
1323 RETURN_ERROR(SP_ERR_MEM, "termiox malloc failed");
1325 if (ioctl(fd, TCGETX, data) < 0) {
1327 RETURN_FAIL("getting termiox failed");
1330 DEBUG("Setting advanced flow control");
1332 set_termiox_flow(data, flow);
1334 if (ioctl(fd, TCSETX, data) < 0) {
1336 RETURN_FAIL("setting termiox failed");
1343 #endif /* USE_TERMIOX */
1344 #endif /* __linux__ */
1346 static enum sp_return get_config(struct sp_port *port, struct port_data *data,
1347 struct sp_port_config *config)
1351 TRACE("%p, %p, %p", port, data, config);
1353 DEBUG("Getting configuration for port %s", port->name);
1356 if (!GetCommState(port->hdl, &data->dcb))
1357 RETURN_FAIL("GetCommState() failed");
1359 for (i = 0; i < NUM_STD_BAUDRATES; i++) {
1360 if (data->dcb.BaudRate == std_baudrates[i].index) {
1361 config->baudrate = std_baudrates[i].value;
1366 if (i == NUM_STD_BAUDRATES)
1367 /* BaudRate field can be either an index or a custom baud rate. */
1368 config->baudrate = data->dcb.BaudRate;
1370 config->bits = data->dcb.ByteSize;
1372 if (data->dcb.fParity)
1373 switch (data->dcb.Parity) {
1375 config->parity = SP_PARITY_NONE;
1378 config->parity = SP_PARITY_ODD;
1381 config->parity = SP_PARITY_EVEN;
1384 config->parity = SP_PARITY_MARK;
1387 config->parity = SP_PARITY_SPACE;
1390 config->parity = -1;
1393 config->parity = SP_PARITY_NONE;
1395 switch (data->dcb.StopBits) {
1397 config->stopbits = 1;
1400 config->stopbits = 2;
1403 config->stopbits = -1;
1406 switch (data->dcb.fRtsControl) {
1407 case RTS_CONTROL_DISABLE:
1408 config->rts = SP_RTS_OFF;
1410 case RTS_CONTROL_ENABLE:
1411 config->rts = SP_RTS_ON;
1413 case RTS_CONTROL_HANDSHAKE:
1414 config->rts = SP_RTS_FLOW_CONTROL;
1420 config->cts = data->dcb.fOutxCtsFlow ? SP_CTS_FLOW_CONTROL : SP_CTS_IGNORE;
1422 switch (data->dcb.fDtrControl) {
1423 case DTR_CONTROL_DISABLE:
1424 config->dtr = SP_DTR_OFF;
1426 case DTR_CONTROL_ENABLE:
1427 config->dtr = SP_DTR_ON;
1429 case DTR_CONTROL_HANDSHAKE:
1430 config->dtr = SP_DTR_FLOW_CONTROL;
1436 config->dsr = data->dcb.fOutxDsrFlow ? SP_DSR_FLOW_CONTROL : SP_DSR_IGNORE;
1438 if (data->dcb.fInX) {
1439 if (data->dcb.fOutX)
1440 config->xon_xoff = SP_XONXOFF_INOUT;
1442 config->xon_xoff = SP_XONXOFF_IN;
1444 if (data->dcb.fOutX)
1445 config->xon_xoff = SP_XONXOFF_OUT;
1447 config->xon_xoff = SP_XONXOFF_DISABLED;
1452 if (tcgetattr(port->fd, &data->term) < 0)
1453 RETURN_FAIL("tcgetattr() failed");
1455 if (ioctl(port->fd, TIOCMGET, &data->controlbits) < 0)
1456 RETURN_FAIL("TIOCMGET ioctl failed");
1459 int ret = get_flow(port->fd, &data->flow);
1461 if (ret == SP_ERR_FAIL && errno == EINVAL)
1462 data->termiox_supported = 0;
1464 RETURN_CODEVAL(ret);
1466 data->termiox_supported = 1;
1468 data->termiox_supported = 0;
1471 for (i = 0; i < NUM_STD_BAUDRATES; i++) {
1472 if (cfgetispeed(&data->term) == std_baudrates[i].index) {
1473 config->baudrate = std_baudrates[i].value;
1478 if (i == NUM_STD_BAUDRATES) {
1480 config->baudrate = (int)data->term.c_ispeed;
1481 #elif defined(__linux__)
1482 TRY(get_baudrate(port->fd, &config->baudrate));
1484 config->baudrate = -1;
1488 switch (data->term.c_cflag & CSIZE) {
1505 if (!(data->term.c_cflag & PARENB) && (data->term.c_iflag & IGNPAR))
1506 config->parity = SP_PARITY_NONE;
1507 else if (!(data->term.c_cflag & PARENB) || (data->term.c_iflag & IGNPAR))
1508 config->parity = -1;
1510 else if (data->term.c_cflag & CMSPAR)
1511 config->parity = (data->term.c_cflag & PARODD) ? SP_PARITY_MARK : SP_PARITY_SPACE;
1514 config->parity = (data->term.c_cflag & PARODD) ? SP_PARITY_ODD : SP_PARITY_EVEN;
1516 config->stopbits = (data->term.c_cflag & CSTOPB) ? 2 : 1;
1518 if (data->term.c_cflag & CRTSCTS) {
1519 config->rts = SP_RTS_FLOW_CONTROL;
1520 config->cts = SP_CTS_FLOW_CONTROL;
1522 if (data->termiox_supported && data->flow & RTS_FLOW)
1523 config->rts = SP_RTS_FLOW_CONTROL;
1525 config->rts = (data->controlbits & TIOCM_RTS) ? SP_RTS_ON : SP_RTS_OFF;
1527 config->cts = (data->termiox_supported && data->flow & CTS_FLOW) ?
1528 SP_CTS_FLOW_CONTROL : SP_CTS_IGNORE;
1531 if (data->termiox_supported && data->flow & DTR_FLOW)
1532 config->dtr = SP_DTR_FLOW_CONTROL;
1534 config->dtr = (data->controlbits & TIOCM_DTR) ? SP_DTR_ON : SP_DTR_OFF;
1536 config->dsr = (data->termiox_supported && data->flow & DSR_FLOW) ?
1537 SP_DSR_FLOW_CONTROL : SP_DSR_IGNORE;
1539 if (data->term.c_iflag & IXOFF) {
1540 if (data->term.c_iflag & IXON)
1541 config->xon_xoff = SP_XONXOFF_INOUT;
1543 config->xon_xoff = SP_XONXOFF_IN;
1545 if (data->term.c_iflag & IXON)
1546 config->xon_xoff = SP_XONXOFF_OUT;
1548 config->xon_xoff = SP_XONXOFF_DISABLED;
1555 static enum sp_return set_config(struct sp_port *port, struct port_data *data,
1556 const struct sp_port_config *config)
1560 BAUD_TYPE baud_nonstd;
1565 int baud_nonstd = 0;
1568 TRACE("%p, %p, %p", port, data, config);
1570 DEBUG("Setting configuration for port %s", port->name);
1573 if (config->baudrate >= 0) {
1574 for (i = 0; i < NUM_STD_BAUDRATES; i++) {
1575 if (config->baudrate == std_baudrates[i].value) {
1576 data->dcb.BaudRate = std_baudrates[i].index;
1581 if (i == NUM_STD_BAUDRATES)
1582 data->dcb.BaudRate = config->baudrate;
1585 if (config->bits >= 0)
1586 data->dcb.ByteSize = config->bits;
1588 if (config->parity >= 0) {
1589 switch (config->parity) {
1590 case SP_PARITY_NONE:
1591 data->dcb.Parity = NOPARITY;
1594 data->dcb.Parity = ODDPARITY;
1596 case SP_PARITY_EVEN:
1597 data->dcb.Parity = EVENPARITY;
1599 case SP_PARITY_MARK:
1600 data->dcb.Parity = MARKPARITY;
1602 case SP_PARITY_SPACE:
1603 data->dcb.Parity = SPACEPARITY;
1606 RETURN_ERROR(SP_ERR_ARG, "Invalid parity setting");
1610 if (config->stopbits >= 0) {
1611 switch (config->stopbits) {
1612 /* Note: There's also ONE5STOPBITS == 1.5 (unneeded so far). */
1614 data->dcb.StopBits = ONESTOPBIT;
1617 data->dcb.StopBits = TWOSTOPBITS;
1620 RETURN_ERROR(SP_ERR_ARG, "Invalid stop bit setting");
1624 if (config->rts >= 0) {
1625 switch (config->rts) {
1627 data->dcb.fRtsControl = RTS_CONTROL_DISABLE;
1630 data->dcb.fRtsControl = RTS_CONTROL_ENABLE;
1632 case SP_RTS_FLOW_CONTROL:
1633 data->dcb.fRtsControl = RTS_CONTROL_HANDSHAKE;
1636 RETURN_ERROR(SP_ERR_ARG, "Invalid RTS setting");
1640 if (config->cts >= 0) {
1641 switch (config->cts) {
1643 data->dcb.fOutxCtsFlow = FALSE;
1645 case SP_CTS_FLOW_CONTROL:
1646 data->dcb.fOutxCtsFlow = TRUE;
1649 RETURN_ERROR(SP_ERR_ARG, "Invalid CTS setting");
1653 if (config->dtr >= 0) {
1654 switch (config->dtr) {
1656 data->dcb.fDtrControl = DTR_CONTROL_DISABLE;
1659 data->dcb.fDtrControl = DTR_CONTROL_ENABLE;
1661 case SP_DTR_FLOW_CONTROL:
1662 data->dcb.fDtrControl = DTR_CONTROL_HANDSHAKE;
1665 RETURN_ERROR(SP_ERR_ARG, "Invalid DTR setting");
1669 if (config->dsr >= 0) {
1670 switch (config->dsr) {
1672 data->dcb.fOutxDsrFlow = FALSE;
1674 case SP_DSR_FLOW_CONTROL:
1675 data->dcb.fOutxDsrFlow = TRUE;
1678 RETURN_ERROR(SP_ERR_ARG, "Invalid DSR setting");
1682 if (config->xon_xoff >= 0) {
1683 switch (config->xon_xoff) {
1684 case SP_XONXOFF_DISABLED:
1685 data->dcb.fInX = FALSE;
1686 data->dcb.fOutX = FALSE;
1689 data->dcb.fInX = TRUE;
1690 data->dcb.fOutX = FALSE;
1692 case SP_XONXOFF_OUT:
1693 data->dcb.fInX = FALSE;
1694 data->dcb.fOutX = TRUE;
1696 case SP_XONXOFF_INOUT:
1697 data->dcb.fInX = TRUE;
1698 data->dcb.fOutX = TRUE;
1701 RETURN_ERROR(SP_ERR_ARG, "Invalid XON/XOFF setting");
1705 if (!SetCommState(port->hdl, &data->dcb))
1706 RETURN_FAIL("SetCommState() failed");
1712 if (config->baudrate >= 0) {
1713 for (i = 0; i < NUM_STD_BAUDRATES; i++) {
1714 if (config->baudrate == std_baudrates[i].value) {
1715 if (cfsetospeed(&data->term, std_baudrates[i].index) < 0)
1716 RETURN_FAIL("cfsetospeed() failed");
1718 if (cfsetispeed(&data->term, std_baudrates[i].index) < 0)
1719 RETURN_FAIL("cfsetispeed() failed");
1724 /* Non-standard baud rate */
1725 if (i == NUM_STD_BAUDRATES) {
1727 /* Set "dummy" baud rate. */
1728 if (cfsetspeed(&data->term, B9600) < 0)
1729 RETURN_FAIL("cfsetspeed() failed");
1730 baud_nonstd = config->baudrate;
1731 #elif defined(__linux__)
1734 RETURN_ERROR(SP_ERR_SUPP, "Non-standard baudrate not supported");
1739 if (config->bits >= 0) {
1740 data->term.c_cflag &= ~CSIZE;
1741 switch (config->bits) {
1743 data->term.c_cflag |= CS8;
1746 data->term.c_cflag |= CS7;
1749 data->term.c_cflag |= CS6;
1752 data->term.c_cflag |= CS5;
1755 RETURN_ERROR(SP_ERR_ARG, "Invalid data bits setting");
1759 if (config->parity >= 0) {
1760 data->term.c_iflag &= ~IGNPAR;
1761 data->term.c_cflag &= ~(PARENB | PARODD);
1763 data->term.c_cflag &= ~CMSPAR;
1765 switch (config->parity) {
1766 case SP_PARITY_NONE:
1767 data->term.c_iflag |= IGNPAR;
1769 case SP_PARITY_EVEN:
1770 data->term.c_cflag |= PARENB;
1773 data->term.c_cflag |= PARENB | PARODD;
1776 case SP_PARITY_MARK:
1777 data->term.c_cflag |= PARENB | PARODD;
1778 data->term.c_cflag |= CMSPAR;
1780 case SP_PARITY_SPACE:
1781 data->term.c_cflag |= PARENB;
1782 data->term.c_cflag |= CMSPAR;
1785 case SP_PARITY_MARK:
1786 case SP_PARITY_SPACE:
1787 RETURN_ERROR(SP_ERR_SUPP, "Mark/space parity not supported");
1790 RETURN_ERROR(SP_ERR_ARG, "Invalid parity setting");
1794 if (config->stopbits >= 0) {
1795 data->term.c_cflag &= ~CSTOPB;
1796 switch (config->stopbits) {
1798 data->term.c_cflag &= ~CSTOPB;
1801 data->term.c_cflag |= CSTOPB;
1804 RETURN_ERROR(SP_ERR_ARG, "Invalid stop bits setting");
1808 if (config->rts >= 0 || config->cts >= 0) {
1809 if (data->termiox_supported) {
1810 data->flow &= ~(RTS_FLOW | CTS_FLOW);
1811 switch (config->rts) {
1814 controlbits = TIOCM_RTS;
1815 if (ioctl(port->fd, config->rts == SP_RTS_ON ? TIOCMBIS : TIOCMBIC, &controlbits) < 0)
1816 RETURN_FAIL("Setting RTS signal level failed");
1818 case SP_RTS_FLOW_CONTROL:
1819 data->flow |= RTS_FLOW;
1824 if (config->cts == SP_CTS_FLOW_CONTROL)
1825 data->flow |= CTS_FLOW;
1827 if (data->flow & (RTS_FLOW | CTS_FLOW))
1828 data->term.c_iflag |= CRTSCTS;
1830 data->term.c_iflag &= ~CRTSCTS;
1832 /* Asymmetric use of RTS/CTS not supported. */
1833 if (data->term.c_iflag & CRTSCTS) {
1834 /* Flow control can only be disabled for both RTS & CTS together. */
1835 if (config->rts >= 0 && config->rts != SP_RTS_FLOW_CONTROL) {
1836 if (config->cts != SP_CTS_IGNORE)
1837 RETURN_ERROR(SP_ERR_SUPP, "RTS & CTS flow control must be disabled together");
1839 if (config->cts >= 0 && config->cts != SP_CTS_FLOW_CONTROL) {
1840 if (config->rts <= 0 || config->rts == SP_RTS_FLOW_CONTROL)
1841 RETURN_ERROR(SP_ERR_SUPP, "RTS & CTS flow control must be disabled together");
1844 /* Flow control can only be enabled for both RTS & CTS together. */
1845 if (((config->rts == SP_RTS_FLOW_CONTROL) && (config->cts != SP_CTS_FLOW_CONTROL)) ||
1846 ((config->cts == SP_CTS_FLOW_CONTROL) && (config->rts != SP_RTS_FLOW_CONTROL)))
1847 RETURN_ERROR(SP_ERR_SUPP, "RTS & CTS flow control must be enabled together");
1850 if (config->rts >= 0) {
1851 if (config->rts == SP_RTS_FLOW_CONTROL) {
1852 data->term.c_iflag |= CRTSCTS;
1854 controlbits = TIOCM_RTS;
1855 if (ioctl(port->fd, config->rts == SP_RTS_ON ? TIOCMBIS : TIOCMBIC,
1857 RETURN_FAIL("Setting RTS signal level failed");
1863 if (config->dtr >= 0 || config->dsr >= 0) {
1864 if (data->termiox_supported) {
1865 data->flow &= ~(DTR_FLOW | DSR_FLOW);
1866 switch (config->dtr) {
1869 controlbits = TIOCM_DTR;
1870 if (ioctl(port->fd, config->dtr == SP_DTR_ON ? TIOCMBIS : TIOCMBIC, &controlbits) < 0)
1871 RETURN_FAIL("Setting DTR signal level failed");
1873 case SP_DTR_FLOW_CONTROL:
1874 data->flow |= DTR_FLOW;
1879 if (config->dsr == SP_DSR_FLOW_CONTROL)
1880 data->flow |= DSR_FLOW;
1882 /* DTR/DSR flow control not supported. */
1883 if (config->dtr == SP_DTR_FLOW_CONTROL || config->dsr == SP_DSR_FLOW_CONTROL)
1884 RETURN_ERROR(SP_ERR_SUPP, "DTR/DSR flow control not supported");
1886 if (config->dtr >= 0) {
1887 controlbits = TIOCM_DTR;
1888 if (ioctl(port->fd, config->dtr == SP_DTR_ON ? TIOCMBIS : TIOCMBIC,
1890 RETURN_FAIL("Setting DTR signal level failed");
1895 if (config->xon_xoff >= 0) {
1896 data->term.c_iflag &= ~(IXON | IXOFF | IXANY);
1897 switch (config->xon_xoff) {
1898 case SP_XONXOFF_DISABLED:
1901 data->term.c_iflag |= IXOFF;
1903 case SP_XONXOFF_OUT:
1904 data->term.c_iflag |= IXON | IXANY;
1906 case SP_XONXOFF_INOUT:
1907 data->term.c_iflag |= IXON | IXOFF | IXANY;
1910 RETURN_ERROR(SP_ERR_ARG, "Invalid XON/XOFF setting");
1914 if (tcsetattr(port->fd, TCSANOW, &data->term) < 0)
1915 RETURN_FAIL("tcsetattr() failed");
1918 if (baud_nonstd != B0) {
1919 if (ioctl(port->fd, IOSSIOSPEED, &baud_nonstd) == -1)
1920 RETURN_FAIL("IOSSIOSPEED ioctl failed");
1921 /* Set baud rates in data->term to correct, but incompatible
1922 * with tcsetattr() value, same as delivered by tcgetattr(). */
1923 if (cfsetspeed(&data->term, baud_nonstd) < 0)
1924 RETURN_FAIL("cfsetspeed() failed");
1926 #elif defined(__linux__)
1928 TRY(set_baudrate(port->fd, config->baudrate));
1930 if (data->termiox_supported)
1931 TRY(set_flow(port->fd, data->flow));
1935 #endif /* !_WIN32 */
1940 enum sp_return sp_new_config(struct sp_port_config **config_ptr)
1942 struct sp_port_config *config;
1944 TRACE("%p", config_ptr);
1947 RETURN_ERROR(SP_ERR_ARG, "Null result pointer");
1951 if (!(config = malloc(sizeof(struct sp_port_config))))
1952 RETURN_ERROR(SP_ERR_MEM, "config malloc failed");
1954 config->baudrate = -1;
1956 config->parity = -1;
1957 config->stopbits = -1;
1963 *config_ptr = config;
1968 void sp_free_config(struct sp_port_config *config)
1970 TRACE("%p", config);
1973 DEBUG("Null config");
1980 enum sp_return sp_get_config(struct sp_port *port, struct sp_port_config *config)
1982 struct port_data data;
1984 TRACE("%p, %p", port, config);
1989 RETURN_ERROR(SP_ERR_ARG, "Null config");
1991 TRY(get_config(port, &data, config));
1996 enum sp_return sp_set_config(struct sp_port *port, const struct sp_port_config *config)
1998 struct port_data data;
1999 struct sp_port_config prev_config;
2001 TRACE("%p, %p", port, config);
2006 RETURN_ERROR(SP_ERR_ARG, "Null config");
2008 TRY(get_config(port, &data, &prev_config));
2009 TRY(set_config(port, &data, config));
2014 #define CREATE_ACCESSORS(x, type) \
2015 enum sp_return sp_set_##x(struct sp_port *port, type x) { \
2016 struct port_data data; \
2017 struct sp_port_config config; \
2018 TRACE("%p, %d", port, x); \
2019 CHECK_OPEN_PORT(); \
2020 TRY(get_config(port, &data, &config)); \
2022 TRY(set_config(port, &data, &config)); \
2025 enum sp_return sp_get_config_##x(const struct sp_port_config *config, type *x) { \
2026 TRACE("%p, %p", config, x); \
2028 RETURN_ERROR(SP_ERR_ARG, "Null config"); \
2032 enum sp_return sp_set_config_##x(struct sp_port_config *config, type x) { \
2033 TRACE("%p, %d", config, x); \
2035 RETURN_ERROR(SP_ERR_ARG, "Null config"); \
2040 CREATE_ACCESSORS(baudrate, int)
2041 CREATE_ACCESSORS(bits, int)
2042 CREATE_ACCESSORS(parity, enum sp_parity)
2043 CREATE_ACCESSORS(stopbits, int)
2044 CREATE_ACCESSORS(rts, enum sp_rts)
2045 CREATE_ACCESSORS(cts, enum sp_cts)
2046 CREATE_ACCESSORS(dtr, enum sp_dtr)
2047 CREATE_ACCESSORS(dsr, enum sp_dsr)
2048 CREATE_ACCESSORS(xon_xoff, enum sp_xonxoff)
2050 enum sp_return sp_set_config_flowcontrol(struct sp_port_config *config, enum sp_flowcontrol flowcontrol)
2053 RETURN_ERROR(SP_ERR_ARG, "Null configuration");
2055 if (flowcontrol > SP_FLOWCONTROL_DTRDSR)
2056 RETURN_ERROR(SP_ERR_ARG, "Invalid flow control setting");
2058 if (flowcontrol == SP_FLOWCONTROL_XONXOFF)
2059 config->xon_xoff = SP_XONXOFF_INOUT;
2061 config->xon_xoff = SP_XONXOFF_DISABLED;
2063 if (flowcontrol == SP_FLOWCONTROL_RTSCTS) {
2064 config->rts = SP_RTS_FLOW_CONTROL;
2065 config->cts = SP_CTS_FLOW_CONTROL;
2067 if (config->rts == SP_RTS_FLOW_CONTROL)
2068 config->rts = SP_RTS_ON;
2069 config->cts = SP_CTS_IGNORE;
2072 if (flowcontrol == SP_FLOWCONTROL_DTRDSR) {
2073 config->dtr = SP_DTR_FLOW_CONTROL;
2074 config->dsr = SP_DSR_FLOW_CONTROL;
2076 if (config->dtr == SP_DTR_FLOW_CONTROL)
2077 config->dtr = SP_DTR_ON;
2078 config->dsr = SP_DSR_IGNORE;
2084 enum sp_return sp_set_flowcontrol(struct sp_port *port, enum sp_flowcontrol flowcontrol)
2086 struct port_data data;
2087 struct sp_port_config config;
2089 TRACE("%p, %d", port, flowcontrol);
2093 TRY(get_config(port, &data, &config));
2095 TRY(sp_set_config_flowcontrol(&config, flowcontrol));
2097 TRY(set_config(port, &data, &config));
2102 enum sp_return sp_get_signals(struct sp_port *port, enum sp_signal *signals)
2104 TRACE("%p, %p", port, signals);
2109 RETURN_ERROR(SP_ERR_ARG, "Null result pointer");
2111 DEBUG("Getting control signals for port %s", port->name);
2116 if (GetCommModemStatus(port->hdl, &bits) == 0)
2117 RETURN_FAIL("GetCommModemStatus() failed");
2118 if (bits & MS_CTS_ON)
2119 *signals |= SP_SIG_CTS;
2120 if (bits & MS_DSR_ON)
2121 *signals |= SP_SIG_DSR;
2122 if (bits & MS_RLSD_ON)
2123 *signals |= SP_SIG_DCD;
2124 if (bits & MS_RING_ON)
2125 *signals |= SP_SIG_RI;
2128 if (ioctl(port->fd, TIOCMGET, &bits) < 0)
2129 RETURN_FAIL("TIOCMGET ioctl failed");
2130 if (bits & TIOCM_CTS)
2131 *signals |= SP_SIG_CTS;
2132 if (bits & TIOCM_DSR)
2133 *signals |= SP_SIG_DSR;
2134 if (bits & TIOCM_CAR)
2135 *signals |= SP_SIG_DCD;
2136 if (bits & TIOCM_RNG)
2137 *signals |= SP_SIG_RI;
2142 enum sp_return sp_start_break(struct sp_port *port)
2148 if (SetCommBreak(port->hdl) == 0)
2149 RETURN_FAIL("SetCommBreak() failed");
2151 if (ioctl(port->fd, TIOCSBRK, 1) < 0)
2152 RETURN_FAIL("TIOCSBRK ioctl failed");
2158 enum sp_return sp_end_break(struct sp_port *port)
2164 if (ClearCommBreak(port->hdl) == 0)
2165 RETURN_FAIL("ClearCommBreak() failed");
2167 if (ioctl(port->fd, TIOCCBRK, 1) < 0)
2168 RETURN_FAIL("TIOCCBRK ioctl failed");
2174 int sp_last_error_code(void)
2178 RETURN_VALUE("%d", GetLastError());
2180 RETURN_VALUE("%d", errno);
2184 char *sp_last_error_message(void)
2190 DWORD error = GetLastError();
2193 FORMAT_MESSAGE_ALLOCATE_BUFFER |
2194 FORMAT_MESSAGE_FROM_SYSTEM |
2195 FORMAT_MESSAGE_IGNORE_INSERTS,
2198 MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
2202 RETURN_VALUE("%s", message);
2204 RETURN_VALUE("%s", strerror(errno));
2208 void sp_free_error_message(char *message)
2210 TRACE("%s", message);
2221 void sp_set_debug_handler(void (*handler)(const char *format, ...))
2223 TRACE("%p", handler);
2225 sp_debug_handler = handler;
2230 void sp_default_debug_handler(const char *format, ...)
2233 va_start(args, format);
2234 if (getenv("LIBSERIALPORT_DEBUG")) {
2235 fputs("sp: ", stderr);
2236 vfprintf(stderr, format, args);