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>
51 #include "linux/serial.h"
52 #include "linux_termios.h"
53 #if defined(TCGETX) && defined(TCSETX) && defined(HAVE_TERMIOX)
59 #include "linux_termios.h"
62 #include "libserialport.h"
68 COMMTIMEOUTS timeouts;
78 struct sp_port_config {
81 enum sp_parity parity;
87 enum sp_xonxoff xon_xoff;
96 int termiox_supported;
101 /* Standard baud rates. */
103 #define BAUD_TYPE DWORD
104 #define BAUD(n) {CBR_##n, n}
106 #define BAUD_TYPE speed_t
107 #define BAUD(n) {B##n, n}
110 struct std_baudrate {
115 const struct std_baudrate std_baudrates[] = {
118 * The baudrates 50/75/134/150/200/1800/230400/460800 do not seem to
119 * have documented CBR_* macros.
121 BAUD(110), BAUD(300), BAUD(600), BAUD(1200), BAUD(2400), BAUD(4800),
122 BAUD(9600), BAUD(14400), BAUD(19200), BAUD(38400), BAUD(57600),
123 BAUD(115200), BAUD(128000), BAUD(256000),
125 BAUD(50), BAUD(75), BAUD(110), BAUD(134), BAUD(150), BAUD(200),
126 BAUD(300), BAUD(600), BAUD(1200), BAUD(1800), BAUD(2400), BAUD(4800),
127 BAUD(9600), BAUD(19200), BAUD(38400), BAUD(57600), BAUD(115200),
129 #if !defined(__APPLE__) && !defined(__OpenBSD__)
135 void (*sp_debug_handler)(const char *format, ...) = sp_default_debug_handler;
137 #define ARRAY_SIZE(x) (sizeof(x) / sizeof(x[0]))
138 #define NUM_STD_BAUDRATES ARRAY_SIZE(std_baudrates)
140 /* Debug output macros. */
141 #define DEBUG(fmt, ...) do { if (sp_debug_handler) sp_debug_handler(fmt ".\n", ##__VA_ARGS__); } while (0)
142 #define DEBUG_ERROR(err, msg) DEBUG("%s returning " #err ": " msg, __func__)
143 #define DEBUG_FAIL(msg) do { \
144 char *errmsg = sp_last_error_message(); \
145 DEBUG("%s returning SP_ERR_FAIL: " msg ": %s", __func__, errmsg); \
146 sp_free_error_message(errmsg); \
148 #define RETURN() do { DEBUG("%s returning", __func__); return; } while(0)
149 #define RETURN_CODE(x) do { DEBUG("%s returning " #x, __func__); return x; } while (0)
150 #define RETURN_CODEVAL(x) do { \
152 case SP_OK: RETURN_CODE(SP_OK); \
153 case SP_ERR_ARG: RETURN_CODE(SP_ERR_ARG); \
154 case SP_ERR_FAIL: RETURN_CODE(SP_ERR_FAIL); \
155 case SP_ERR_MEM: RETURN_CODE(SP_ERR_MEM); \
156 case SP_ERR_SUPP: RETURN_CODE(SP_ERR_SUPP); \
159 #define RETURN_OK() RETURN_CODE(SP_OK);
160 #define RETURN_ERROR(err, msg) do { DEBUG_ERROR(err, msg); return err; } while (0)
161 #define RETURN_FAIL(msg) do { DEBUG_FAIL(msg); return SP_ERR_FAIL; } while (0)
162 #define RETURN_VALUE(fmt, x) do { DEBUG("%s returning " fmt, __func__, x); return x; } while (0)
163 #define SET_ERROR(val, err, msg) do { DEBUG_ERROR(err, msg); val = err; } while (0)
164 #define SET_FAIL(val, msg) do { DEBUG_FAIL(msg); val = SP_ERR_FAIL; } while (0)
165 #define TRACE(fmt, ...) DEBUG("%s(" fmt ") called", __func__, ##__VA_ARGS__)
167 #define TRY(x) do { int ret = x; if (ret != SP_OK) RETURN_CODEVAL(ret); } while (0)
169 /* Helper functions. */
170 static struct sp_port **list_append(struct sp_port **list, const char *portname);
171 static enum sp_return get_config(struct sp_port *port, struct port_data *data,
172 struct sp_port_config *config);
173 static enum sp_return set_config(struct sp_port *port, struct port_data *data,
174 const struct sp_port_config *config);
176 enum sp_return sp_get_port_by_name(const char *portname, struct sp_port **port_ptr)
178 struct sp_port *port;
181 TRACE("%s, %p", portname, port_ptr);
184 RETURN_ERROR(SP_ERR_ARG, "Null result pointer");
189 RETURN_ERROR(SP_ERR_ARG, "Null port name");
191 DEBUG("Building structure for port %s", portname);
193 if (!(port = malloc(sizeof(struct sp_port))))
194 RETURN_ERROR(SP_ERR_MEM, "Port structure malloc failed");
196 len = strlen(portname) + 1;
198 if (!(port->name = malloc(len))) {
200 RETURN_ERROR(SP_ERR_MEM, "Port name malloc failed");
203 memcpy(port->name, portname, len);
206 port->hdl = INVALID_HANDLE_VALUE;
216 char *sp_get_port_name(const struct sp_port *port)
223 RETURN_VALUE("%s", port->name);
226 enum sp_return sp_get_port_handle(const struct sp_port *port, void *result_ptr)
228 TRACE("%p, %p", port, result_ptr);
231 RETURN_ERROR(SP_ERR_ARG, "Null port");
234 HANDLE *handle_ptr = result_ptr;
235 *handle_ptr = port->hdl;
237 int *fd_ptr = result_ptr;
244 enum sp_return sp_copy_port(const struct sp_port *port, struct sp_port **copy_ptr)
246 TRACE("%p, %p", port, copy_ptr);
249 RETURN_ERROR(SP_ERR_ARG, "Null result pointer");
254 RETURN_ERROR(SP_ERR_ARG, "Null port");
257 RETURN_ERROR(SP_ERR_ARG, "Null port name");
259 DEBUG("Copying port structure");
261 RETURN_VALUE("%p", sp_get_port_by_name(port->name, copy_ptr));
264 void sp_free_port(struct sp_port *port)
273 DEBUG("Freeing port structure");
283 static struct sp_port **list_append(struct sp_port **list, const char *portname)
288 for (count = 0; list[count]; count++);
289 if (!(tmp = realloc(list, sizeof(struct sp_port *) * (count + 2))))
292 if (sp_get_port_by_name(portname, &list[count]) != SP_OK)
294 list[count + 1] = NULL;
298 sp_free_port_list(list);
302 enum sp_return sp_list_ports(struct sp_port ***list_ptr)
304 struct sp_port **list;
305 int ret = SP_ERR_SUPP;
307 TRACE("%p", list_ptr);
310 RETURN_ERROR(SP_ERR_ARG, "Null result pointer");
312 DEBUG("Enumerating ports");
314 if (!(list = malloc(sizeof(struct sp_port **))))
315 RETURN_ERROR(SP_ERR_MEM, "Port list malloc failed");
322 DWORD max_value_len, max_data_size, max_data_len;
323 DWORD value_len, data_size, data_len;
324 DWORD type, index = 0;
330 DEBUG("Opening registry key");
331 if (RegOpenKeyEx(HKEY_LOCAL_MACHINE, _T("HARDWARE\\DEVICEMAP\\SERIALCOMM"),
332 0, KEY_QUERY_VALUE, &key) != ERROR_SUCCESS) {
333 SET_FAIL(ret, "RegOpenKeyEx() failed");
336 DEBUG("Querying registry key value and data sizes");
337 if (RegQueryInfoKey(key, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
338 &max_value_len, &max_data_size, NULL, NULL) != ERROR_SUCCESS) {
339 SET_FAIL(ret, "RegQueryInfoKey() failed");
342 max_data_len = max_data_size / sizeof(TCHAR);
343 if (!(value = malloc((max_value_len + 1) * sizeof(TCHAR)))) {
344 SET_ERROR(ret, SP_ERR_MEM, "registry value malloc failed");
347 if (!(data = malloc((max_data_len + 1) * sizeof(TCHAR)))) {
348 SET_ERROR(ret, SP_ERR_MEM, "registry data malloc failed");
351 DEBUG("Iterating over values");
353 value_len = max_value_len + 1,
354 data_size = max_data_size,
355 RegEnumValue(key, index, value, &value_len,
356 NULL, &type, (LPBYTE)data, &data_size) == ERROR_SUCCESS)
358 data_len = data_size / sizeof(TCHAR);
359 data[data_len] = '\0';
361 name_len = WideCharToMultiByte(CP_ACP, 0, data, -1, NULL, 0, NULL, NULL)
363 name_len = data_len + 1;
365 if (!(name = malloc(name_len))) {
366 SET_ERROR(ret, SP_ERR_MEM, "registry port name malloc failed");
370 WideCharToMultiByte(CP_ACP, 0, data, -1, name, name_len, NULL, NULL);
374 if (type == REG_SZ) {
375 DEBUG("Found port %s", name);
376 if (!(list = list_append(list, name))) {
377 SET_ERROR(ret, SP_ERR_MEM, "list append failed");
393 CFMutableDictionaryRef classes;
402 DEBUG("Getting IOKit master port");
403 if (IOMasterPort(MACH_PORT_NULL, &master) != KERN_SUCCESS) {
404 SET_FAIL(ret, "IOMasterPort() failed");
408 DEBUG("Creating matching dictionary");
409 if (!(classes = IOServiceMatching(kIOSerialBSDServiceValue))) {
410 SET_FAIL(ret, "IOServiceMatching() failed");
414 CFDictionarySetValue(classes,
415 CFSTR(kIOSerialBSDTypeKey), CFSTR(kIOSerialBSDAllTypes));
417 DEBUG("Getting matching services");
418 if (IOServiceGetMatchingServices(master, classes, &iter) != KERN_SUCCESS) {
419 SET_FAIL(ret, "IOServiceGetMatchingServices() failed");
423 if (!(path = malloc(PATH_MAX))) {
424 SET_ERROR(ret, SP_ERR_MEM, "device path malloc failed");
428 DEBUG("Iterating over results");
429 while ((port = IOIteratorNext(iter))) {
430 cf_path = IORegistryEntryCreateCFProperty(port,
431 CFSTR(kIOCalloutDeviceKey), kCFAllocatorDefault, 0);
433 result = CFStringGetCString(cf_path,
434 path, PATH_MAX, kCFStringEncodingASCII);
437 DEBUG("Found port %s", path);
438 if (!(list = list_append(list, path))) {
439 SET_ERROR(ret, SP_ERR_MEM, "list append failed");
440 IOObjectRelease(port);
445 IOObjectRelease(port);
450 IOObjectRelease(iter);
455 struct udev_enumerate *ud_enumerate;
456 struct udev_list_entry *ud_list;
457 struct udev_list_entry *ud_entry;
459 struct udev_device *ud_dev, *ud_parent;
462 int fd, ioctl_result;
463 struct serial_struct serial_info;
467 DEBUG("Enumerating tty devices");
469 ud_enumerate = udev_enumerate_new(ud);
470 udev_enumerate_add_match_subsystem(ud_enumerate, "tty");
471 udev_enumerate_scan_devices(ud_enumerate);
472 ud_list = udev_enumerate_get_list_entry(ud_enumerate);
473 DEBUG("Iterating over results");
474 udev_list_entry_foreach(ud_entry, ud_list) {
475 path = udev_list_entry_get_name(ud_entry);
476 DEBUG("Found device %s", path);
477 ud_dev = udev_device_new_from_syspath(ud, path);
478 /* If there is no parent device, this is a virtual tty. */
479 ud_parent = udev_device_get_parent(ud_dev);
480 if (ud_parent == NULL) {
481 DEBUG("No parent device, assuming virtual tty");
482 udev_device_unref(ud_dev);
485 name = udev_device_get_devnode(ud_dev);
486 /* The serial8250 driver has a hardcoded number of ports.
487 * The only way to tell which actually exist on a given system
488 * is to try to open them and make an ioctl call. */
489 driver = udev_device_get_driver(ud_parent);
490 if (driver && !strcmp(driver, "serial8250")) {
491 DEBUG("serial8250 device, attempting to open");
492 if ((fd = open(name, O_RDWR | O_NONBLOCK | O_NOCTTY)) < 0) {
493 DEBUG("open failed, skipping");
496 ioctl_result = ioctl(fd, TIOCGSERIAL, &serial_info);
498 if (ioctl_result != 0) {
499 DEBUG("ioctl failed, skipping");
502 if (serial_info.type == PORT_UNKNOWN) {
503 DEBUG("port type is unknown, skipping");
507 DEBUG("Found port %s", name);
508 list = list_append(list, name);
510 udev_device_unref(ud_dev);
512 SET_ERROR(ret, SP_ERR_MEM, "list append failed");
517 udev_enumerate_unref(ud_enumerate);
526 DEBUG_ERROR(SP_ERR_SUPP, "Enumeration not supported on this platform.");
529 sp_free_port_list(list);
535 void sp_free_port_list(struct sp_port **list)
546 DEBUG("Freeing port list");
548 for (i = 0; list[i]; i++)
549 sp_free_port(list[i]);
555 #define CHECK_PORT() do { \
557 RETURN_ERROR(SP_ERR_ARG, "Null port"); \
558 if (port->name == NULL) \
559 RETURN_ERROR(SP_ERR_ARG, "Null port name"); \
562 #define CHECK_PORT_HANDLE() do { \
563 if (port->hdl == INVALID_HANDLE_VALUE) \
564 RETURN_ERROR(SP_ERR_ARG, "Invalid port handle"); \
567 #define CHECK_PORT_HANDLE() do { \
569 RETURN_ERROR(SP_ERR_ARG, "Invalid port fd"); \
572 #define CHECK_OPEN_PORT() do { \
574 CHECK_PORT_HANDLE(); \
577 enum sp_return sp_open(struct sp_port *port, enum sp_mode flags)
579 struct port_data data;
580 struct sp_port_config config;
583 TRACE("%p, 0x%x", port, flags);
587 if (flags > (SP_MODE_READ | SP_MODE_WRITE))
588 RETURN_ERROR(SP_ERR_ARG, "Invalid flags");
590 DEBUG("Opening port %s", port->name);
593 DWORD desired_access = 0, flags_and_attributes = 0;
594 char *escaped_port_name;
596 /* Prefix port name with '\\.\' to work with ports above COM9. */
597 if (!(escaped_port_name = malloc(strlen(port->name + 5))))
598 RETURN_ERROR(SP_ERR_MEM, "Escaped port name malloc failed");
599 sprintf(escaped_port_name, "\\\\.\\%s", port->name);
601 /* Map 'flags' to the OS-specific settings. */
602 flags_and_attributes = FILE_ATTRIBUTE_NORMAL | FILE_FLAG_OVERLAPPED;
603 if (flags & SP_MODE_READ)
604 desired_access |= GENERIC_READ;
605 if (flags & SP_MODE_WRITE)
606 desired_access |= GENERIC_WRITE;
608 port->hdl = CreateFile(escaped_port_name, desired_access, 0, 0,
609 OPEN_EXISTING, flags_and_attributes, 0);
611 free(escaped_port_name);
613 if (port->hdl == INVALID_HANDLE_VALUE)
614 RETURN_FAIL("port CreateFile() failed");
616 /* All timeouts initially disabled. */
617 port->timeouts.ReadIntervalTimeout = 0;
618 port->timeouts.ReadTotalTimeoutMultiplier = 0;
619 port->timeouts.ReadTotalTimeoutConstant = 0;
620 port->timeouts.WriteTotalTimeoutMultiplier = 0;
621 port->timeouts.WriteTotalTimeoutConstant = 0;
623 if (SetCommTimeouts(port->hdl, &port->timeouts) == 0) {
625 RETURN_FAIL("SetCommTimeouts() failed");
628 /* Prepare OVERLAPPED structures. */
629 memset(&port->read_ovl, 0, sizeof(port->read_ovl));
630 memset(&port->write_ovl, 0, sizeof(port->write_ovl));
631 port->read_ovl.hEvent = INVALID_HANDLE_VALUE;
632 port->write_ovl.hEvent = INVALID_HANDLE_VALUE;
633 if ((port->read_ovl.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL)) == INVALID_HANDLE_VALUE) {
635 RETURN_FAIL("read event CreateEvent() failed");
637 if ((port->write_ovl.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL)) == INVALID_HANDLE_VALUE) {
639 RETURN_FAIL("write event CreateEvent() failed");
642 port->writing = FALSE;
645 int flags_local = O_NONBLOCK | O_NOCTTY;
647 /* Map 'flags' to the OS-specific settings. */
648 if (flags & (SP_MODE_READ | SP_MODE_WRITE))
649 flags_local |= O_RDWR;
650 else if (flags & SP_MODE_READ)
651 flags_local |= O_RDONLY;
652 else if (flags & SP_MODE_WRITE)
653 flags_local |= O_WRONLY;
655 if ((port->fd = open(port->name, flags_local)) < 0)
656 RETURN_FAIL("open() failed");
659 ret = get_config(port, &data, &config);
666 /* Set sane port settings. */
668 data.dcb.fBinary = TRUE;
669 data.dcb.fDsrSensitivity = FALSE;
670 data.dcb.fErrorChar = FALSE;
671 data.dcb.fNull = FALSE;
672 data.dcb.fAbortOnError = TRUE;
674 /* Turn off all fancy termios tricks, give us a raw channel. */
675 data.term.c_iflag &= ~(IGNBRK | BRKINT | PARMRK | ISTRIP | INLCR | IGNCR | ICRNL | IMAXBEL);
677 data.term.c_iflag &= ~IUCLC;
679 data.term.c_oflag &= ~(OPOST | ONLCR | OCRNL | ONOCR | ONLRET);
681 data.term.c_oflag &= ~OLCUC;
684 data.term.c_oflag &= ~NLDLY;
687 data.term.c_oflag &= ~CRDLY;
690 data.term.c_oflag &= ~TABDLY;
693 data.term.c_oflag &= ~BSDLY;
696 data.term.c_oflag &= ~VTDLY;
699 data.term.c_oflag &= ~FFDLY;
702 data.term.c_oflag &= ~OFILL;
704 data.term.c_lflag &= ~(ISIG | ICANON | ECHO | IEXTEN);
705 data.term.c_cc[VMIN] = 0;
706 data.term.c_cc[VTIME] = 0;
708 /* Ignore modem status lines; enable receiver; leave control lines alone on close. */
709 data.term.c_cflag |= (CLOCAL | CREAD | HUPCL);
712 ret = set_config(port, &data, &config);
722 enum sp_return sp_close(struct sp_port *port)
728 DEBUG("Closing port %s", port->name);
731 /* Returns non-zero upon success, 0 upon failure. */
732 if (CloseHandle(port->hdl) == 0)
733 RETURN_FAIL("port CloseHandle() failed");
734 port->hdl = INVALID_HANDLE_VALUE;
735 /* Close event handle created for overlapped reads. */
736 if (port->read_ovl.hEvent != INVALID_HANDLE_VALUE && CloseHandle(port->read_ovl.hEvent) == 0)
737 RETURN_FAIL("read event CloseHandle() failed");
738 /* Close event handle created for overlapped writes. */
739 if (port->write_ovl.hEvent != INVALID_HANDLE_VALUE && CloseHandle(port->write_ovl.hEvent) == 0)
740 RETURN_FAIL("write event CloseHandle() failed");
742 /* Returns 0 upon success, -1 upon failure. */
743 if (close(port->fd) == -1)
744 RETURN_FAIL("close() failed");
751 enum sp_return sp_flush(struct sp_port *port, enum sp_buffer buffers)
753 TRACE("%p, 0x%x", port, buffers);
757 if (buffers > SP_BUF_BOTH)
758 RETURN_ERROR(SP_ERR_ARG, "Invalid buffer selection");
760 const char *buffer_names[] = {"no", "input", "output", "both"};
762 DEBUG("Flushing %s buffers on port %s", buffer_names[buffers], port->name);
766 if (buffers & SP_BUF_INPUT)
767 flags |= PURGE_RXCLEAR;
768 if (buffers & SP_BUF_OUTPUT)
769 flags |= PURGE_TXCLEAR;
771 /* Returns non-zero upon success, 0 upon failure. */
772 if (PurgeComm(port->hdl, flags) == 0)
773 RETURN_FAIL("PurgeComm() failed");
776 if (buffers & SP_BUF_BOTH)
778 else if (buffers & SP_BUF_INPUT)
780 else if (buffers & SP_BUF_OUTPUT)
783 /* Returns 0 upon success, -1 upon failure. */
784 if (tcflush(port->fd, flags) < 0)
785 RETURN_FAIL("tcflush() failed");
790 enum sp_return sp_drain(struct sp_port *port)
796 DEBUG("Draining port %s", port->name);
799 /* Returns non-zero upon success, 0 upon failure. */
800 if (FlushFileBuffers(port->hdl) == 0)
801 RETURN_FAIL("FlushFileBuffers() failed");
803 /* Returns 0 upon success, -1 upon failure. */
804 if (tcdrain(port->fd) < 0)
805 RETURN_FAIL("tcdrain() failed");
811 enum sp_return sp_blocking_write(struct sp_port *port, const void *buf, size_t count, unsigned int timeout)
813 TRACE("%p, %p, %d, %d", port, buf, count, timeout);
818 RETURN_ERROR(SP_ERR_ARG, "Null buffer");
821 DEBUG("Writing %d bytes to port %s, timeout %d ms", count, port->name, timeout);
823 DEBUG("Writing %d bytes to port %s, no timeout", count, port->name);
826 RETURN_VALUE("0", 0);
829 DWORD bytes_written = 0;
832 /* Wait for previous non-blocking write to complete, if any. */
834 DEBUG("Waiting for previous write to complete");
835 result = GetOverlappedResult(port->hdl, &port->write_ovl, &bytes_written, TRUE);
838 RETURN_FAIL("Previous write failed to complete");
839 DEBUG("Previous write completed");
843 port->timeouts.WriteTotalTimeoutConstant = timeout;
844 if (SetCommTimeouts(port->hdl, &port->timeouts) == 0)
845 RETURN_FAIL("SetCommTimeouts() failed");
848 if (WriteFile(port->hdl, buf, count, NULL, &port->write_ovl) == 0) {
849 if (GetLastError() == ERROR_IO_PENDING) {
850 DEBUG("Waiting for write to complete");
851 GetOverlappedResult(port->hdl, &port->write_ovl, &bytes_written, TRUE);
852 DEBUG("Write completed, %d/%d bytes written", bytes_written, count);
853 RETURN_VALUE("%d", bytes_written);
855 RETURN_FAIL("WriteFile() failed");
858 DEBUG("Write completed immediately");
859 RETURN_VALUE("%d", count);
862 size_t bytes_written = 0;
863 unsigned char *ptr = (unsigned char *) buf;
864 struct timeval start, delta, now, end = {0, 0};
869 /* Get time at start of operation. */
870 gettimeofday(&start, NULL);
871 /* Define duration of timeout. */
872 delta.tv_sec = timeout / 1000;
873 delta.tv_usec = (timeout % 1000) * 1000;
874 /* Calculate time at which we should give up. */
875 timeradd(&start, &delta, &end);
878 /* Loop until we have written the requested number of bytes. */
879 while (bytes_written < count)
881 /* Wait until space is available. */
883 FD_SET(port->fd, &fds);
885 gettimeofday(&now, NULL);
886 if (timercmp(&now, &end, >)) {
887 DEBUG("write timed out");
888 RETURN_VALUE("%d", bytes_written);
890 timersub(&end, &now, &delta);
892 result = select(port->fd + 1, NULL, &fds, NULL, timeout ? &delta : NULL);
894 if (errno == EINTR) {
895 DEBUG("select() call was interrupted, repeating");
898 RETURN_FAIL("select() failed");
900 } else if (result == 0) {
901 DEBUG("write timed out");
902 RETURN_VALUE("%d", bytes_written);
906 result = write(port->fd, ptr, count - bytes_written);
910 /* This shouldn't happen because we did a select() first, but handle anyway. */
913 /* This is an actual failure. */
914 RETURN_FAIL("write() failed");
917 bytes_written += result;
921 RETURN_VALUE("%d", bytes_written);
925 enum sp_return sp_nonblocking_write(struct sp_port *port, const void *buf, size_t count)
927 TRACE("%p, %p, %d", port, buf, count);
932 RETURN_ERROR(SP_ERR_ARG, "Null buffer");
934 DEBUG("Writing up to %d bytes to port %s", count, port->name);
937 RETURN_VALUE("0", 0);
941 BYTE *ptr = (BYTE *) buf;
943 /* Check whether previous write is complete. */
945 if (HasOverlappedIoCompleted(&port->write_ovl)) {
946 DEBUG("Previous write completed");
949 DEBUG("Previous write not complete");
950 /* Can't take a new write until the previous one finishes. */
951 RETURN_VALUE("0", 0);
956 port->timeouts.WriteTotalTimeoutConstant = 0;
957 if (SetCommTimeouts(port->hdl, &port->timeouts) == 0)
958 RETURN_FAIL("SetCommTimeouts() failed");
960 /* Keep writing data until the OS has to actually start an async IO for it.
961 * At that point we know the buffer is full. */
962 while (written < count)
964 /* Copy first byte of user buffer. */
965 port->pending_byte = *ptr++;
967 /* Start asynchronous write. */
968 if (WriteFile(port->hdl, &port->pending_byte, 1, NULL, &port->write_ovl) == 0) {
969 if (GetLastError() == ERROR_IO_PENDING) {
970 DEBUG("Asynchronous write started");
972 RETURN_VALUE("%d", ++written);
974 /* Actual failure of some kind. */
975 RETURN_FAIL("WriteFile() failed");
978 DEBUG("Single byte written immediately.");
983 DEBUG("All bytes written immediately.");
985 RETURN_VALUE("%d", written);
987 /* Returns the number of bytes written, or -1 upon failure. */
988 ssize_t written = write(port->fd, buf, count);
991 RETURN_FAIL("write() failed");
993 RETURN_VALUE("%d", written);
997 enum sp_return sp_blocking_read(struct sp_port *port, void *buf, size_t count, unsigned int timeout)
999 TRACE("%p, %p, %d, %d", port, buf, count, timeout);
1004 RETURN_ERROR(SP_ERR_ARG, "Null buffer");
1007 DEBUG("Reading %d bytes from port %s, timeout %d ms", count, port->name, timeout);
1009 DEBUG("Reading %d bytes from port %s, no timeout", count, port->name);
1012 RETURN_VALUE("0", 0);
1015 DWORD bytes_read = 0;
1018 port->timeouts.ReadIntervalTimeout = 0;
1019 port->timeouts.ReadTotalTimeoutConstant = timeout;
1020 if (SetCommTimeouts(port->hdl, &port->timeouts) == 0)
1021 RETURN_FAIL("SetCommTimeouts() failed");
1024 if (ReadFile(port->hdl, buf, count, NULL, &port->read_ovl) == 0) {
1025 if (GetLastError() == ERROR_IO_PENDING) {
1026 DEBUG("Waiting for read to complete");
1027 GetOverlappedResult(port->hdl, &port->read_ovl, &bytes_read, TRUE);
1028 DEBUG("Read completed, %d/%d bytes read", bytes_read, count);
1029 RETURN_VALUE("%d", bytes_read);
1031 RETURN_FAIL("ReadFile() failed");
1034 DEBUG("Read completed immediately");
1035 RETURN_VALUE("%d", count);
1038 size_t bytes_read = 0;
1039 unsigned char *ptr = (unsigned char *) buf;
1040 struct timeval start, delta, now, end = {0, 0};
1045 /* Get time at start of operation. */
1046 gettimeofday(&start, NULL);
1047 /* Define duration of timeout. */
1048 delta.tv_sec = timeout / 1000;
1049 delta.tv_usec = (timeout % 1000) * 1000;
1050 /* Calculate time at which we should give up. */
1051 timeradd(&start, &delta, &end);
1054 /* Loop until we have the requested number of bytes. */
1055 while (bytes_read < count)
1057 /* Wait until data is available. */
1059 FD_SET(port->fd, &fds);
1061 gettimeofday(&now, NULL);
1062 if (timercmp(&now, &end, >))
1063 /* Timeout has expired. */
1064 RETURN_VALUE("%d", bytes_read);
1065 timersub(&end, &now, &delta);
1067 result = select(port->fd + 1, &fds, NULL, NULL, timeout ? &delta : NULL);
1069 if (errno == EINTR) {
1070 DEBUG("select() call was interrupted, repeating");
1073 RETURN_FAIL("select() failed");
1075 } else if (result == 0) {
1076 DEBUG("read timed out");
1077 RETURN_VALUE("%d", bytes_read);
1081 result = read(port->fd, ptr, count - bytes_read);
1084 if (errno == EAGAIN)
1085 /* This shouldn't happen because we did a select() first, but handle anyway. */
1088 /* This is an actual failure. */
1089 RETURN_FAIL("read() failed");
1092 bytes_read += result;
1096 RETURN_VALUE("%d", bytes_read);
1100 enum sp_return sp_nonblocking_read(struct sp_port *port, void *buf, size_t count)
1102 TRACE("%p, %p, %d", port, buf, count);
1107 RETURN_ERROR(SP_ERR_ARG, "Null buffer");
1109 DEBUG("Reading up to %d bytes from port %s", count, port->name);
1115 port->timeouts.ReadIntervalTimeout = MAXDWORD;
1116 port->timeouts.ReadTotalTimeoutConstant = 0;
1117 if (SetCommTimeouts(port->hdl, &port->timeouts) == 0)
1118 RETURN_FAIL("SetCommTimeouts() failed");
1121 if (ReadFile(port->hdl, buf, count, NULL, &port->read_ovl) == 0)
1122 RETURN_FAIL("ReadFile() failed");
1124 /* Get number of bytes read. */
1125 GetOverlappedResult(port->hdl, &port->read_ovl, &bytes_read, TRUE);
1127 RETURN_VALUE("%d", bytes_read);
1131 /* Returns the number of bytes read, or -1 upon failure. */
1132 if ((bytes_read = read(port->fd, buf, count)) < 0) {
1133 if (errno == EAGAIN)
1134 /* No bytes available. */
1137 /* This is an actual failure. */
1138 RETURN_FAIL("read() failed");
1140 RETURN_VALUE("%d", bytes_read);
1144 enum sp_return sp_input_waiting(struct sp_port *port)
1150 DEBUG("Checking input bytes waiting on port %s", port->name);
1156 if (ClearCommError(port->hdl, &errors, &comstat) == 0)
1157 RETURN_FAIL("ClearComError() failed");
1158 RETURN_VALUE("%d", comstat.cbInQue);
1161 if (ioctl(port->fd, TIOCINQ, &bytes_waiting) < 0)
1162 RETURN_FAIL("TIOCINQ ioctl failed");
1163 RETURN_VALUE("%d", bytes_waiting);
1167 enum sp_return sp_output_waiting(struct sp_port *port)
1173 DEBUG("Checking output bytes waiting on port %s", port->name);
1179 if (ClearCommError(port->hdl, &errors, &comstat) == 0)
1180 RETURN_FAIL("ClearComError() failed");
1181 RETURN_VALUE("%d", comstat.cbOutQue);
1184 if (ioctl(port->fd, TIOCOUTQ, &bytes_waiting) < 0)
1185 RETURN_FAIL("TIOCOUTQ ioctl failed");
1186 RETURN_VALUE("%d", bytes_waiting);
1191 static enum sp_return get_baudrate(int fd, int *baudrate)
1195 TRACE("%d, %p", fd, baudrate);
1197 DEBUG("Getting baud rate");
1199 if (!(data = malloc(get_termios_size())))
1200 RETURN_ERROR(SP_ERR_MEM, "termios malloc failed");
1202 if (ioctl(fd, get_termios_get_ioctl(), data) < 0) {
1204 RETURN_FAIL("getting termios failed");
1207 *baudrate = get_termios_speed(data);
1214 static enum sp_return set_baudrate(int fd, int baudrate)
1218 TRACE("%d, %d", fd, baudrate);
1220 DEBUG("Getting baud rate");
1222 if (!(data = malloc(get_termios_size())))
1223 RETURN_ERROR(SP_ERR_MEM, "termios malloc failed");
1225 if (ioctl(fd, get_termios_get_ioctl(), data) < 0) {
1227 RETURN_FAIL("getting termios failed");
1230 DEBUG("Setting baud rate");
1232 set_termios_speed(data, baudrate);
1234 if (ioctl(fd, get_termios_set_ioctl(), data) < 0) {
1236 RETURN_FAIL("setting termios failed");
1245 static enum sp_return get_flow(int fd, int *flow)
1249 TRACE("%d, %p", fd, flow);
1251 DEBUG("Getting advanced flow control");
1253 if (!(data = malloc(get_termiox_size())))
1254 RETURN_ERROR(SP_ERR_MEM, "termiox malloc failed");
1256 if (ioctl(fd, TCGETX, data) < 0) {
1258 RETURN_FAIL("getting termiox failed");
1261 *flow = get_termiox_flow(data);
1268 static enum sp_return set_flow(int fd, int flow)
1272 TRACE("%d, %d", fd, flow);
1274 DEBUG("Getting advanced flow control");
1276 if (!(data = malloc(get_termiox_size())))
1277 RETURN_ERROR(SP_ERR_MEM, "termiox malloc failed");
1279 if (ioctl(fd, TCGETX, data) < 0) {
1281 RETURN_FAIL("getting termiox failed");
1284 DEBUG("Setting advanced flow control");
1286 set_termiox_flow(data, flow);
1288 if (ioctl(fd, TCSETX, data) < 0) {
1290 RETURN_FAIL("setting termiox failed");
1297 #endif /* USE_TERMIOX */
1298 #endif /* __linux__ */
1300 static enum sp_return get_config(struct sp_port *port, struct port_data *data,
1301 struct sp_port_config *config)
1305 TRACE("%p, %p, %p", port, data, config);
1307 DEBUG("Getting configuration for port %s", port->name);
1310 if (!GetCommState(port->hdl, &data->dcb))
1311 RETURN_FAIL("GetCommState() failed");
1313 for (i = 0; i < NUM_STD_BAUDRATES; i++) {
1314 if (data->dcb.BaudRate == std_baudrates[i].index) {
1315 config->baudrate = std_baudrates[i].value;
1320 if (i == NUM_STD_BAUDRATES)
1321 /* BaudRate field can be either an index or a custom baud rate. */
1322 config->baudrate = data->dcb.BaudRate;
1324 config->bits = data->dcb.ByteSize;
1326 if (data->dcb.fParity)
1327 switch (data->dcb.Parity) {
1329 config->parity = SP_PARITY_NONE;
1332 config->parity = SP_PARITY_ODD;
1335 config->parity = SP_PARITY_EVEN;
1338 config->parity = SP_PARITY_MARK;
1341 config->parity = SP_PARITY_SPACE;
1344 config->parity = -1;
1347 config->parity = SP_PARITY_NONE;
1349 switch (data->dcb.StopBits) {
1351 config->stopbits = 1;
1354 config->stopbits = 2;
1357 config->stopbits = -1;
1360 switch (data->dcb.fRtsControl) {
1361 case RTS_CONTROL_DISABLE:
1362 config->rts = SP_RTS_OFF;
1364 case RTS_CONTROL_ENABLE:
1365 config->rts = SP_RTS_ON;
1367 case RTS_CONTROL_HANDSHAKE:
1368 config->rts = SP_RTS_FLOW_CONTROL;
1374 config->cts = data->dcb.fOutxCtsFlow ? SP_CTS_FLOW_CONTROL : SP_CTS_IGNORE;
1376 switch (data->dcb.fDtrControl) {
1377 case DTR_CONTROL_DISABLE:
1378 config->dtr = SP_DTR_OFF;
1380 case DTR_CONTROL_ENABLE:
1381 config->dtr = SP_DTR_ON;
1383 case DTR_CONTROL_HANDSHAKE:
1384 config->dtr = SP_DTR_FLOW_CONTROL;
1390 config->dsr = data->dcb.fOutxDsrFlow ? SP_DSR_FLOW_CONTROL : SP_DSR_IGNORE;
1392 if (data->dcb.fInX) {
1393 if (data->dcb.fOutX)
1394 config->xon_xoff = SP_XONXOFF_INOUT;
1396 config->xon_xoff = SP_XONXOFF_IN;
1398 if (data->dcb.fOutX)
1399 config->xon_xoff = SP_XONXOFF_OUT;
1401 config->xon_xoff = SP_XONXOFF_DISABLED;
1406 if (tcgetattr(port->fd, &data->term) < 0)
1407 RETURN_FAIL("tcgetattr() failed");
1409 if (ioctl(port->fd, TIOCMGET, &data->controlbits) < 0)
1410 RETURN_FAIL("TIOCMGET ioctl failed");
1413 int ret = get_flow(port->fd, &data->flow);
1415 if (ret == SP_ERR_FAIL && errno == EINVAL)
1416 data->termiox_supported = 0;
1418 RETURN_CODEVAL(ret);
1420 data->termiox_supported = 1;
1422 data->termiox_supported = 0;
1425 for (i = 0; i < NUM_STD_BAUDRATES; i++) {
1426 if (cfgetispeed(&data->term) == std_baudrates[i].index) {
1427 config->baudrate = std_baudrates[i].value;
1432 if (i == NUM_STD_BAUDRATES) {
1434 config->baudrate = (int)data->term.c_ispeed;
1435 #elif defined(__linux__)
1436 TRY(get_baudrate(port->fd, &config->baudrate));
1438 config->baudrate = -1;
1442 switch (data->term.c_cflag & CSIZE) {
1459 if (!(data->term.c_cflag & PARENB) && (data->term.c_iflag & IGNPAR))
1460 config->parity = SP_PARITY_NONE;
1461 else if (!(data->term.c_cflag & PARENB) || (data->term.c_iflag & IGNPAR))
1462 config->parity = -1;
1464 else if (data->term.c_cflag & CMSPAR)
1465 config->parity = (data->term.c_cflag & PARODD) ? SP_PARITY_MARK : SP_PARITY_SPACE;
1468 config->parity = (data->term.c_cflag & PARODD) ? SP_PARITY_ODD : SP_PARITY_EVEN;
1470 config->stopbits = (data->term.c_cflag & CSTOPB) ? 2 : 1;
1472 if (data->term.c_cflag & CRTSCTS) {
1473 config->rts = SP_RTS_FLOW_CONTROL;
1474 config->cts = SP_CTS_FLOW_CONTROL;
1476 if (data->termiox_supported && data->flow & RTS_FLOW)
1477 config->rts = SP_RTS_FLOW_CONTROL;
1479 config->rts = (data->controlbits & TIOCM_RTS) ? SP_RTS_ON : SP_RTS_OFF;
1481 config->cts = (data->termiox_supported && data->flow & CTS_FLOW) ?
1482 SP_CTS_FLOW_CONTROL : SP_CTS_IGNORE;
1485 if (data->termiox_supported && data->flow & DTR_FLOW)
1486 config->dtr = SP_DTR_FLOW_CONTROL;
1488 config->dtr = (data->controlbits & TIOCM_DTR) ? SP_DTR_ON : SP_DTR_OFF;
1490 config->dsr = (data->termiox_supported && data->flow & DSR_FLOW) ?
1491 SP_DSR_FLOW_CONTROL : SP_DSR_IGNORE;
1493 if (data->term.c_iflag & IXOFF) {
1494 if (data->term.c_iflag & IXON)
1495 config->xon_xoff = SP_XONXOFF_INOUT;
1497 config->xon_xoff = SP_XONXOFF_IN;
1499 if (data->term.c_iflag & IXON)
1500 config->xon_xoff = SP_XONXOFF_OUT;
1502 config->xon_xoff = SP_XONXOFF_DISABLED;
1509 static enum sp_return set_config(struct sp_port *port, struct port_data *data,
1510 const struct sp_port_config *config)
1514 BAUD_TYPE baud_nonstd;
1519 int baud_nonstd = 0;
1522 TRACE("%p, %p, %p", port, data, config);
1524 DEBUG("Setting configuration for port %s", port->name);
1527 if (config->baudrate >= 0) {
1528 for (i = 0; i < NUM_STD_BAUDRATES; i++) {
1529 if (config->baudrate == std_baudrates[i].value) {
1530 data->dcb.BaudRate = std_baudrates[i].index;
1535 if (i == NUM_STD_BAUDRATES)
1536 data->dcb.BaudRate = config->baudrate;
1539 if (config->bits >= 0)
1540 data->dcb.ByteSize = config->bits;
1542 if (config->parity >= 0) {
1543 switch (config->parity) {
1544 /* Note: There's also SPACEPARITY, MARKPARITY (unneeded so far). */
1545 case SP_PARITY_NONE:
1546 data->dcb.Parity = NOPARITY;
1549 data->dcb.Parity = ODDPARITY;
1551 case SP_PARITY_EVEN:
1552 data->dcb.Parity = EVENPARITY;
1554 case SP_PARITY_MARK:
1555 data->dcb.Parity = MARKPARITY;
1557 case SP_PARITY_SPACE:
1558 data->dcb.Parity = SPACEPARITY;
1561 RETURN_ERROR(SP_ERR_ARG, "Invalid parity setting");
1565 if (config->stopbits >= 0) {
1566 switch (config->stopbits) {
1567 /* Note: There's also ONE5STOPBITS == 1.5 (unneeded so far). */
1569 data->dcb.StopBits = ONESTOPBIT;
1572 data->dcb.StopBits = TWOSTOPBITS;
1575 RETURN_ERROR(SP_ERR_ARG, "Invalid stop bit setting");
1579 if (config->rts >= 0) {
1580 switch (config->rts) {
1582 data->dcb.fRtsControl = RTS_CONTROL_DISABLE;
1585 data->dcb.fRtsControl = RTS_CONTROL_ENABLE;
1587 case SP_RTS_FLOW_CONTROL:
1588 data->dcb.fRtsControl = RTS_CONTROL_HANDSHAKE;
1591 RETURN_ERROR(SP_ERR_ARG, "Invalid RTS setting");
1595 if (config->cts >= 0) {
1596 switch (config->cts) {
1598 data->dcb.fOutxCtsFlow = FALSE;
1600 case SP_CTS_FLOW_CONTROL:
1601 data->dcb.fOutxCtsFlow = TRUE;
1604 RETURN_ERROR(SP_ERR_ARG, "Invalid CTS setting");
1608 if (config->dtr >= 0) {
1609 switch (config->dtr) {
1611 data->dcb.fDtrControl = DTR_CONTROL_DISABLE;
1614 data->dcb.fDtrControl = DTR_CONTROL_ENABLE;
1616 case SP_DTR_FLOW_CONTROL:
1617 data->dcb.fDtrControl = DTR_CONTROL_HANDSHAKE;
1620 RETURN_ERROR(SP_ERR_ARG, "Invalid DTR setting");
1624 if (config->dsr >= 0) {
1625 switch (config->dsr) {
1627 data->dcb.fOutxDsrFlow = FALSE;
1629 case SP_DSR_FLOW_CONTROL:
1630 data->dcb.fOutxDsrFlow = TRUE;
1633 RETURN_ERROR(SP_ERR_ARG, "Invalid DSR setting");
1637 if (config->xon_xoff >= 0) {
1638 switch (config->xon_xoff) {
1639 case SP_XONXOFF_DISABLED:
1640 data->dcb.fInX = FALSE;
1641 data->dcb.fOutX = FALSE;
1644 data->dcb.fInX = TRUE;
1645 data->dcb.fOutX = FALSE;
1647 case SP_XONXOFF_OUT:
1648 data->dcb.fInX = FALSE;
1649 data->dcb.fOutX = TRUE;
1651 case SP_XONXOFF_INOUT:
1652 data->dcb.fInX = TRUE;
1653 data->dcb.fOutX = TRUE;
1656 RETURN_ERROR(SP_ERR_ARG, "Invalid XON/XOFF setting");
1660 if (!SetCommState(port->hdl, &data->dcb))
1661 RETURN_FAIL("SetCommState() failed");
1667 if (config->baudrate >= 0) {
1668 for (i = 0; i < NUM_STD_BAUDRATES; i++) {
1669 if (config->baudrate == std_baudrates[i].value) {
1670 if (cfsetospeed(&data->term, std_baudrates[i].index) < 0)
1671 RETURN_FAIL("cfsetospeed() failed");
1673 if (cfsetispeed(&data->term, std_baudrates[i].index) < 0)
1674 RETURN_FAIL("cfsetispeed() failed");
1679 /* Non-standard baud rate */
1680 if (i == NUM_STD_BAUDRATES) {
1682 /* Set "dummy" baud rate. */
1683 if (cfsetspeed(&data->term, B9600) < 0)
1684 RETURN_FAIL("cfsetspeed() failed");
1685 baud_nonstd = config->baudrate;
1686 #elif defined(__linux__)
1689 RETURN_ERROR(SP_ERR_SUPP, "Non-standard baudrate not supported");
1694 if (config->bits >= 0) {
1695 data->term.c_cflag &= ~CSIZE;
1696 switch (config->bits) {
1698 data->term.c_cflag |= CS8;
1701 data->term.c_cflag |= CS7;
1704 data->term.c_cflag |= CS6;
1707 data->term.c_cflag |= CS5;
1710 RETURN_ERROR(SP_ERR_ARG, "Invalid data bits setting");
1714 if (config->parity >= 0) {
1715 data->term.c_iflag &= ~IGNPAR;
1716 data->term.c_cflag &= ~(PARENB | PARODD);
1718 data->term.c_cflag &= ~CMSPAR;
1720 switch (config->parity) {
1721 case SP_PARITY_NONE:
1722 data->term.c_iflag |= IGNPAR;
1724 case SP_PARITY_EVEN:
1725 data->term.c_cflag |= PARENB;
1728 data->term.c_cflag |= PARENB | PARODD;
1731 case SP_PARITY_MARK:
1732 data->term.c_cflag |= PARENB | PARODD;
1733 data->term.c_cflag |= CMSPAR;
1735 case SP_PARITY_SPACE:
1736 data->term.c_cflag |= PARENB;
1737 data->term.c_cflag |= CMSPAR;
1740 case SP_PARITY_MARK:
1741 case SP_PARITY_SPACE:
1742 RETURN_ERROR(SP_ERR_SUPP, "Mark/space parity not supported");
1745 RETURN_ERROR(SP_ERR_ARG, "Invalid parity setting");
1749 if (config->stopbits >= 0) {
1750 data->term.c_cflag &= ~CSTOPB;
1751 switch (config->stopbits) {
1753 data->term.c_cflag &= ~CSTOPB;
1756 data->term.c_cflag |= CSTOPB;
1759 RETURN_ERROR(SP_ERR_ARG, "Invalid stop bits setting");
1763 if (config->rts >= 0 || config->cts >= 0) {
1764 if (data->termiox_supported) {
1765 data->flow &= ~(RTS_FLOW | CTS_FLOW);
1766 switch (config->rts) {
1769 controlbits = TIOCM_RTS;
1770 if (ioctl(port->fd, config->rts == SP_RTS_ON ? TIOCMBIS : TIOCMBIC, &controlbits) < 0)
1771 RETURN_FAIL("Setting RTS signal level failed");
1773 case SP_RTS_FLOW_CONTROL:
1774 data->flow |= RTS_FLOW;
1779 if (config->cts == SP_CTS_FLOW_CONTROL)
1780 data->flow |= CTS_FLOW;
1782 if (data->flow & (RTS_FLOW | CTS_FLOW))
1783 data->term.c_iflag |= CRTSCTS;
1785 data->term.c_iflag &= ~CRTSCTS;
1787 /* Asymmetric use of RTS/CTS not supported. */
1788 if (data->term.c_iflag & CRTSCTS) {
1789 /* Flow control can only be disabled for both RTS & CTS together. */
1790 if (config->rts >= 0 && config->rts != SP_RTS_FLOW_CONTROL) {
1791 if (config->cts != SP_CTS_IGNORE)
1792 RETURN_ERROR(SP_ERR_SUPP, "RTS & CTS flow control must be disabled together");
1794 if (config->cts >= 0 && config->cts != SP_CTS_FLOW_CONTROL) {
1795 if (config->rts <= 0 || config->rts == SP_RTS_FLOW_CONTROL)
1796 RETURN_ERROR(SP_ERR_SUPP, "RTS & CTS flow control must be disabled together");
1799 /* Flow control can only be enabled for both RTS & CTS together. */
1800 if (((config->rts == SP_RTS_FLOW_CONTROL) && (config->cts != SP_CTS_FLOW_CONTROL)) ||
1801 ((config->cts == SP_CTS_FLOW_CONTROL) && (config->rts != SP_RTS_FLOW_CONTROL)))
1802 RETURN_ERROR(SP_ERR_SUPP, "RTS & CTS flow control must be enabled together");
1805 if (config->rts >= 0) {
1806 if (config->rts == SP_RTS_FLOW_CONTROL) {
1807 data->term.c_iflag |= CRTSCTS;
1809 controlbits = TIOCM_RTS;
1810 if (ioctl(port->fd, config->rts == SP_RTS_ON ? TIOCMBIS : TIOCMBIC,
1812 RETURN_FAIL("Setting RTS signal level failed");
1818 if (config->dtr >= 0 || config->dsr >= 0) {
1819 if (data->termiox_supported) {
1820 data->flow &= ~(DTR_FLOW | DSR_FLOW);
1821 switch (config->dtr) {
1824 controlbits = TIOCM_DTR;
1825 if (ioctl(port->fd, config->dtr == SP_DTR_ON ? TIOCMBIS : TIOCMBIC, &controlbits) < 0)
1826 RETURN_FAIL("Setting DTR signal level failed");
1828 case SP_DTR_FLOW_CONTROL:
1829 data->flow |= DTR_FLOW;
1834 if (config->dsr == SP_DSR_FLOW_CONTROL)
1835 data->flow |= DSR_FLOW;
1837 /* DTR/DSR flow control not supported. */
1838 if (config->dtr == SP_DTR_FLOW_CONTROL || config->dsr == SP_DSR_FLOW_CONTROL)
1839 RETURN_ERROR(SP_ERR_SUPP, "DTR/DSR flow control not supported");
1841 if (config->dtr >= 0) {
1842 controlbits = TIOCM_DTR;
1843 if (ioctl(port->fd, config->dtr == SP_DTR_ON ? TIOCMBIS : TIOCMBIC,
1845 RETURN_FAIL("Setting DTR signal level failed");
1850 if (config->xon_xoff >= 0) {
1851 data->term.c_iflag &= ~(IXON | IXOFF | IXANY);
1852 switch (config->xon_xoff) {
1853 case SP_XONXOFF_DISABLED:
1856 data->term.c_iflag |= IXOFF;
1858 case SP_XONXOFF_OUT:
1859 data->term.c_iflag |= IXON | IXANY;
1861 case SP_XONXOFF_INOUT:
1862 data->term.c_iflag |= IXON | IXOFF | IXANY;
1865 RETURN_ERROR(SP_ERR_ARG, "Invalid XON/XOFF setting");
1869 if (tcsetattr(port->fd, TCSANOW, &data->term) < 0)
1870 RETURN_FAIL("tcsetattr() failed");
1873 if (baud_nonstd != B0) {
1874 if (ioctl(port->fd, IOSSIOSPEED, &baud_nonstd) == -1)
1875 RETURN_FAIL("IOSSIOSPEED ioctl failed");
1876 /* Set baud rates in data->term to correct, but incompatible
1877 * with tcsetattr() value, same as delivered by tcgetattr(). */
1878 if (cfsetspeed(&data->term, baud_nonstd) < 0)
1879 RETURN_FAIL("cfsetspeed() failed");
1881 #elif defined(__linux__)
1883 TRY(set_baudrate(port->fd, config->baudrate));
1885 if (data->termiox_supported)
1886 TRY(set_flow(port->fd, data->flow));
1890 #endif /* !_WIN32 */
1895 enum sp_return sp_new_config(struct sp_port_config **config_ptr)
1897 struct sp_port_config *config;
1899 TRACE("%p", config_ptr);
1902 RETURN_ERROR(SP_ERR_ARG, "Null result pointer");
1906 if (!(config = malloc(sizeof(struct sp_port_config))))
1907 RETURN_ERROR(SP_ERR_MEM, "config malloc failed");
1909 config->baudrate = -1;
1911 config->parity = -1;
1912 config->stopbits = -1;
1918 *config_ptr = config;
1923 void sp_free_config(struct sp_port_config *config)
1925 TRACE("%p", config);
1928 DEBUG("Null config");
1935 enum sp_return sp_get_config(struct sp_port *port, struct sp_port_config *config)
1937 struct port_data data;
1939 TRACE("%p, %p", port, config);
1944 RETURN_ERROR(SP_ERR_ARG, "Null config");
1946 TRY(get_config(port, &data, config));
1951 enum sp_return sp_set_config(struct sp_port *port, const struct sp_port_config *config)
1953 struct port_data data;
1954 struct sp_port_config prev_config;
1956 TRACE("%p, %p", port, config);
1961 RETURN_ERROR(SP_ERR_ARG, "Null config");
1963 TRY(get_config(port, &data, &prev_config));
1964 TRY(set_config(port, &data, config));
1969 #define CREATE_ACCESSORS(x, type) \
1970 enum sp_return sp_set_##x(struct sp_port *port, type x) { \
1971 struct port_data data; \
1972 struct sp_port_config config; \
1973 TRACE("%p, %d", port, x); \
1974 CHECK_OPEN_PORT(); \
1975 TRY(get_config(port, &data, &config)); \
1977 TRY(set_config(port, &data, &config)); \
1980 enum sp_return sp_get_config_##x(const struct sp_port_config *config, type *x) { \
1981 TRACE("%p, %p", config, x); \
1983 RETURN_ERROR(SP_ERR_ARG, "Null config"); \
1987 enum sp_return sp_set_config_##x(struct sp_port_config *config, type x) { \
1988 TRACE("%p, %d", config, x); \
1990 RETURN_ERROR(SP_ERR_ARG, "Null config"); \
1995 CREATE_ACCESSORS(baudrate, int)
1996 CREATE_ACCESSORS(bits, int)
1997 CREATE_ACCESSORS(parity, enum sp_parity)
1998 CREATE_ACCESSORS(stopbits, int)
1999 CREATE_ACCESSORS(rts, enum sp_rts)
2000 CREATE_ACCESSORS(cts, enum sp_cts)
2001 CREATE_ACCESSORS(dtr, enum sp_dtr)
2002 CREATE_ACCESSORS(dsr, enum sp_dsr)
2003 CREATE_ACCESSORS(xon_xoff, enum sp_xonxoff)
2005 enum sp_return sp_set_config_flowcontrol(struct sp_port_config *config, enum sp_flowcontrol flowcontrol)
2008 RETURN_ERROR(SP_ERR_ARG, "Null configuration");
2010 if (flowcontrol > SP_FLOWCONTROL_DTRDSR)
2011 RETURN_ERROR(SP_ERR_ARG, "Invalid flow control setting");
2013 if (flowcontrol == SP_FLOWCONTROL_XONXOFF)
2014 config->xon_xoff = SP_XONXOFF_INOUT;
2016 config->xon_xoff = SP_XONXOFF_DISABLED;
2018 if (flowcontrol == SP_FLOWCONTROL_RTSCTS) {
2019 config->rts = SP_RTS_FLOW_CONTROL;
2020 config->cts = SP_CTS_FLOW_CONTROL;
2022 if (config->rts == SP_RTS_FLOW_CONTROL)
2023 config->rts = SP_RTS_ON;
2024 config->cts = SP_CTS_IGNORE;
2027 if (flowcontrol == SP_FLOWCONTROL_DTRDSR) {
2028 config->dtr = SP_DTR_FLOW_CONTROL;
2029 config->dsr = SP_DSR_FLOW_CONTROL;
2031 if (config->dtr == SP_DTR_FLOW_CONTROL)
2032 config->dtr = SP_DTR_ON;
2033 config->dsr = SP_DSR_IGNORE;
2039 enum sp_return sp_set_flowcontrol(struct sp_port *port, enum sp_flowcontrol flowcontrol)
2041 struct port_data data;
2042 struct sp_port_config config;
2044 TRACE("%p, %d", port, flowcontrol);
2048 TRY(get_config(port, &data, &config));
2050 TRY(sp_set_config_flowcontrol(&config, flowcontrol));
2052 TRY(set_config(port, &data, &config));
2057 enum sp_return sp_get_signals(struct sp_port *port, enum sp_signal *signals)
2059 TRACE("%p, %p", port, signals);
2064 RETURN_ERROR(SP_ERR_ARG, "Null result pointer");
2066 DEBUG("Getting control signals for port %s", port->name);
2071 if (GetCommModemStatus(port->hdl, &bits) == 0)
2072 RETURN_FAIL("GetCommModemStatus() failed");
2073 if (bits & MS_CTS_ON)
2074 *signals |= SP_SIG_CTS;
2075 if (bits & MS_DSR_ON)
2076 *signals |= SP_SIG_DSR;
2077 if (bits & MS_RLSD_ON)
2078 *signals |= SP_SIG_DCD;
2079 if (bits & MS_RING_ON)
2080 *signals |= SP_SIG_RI;
2083 if (ioctl(port->fd, TIOCMGET, &bits) < 0)
2084 RETURN_FAIL("TIOCMGET ioctl failed");
2085 if (bits & TIOCM_CTS)
2086 *signals |= SP_SIG_CTS;
2087 if (bits & TIOCM_DSR)
2088 *signals |= SP_SIG_DSR;
2089 if (bits & TIOCM_CAR)
2090 *signals |= SP_SIG_DCD;
2091 if (bits & TIOCM_RNG)
2092 *signals |= SP_SIG_RI;
2097 enum sp_return sp_start_break(struct sp_port *port)
2103 if (SetCommBreak(port->hdl) == 0)
2104 RETURN_FAIL("SetCommBreak() failed");
2106 if (ioctl(port->fd, TIOCSBRK, 1) < 0)
2107 RETURN_FAIL("TIOCSBRK ioctl failed");
2113 enum sp_return sp_end_break(struct sp_port *port)
2119 if (ClearCommBreak(port->hdl) == 0)
2120 RETURN_FAIL("ClearCommBreak() failed");
2122 if (ioctl(port->fd, TIOCCBRK, 1) < 0)
2123 RETURN_FAIL("TIOCCBRK ioctl failed");
2129 int sp_last_error_code(void)
2133 RETURN_VALUE("%d", GetLastError());
2135 RETURN_VALUE("%d", errno);
2139 char *sp_last_error_message(void)
2145 DWORD error = GetLastError();
2148 FORMAT_MESSAGE_ALLOCATE_BUFFER |
2149 FORMAT_MESSAGE_FROM_SYSTEM |
2150 FORMAT_MESSAGE_IGNORE_INSERTS,
2153 MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
2157 RETURN_VALUE("%s", message);
2159 RETURN_VALUE("%s", strerror(errno));
2163 void sp_free_error_message(char *message)
2165 TRACE("%s", message);
2176 void sp_set_debug_handler(void (*handler)(const char *format, ...))
2178 TRACE("%p", handler);
2180 sp_debug_handler = handler;
2185 void sp_default_debug_handler(const char *format, ...)
2188 va_start(args, format);
2189 if (getenv("LIBSERIALPORT_DEBUG")) {
2190 fputs("sp: ", stderr);
2191 vfprintf(stderr, format, args);