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>
53 #include "linux/serial.h"
54 #include "linux_termios.h"
56 /* TCGETX/TCSETX is not available everywhere. */
57 #if defined(TCGETX) && defined(TCSETX) && defined(HAVE_TERMIOX)
62 /* TIOCINQ/TIOCOUTQ is not available everywhere. */
63 #if !defined(TIOCINQ) && defined(FIONREAD)
64 #define TIOCINQ FIONREAD
66 #if !defined(TIOCOUTQ) && defined(FIONWRITE)
67 #define TIOCOUTQ FIONWRITE
71 #include "linux_termios.h"
74 #include "libserialport.h"
80 COMMTIMEOUTS timeouts;
90 struct sp_port_config {
93 enum sp_parity parity;
99 enum sp_xonxoff xon_xoff;
108 int termiox_supported;
113 /* Standard baud rates. */
115 #define BAUD_TYPE DWORD
116 #define BAUD(n) {CBR_##n, n}
118 #define BAUD_TYPE speed_t
119 #define BAUD(n) {B##n, n}
122 struct std_baudrate {
127 const struct std_baudrate std_baudrates[] = {
130 * The baudrates 50/75/134/150/200/1800/230400/460800 do not seem to
131 * have documented CBR_* macros.
133 BAUD(110), BAUD(300), BAUD(600), BAUD(1200), BAUD(2400), BAUD(4800),
134 BAUD(9600), BAUD(14400), BAUD(19200), BAUD(38400), BAUD(57600),
135 BAUD(115200), BAUD(128000), BAUD(256000),
137 BAUD(50), BAUD(75), BAUD(110), BAUD(134), BAUD(150), BAUD(200),
138 BAUD(300), BAUD(600), BAUD(1200), BAUD(1800), BAUD(2400), BAUD(4800),
139 BAUD(9600), BAUD(19200), BAUD(38400), BAUD(57600), BAUD(115200),
141 #if !defined(__APPLE__) && !defined(__OpenBSD__)
147 void (*sp_debug_handler)(const char *format, ...) = sp_default_debug_handler;
149 #define ARRAY_SIZE(x) (sizeof(x) / sizeof(x[0]))
150 #define NUM_STD_BAUDRATES ARRAY_SIZE(std_baudrates)
152 /* Debug output macros. */
153 #define DEBUG(fmt, ...) do { if (sp_debug_handler) sp_debug_handler(fmt ".\n", ##__VA_ARGS__); } while (0)
154 #define DEBUG_ERROR(err, msg) DEBUG("%s returning " #err ": " msg, __func__)
155 #define DEBUG_FAIL(msg) do { \
156 char *errmsg = sp_last_error_message(); \
157 DEBUG("%s returning SP_ERR_FAIL: " msg ": %s", __func__, errmsg); \
158 sp_free_error_message(errmsg); \
160 #define RETURN() do { DEBUG("%s returning", __func__); return; } while(0)
161 #define RETURN_CODE(x) do { DEBUG("%s returning " #x, __func__); return x; } while (0)
162 #define RETURN_CODEVAL(x) do { \
164 case SP_OK: RETURN_CODE(SP_OK); \
165 case SP_ERR_ARG: RETURN_CODE(SP_ERR_ARG); \
166 case SP_ERR_FAIL: RETURN_CODE(SP_ERR_FAIL); \
167 case SP_ERR_MEM: RETURN_CODE(SP_ERR_MEM); \
168 case SP_ERR_SUPP: RETURN_CODE(SP_ERR_SUPP); \
171 #define RETURN_OK() RETURN_CODE(SP_OK);
172 #define RETURN_ERROR(err, msg) do { DEBUG_ERROR(err, msg); return err; } while (0)
173 #define RETURN_FAIL(msg) do { DEBUG_FAIL(msg); return SP_ERR_FAIL; } while (0)
174 #define RETURN_VALUE(fmt, x) do { DEBUG("%s returning " fmt, __func__, x); return x; } while (0)
175 #define SET_ERROR(val, err, msg) do { DEBUG_ERROR(err, msg); val = err; } while (0)
176 #define SET_FAIL(val, msg) do { DEBUG_FAIL(msg); val = SP_ERR_FAIL; } while (0)
177 #define TRACE(fmt, ...) DEBUG("%s(" fmt ") called", __func__, ##__VA_ARGS__)
179 #define TRY(x) do { int ret = x; if (ret != SP_OK) RETURN_CODEVAL(ret); } while (0)
181 /* Helper functions. */
182 static struct sp_port **list_append(struct sp_port **list, const char *portname);
183 static enum sp_return get_config(struct sp_port *port, struct port_data *data,
184 struct sp_port_config *config);
185 static enum sp_return set_config(struct sp_port *port, struct port_data *data,
186 const struct sp_port_config *config);
188 enum sp_return sp_get_port_by_name(const char *portname, struct sp_port **port_ptr)
190 struct sp_port *port;
193 TRACE("%s, %p", portname, port_ptr);
196 RETURN_ERROR(SP_ERR_ARG, "Null result pointer");
201 RETURN_ERROR(SP_ERR_ARG, "Null port name");
203 DEBUG("Building structure for port %s", portname);
205 if (!(port = malloc(sizeof(struct sp_port))))
206 RETURN_ERROR(SP_ERR_MEM, "Port structure malloc failed");
208 len = strlen(portname) + 1;
210 if (!(port->name = malloc(len))) {
212 RETURN_ERROR(SP_ERR_MEM, "Port name malloc failed");
215 memcpy(port->name, portname, len);
218 port->hdl = INVALID_HANDLE_VALUE;
228 char *sp_get_port_name(const struct sp_port *port)
235 RETURN_VALUE("%s", port->name);
238 enum sp_return sp_get_port_handle(const struct sp_port *port, void *result_ptr)
240 TRACE("%p, %p", port, result_ptr);
243 RETURN_ERROR(SP_ERR_ARG, "Null port");
246 HANDLE *handle_ptr = result_ptr;
247 *handle_ptr = port->hdl;
249 int *fd_ptr = result_ptr;
256 enum sp_return sp_copy_port(const struct sp_port *port, struct sp_port **copy_ptr)
258 TRACE("%p, %p", port, copy_ptr);
261 RETURN_ERROR(SP_ERR_ARG, "Null result pointer");
266 RETURN_ERROR(SP_ERR_ARG, "Null port");
269 RETURN_ERROR(SP_ERR_ARG, "Null port name");
271 DEBUG("Copying port structure");
273 RETURN_VALUE("%p", sp_get_port_by_name(port->name, copy_ptr));
276 void sp_free_port(struct sp_port *port)
285 DEBUG("Freeing port structure");
295 static struct sp_port **list_append(struct sp_port **list, const char *portname)
300 for (count = 0; list[count]; count++);
301 if (!(tmp = realloc(list, sizeof(struct sp_port *) * (count + 2))))
304 if (sp_get_port_by_name(portname, &list[count]) != SP_OK)
306 list[count + 1] = NULL;
310 sp_free_port_list(list);
314 enum sp_return sp_list_ports(struct sp_port ***list_ptr)
316 struct sp_port **list;
317 int ret = SP_ERR_SUPP;
319 TRACE("%p", list_ptr);
322 RETURN_ERROR(SP_ERR_ARG, "Null result pointer");
324 DEBUG("Enumerating ports");
326 if (!(list = malloc(sizeof(struct sp_port **))))
327 RETURN_ERROR(SP_ERR_MEM, "Port list malloc failed");
334 DWORD max_value_len, max_data_size, max_data_len;
335 DWORD value_len, data_size, data_len;
336 DWORD type, index = 0;
342 DEBUG("Opening registry key");
343 if (RegOpenKeyEx(HKEY_LOCAL_MACHINE, _T("HARDWARE\\DEVICEMAP\\SERIALCOMM"),
344 0, KEY_QUERY_VALUE, &key) != ERROR_SUCCESS) {
345 SET_FAIL(ret, "RegOpenKeyEx() failed");
348 DEBUG("Querying registry key value and data sizes");
349 if (RegQueryInfoKey(key, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
350 &max_value_len, &max_data_size, NULL, NULL) != ERROR_SUCCESS) {
351 SET_FAIL(ret, "RegQueryInfoKey() failed");
354 max_data_len = max_data_size / sizeof(TCHAR);
355 if (!(value = malloc((max_value_len + 1) * sizeof(TCHAR)))) {
356 SET_ERROR(ret, SP_ERR_MEM, "registry value malloc failed");
359 if (!(data = malloc((max_data_len + 1) * sizeof(TCHAR)))) {
360 SET_ERROR(ret, SP_ERR_MEM, "registry data malloc failed");
363 DEBUG("Iterating over values");
365 value_len = max_value_len + 1,
366 data_size = max_data_size,
367 RegEnumValue(key, index, value, &value_len,
368 NULL, &type, (LPBYTE)data, &data_size) == ERROR_SUCCESS)
370 data_len = data_size / sizeof(TCHAR);
371 data[data_len] = '\0';
373 name_len = WideCharToMultiByte(CP_ACP, 0, data, -1, NULL, 0, NULL, NULL)
375 name_len = data_len + 1;
377 if (!(name = malloc(name_len))) {
378 SET_ERROR(ret, SP_ERR_MEM, "registry port name malloc failed");
382 WideCharToMultiByte(CP_ACP, 0, data, -1, name, name_len, NULL, NULL);
386 if (type == REG_SZ) {
387 DEBUG("Found port %s", name);
388 if (!(list = list_append(list, name))) {
389 SET_ERROR(ret, SP_ERR_MEM, "list append failed");
405 CFMutableDictionaryRef classes;
414 DEBUG("Getting IOKit master port");
415 if (IOMasterPort(MACH_PORT_NULL, &master) != KERN_SUCCESS) {
416 SET_FAIL(ret, "IOMasterPort() failed");
420 DEBUG("Creating matching dictionary");
421 if (!(classes = IOServiceMatching(kIOSerialBSDServiceValue))) {
422 SET_FAIL(ret, "IOServiceMatching() failed");
426 CFDictionarySetValue(classes,
427 CFSTR(kIOSerialBSDTypeKey), CFSTR(kIOSerialBSDAllTypes));
429 DEBUG("Getting matching services");
430 if (IOServiceGetMatchingServices(master, classes, &iter) != KERN_SUCCESS) {
431 SET_FAIL(ret, "IOServiceGetMatchingServices() failed");
435 if (!(path = malloc(PATH_MAX))) {
436 SET_ERROR(ret, SP_ERR_MEM, "device path malloc failed");
440 DEBUG("Iterating over results");
441 while ((port = IOIteratorNext(iter))) {
442 cf_path = IORegistryEntryCreateCFProperty(port,
443 CFSTR(kIOCalloutDeviceKey), kCFAllocatorDefault, 0);
445 result = CFStringGetCString(cf_path,
446 path, PATH_MAX, kCFStringEncodingASCII);
449 DEBUG("Found port %s", path);
450 if (!(list = list_append(list, path))) {
451 SET_ERROR(ret, SP_ERR_MEM, "list append failed");
452 IOObjectRelease(port);
457 IOObjectRelease(port);
462 IOObjectRelease(iter);
465 #if defined(__linux__) && defined(HAVE_LIBUDEV)
467 struct udev_enumerate *ud_enumerate;
468 struct udev_list_entry *ud_list;
469 struct udev_list_entry *ud_entry;
471 struct udev_device *ud_dev, *ud_parent;
474 int fd, ioctl_result;
475 struct serial_struct serial_info;
479 DEBUG("Enumerating tty devices");
481 ud_enumerate = udev_enumerate_new(ud);
482 udev_enumerate_add_match_subsystem(ud_enumerate, "tty");
483 udev_enumerate_scan_devices(ud_enumerate);
484 ud_list = udev_enumerate_get_list_entry(ud_enumerate);
485 DEBUG("Iterating over results");
486 udev_list_entry_foreach(ud_entry, ud_list) {
487 path = udev_list_entry_get_name(ud_entry);
488 DEBUG("Found device %s", path);
489 ud_dev = udev_device_new_from_syspath(ud, path);
490 /* If there is no parent device, this is a virtual tty. */
491 ud_parent = udev_device_get_parent(ud_dev);
492 if (ud_parent == NULL) {
493 DEBUG("No parent device, assuming virtual tty");
494 udev_device_unref(ud_dev);
497 name = udev_device_get_devnode(ud_dev);
498 /* The serial8250 driver has a hardcoded number of ports.
499 * The only way to tell which actually exist on a given system
500 * is to try to open them and make an ioctl call. */
501 driver = udev_device_get_driver(ud_parent);
502 if (driver && !strcmp(driver, "serial8250")) {
503 DEBUG("serial8250 device, attempting to open");
504 if ((fd = open(name, O_RDWR | O_NONBLOCK | O_NOCTTY)) < 0) {
505 DEBUG("open failed, skipping");
508 ioctl_result = ioctl(fd, TIOCGSERIAL, &serial_info);
510 if (ioctl_result != 0) {
511 DEBUG("ioctl failed, skipping");
514 if (serial_info.type == PORT_UNKNOWN) {
515 DEBUG("port type is unknown, skipping");
519 DEBUG("Found port %s", name);
520 list = list_append(list, name);
522 udev_device_unref(ud_dev);
524 SET_ERROR(ret, SP_ERR_MEM, "list append failed");
529 udev_enumerate_unref(ud_enumerate);
538 DEBUG_ERROR(SP_ERR_SUPP, "Enumeration not supported on this platform.");
541 sp_free_port_list(list);
547 void sp_free_port_list(struct sp_port **list)
558 DEBUG("Freeing port list");
560 for (i = 0; list[i]; i++)
561 sp_free_port(list[i]);
567 #define CHECK_PORT() do { \
569 RETURN_ERROR(SP_ERR_ARG, "Null port"); \
570 if (port->name == NULL) \
571 RETURN_ERROR(SP_ERR_ARG, "Null port name"); \
574 #define CHECK_PORT_HANDLE() do { \
575 if (port->hdl == INVALID_HANDLE_VALUE) \
576 RETURN_ERROR(SP_ERR_ARG, "Invalid port handle"); \
579 #define CHECK_PORT_HANDLE() do { \
581 RETURN_ERROR(SP_ERR_ARG, "Invalid port fd"); \
584 #define CHECK_OPEN_PORT() do { \
586 CHECK_PORT_HANDLE(); \
589 enum sp_return sp_open(struct sp_port *port, enum sp_mode flags)
591 struct port_data data;
592 struct sp_port_config config;
595 TRACE("%p, 0x%x", port, flags);
599 if (flags > (SP_MODE_READ | SP_MODE_WRITE))
600 RETURN_ERROR(SP_ERR_ARG, "Invalid flags");
602 DEBUG("Opening port %s", port->name);
605 DWORD desired_access = 0, flags_and_attributes = 0;
606 char *escaped_port_name;
608 /* Prefix port name with '\\.\' to work with ports above COM9. */
609 if (!(escaped_port_name = malloc(strlen(port->name + 5))))
610 RETURN_ERROR(SP_ERR_MEM, "Escaped port name malloc failed");
611 sprintf(escaped_port_name, "\\\\.\\%s", port->name);
613 /* Map 'flags' to the OS-specific settings. */
614 flags_and_attributes = FILE_ATTRIBUTE_NORMAL | FILE_FLAG_OVERLAPPED;
615 if (flags & SP_MODE_READ)
616 desired_access |= GENERIC_READ;
617 if (flags & SP_MODE_WRITE)
618 desired_access |= GENERIC_WRITE;
620 port->hdl = CreateFile(escaped_port_name, desired_access, 0, 0,
621 OPEN_EXISTING, flags_and_attributes, 0);
623 free(escaped_port_name);
625 if (port->hdl == INVALID_HANDLE_VALUE)
626 RETURN_FAIL("port CreateFile() failed");
628 /* All timeouts initially disabled. */
629 port->timeouts.ReadIntervalTimeout = 0;
630 port->timeouts.ReadTotalTimeoutMultiplier = 0;
631 port->timeouts.ReadTotalTimeoutConstant = 0;
632 port->timeouts.WriteTotalTimeoutMultiplier = 0;
633 port->timeouts.WriteTotalTimeoutConstant = 0;
635 if (SetCommTimeouts(port->hdl, &port->timeouts) == 0) {
637 RETURN_FAIL("SetCommTimeouts() failed");
640 /* Prepare OVERLAPPED structures. */
641 memset(&port->read_ovl, 0, sizeof(port->read_ovl));
642 memset(&port->write_ovl, 0, sizeof(port->write_ovl));
643 port->read_ovl.hEvent = INVALID_HANDLE_VALUE;
644 port->write_ovl.hEvent = INVALID_HANDLE_VALUE;
645 if ((port->read_ovl.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL)) == INVALID_HANDLE_VALUE) {
647 RETURN_FAIL("read event CreateEvent() failed");
649 if ((port->write_ovl.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL)) == INVALID_HANDLE_VALUE) {
651 RETURN_FAIL("write event CreateEvent() failed");
654 port->writing = FALSE;
657 int flags_local = O_NONBLOCK | O_NOCTTY;
659 /* Map 'flags' to the OS-specific settings. */
660 if (flags & (SP_MODE_READ | SP_MODE_WRITE))
661 flags_local |= O_RDWR;
662 else if (flags & SP_MODE_READ)
663 flags_local |= O_RDONLY;
664 else if (flags & SP_MODE_WRITE)
665 flags_local |= O_WRONLY;
667 if ((port->fd = open(port->name, flags_local)) < 0)
668 RETURN_FAIL("open() failed");
671 ret = get_config(port, &data, &config);
678 /* Set sane port settings. */
680 data.dcb.fBinary = TRUE;
681 data.dcb.fDsrSensitivity = FALSE;
682 data.dcb.fErrorChar = FALSE;
683 data.dcb.fNull = FALSE;
684 data.dcb.fAbortOnError = TRUE;
686 /* Turn off all fancy termios tricks, give us a raw channel. */
687 data.term.c_iflag &= ~(IGNBRK | BRKINT | PARMRK | ISTRIP | INLCR | IGNCR | ICRNL | IMAXBEL);
689 data.term.c_iflag &= ~IUCLC;
691 data.term.c_oflag &= ~(OPOST | ONLCR | OCRNL | ONOCR | ONLRET);
693 data.term.c_oflag &= ~OLCUC;
696 data.term.c_oflag &= ~NLDLY;
699 data.term.c_oflag &= ~CRDLY;
702 data.term.c_oflag &= ~TABDLY;
705 data.term.c_oflag &= ~BSDLY;
708 data.term.c_oflag &= ~VTDLY;
711 data.term.c_oflag &= ~FFDLY;
714 data.term.c_oflag &= ~OFILL;
716 data.term.c_lflag &= ~(ISIG | ICANON | ECHO | IEXTEN);
717 data.term.c_cc[VMIN] = 0;
718 data.term.c_cc[VTIME] = 0;
720 /* Ignore modem status lines; enable receiver; leave control lines alone on close. */
721 data.term.c_cflag |= (CLOCAL | CREAD | HUPCL);
724 ret = set_config(port, &data, &config);
734 enum sp_return sp_close(struct sp_port *port)
740 DEBUG("Closing port %s", port->name);
743 /* Returns non-zero upon success, 0 upon failure. */
744 if (CloseHandle(port->hdl) == 0)
745 RETURN_FAIL("port CloseHandle() failed");
746 port->hdl = INVALID_HANDLE_VALUE;
747 /* Close event handle created for overlapped reads. */
748 if (port->read_ovl.hEvent != INVALID_HANDLE_VALUE && CloseHandle(port->read_ovl.hEvent) == 0)
749 RETURN_FAIL("read event CloseHandle() failed");
750 /* Close event handle created for overlapped writes. */
751 if (port->write_ovl.hEvent != INVALID_HANDLE_VALUE && CloseHandle(port->write_ovl.hEvent) == 0)
752 RETURN_FAIL("write event CloseHandle() failed");
754 /* Returns 0 upon success, -1 upon failure. */
755 if (close(port->fd) == -1)
756 RETURN_FAIL("close() failed");
763 enum sp_return sp_flush(struct sp_port *port, enum sp_buffer buffers)
765 TRACE("%p, 0x%x", port, buffers);
769 if (buffers > SP_BUF_BOTH)
770 RETURN_ERROR(SP_ERR_ARG, "Invalid buffer selection");
772 const char *buffer_names[] = {"no", "input", "output", "both"};
774 DEBUG("Flushing %s buffers on port %s", buffer_names[buffers], port->name);
778 if (buffers & SP_BUF_INPUT)
779 flags |= PURGE_RXCLEAR;
780 if (buffers & SP_BUF_OUTPUT)
781 flags |= PURGE_TXCLEAR;
783 /* Returns non-zero upon success, 0 upon failure. */
784 if (PurgeComm(port->hdl, flags) == 0)
785 RETURN_FAIL("PurgeComm() failed");
788 if (buffers & SP_BUF_BOTH)
790 else if (buffers & SP_BUF_INPUT)
792 else if (buffers & SP_BUF_OUTPUT)
795 /* Returns 0 upon success, -1 upon failure. */
796 if (tcflush(port->fd, flags) < 0)
797 RETURN_FAIL("tcflush() failed");
802 enum sp_return sp_drain(struct sp_port *port)
808 DEBUG("Draining port %s", port->name);
811 /* Returns non-zero upon success, 0 upon failure. */
812 if (FlushFileBuffers(port->hdl) == 0)
813 RETURN_FAIL("FlushFileBuffers() failed");
818 result = tcdrain(port->fd);
820 if (errno == EINTR) {
821 DEBUG("tcdrain() was interrupted");
824 RETURN_FAIL("tcdrain() failed");
833 enum sp_return sp_blocking_write(struct sp_port *port, const void *buf, size_t count, unsigned int timeout)
835 TRACE("%p, %p, %d, %d", port, buf, count, timeout);
840 RETURN_ERROR(SP_ERR_ARG, "Null buffer");
843 DEBUG("Writing %d bytes to port %s, timeout %d ms", count, port->name, timeout);
845 DEBUG("Writing %d bytes to port %s, no timeout", count, port->name);
848 RETURN_VALUE("0", 0);
851 DWORD bytes_written = 0;
854 /* Wait for previous non-blocking write to complete, if any. */
856 DEBUG("Waiting for previous write to complete");
857 result = GetOverlappedResult(port->hdl, &port->write_ovl, &bytes_written, TRUE);
860 RETURN_FAIL("Previous write failed to complete");
861 DEBUG("Previous write completed");
865 port->timeouts.WriteTotalTimeoutConstant = timeout;
866 if (SetCommTimeouts(port->hdl, &port->timeouts) == 0)
867 RETURN_FAIL("SetCommTimeouts() failed");
870 if (WriteFile(port->hdl, buf, count, NULL, &port->write_ovl) == 0) {
871 if (GetLastError() == ERROR_IO_PENDING) {
872 DEBUG("Waiting for write to complete");
873 GetOverlappedResult(port->hdl, &port->write_ovl, &bytes_written, TRUE);
874 DEBUG("Write completed, %d/%d bytes written", bytes_written, count);
875 RETURN_VALUE("%d", bytes_written);
877 RETURN_FAIL("WriteFile() failed");
880 DEBUG("Write completed immediately");
881 RETURN_VALUE("%d", count);
884 size_t bytes_written = 0;
885 unsigned char *ptr = (unsigned char *) buf;
886 struct timeval start, delta, now, end = {0, 0};
891 /* Get time at start of operation. */
892 gettimeofday(&start, NULL);
893 /* Define duration of timeout. */
894 delta.tv_sec = timeout / 1000;
895 delta.tv_usec = (timeout % 1000) * 1000;
896 /* Calculate time at which we should give up. */
897 timeradd(&start, &delta, &end);
900 /* Loop until we have written the requested number of bytes. */
901 while (bytes_written < count)
903 /* Wait until space is available. */
905 FD_SET(port->fd, &fds);
907 gettimeofday(&now, NULL);
908 if (timercmp(&now, &end, >)) {
909 DEBUG("write timed out");
910 RETURN_VALUE("%d", bytes_written);
912 timersub(&end, &now, &delta);
914 result = select(port->fd + 1, NULL, &fds, NULL, timeout ? &delta : NULL);
916 if (errno == EINTR) {
917 DEBUG("select() call was interrupted, repeating");
920 RETURN_FAIL("select() failed");
922 } else if (result == 0) {
923 DEBUG("write timed out");
924 RETURN_VALUE("%d", bytes_written);
928 result = write(port->fd, ptr, count - bytes_written);
932 /* This shouldn't happen because we did a select() first, but handle anyway. */
935 /* This is an actual failure. */
936 RETURN_FAIL("write() failed");
939 bytes_written += result;
943 RETURN_VALUE("%d", bytes_written);
947 enum sp_return sp_nonblocking_write(struct sp_port *port, const void *buf, size_t count)
949 TRACE("%p, %p, %d", port, buf, count);
954 RETURN_ERROR(SP_ERR_ARG, "Null buffer");
956 DEBUG("Writing up to %d bytes to port %s", count, port->name);
959 RETURN_VALUE("0", 0);
963 BYTE *ptr = (BYTE *) buf;
965 /* Check whether previous write is complete. */
967 if (HasOverlappedIoCompleted(&port->write_ovl)) {
968 DEBUG("Previous write completed");
971 DEBUG("Previous write not complete");
972 /* Can't take a new write until the previous one finishes. */
973 RETURN_VALUE("0", 0);
978 port->timeouts.WriteTotalTimeoutConstant = 0;
979 if (SetCommTimeouts(port->hdl, &port->timeouts) == 0)
980 RETURN_FAIL("SetCommTimeouts() failed");
982 /* Keep writing data until the OS has to actually start an async IO for it.
983 * At that point we know the buffer is full. */
984 while (written < count)
986 /* Copy first byte of user buffer. */
987 port->pending_byte = *ptr++;
989 /* Start asynchronous write. */
990 if (WriteFile(port->hdl, &port->pending_byte, 1, NULL, &port->write_ovl) == 0) {
991 if (GetLastError() == ERROR_IO_PENDING) {
992 DEBUG("Asynchronous write started");
994 RETURN_VALUE("%d", ++written);
996 /* Actual failure of some kind. */
997 RETURN_FAIL("WriteFile() failed");
1000 DEBUG("Single byte written immediately.");
1005 DEBUG("All bytes written immediately.");
1007 RETURN_VALUE("%d", written);
1009 /* Returns the number of bytes written, or -1 upon failure. */
1010 ssize_t written = write(port->fd, buf, count);
1013 RETURN_FAIL("write() failed");
1015 RETURN_VALUE("%d", written);
1019 enum sp_return sp_blocking_read(struct sp_port *port, void *buf, size_t count, unsigned int timeout)
1021 TRACE("%p, %p, %d, %d", port, buf, count, timeout);
1026 RETURN_ERROR(SP_ERR_ARG, "Null buffer");
1029 DEBUG("Reading %d bytes from port %s, timeout %d ms", count, port->name, timeout);
1031 DEBUG("Reading %d bytes from port %s, no timeout", count, port->name);
1034 RETURN_VALUE("0", 0);
1037 DWORD bytes_read = 0;
1040 port->timeouts.ReadIntervalTimeout = 0;
1041 port->timeouts.ReadTotalTimeoutConstant = timeout;
1042 if (SetCommTimeouts(port->hdl, &port->timeouts) == 0)
1043 RETURN_FAIL("SetCommTimeouts() failed");
1046 if (ReadFile(port->hdl, buf, count, NULL, &port->read_ovl) == 0) {
1047 if (GetLastError() == ERROR_IO_PENDING) {
1048 DEBUG("Waiting for read to complete");
1049 GetOverlappedResult(port->hdl, &port->read_ovl, &bytes_read, TRUE);
1050 DEBUG("Read completed, %d/%d bytes read", bytes_read, count);
1051 RETURN_VALUE("%d", bytes_read);
1053 RETURN_FAIL("ReadFile() failed");
1056 DEBUG("Read completed immediately");
1057 RETURN_VALUE("%d", count);
1060 size_t bytes_read = 0;
1061 unsigned char *ptr = (unsigned char *) buf;
1062 struct timeval start, delta, now, end = {0, 0};
1067 /* Get time at start of operation. */
1068 gettimeofday(&start, NULL);
1069 /* Define duration of timeout. */
1070 delta.tv_sec = timeout / 1000;
1071 delta.tv_usec = (timeout % 1000) * 1000;
1072 /* Calculate time at which we should give up. */
1073 timeradd(&start, &delta, &end);
1076 /* Loop until we have the requested number of bytes. */
1077 while (bytes_read < count)
1079 /* Wait until data is available. */
1081 FD_SET(port->fd, &fds);
1083 gettimeofday(&now, NULL);
1084 if (timercmp(&now, &end, >))
1085 /* Timeout has expired. */
1086 RETURN_VALUE("%d", bytes_read);
1087 timersub(&end, &now, &delta);
1089 result = select(port->fd + 1, &fds, NULL, NULL, timeout ? &delta : NULL);
1091 if (errno == EINTR) {
1092 DEBUG("select() call was interrupted, repeating");
1095 RETURN_FAIL("select() failed");
1097 } else if (result == 0) {
1098 DEBUG("read timed out");
1099 RETURN_VALUE("%d", bytes_read);
1103 result = read(port->fd, ptr, count - bytes_read);
1106 if (errno == EAGAIN)
1107 /* This shouldn't happen because we did a select() first, but handle anyway. */
1110 /* This is an actual failure. */
1111 RETURN_FAIL("read() failed");
1114 bytes_read += result;
1118 RETURN_VALUE("%d", bytes_read);
1122 enum sp_return sp_nonblocking_read(struct sp_port *port, void *buf, size_t count)
1124 TRACE("%p, %p, %d", port, buf, count);
1129 RETURN_ERROR(SP_ERR_ARG, "Null buffer");
1131 DEBUG("Reading up to %d bytes from port %s", count, port->name);
1137 port->timeouts.ReadIntervalTimeout = MAXDWORD;
1138 port->timeouts.ReadTotalTimeoutConstant = 0;
1139 if (SetCommTimeouts(port->hdl, &port->timeouts) == 0)
1140 RETURN_FAIL("SetCommTimeouts() failed");
1143 if (ReadFile(port->hdl, buf, count, NULL, &port->read_ovl) == 0)
1144 RETURN_FAIL("ReadFile() failed");
1146 /* Get number of bytes read. */
1147 GetOverlappedResult(port->hdl, &port->read_ovl, &bytes_read, TRUE);
1149 RETURN_VALUE("%d", bytes_read);
1153 /* Returns the number of bytes read, or -1 upon failure. */
1154 if ((bytes_read = read(port->fd, buf, count)) < 0) {
1155 if (errno == EAGAIN)
1156 /* No bytes available. */
1159 /* This is an actual failure. */
1160 RETURN_FAIL("read() failed");
1162 RETURN_VALUE("%d", bytes_read);
1166 enum sp_return sp_input_waiting(struct sp_port *port)
1172 DEBUG("Checking input bytes waiting on port %s", port->name);
1178 if (ClearCommError(port->hdl, &errors, &comstat) == 0)
1179 RETURN_FAIL("ClearComError() failed");
1180 RETURN_VALUE("%d", comstat.cbInQue);
1183 if (ioctl(port->fd, TIOCINQ, &bytes_waiting) < 0)
1184 RETURN_FAIL("TIOCINQ ioctl failed");
1185 RETURN_VALUE("%d", bytes_waiting);
1189 enum sp_return sp_output_waiting(struct sp_port *port)
1195 DEBUG("Checking output bytes waiting on port %s", port->name);
1201 if (ClearCommError(port->hdl, &errors, &comstat) == 0)
1202 RETURN_FAIL("ClearComError() failed");
1203 RETURN_VALUE("%d", comstat.cbOutQue);
1206 if (ioctl(port->fd, TIOCOUTQ, &bytes_waiting) < 0)
1207 RETURN_FAIL("TIOCOUTQ ioctl failed");
1208 RETURN_VALUE("%d", bytes_waiting);
1213 static enum sp_return get_baudrate(int fd, int *baudrate)
1217 TRACE("%d, %p", fd, baudrate);
1219 DEBUG("Getting baud rate");
1221 if (!(data = malloc(get_termios_size())))
1222 RETURN_ERROR(SP_ERR_MEM, "termios malloc failed");
1224 if (ioctl(fd, get_termios_get_ioctl(), data) < 0) {
1226 RETURN_FAIL("getting termios failed");
1229 *baudrate = get_termios_speed(data);
1236 static enum sp_return set_baudrate(int fd, int baudrate)
1240 TRACE("%d, %d", fd, baudrate);
1242 DEBUG("Getting baud rate");
1244 if (!(data = malloc(get_termios_size())))
1245 RETURN_ERROR(SP_ERR_MEM, "termios malloc failed");
1247 if (ioctl(fd, get_termios_get_ioctl(), data) < 0) {
1249 RETURN_FAIL("getting termios failed");
1252 DEBUG("Setting baud rate");
1254 set_termios_speed(data, baudrate);
1256 if (ioctl(fd, get_termios_set_ioctl(), data) < 0) {
1258 RETURN_FAIL("setting termios failed");
1267 static enum sp_return get_flow(int fd, int *flow)
1271 TRACE("%d, %p", fd, flow);
1273 DEBUG("Getting advanced flow control");
1275 if (!(data = malloc(get_termiox_size())))
1276 RETURN_ERROR(SP_ERR_MEM, "termiox malloc failed");
1278 if (ioctl(fd, TCGETX, data) < 0) {
1280 RETURN_FAIL("getting termiox failed");
1283 *flow = get_termiox_flow(data);
1290 static enum sp_return set_flow(int fd, int flow)
1294 TRACE("%d, %d", fd, flow);
1296 DEBUG("Getting advanced flow control");
1298 if (!(data = malloc(get_termiox_size())))
1299 RETURN_ERROR(SP_ERR_MEM, "termiox malloc failed");
1301 if (ioctl(fd, TCGETX, data) < 0) {
1303 RETURN_FAIL("getting termiox failed");
1306 DEBUG("Setting advanced flow control");
1308 set_termiox_flow(data, flow);
1310 if (ioctl(fd, TCSETX, data) < 0) {
1312 RETURN_FAIL("setting termiox failed");
1319 #endif /* USE_TERMIOX */
1320 #endif /* __linux__ */
1322 static enum sp_return get_config(struct sp_port *port, struct port_data *data,
1323 struct sp_port_config *config)
1327 TRACE("%p, %p, %p", port, data, config);
1329 DEBUG("Getting configuration for port %s", port->name);
1332 if (!GetCommState(port->hdl, &data->dcb))
1333 RETURN_FAIL("GetCommState() failed");
1335 for (i = 0; i < NUM_STD_BAUDRATES; i++) {
1336 if (data->dcb.BaudRate == std_baudrates[i].index) {
1337 config->baudrate = std_baudrates[i].value;
1342 if (i == NUM_STD_BAUDRATES)
1343 /* BaudRate field can be either an index or a custom baud rate. */
1344 config->baudrate = data->dcb.BaudRate;
1346 config->bits = data->dcb.ByteSize;
1348 if (data->dcb.fParity)
1349 switch (data->dcb.Parity) {
1351 config->parity = SP_PARITY_NONE;
1354 config->parity = SP_PARITY_ODD;
1357 config->parity = SP_PARITY_EVEN;
1360 config->parity = SP_PARITY_MARK;
1363 config->parity = SP_PARITY_SPACE;
1366 config->parity = -1;
1369 config->parity = SP_PARITY_NONE;
1371 switch (data->dcb.StopBits) {
1373 config->stopbits = 1;
1376 config->stopbits = 2;
1379 config->stopbits = -1;
1382 switch (data->dcb.fRtsControl) {
1383 case RTS_CONTROL_DISABLE:
1384 config->rts = SP_RTS_OFF;
1386 case RTS_CONTROL_ENABLE:
1387 config->rts = SP_RTS_ON;
1389 case RTS_CONTROL_HANDSHAKE:
1390 config->rts = SP_RTS_FLOW_CONTROL;
1396 config->cts = data->dcb.fOutxCtsFlow ? SP_CTS_FLOW_CONTROL : SP_CTS_IGNORE;
1398 switch (data->dcb.fDtrControl) {
1399 case DTR_CONTROL_DISABLE:
1400 config->dtr = SP_DTR_OFF;
1402 case DTR_CONTROL_ENABLE:
1403 config->dtr = SP_DTR_ON;
1405 case DTR_CONTROL_HANDSHAKE:
1406 config->dtr = SP_DTR_FLOW_CONTROL;
1412 config->dsr = data->dcb.fOutxDsrFlow ? SP_DSR_FLOW_CONTROL : SP_DSR_IGNORE;
1414 if (data->dcb.fInX) {
1415 if (data->dcb.fOutX)
1416 config->xon_xoff = SP_XONXOFF_INOUT;
1418 config->xon_xoff = SP_XONXOFF_IN;
1420 if (data->dcb.fOutX)
1421 config->xon_xoff = SP_XONXOFF_OUT;
1423 config->xon_xoff = SP_XONXOFF_DISABLED;
1428 if (tcgetattr(port->fd, &data->term) < 0)
1429 RETURN_FAIL("tcgetattr() failed");
1431 if (ioctl(port->fd, TIOCMGET, &data->controlbits) < 0)
1432 RETURN_FAIL("TIOCMGET ioctl failed");
1435 int ret = get_flow(port->fd, &data->flow);
1437 if (ret == SP_ERR_FAIL && errno == EINVAL)
1438 data->termiox_supported = 0;
1440 RETURN_CODEVAL(ret);
1442 data->termiox_supported = 1;
1444 data->termiox_supported = 0;
1447 for (i = 0; i < NUM_STD_BAUDRATES; i++) {
1448 if (cfgetispeed(&data->term) == std_baudrates[i].index) {
1449 config->baudrate = std_baudrates[i].value;
1454 if (i == NUM_STD_BAUDRATES) {
1456 config->baudrate = (int)data->term.c_ispeed;
1457 #elif defined(__linux__)
1458 TRY(get_baudrate(port->fd, &config->baudrate));
1460 config->baudrate = -1;
1464 switch (data->term.c_cflag & CSIZE) {
1481 if (!(data->term.c_cflag & PARENB) && (data->term.c_iflag & IGNPAR))
1482 config->parity = SP_PARITY_NONE;
1483 else if (!(data->term.c_cflag & PARENB) || (data->term.c_iflag & IGNPAR))
1484 config->parity = -1;
1486 else if (data->term.c_cflag & CMSPAR)
1487 config->parity = (data->term.c_cflag & PARODD) ? SP_PARITY_MARK : SP_PARITY_SPACE;
1490 config->parity = (data->term.c_cflag & PARODD) ? SP_PARITY_ODD : SP_PARITY_EVEN;
1492 config->stopbits = (data->term.c_cflag & CSTOPB) ? 2 : 1;
1494 if (data->term.c_cflag & CRTSCTS) {
1495 config->rts = SP_RTS_FLOW_CONTROL;
1496 config->cts = SP_CTS_FLOW_CONTROL;
1498 if (data->termiox_supported && data->flow & RTS_FLOW)
1499 config->rts = SP_RTS_FLOW_CONTROL;
1501 config->rts = (data->controlbits & TIOCM_RTS) ? SP_RTS_ON : SP_RTS_OFF;
1503 config->cts = (data->termiox_supported && data->flow & CTS_FLOW) ?
1504 SP_CTS_FLOW_CONTROL : SP_CTS_IGNORE;
1507 if (data->termiox_supported && data->flow & DTR_FLOW)
1508 config->dtr = SP_DTR_FLOW_CONTROL;
1510 config->dtr = (data->controlbits & TIOCM_DTR) ? SP_DTR_ON : SP_DTR_OFF;
1512 config->dsr = (data->termiox_supported && data->flow & DSR_FLOW) ?
1513 SP_DSR_FLOW_CONTROL : SP_DSR_IGNORE;
1515 if (data->term.c_iflag & IXOFF) {
1516 if (data->term.c_iflag & IXON)
1517 config->xon_xoff = SP_XONXOFF_INOUT;
1519 config->xon_xoff = SP_XONXOFF_IN;
1521 if (data->term.c_iflag & IXON)
1522 config->xon_xoff = SP_XONXOFF_OUT;
1524 config->xon_xoff = SP_XONXOFF_DISABLED;
1531 static enum sp_return set_config(struct sp_port *port, struct port_data *data,
1532 const struct sp_port_config *config)
1536 BAUD_TYPE baud_nonstd;
1541 int baud_nonstd = 0;
1544 TRACE("%p, %p, %p", port, data, config);
1546 DEBUG("Setting configuration for port %s", port->name);
1549 if (config->baudrate >= 0) {
1550 for (i = 0; i < NUM_STD_BAUDRATES; i++) {
1551 if (config->baudrate == std_baudrates[i].value) {
1552 data->dcb.BaudRate = std_baudrates[i].index;
1557 if (i == NUM_STD_BAUDRATES)
1558 data->dcb.BaudRate = config->baudrate;
1561 if (config->bits >= 0)
1562 data->dcb.ByteSize = config->bits;
1564 if (config->parity >= 0) {
1565 switch (config->parity) {
1566 /* Note: There's also SPACEPARITY, MARKPARITY (unneeded so far). */
1567 case SP_PARITY_NONE:
1568 data->dcb.Parity = NOPARITY;
1571 data->dcb.Parity = ODDPARITY;
1573 case SP_PARITY_EVEN:
1574 data->dcb.Parity = EVENPARITY;
1576 case SP_PARITY_MARK:
1577 data->dcb.Parity = MARKPARITY;
1579 case SP_PARITY_SPACE:
1580 data->dcb.Parity = SPACEPARITY;
1583 RETURN_ERROR(SP_ERR_ARG, "Invalid parity setting");
1587 if (config->stopbits >= 0) {
1588 switch (config->stopbits) {
1589 /* Note: There's also ONE5STOPBITS == 1.5 (unneeded so far). */
1591 data->dcb.StopBits = ONESTOPBIT;
1594 data->dcb.StopBits = TWOSTOPBITS;
1597 RETURN_ERROR(SP_ERR_ARG, "Invalid stop bit setting");
1601 if (config->rts >= 0) {
1602 switch (config->rts) {
1604 data->dcb.fRtsControl = RTS_CONTROL_DISABLE;
1607 data->dcb.fRtsControl = RTS_CONTROL_ENABLE;
1609 case SP_RTS_FLOW_CONTROL:
1610 data->dcb.fRtsControl = RTS_CONTROL_HANDSHAKE;
1613 RETURN_ERROR(SP_ERR_ARG, "Invalid RTS setting");
1617 if (config->cts >= 0) {
1618 switch (config->cts) {
1620 data->dcb.fOutxCtsFlow = FALSE;
1622 case SP_CTS_FLOW_CONTROL:
1623 data->dcb.fOutxCtsFlow = TRUE;
1626 RETURN_ERROR(SP_ERR_ARG, "Invalid CTS setting");
1630 if (config->dtr >= 0) {
1631 switch (config->dtr) {
1633 data->dcb.fDtrControl = DTR_CONTROL_DISABLE;
1636 data->dcb.fDtrControl = DTR_CONTROL_ENABLE;
1638 case SP_DTR_FLOW_CONTROL:
1639 data->dcb.fDtrControl = DTR_CONTROL_HANDSHAKE;
1642 RETURN_ERROR(SP_ERR_ARG, "Invalid DTR setting");
1646 if (config->dsr >= 0) {
1647 switch (config->dsr) {
1649 data->dcb.fOutxDsrFlow = FALSE;
1651 case SP_DSR_FLOW_CONTROL:
1652 data->dcb.fOutxDsrFlow = TRUE;
1655 RETURN_ERROR(SP_ERR_ARG, "Invalid DSR setting");
1659 if (config->xon_xoff >= 0) {
1660 switch (config->xon_xoff) {
1661 case SP_XONXOFF_DISABLED:
1662 data->dcb.fInX = FALSE;
1663 data->dcb.fOutX = FALSE;
1666 data->dcb.fInX = TRUE;
1667 data->dcb.fOutX = FALSE;
1669 case SP_XONXOFF_OUT:
1670 data->dcb.fInX = FALSE;
1671 data->dcb.fOutX = TRUE;
1673 case SP_XONXOFF_INOUT:
1674 data->dcb.fInX = TRUE;
1675 data->dcb.fOutX = TRUE;
1678 RETURN_ERROR(SP_ERR_ARG, "Invalid XON/XOFF setting");
1682 if (!SetCommState(port->hdl, &data->dcb))
1683 RETURN_FAIL("SetCommState() failed");
1689 if (config->baudrate >= 0) {
1690 for (i = 0; i < NUM_STD_BAUDRATES; i++) {
1691 if (config->baudrate == std_baudrates[i].value) {
1692 if (cfsetospeed(&data->term, std_baudrates[i].index) < 0)
1693 RETURN_FAIL("cfsetospeed() failed");
1695 if (cfsetispeed(&data->term, std_baudrates[i].index) < 0)
1696 RETURN_FAIL("cfsetispeed() failed");
1701 /* Non-standard baud rate */
1702 if (i == NUM_STD_BAUDRATES) {
1704 /* Set "dummy" baud rate. */
1705 if (cfsetspeed(&data->term, B9600) < 0)
1706 RETURN_FAIL("cfsetspeed() failed");
1707 baud_nonstd = config->baudrate;
1708 #elif defined(__linux__)
1711 RETURN_ERROR(SP_ERR_SUPP, "Non-standard baudrate not supported");
1716 if (config->bits >= 0) {
1717 data->term.c_cflag &= ~CSIZE;
1718 switch (config->bits) {
1720 data->term.c_cflag |= CS8;
1723 data->term.c_cflag |= CS7;
1726 data->term.c_cflag |= CS6;
1729 data->term.c_cflag |= CS5;
1732 RETURN_ERROR(SP_ERR_ARG, "Invalid data bits setting");
1736 if (config->parity >= 0) {
1737 data->term.c_iflag &= ~IGNPAR;
1738 data->term.c_cflag &= ~(PARENB | PARODD);
1740 data->term.c_cflag &= ~CMSPAR;
1742 switch (config->parity) {
1743 case SP_PARITY_NONE:
1744 data->term.c_iflag |= IGNPAR;
1746 case SP_PARITY_EVEN:
1747 data->term.c_cflag |= PARENB;
1750 data->term.c_cflag |= PARENB | PARODD;
1753 case SP_PARITY_MARK:
1754 data->term.c_cflag |= PARENB | PARODD;
1755 data->term.c_cflag |= CMSPAR;
1757 case SP_PARITY_SPACE:
1758 data->term.c_cflag |= PARENB;
1759 data->term.c_cflag |= CMSPAR;
1762 case SP_PARITY_MARK:
1763 case SP_PARITY_SPACE:
1764 RETURN_ERROR(SP_ERR_SUPP, "Mark/space parity not supported");
1767 RETURN_ERROR(SP_ERR_ARG, "Invalid parity setting");
1771 if (config->stopbits >= 0) {
1772 data->term.c_cflag &= ~CSTOPB;
1773 switch (config->stopbits) {
1775 data->term.c_cflag &= ~CSTOPB;
1778 data->term.c_cflag |= CSTOPB;
1781 RETURN_ERROR(SP_ERR_ARG, "Invalid stop bits setting");
1785 if (config->rts >= 0 || config->cts >= 0) {
1786 if (data->termiox_supported) {
1787 data->flow &= ~(RTS_FLOW | CTS_FLOW);
1788 switch (config->rts) {
1791 controlbits = TIOCM_RTS;
1792 if (ioctl(port->fd, config->rts == SP_RTS_ON ? TIOCMBIS : TIOCMBIC, &controlbits) < 0)
1793 RETURN_FAIL("Setting RTS signal level failed");
1795 case SP_RTS_FLOW_CONTROL:
1796 data->flow |= RTS_FLOW;
1801 if (config->cts == SP_CTS_FLOW_CONTROL)
1802 data->flow |= CTS_FLOW;
1804 if (data->flow & (RTS_FLOW | CTS_FLOW))
1805 data->term.c_iflag |= CRTSCTS;
1807 data->term.c_iflag &= ~CRTSCTS;
1809 /* Asymmetric use of RTS/CTS not supported. */
1810 if (data->term.c_iflag & CRTSCTS) {
1811 /* Flow control can only be disabled for both RTS & CTS together. */
1812 if (config->rts >= 0 && config->rts != SP_RTS_FLOW_CONTROL) {
1813 if (config->cts != SP_CTS_IGNORE)
1814 RETURN_ERROR(SP_ERR_SUPP, "RTS & CTS flow control must be disabled together");
1816 if (config->cts >= 0 && config->cts != SP_CTS_FLOW_CONTROL) {
1817 if (config->rts <= 0 || config->rts == SP_RTS_FLOW_CONTROL)
1818 RETURN_ERROR(SP_ERR_SUPP, "RTS & CTS flow control must be disabled together");
1821 /* Flow control can only be enabled for both RTS & CTS together. */
1822 if (((config->rts == SP_RTS_FLOW_CONTROL) && (config->cts != SP_CTS_FLOW_CONTROL)) ||
1823 ((config->cts == SP_CTS_FLOW_CONTROL) && (config->rts != SP_RTS_FLOW_CONTROL)))
1824 RETURN_ERROR(SP_ERR_SUPP, "RTS & CTS flow control must be enabled together");
1827 if (config->rts >= 0) {
1828 if (config->rts == SP_RTS_FLOW_CONTROL) {
1829 data->term.c_iflag |= CRTSCTS;
1831 controlbits = TIOCM_RTS;
1832 if (ioctl(port->fd, config->rts == SP_RTS_ON ? TIOCMBIS : TIOCMBIC,
1834 RETURN_FAIL("Setting RTS signal level failed");
1840 if (config->dtr >= 0 || config->dsr >= 0) {
1841 if (data->termiox_supported) {
1842 data->flow &= ~(DTR_FLOW | DSR_FLOW);
1843 switch (config->dtr) {
1846 controlbits = TIOCM_DTR;
1847 if (ioctl(port->fd, config->dtr == SP_DTR_ON ? TIOCMBIS : TIOCMBIC, &controlbits) < 0)
1848 RETURN_FAIL("Setting DTR signal level failed");
1850 case SP_DTR_FLOW_CONTROL:
1851 data->flow |= DTR_FLOW;
1856 if (config->dsr == SP_DSR_FLOW_CONTROL)
1857 data->flow |= DSR_FLOW;
1859 /* DTR/DSR flow control not supported. */
1860 if (config->dtr == SP_DTR_FLOW_CONTROL || config->dsr == SP_DSR_FLOW_CONTROL)
1861 RETURN_ERROR(SP_ERR_SUPP, "DTR/DSR flow control not supported");
1863 if (config->dtr >= 0) {
1864 controlbits = TIOCM_DTR;
1865 if (ioctl(port->fd, config->dtr == SP_DTR_ON ? TIOCMBIS : TIOCMBIC,
1867 RETURN_FAIL("Setting DTR signal level failed");
1872 if (config->xon_xoff >= 0) {
1873 data->term.c_iflag &= ~(IXON | IXOFF | IXANY);
1874 switch (config->xon_xoff) {
1875 case SP_XONXOFF_DISABLED:
1878 data->term.c_iflag |= IXOFF;
1880 case SP_XONXOFF_OUT:
1881 data->term.c_iflag |= IXON | IXANY;
1883 case SP_XONXOFF_INOUT:
1884 data->term.c_iflag |= IXON | IXOFF | IXANY;
1887 RETURN_ERROR(SP_ERR_ARG, "Invalid XON/XOFF setting");
1891 if (tcsetattr(port->fd, TCSANOW, &data->term) < 0)
1892 RETURN_FAIL("tcsetattr() failed");
1895 if (baud_nonstd != B0) {
1896 if (ioctl(port->fd, IOSSIOSPEED, &baud_nonstd) == -1)
1897 RETURN_FAIL("IOSSIOSPEED ioctl failed");
1898 /* Set baud rates in data->term to correct, but incompatible
1899 * with tcsetattr() value, same as delivered by tcgetattr(). */
1900 if (cfsetspeed(&data->term, baud_nonstd) < 0)
1901 RETURN_FAIL("cfsetspeed() failed");
1903 #elif defined(__linux__)
1905 TRY(set_baudrate(port->fd, config->baudrate));
1907 if (data->termiox_supported)
1908 TRY(set_flow(port->fd, data->flow));
1912 #endif /* !_WIN32 */
1917 enum sp_return sp_new_config(struct sp_port_config **config_ptr)
1919 struct sp_port_config *config;
1921 TRACE("%p", config_ptr);
1924 RETURN_ERROR(SP_ERR_ARG, "Null result pointer");
1928 if (!(config = malloc(sizeof(struct sp_port_config))))
1929 RETURN_ERROR(SP_ERR_MEM, "config malloc failed");
1931 config->baudrate = -1;
1933 config->parity = -1;
1934 config->stopbits = -1;
1940 *config_ptr = config;
1945 void sp_free_config(struct sp_port_config *config)
1947 TRACE("%p", config);
1950 DEBUG("Null config");
1957 enum sp_return sp_get_config(struct sp_port *port, struct sp_port_config *config)
1959 struct port_data data;
1961 TRACE("%p, %p", port, config);
1966 RETURN_ERROR(SP_ERR_ARG, "Null config");
1968 TRY(get_config(port, &data, config));
1973 enum sp_return sp_set_config(struct sp_port *port, const struct sp_port_config *config)
1975 struct port_data data;
1976 struct sp_port_config prev_config;
1978 TRACE("%p, %p", port, config);
1983 RETURN_ERROR(SP_ERR_ARG, "Null config");
1985 TRY(get_config(port, &data, &prev_config));
1986 TRY(set_config(port, &data, config));
1991 #define CREATE_ACCESSORS(x, type) \
1992 enum sp_return sp_set_##x(struct sp_port *port, type x) { \
1993 struct port_data data; \
1994 struct sp_port_config config; \
1995 TRACE("%p, %d", port, x); \
1996 CHECK_OPEN_PORT(); \
1997 TRY(get_config(port, &data, &config)); \
1999 TRY(set_config(port, &data, &config)); \
2002 enum sp_return sp_get_config_##x(const struct sp_port_config *config, type *x) { \
2003 TRACE("%p, %p", config, x); \
2005 RETURN_ERROR(SP_ERR_ARG, "Null config"); \
2009 enum sp_return sp_set_config_##x(struct sp_port_config *config, type x) { \
2010 TRACE("%p, %d", config, x); \
2012 RETURN_ERROR(SP_ERR_ARG, "Null config"); \
2017 CREATE_ACCESSORS(baudrate, int)
2018 CREATE_ACCESSORS(bits, int)
2019 CREATE_ACCESSORS(parity, enum sp_parity)
2020 CREATE_ACCESSORS(stopbits, int)
2021 CREATE_ACCESSORS(rts, enum sp_rts)
2022 CREATE_ACCESSORS(cts, enum sp_cts)
2023 CREATE_ACCESSORS(dtr, enum sp_dtr)
2024 CREATE_ACCESSORS(dsr, enum sp_dsr)
2025 CREATE_ACCESSORS(xon_xoff, enum sp_xonxoff)
2027 enum sp_return sp_set_config_flowcontrol(struct sp_port_config *config, enum sp_flowcontrol flowcontrol)
2030 RETURN_ERROR(SP_ERR_ARG, "Null configuration");
2032 if (flowcontrol > SP_FLOWCONTROL_DTRDSR)
2033 RETURN_ERROR(SP_ERR_ARG, "Invalid flow control setting");
2035 if (flowcontrol == SP_FLOWCONTROL_XONXOFF)
2036 config->xon_xoff = SP_XONXOFF_INOUT;
2038 config->xon_xoff = SP_XONXOFF_DISABLED;
2040 if (flowcontrol == SP_FLOWCONTROL_RTSCTS) {
2041 config->rts = SP_RTS_FLOW_CONTROL;
2042 config->cts = SP_CTS_FLOW_CONTROL;
2044 if (config->rts == SP_RTS_FLOW_CONTROL)
2045 config->rts = SP_RTS_ON;
2046 config->cts = SP_CTS_IGNORE;
2049 if (flowcontrol == SP_FLOWCONTROL_DTRDSR) {
2050 config->dtr = SP_DTR_FLOW_CONTROL;
2051 config->dsr = SP_DSR_FLOW_CONTROL;
2053 if (config->dtr == SP_DTR_FLOW_CONTROL)
2054 config->dtr = SP_DTR_ON;
2055 config->dsr = SP_DSR_IGNORE;
2061 enum sp_return sp_set_flowcontrol(struct sp_port *port, enum sp_flowcontrol flowcontrol)
2063 struct port_data data;
2064 struct sp_port_config config;
2066 TRACE("%p, %d", port, flowcontrol);
2070 TRY(get_config(port, &data, &config));
2072 TRY(sp_set_config_flowcontrol(&config, flowcontrol));
2074 TRY(set_config(port, &data, &config));
2079 enum sp_return sp_get_signals(struct sp_port *port, enum sp_signal *signals)
2081 TRACE("%p, %p", port, signals);
2086 RETURN_ERROR(SP_ERR_ARG, "Null result pointer");
2088 DEBUG("Getting control signals for port %s", port->name);
2093 if (GetCommModemStatus(port->hdl, &bits) == 0)
2094 RETURN_FAIL("GetCommModemStatus() failed");
2095 if (bits & MS_CTS_ON)
2096 *signals |= SP_SIG_CTS;
2097 if (bits & MS_DSR_ON)
2098 *signals |= SP_SIG_DSR;
2099 if (bits & MS_RLSD_ON)
2100 *signals |= SP_SIG_DCD;
2101 if (bits & MS_RING_ON)
2102 *signals |= SP_SIG_RI;
2105 if (ioctl(port->fd, TIOCMGET, &bits) < 0)
2106 RETURN_FAIL("TIOCMGET ioctl failed");
2107 if (bits & TIOCM_CTS)
2108 *signals |= SP_SIG_CTS;
2109 if (bits & TIOCM_DSR)
2110 *signals |= SP_SIG_DSR;
2111 if (bits & TIOCM_CAR)
2112 *signals |= SP_SIG_DCD;
2113 if (bits & TIOCM_RNG)
2114 *signals |= SP_SIG_RI;
2119 enum sp_return sp_start_break(struct sp_port *port)
2125 if (SetCommBreak(port->hdl) == 0)
2126 RETURN_FAIL("SetCommBreak() failed");
2128 if (ioctl(port->fd, TIOCSBRK, 1) < 0)
2129 RETURN_FAIL("TIOCSBRK ioctl failed");
2135 enum sp_return sp_end_break(struct sp_port *port)
2141 if (ClearCommBreak(port->hdl) == 0)
2142 RETURN_FAIL("ClearCommBreak() failed");
2144 if (ioctl(port->fd, TIOCCBRK, 1) < 0)
2145 RETURN_FAIL("TIOCCBRK ioctl failed");
2151 int sp_last_error_code(void)
2155 RETURN_VALUE("%d", GetLastError());
2157 RETURN_VALUE("%d", errno);
2161 char *sp_last_error_message(void)
2167 DWORD error = GetLastError();
2170 FORMAT_MESSAGE_ALLOCATE_BUFFER |
2171 FORMAT_MESSAGE_FROM_SYSTEM |
2172 FORMAT_MESSAGE_IGNORE_INSERTS,
2175 MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
2179 RETURN_VALUE("%s", message);
2181 RETURN_VALUE("%s", strerror(errno));
2185 void sp_free_error_message(char *message)
2187 TRACE("%s", message);
2198 void sp_set_debug_handler(void (*handler)(const char *format, ...))
2200 TRACE("%p", handler);
2202 sp_debug_handler = handler;
2207 void sp_default_debug_handler(const char *format, ...)
2210 va_start(args, format);
2211 if (getenv("LIBSERIALPORT_DEBUG")) {
2212 fputs("sp: ", stderr);
2213 vfprintf(stderr, format, args);