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 if (ClearCommError(port->hdl, &errors, &status) == 0)
733 RETURN_FAIL("ClearCommError() failed");
736 ret = set_config(port, &data, &config);
746 enum sp_return sp_close(struct sp_port *port)
752 DEBUG("Closing port %s", port->name);
755 /* Returns non-zero upon success, 0 upon failure. */
756 if (CloseHandle(port->hdl) == 0)
757 RETURN_FAIL("port CloseHandle() failed");
758 port->hdl = INVALID_HANDLE_VALUE;
759 /* Close event handle created for overlapped reads. */
760 if (port->read_ovl.hEvent != INVALID_HANDLE_VALUE && CloseHandle(port->read_ovl.hEvent) == 0)
761 RETURN_FAIL("read event CloseHandle() failed");
762 /* Close event handle created for overlapped writes. */
763 if (port->write_ovl.hEvent != INVALID_HANDLE_VALUE && CloseHandle(port->write_ovl.hEvent) == 0)
764 RETURN_FAIL("write event CloseHandle() failed");
766 /* Returns 0 upon success, -1 upon failure. */
767 if (close(port->fd) == -1)
768 RETURN_FAIL("close() failed");
775 enum sp_return sp_flush(struct sp_port *port, enum sp_buffer buffers)
777 TRACE("%p, 0x%x", port, buffers);
781 if (buffers > SP_BUF_BOTH)
782 RETURN_ERROR(SP_ERR_ARG, "Invalid buffer selection");
784 const char *buffer_names[] = {"no", "input", "output", "both"};
786 DEBUG("Flushing %s buffers on port %s", buffer_names[buffers], port->name);
790 if (buffers & SP_BUF_INPUT)
791 flags |= PURGE_RXCLEAR;
792 if (buffers & SP_BUF_OUTPUT)
793 flags |= PURGE_TXCLEAR;
795 /* Returns non-zero upon success, 0 upon failure. */
796 if (PurgeComm(port->hdl, flags) == 0)
797 RETURN_FAIL("PurgeComm() failed");
800 if (buffers & SP_BUF_BOTH)
802 else if (buffers & SP_BUF_INPUT)
804 else if (buffers & SP_BUF_OUTPUT)
807 /* Returns 0 upon success, -1 upon failure. */
808 if (tcflush(port->fd, flags) < 0)
809 RETURN_FAIL("tcflush() failed");
814 enum sp_return sp_drain(struct sp_port *port)
820 DEBUG("Draining port %s", port->name);
823 /* Returns non-zero upon success, 0 upon failure. */
824 if (FlushFileBuffers(port->hdl) == 0)
825 RETURN_FAIL("FlushFileBuffers() failed");
832 result = ioctl(port->fd, TCSBRK, &arg);
834 result = tcdrain(port->fd);
837 if (errno == EINTR) {
838 DEBUG("tcdrain() was interrupted");
841 RETURN_FAIL("tcdrain() failed");
850 enum sp_return sp_blocking_write(struct sp_port *port, const void *buf, size_t count, unsigned int timeout)
852 TRACE("%p, %p, %d, %d", port, buf, count, timeout);
857 RETURN_ERROR(SP_ERR_ARG, "Null buffer");
860 DEBUG("Writing %d bytes to port %s, timeout %d ms", count, port->name, timeout);
862 DEBUG("Writing %d bytes to port %s, no timeout", count, port->name);
865 RETURN_VALUE("0", 0);
868 DWORD bytes_written = 0;
871 /* Wait for previous non-blocking write to complete, if any. */
873 DEBUG("Waiting for previous write to complete");
874 result = GetOverlappedResult(port->hdl, &port->write_ovl, &bytes_written, TRUE);
877 RETURN_FAIL("Previous write failed to complete");
878 DEBUG("Previous write completed");
882 port->timeouts.WriteTotalTimeoutConstant = timeout;
883 if (SetCommTimeouts(port->hdl, &port->timeouts) == 0)
884 RETURN_FAIL("SetCommTimeouts() failed");
887 if (WriteFile(port->hdl, buf, count, NULL, &port->write_ovl) == 0) {
888 if (GetLastError() == ERROR_IO_PENDING) {
889 DEBUG("Waiting for write to complete");
890 GetOverlappedResult(port->hdl, &port->write_ovl, &bytes_written, TRUE);
891 DEBUG("Write completed, %d/%d bytes written", bytes_written, count);
892 RETURN_VALUE("%d", bytes_written);
894 RETURN_FAIL("WriteFile() failed");
897 DEBUG("Write completed immediately");
898 RETURN_VALUE("%d", count);
901 size_t bytes_written = 0;
902 unsigned char *ptr = (unsigned char *) buf;
903 struct timeval start, delta, now, end = {0, 0};
908 /* Get time at start of operation. */
909 gettimeofday(&start, NULL);
910 /* Define duration of timeout. */
911 delta.tv_sec = timeout / 1000;
912 delta.tv_usec = (timeout % 1000) * 1000;
913 /* Calculate time at which we should give up. */
914 timeradd(&start, &delta, &end);
917 /* Loop until we have written the requested number of bytes. */
918 while (bytes_written < count)
920 /* Wait until space is available. */
922 FD_SET(port->fd, &fds);
924 gettimeofday(&now, NULL);
925 if (timercmp(&now, &end, >)) {
926 DEBUG("write timed out");
927 RETURN_VALUE("%d", bytes_written);
929 timersub(&end, &now, &delta);
931 result = select(port->fd + 1, NULL, &fds, NULL, timeout ? &delta : NULL);
933 if (errno == EINTR) {
934 DEBUG("select() call was interrupted, repeating");
937 RETURN_FAIL("select() failed");
939 } else if (result == 0) {
940 DEBUG("write timed out");
941 RETURN_VALUE("%d", bytes_written);
945 result = write(port->fd, ptr, count - bytes_written);
949 /* This shouldn't happen because we did a select() first, but handle anyway. */
952 /* This is an actual failure. */
953 RETURN_FAIL("write() failed");
956 bytes_written += result;
960 RETURN_VALUE("%d", bytes_written);
964 enum sp_return sp_nonblocking_write(struct sp_port *port, const void *buf, size_t count)
966 TRACE("%p, %p, %d", port, buf, count);
971 RETURN_ERROR(SP_ERR_ARG, "Null buffer");
973 DEBUG("Writing up to %d bytes to port %s", count, port->name);
976 RETURN_VALUE("0", 0);
980 BYTE *ptr = (BYTE *) buf;
982 /* Check whether previous write is complete. */
984 if (HasOverlappedIoCompleted(&port->write_ovl)) {
985 DEBUG("Previous write completed");
988 DEBUG("Previous write not complete");
989 /* Can't take a new write until the previous one finishes. */
990 RETURN_VALUE("0", 0);
995 port->timeouts.WriteTotalTimeoutConstant = 0;
996 if (SetCommTimeouts(port->hdl, &port->timeouts) == 0)
997 RETURN_FAIL("SetCommTimeouts() failed");
999 /* Keep writing data until the OS has to actually start an async IO for it.
1000 * At that point we know the buffer is full. */
1001 while (written < count)
1003 /* Copy first byte of user buffer. */
1004 port->pending_byte = *ptr++;
1006 /* Start asynchronous write. */
1007 if (WriteFile(port->hdl, &port->pending_byte, 1, NULL, &port->write_ovl) == 0) {
1008 if (GetLastError() == ERROR_IO_PENDING) {
1009 if (HasOverlappedIoCompleted(&port->write_ovl)) {
1010 DEBUG("Asynchronous write completed immediately");
1015 DEBUG("Asynchronous write running");
1017 RETURN_VALUE("%d", ++written);
1020 /* Actual failure of some kind. */
1021 RETURN_FAIL("WriteFile() failed");
1024 DEBUG("Single byte written immediately");
1029 DEBUG("All bytes written immediately");
1031 RETURN_VALUE("%d", written);
1033 /* Returns the number of bytes written, or -1 upon failure. */
1034 ssize_t written = write(port->fd, buf, count);
1037 RETURN_FAIL("write() failed");
1039 RETURN_VALUE("%d", written);
1043 enum sp_return sp_blocking_read(struct sp_port *port, void *buf, size_t count, unsigned int timeout)
1045 TRACE("%p, %p, %d, %d", port, buf, count, timeout);
1050 RETURN_ERROR(SP_ERR_ARG, "Null buffer");
1053 DEBUG("Reading %d bytes from port %s, timeout %d ms", count, port->name, timeout);
1055 DEBUG("Reading %d bytes from port %s, no timeout", count, port->name);
1058 RETURN_VALUE("0", 0);
1061 DWORD bytes_read = 0;
1064 port->timeouts.ReadIntervalTimeout = 0;
1065 port->timeouts.ReadTotalTimeoutConstant = timeout;
1066 if (SetCommTimeouts(port->hdl, &port->timeouts) == 0)
1067 RETURN_FAIL("SetCommTimeouts() failed");
1070 if (ReadFile(port->hdl, buf, count, NULL, &port->read_ovl) == 0) {
1071 if (GetLastError() == ERROR_IO_PENDING) {
1072 DEBUG("Waiting for read to complete");
1073 GetOverlappedResult(port->hdl, &port->read_ovl, &bytes_read, TRUE);
1074 DEBUG("Read completed, %d/%d bytes read", bytes_read, count);
1075 RETURN_VALUE("%d", bytes_read);
1077 RETURN_FAIL("ReadFile() failed");
1080 DEBUG("Read completed immediately");
1081 RETURN_VALUE("%d", count);
1084 size_t bytes_read = 0;
1085 unsigned char *ptr = (unsigned char *) buf;
1086 struct timeval start, delta, now, end = {0, 0};
1091 /* Get time at start of operation. */
1092 gettimeofday(&start, NULL);
1093 /* Define duration of timeout. */
1094 delta.tv_sec = timeout / 1000;
1095 delta.tv_usec = (timeout % 1000) * 1000;
1096 /* Calculate time at which we should give up. */
1097 timeradd(&start, &delta, &end);
1100 /* Loop until we have the requested number of bytes. */
1101 while (bytes_read < count)
1103 /* Wait until data is available. */
1105 FD_SET(port->fd, &fds);
1107 gettimeofday(&now, NULL);
1108 if (timercmp(&now, &end, >))
1109 /* Timeout has expired. */
1110 RETURN_VALUE("%d", bytes_read);
1111 timersub(&end, &now, &delta);
1113 result = select(port->fd + 1, &fds, NULL, NULL, timeout ? &delta : NULL);
1115 if (errno == EINTR) {
1116 DEBUG("select() call was interrupted, repeating");
1119 RETURN_FAIL("select() failed");
1121 } else if (result == 0) {
1122 DEBUG("read timed out");
1123 RETURN_VALUE("%d", bytes_read);
1127 result = read(port->fd, ptr, count - bytes_read);
1130 if (errno == EAGAIN)
1131 /* This shouldn't happen because we did a select() first, but handle anyway. */
1134 /* This is an actual failure. */
1135 RETURN_FAIL("read() failed");
1138 bytes_read += result;
1142 RETURN_VALUE("%d", bytes_read);
1146 enum sp_return sp_nonblocking_read(struct sp_port *port, void *buf, size_t count)
1148 TRACE("%p, %p, %d", port, buf, count);
1153 RETURN_ERROR(SP_ERR_ARG, "Null buffer");
1155 DEBUG("Reading up to %d bytes from port %s", count, port->name);
1161 port->timeouts.ReadIntervalTimeout = MAXDWORD;
1162 port->timeouts.ReadTotalTimeoutConstant = 0;
1163 if (SetCommTimeouts(port->hdl, &port->timeouts) == 0)
1164 RETURN_FAIL("SetCommTimeouts() failed");
1167 if (ReadFile(port->hdl, buf, count, NULL, &port->read_ovl) == 0)
1168 RETURN_FAIL("ReadFile() failed");
1170 /* Get number of bytes read. */
1171 if (GetOverlappedResult(port->hdl, &port->read_ovl, &bytes_read, TRUE) == 0)
1172 RETURN_FAIL("GetOverlappedResult() failed");
1174 RETURN_VALUE("%d", bytes_read);
1178 /* Returns the number of bytes read, or -1 upon failure. */
1179 if ((bytes_read = read(port->fd, buf, count)) < 0) {
1180 if (errno == EAGAIN)
1181 /* No bytes available. */
1184 /* This is an actual failure. */
1185 RETURN_FAIL("read() failed");
1187 RETURN_VALUE("%d", bytes_read);
1191 enum sp_return sp_input_waiting(struct sp_port *port)
1197 DEBUG("Checking input bytes waiting on port %s", port->name);
1203 if (ClearCommError(port->hdl, &errors, &comstat) == 0)
1204 RETURN_FAIL("ClearCommError() failed");
1205 RETURN_VALUE("%d", comstat.cbInQue);
1208 if (ioctl(port->fd, TIOCINQ, &bytes_waiting) < 0)
1209 RETURN_FAIL("TIOCINQ ioctl failed");
1210 RETURN_VALUE("%d", bytes_waiting);
1214 enum sp_return sp_output_waiting(struct sp_port *port)
1220 DEBUG("Checking output bytes waiting on port %s", port->name);
1226 if (ClearCommError(port->hdl, &errors, &comstat) == 0)
1227 RETURN_FAIL("ClearCommError() failed");
1228 RETURN_VALUE("%d", comstat.cbOutQue);
1231 if (ioctl(port->fd, TIOCOUTQ, &bytes_waiting) < 0)
1232 RETURN_FAIL("TIOCOUTQ ioctl failed");
1233 RETURN_VALUE("%d", bytes_waiting);
1238 static enum sp_return get_baudrate(int fd, int *baudrate)
1242 TRACE("%d, %p", fd, baudrate);
1244 DEBUG("Getting baud rate");
1246 if (!(data = malloc(get_termios_size())))
1247 RETURN_ERROR(SP_ERR_MEM, "termios malloc failed");
1249 if (ioctl(fd, get_termios_get_ioctl(), data) < 0) {
1251 RETURN_FAIL("getting termios failed");
1254 *baudrate = get_termios_speed(data);
1261 static enum sp_return set_baudrate(int fd, int baudrate)
1265 TRACE("%d, %d", fd, baudrate);
1267 DEBUG("Getting baud rate");
1269 if (!(data = malloc(get_termios_size())))
1270 RETURN_ERROR(SP_ERR_MEM, "termios malloc failed");
1272 if (ioctl(fd, get_termios_get_ioctl(), data) < 0) {
1274 RETURN_FAIL("getting termios failed");
1277 DEBUG("Setting baud rate");
1279 set_termios_speed(data, baudrate);
1281 if (ioctl(fd, get_termios_set_ioctl(), data) < 0) {
1283 RETURN_FAIL("setting termios failed");
1292 static enum sp_return get_flow(int fd, int *flow)
1296 TRACE("%d, %p", fd, flow);
1298 DEBUG("Getting advanced flow control");
1300 if (!(data = malloc(get_termiox_size())))
1301 RETURN_ERROR(SP_ERR_MEM, "termiox malloc failed");
1303 if (ioctl(fd, TCGETX, data) < 0) {
1305 RETURN_FAIL("getting termiox failed");
1308 *flow = get_termiox_flow(data);
1315 static enum sp_return set_flow(int fd, int flow)
1319 TRACE("%d, %d", fd, flow);
1321 DEBUG("Getting advanced flow control");
1323 if (!(data = malloc(get_termiox_size())))
1324 RETURN_ERROR(SP_ERR_MEM, "termiox malloc failed");
1326 if (ioctl(fd, TCGETX, data) < 0) {
1328 RETURN_FAIL("getting termiox failed");
1331 DEBUG("Setting advanced flow control");
1333 set_termiox_flow(data, flow);
1335 if (ioctl(fd, TCSETX, data) < 0) {
1337 RETURN_FAIL("setting termiox failed");
1344 #endif /* USE_TERMIOX */
1345 #endif /* __linux__ */
1347 static enum sp_return get_config(struct sp_port *port, struct port_data *data,
1348 struct sp_port_config *config)
1352 TRACE("%p, %p, %p", port, data, config);
1354 DEBUG("Getting configuration for port %s", port->name);
1357 if (!GetCommState(port->hdl, &data->dcb))
1358 RETURN_FAIL("GetCommState() failed");
1360 for (i = 0; i < NUM_STD_BAUDRATES; i++) {
1361 if (data->dcb.BaudRate == std_baudrates[i].index) {
1362 config->baudrate = std_baudrates[i].value;
1367 if (i == NUM_STD_BAUDRATES)
1368 /* BaudRate field can be either an index or a custom baud rate. */
1369 config->baudrate = data->dcb.BaudRate;
1371 config->bits = data->dcb.ByteSize;
1373 if (data->dcb.fParity)
1374 switch (data->dcb.Parity) {
1376 config->parity = SP_PARITY_NONE;
1379 config->parity = SP_PARITY_ODD;
1382 config->parity = SP_PARITY_EVEN;
1385 config->parity = SP_PARITY_MARK;
1388 config->parity = SP_PARITY_SPACE;
1391 config->parity = -1;
1394 config->parity = SP_PARITY_NONE;
1396 switch (data->dcb.StopBits) {
1398 config->stopbits = 1;
1401 config->stopbits = 2;
1404 config->stopbits = -1;
1407 switch (data->dcb.fRtsControl) {
1408 case RTS_CONTROL_DISABLE:
1409 config->rts = SP_RTS_OFF;
1411 case RTS_CONTROL_ENABLE:
1412 config->rts = SP_RTS_ON;
1414 case RTS_CONTROL_HANDSHAKE:
1415 config->rts = SP_RTS_FLOW_CONTROL;
1421 config->cts = data->dcb.fOutxCtsFlow ? SP_CTS_FLOW_CONTROL : SP_CTS_IGNORE;
1423 switch (data->dcb.fDtrControl) {
1424 case DTR_CONTROL_DISABLE:
1425 config->dtr = SP_DTR_OFF;
1427 case DTR_CONTROL_ENABLE:
1428 config->dtr = SP_DTR_ON;
1430 case DTR_CONTROL_HANDSHAKE:
1431 config->dtr = SP_DTR_FLOW_CONTROL;
1437 config->dsr = data->dcb.fOutxDsrFlow ? SP_DSR_FLOW_CONTROL : SP_DSR_IGNORE;
1439 if (data->dcb.fInX) {
1440 if (data->dcb.fOutX)
1441 config->xon_xoff = SP_XONXOFF_INOUT;
1443 config->xon_xoff = SP_XONXOFF_IN;
1445 if (data->dcb.fOutX)
1446 config->xon_xoff = SP_XONXOFF_OUT;
1448 config->xon_xoff = SP_XONXOFF_DISABLED;
1453 if (tcgetattr(port->fd, &data->term) < 0)
1454 RETURN_FAIL("tcgetattr() failed");
1456 if (ioctl(port->fd, TIOCMGET, &data->controlbits) < 0)
1457 RETURN_FAIL("TIOCMGET ioctl failed");
1460 int ret = get_flow(port->fd, &data->flow);
1462 if (ret == SP_ERR_FAIL && errno == EINVAL)
1463 data->termiox_supported = 0;
1465 RETURN_CODEVAL(ret);
1467 data->termiox_supported = 1;
1469 data->termiox_supported = 0;
1472 for (i = 0; i < NUM_STD_BAUDRATES; i++) {
1473 if (cfgetispeed(&data->term) == std_baudrates[i].index) {
1474 config->baudrate = std_baudrates[i].value;
1479 if (i == NUM_STD_BAUDRATES) {
1481 config->baudrate = (int)data->term.c_ispeed;
1482 #elif defined(__linux__)
1483 TRY(get_baudrate(port->fd, &config->baudrate));
1485 config->baudrate = -1;
1489 switch (data->term.c_cflag & CSIZE) {
1506 if (!(data->term.c_cflag & PARENB) && (data->term.c_iflag & IGNPAR))
1507 config->parity = SP_PARITY_NONE;
1508 else if (!(data->term.c_cflag & PARENB) || (data->term.c_iflag & IGNPAR))
1509 config->parity = -1;
1511 else if (data->term.c_cflag & CMSPAR)
1512 config->parity = (data->term.c_cflag & PARODD) ? SP_PARITY_MARK : SP_PARITY_SPACE;
1515 config->parity = (data->term.c_cflag & PARODD) ? SP_PARITY_ODD : SP_PARITY_EVEN;
1517 config->stopbits = (data->term.c_cflag & CSTOPB) ? 2 : 1;
1519 if (data->term.c_cflag & CRTSCTS) {
1520 config->rts = SP_RTS_FLOW_CONTROL;
1521 config->cts = SP_CTS_FLOW_CONTROL;
1523 if (data->termiox_supported && data->flow & RTS_FLOW)
1524 config->rts = SP_RTS_FLOW_CONTROL;
1526 config->rts = (data->controlbits & TIOCM_RTS) ? SP_RTS_ON : SP_RTS_OFF;
1528 config->cts = (data->termiox_supported && data->flow & CTS_FLOW) ?
1529 SP_CTS_FLOW_CONTROL : SP_CTS_IGNORE;
1532 if (data->termiox_supported && data->flow & DTR_FLOW)
1533 config->dtr = SP_DTR_FLOW_CONTROL;
1535 config->dtr = (data->controlbits & TIOCM_DTR) ? SP_DTR_ON : SP_DTR_OFF;
1537 config->dsr = (data->termiox_supported && data->flow & DSR_FLOW) ?
1538 SP_DSR_FLOW_CONTROL : SP_DSR_IGNORE;
1540 if (data->term.c_iflag & IXOFF) {
1541 if (data->term.c_iflag & IXON)
1542 config->xon_xoff = SP_XONXOFF_INOUT;
1544 config->xon_xoff = SP_XONXOFF_IN;
1546 if (data->term.c_iflag & IXON)
1547 config->xon_xoff = SP_XONXOFF_OUT;
1549 config->xon_xoff = SP_XONXOFF_DISABLED;
1556 static enum sp_return set_config(struct sp_port *port, struct port_data *data,
1557 const struct sp_port_config *config)
1561 BAUD_TYPE baud_nonstd;
1566 int baud_nonstd = 0;
1569 TRACE("%p, %p, %p", port, data, config);
1571 DEBUG("Setting configuration for port %s", port->name);
1574 if (config->baudrate >= 0) {
1575 for (i = 0; i < NUM_STD_BAUDRATES; i++) {
1576 if (config->baudrate == std_baudrates[i].value) {
1577 data->dcb.BaudRate = std_baudrates[i].index;
1582 if (i == NUM_STD_BAUDRATES)
1583 data->dcb.BaudRate = config->baudrate;
1586 if (config->bits >= 0)
1587 data->dcb.ByteSize = config->bits;
1589 if (config->parity >= 0) {
1590 switch (config->parity) {
1591 case SP_PARITY_NONE:
1592 data->dcb.Parity = NOPARITY;
1595 data->dcb.Parity = ODDPARITY;
1597 case SP_PARITY_EVEN:
1598 data->dcb.Parity = EVENPARITY;
1600 case SP_PARITY_MARK:
1601 data->dcb.Parity = MARKPARITY;
1603 case SP_PARITY_SPACE:
1604 data->dcb.Parity = SPACEPARITY;
1607 RETURN_ERROR(SP_ERR_ARG, "Invalid parity setting");
1611 if (config->stopbits >= 0) {
1612 switch (config->stopbits) {
1613 /* Note: There's also ONE5STOPBITS == 1.5 (unneeded so far). */
1615 data->dcb.StopBits = ONESTOPBIT;
1618 data->dcb.StopBits = TWOSTOPBITS;
1621 RETURN_ERROR(SP_ERR_ARG, "Invalid stop bit setting");
1625 if (config->rts >= 0) {
1626 switch (config->rts) {
1628 data->dcb.fRtsControl = RTS_CONTROL_DISABLE;
1631 data->dcb.fRtsControl = RTS_CONTROL_ENABLE;
1633 case SP_RTS_FLOW_CONTROL:
1634 data->dcb.fRtsControl = RTS_CONTROL_HANDSHAKE;
1637 RETURN_ERROR(SP_ERR_ARG, "Invalid RTS setting");
1641 if (config->cts >= 0) {
1642 switch (config->cts) {
1644 data->dcb.fOutxCtsFlow = FALSE;
1646 case SP_CTS_FLOW_CONTROL:
1647 data->dcb.fOutxCtsFlow = TRUE;
1650 RETURN_ERROR(SP_ERR_ARG, "Invalid CTS setting");
1654 if (config->dtr >= 0) {
1655 switch (config->dtr) {
1657 data->dcb.fDtrControl = DTR_CONTROL_DISABLE;
1660 data->dcb.fDtrControl = DTR_CONTROL_ENABLE;
1662 case SP_DTR_FLOW_CONTROL:
1663 data->dcb.fDtrControl = DTR_CONTROL_HANDSHAKE;
1666 RETURN_ERROR(SP_ERR_ARG, "Invalid DTR setting");
1670 if (config->dsr >= 0) {
1671 switch (config->dsr) {
1673 data->dcb.fOutxDsrFlow = FALSE;
1675 case SP_DSR_FLOW_CONTROL:
1676 data->dcb.fOutxDsrFlow = TRUE;
1679 RETURN_ERROR(SP_ERR_ARG, "Invalid DSR setting");
1683 if (config->xon_xoff >= 0) {
1684 switch (config->xon_xoff) {
1685 case SP_XONXOFF_DISABLED:
1686 data->dcb.fInX = FALSE;
1687 data->dcb.fOutX = FALSE;
1690 data->dcb.fInX = TRUE;
1691 data->dcb.fOutX = FALSE;
1693 case SP_XONXOFF_OUT:
1694 data->dcb.fInX = FALSE;
1695 data->dcb.fOutX = TRUE;
1697 case SP_XONXOFF_INOUT:
1698 data->dcb.fInX = TRUE;
1699 data->dcb.fOutX = TRUE;
1702 RETURN_ERROR(SP_ERR_ARG, "Invalid XON/XOFF setting");
1706 if (!SetCommState(port->hdl, &data->dcb))
1707 RETURN_FAIL("SetCommState() failed");
1713 if (config->baudrate >= 0) {
1714 for (i = 0; i < NUM_STD_BAUDRATES; i++) {
1715 if (config->baudrate == std_baudrates[i].value) {
1716 if (cfsetospeed(&data->term, std_baudrates[i].index) < 0)
1717 RETURN_FAIL("cfsetospeed() failed");
1719 if (cfsetispeed(&data->term, std_baudrates[i].index) < 0)
1720 RETURN_FAIL("cfsetispeed() failed");
1725 /* Non-standard baud rate */
1726 if (i == NUM_STD_BAUDRATES) {
1728 /* Set "dummy" baud rate. */
1729 if (cfsetspeed(&data->term, B9600) < 0)
1730 RETURN_FAIL("cfsetspeed() failed");
1731 baud_nonstd = config->baudrate;
1732 #elif defined(__linux__)
1735 RETURN_ERROR(SP_ERR_SUPP, "Non-standard baudrate not supported");
1740 if (config->bits >= 0) {
1741 data->term.c_cflag &= ~CSIZE;
1742 switch (config->bits) {
1744 data->term.c_cflag |= CS8;
1747 data->term.c_cflag |= CS7;
1750 data->term.c_cflag |= CS6;
1753 data->term.c_cflag |= CS5;
1756 RETURN_ERROR(SP_ERR_ARG, "Invalid data bits setting");
1760 if (config->parity >= 0) {
1761 data->term.c_iflag &= ~IGNPAR;
1762 data->term.c_cflag &= ~(PARENB | PARODD);
1764 data->term.c_cflag &= ~CMSPAR;
1766 switch (config->parity) {
1767 case SP_PARITY_NONE:
1768 data->term.c_iflag |= IGNPAR;
1770 case SP_PARITY_EVEN:
1771 data->term.c_cflag |= PARENB;
1774 data->term.c_cflag |= PARENB | PARODD;
1777 case SP_PARITY_MARK:
1778 data->term.c_cflag |= PARENB | PARODD;
1779 data->term.c_cflag |= CMSPAR;
1781 case SP_PARITY_SPACE:
1782 data->term.c_cflag |= PARENB;
1783 data->term.c_cflag |= CMSPAR;
1786 case SP_PARITY_MARK:
1787 case SP_PARITY_SPACE:
1788 RETURN_ERROR(SP_ERR_SUPP, "Mark/space parity not supported");
1791 RETURN_ERROR(SP_ERR_ARG, "Invalid parity setting");
1795 if (config->stopbits >= 0) {
1796 data->term.c_cflag &= ~CSTOPB;
1797 switch (config->stopbits) {
1799 data->term.c_cflag &= ~CSTOPB;
1802 data->term.c_cflag |= CSTOPB;
1805 RETURN_ERROR(SP_ERR_ARG, "Invalid stop bits setting");
1809 if (config->rts >= 0 || config->cts >= 0) {
1810 if (data->termiox_supported) {
1811 data->flow &= ~(RTS_FLOW | CTS_FLOW);
1812 switch (config->rts) {
1815 controlbits = TIOCM_RTS;
1816 if (ioctl(port->fd, config->rts == SP_RTS_ON ? TIOCMBIS : TIOCMBIC, &controlbits) < 0)
1817 RETURN_FAIL("Setting RTS signal level failed");
1819 case SP_RTS_FLOW_CONTROL:
1820 data->flow |= RTS_FLOW;
1825 if (config->cts == SP_CTS_FLOW_CONTROL)
1826 data->flow |= CTS_FLOW;
1828 if (data->flow & (RTS_FLOW | CTS_FLOW))
1829 data->term.c_iflag |= CRTSCTS;
1831 data->term.c_iflag &= ~CRTSCTS;
1833 /* Asymmetric use of RTS/CTS not supported. */
1834 if (data->term.c_iflag & CRTSCTS) {
1835 /* Flow control can only be disabled for both RTS & CTS together. */
1836 if (config->rts >= 0 && config->rts != SP_RTS_FLOW_CONTROL) {
1837 if (config->cts != SP_CTS_IGNORE)
1838 RETURN_ERROR(SP_ERR_SUPP, "RTS & CTS flow control must be disabled together");
1840 if (config->cts >= 0 && config->cts != SP_CTS_FLOW_CONTROL) {
1841 if (config->rts <= 0 || config->rts == SP_RTS_FLOW_CONTROL)
1842 RETURN_ERROR(SP_ERR_SUPP, "RTS & CTS flow control must be disabled together");
1845 /* Flow control can only be enabled for both RTS & CTS together. */
1846 if (((config->rts == SP_RTS_FLOW_CONTROL) && (config->cts != SP_CTS_FLOW_CONTROL)) ||
1847 ((config->cts == SP_CTS_FLOW_CONTROL) && (config->rts != SP_RTS_FLOW_CONTROL)))
1848 RETURN_ERROR(SP_ERR_SUPP, "RTS & CTS flow control must be enabled together");
1851 if (config->rts >= 0) {
1852 if (config->rts == SP_RTS_FLOW_CONTROL) {
1853 data->term.c_iflag |= CRTSCTS;
1855 controlbits = TIOCM_RTS;
1856 if (ioctl(port->fd, config->rts == SP_RTS_ON ? TIOCMBIS : TIOCMBIC,
1858 RETURN_FAIL("Setting RTS signal level failed");
1864 if (config->dtr >= 0 || config->dsr >= 0) {
1865 if (data->termiox_supported) {
1866 data->flow &= ~(DTR_FLOW | DSR_FLOW);
1867 switch (config->dtr) {
1870 controlbits = TIOCM_DTR;
1871 if (ioctl(port->fd, config->dtr == SP_DTR_ON ? TIOCMBIS : TIOCMBIC, &controlbits) < 0)
1872 RETURN_FAIL("Setting DTR signal level failed");
1874 case SP_DTR_FLOW_CONTROL:
1875 data->flow |= DTR_FLOW;
1880 if (config->dsr == SP_DSR_FLOW_CONTROL)
1881 data->flow |= DSR_FLOW;
1883 /* DTR/DSR flow control not supported. */
1884 if (config->dtr == SP_DTR_FLOW_CONTROL || config->dsr == SP_DSR_FLOW_CONTROL)
1885 RETURN_ERROR(SP_ERR_SUPP, "DTR/DSR flow control not supported");
1887 if (config->dtr >= 0) {
1888 controlbits = TIOCM_DTR;
1889 if (ioctl(port->fd, config->dtr == SP_DTR_ON ? TIOCMBIS : TIOCMBIC,
1891 RETURN_FAIL("Setting DTR signal level failed");
1896 if (config->xon_xoff >= 0) {
1897 data->term.c_iflag &= ~(IXON | IXOFF | IXANY);
1898 switch (config->xon_xoff) {
1899 case SP_XONXOFF_DISABLED:
1902 data->term.c_iflag |= IXOFF;
1904 case SP_XONXOFF_OUT:
1905 data->term.c_iflag |= IXON | IXANY;
1907 case SP_XONXOFF_INOUT:
1908 data->term.c_iflag |= IXON | IXOFF | IXANY;
1911 RETURN_ERROR(SP_ERR_ARG, "Invalid XON/XOFF setting");
1915 if (tcsetattr(port->fd, TCSANOW, &data->term) < 0)
1916 RETURN_FAIL("tcsetattr() failed");
1919 if (baud_nonstd != B0) {
1920 if (ioctl(port->fd, IOSSIOSPEED, &baud_nonstd) == -1)
1921 RETURN_FAIL("IOSSIOSPEED ioctl failed");
1922 /* Set baud rates in data->term to correct, but incompatible
1923 * with tcsetattr() value, same as delivered by tcgetattr(). */
1924 if (cfsetspeed(&data->term, baud_nonstd) < 0)
1925 RETURN_FAIL("cfsetspeed() failed");
1927 #elif defined(__linux__)
1929 TRY(set_baudrate(port->fd, config->baudrate));
1931 if (data->termiox_supported)
1932 TRY(set_flow(port->fd, data->flow));
1936 #endif /* !_WIN32 */
1941 enum sp_return sp_new_config(struct sp_port_config **config_ptr)
1943 struct sp_port_config *config;
1945 TRACE("%p", config_ptr);
1948 RETURN_ERROR(SP_ERR_ARG, "Null result pointer");
1952 if (!(config = malloc(sizeof(struct sp_port_config))))
1953 RETURN_ERROR(SP_ERR_MEM, "config malloc failed");
1955 config->baudrate = -1;
1957 config->parity = -1;
1958 config->stopbits = -1;
1964 *config_ptr = config;
1969 void sp_free_config(struct sp_port_config *config)
1971 TRACE("%p", config);
1974 DEBUG("Null config");
1981 enum sp_return sp_get_config(struct sp_port *port, struct sp_port_config *config)
1983 struct port_data data;
1985 TRACE("%p, %p", port, config);
1990 RETURN_ERROR(SP_ERR_ARG, "Null config");
1992 TRY(get_config(port, &data, config));
1997 enum sp_return sp_set_config(struct sp_port *port, const struct sp_port_config *config)
1999 struct port_data data;
2000 struct sp_port_config prev_config;
2002 TRACE("%p, %p", port, config);
2007 RETURN_ERROR(SP_ERR_ARG, "Null config");
2009 TRY(get_config(port, &data, &prev_config));
2010 TRY(set_config(port, &data, config));
2015 #define CREATE_ACCESSORS(x, type) \
2016 enum sp_return sp_set_##x(struct sp_port *port, type x) { \
2017 struct port_data data; \
2018 struct sp_port_config config; \
2019 TRACE("%p, %d", port, x); \
2020 CHECK_OPEN_PORT(); \
2021 TRY(get_config(port, &data, &config)); \
2023 TRY(set_config(port, &data, &config)); \
2026 enum sp_return sp_get_config_##x(const struct sp_port_config *config, type *x) { \
2027 TRACE("%p, %p", config, x); \
2029 RETURN_ERROR(SP_ERR_ARG, "Null config"); \
2033 enum sp_return sp_set_config_##x(struct sp_port_config *config, type x) { \
2034 TRACE("%p, %d", config, x); \
2036 RETURN_ERROR(SP_ERR_ARG, "Null config"); \
2041 CREATE_ACCESSORS(baudrate, int)
2042 CREATE_ACCESSORS(bits, int)
2043 CREATE_ACCESSORS(parity, enum sp_parity)
2044 CREATE_ACCESSORS(stopbits, int)
2045 CREATE_ACCESSORS(rts, enum sp_rts)
2046 CREATE_ACCESSORS(cts, enum sp_cts)
2047 CREATE_ACCESSORS(dtr, enum sp_dtr)
2048 CREATE_ACCESSORS(dsr, enum sp_dsr)
2049 CREATE_ACCESSORS(xon_xoff, enum sp_xonxoff)
2051 enum sp_return sp_set_config_flowcontrol(struct sp_port_config *config, enum sp_flowcontrol flowcontrol)
2054 RETURN_ERROR(SP_ERR_ARG, "Null configuration");
2056 if (flowcontrol > SP_FLOWCONTROL_DTRDSR)
2057 RETURN_ERROR(SP_ERR_ARG, "Invalid flow control setting");
2059 if (flowcontrol == SP_FLOWCONTROL_XONXOFF)
2060 config->xon_xoff = SP_XONXOFF_INOUT;
2062 config->xon_xoff = SP_XONXOFF_DISABLED;
2064 if (flowcontrol == SP_FLOWCONTROL_RTSCTS) {
2065 config->rts = SP_RTS_FLOW_CONTROL;
2066 config->cts = SP_CTS_FLOW_CONTROL;
2068 if (config->rts == SP_RTS_FLOW_CONTROL)
2069 config->rts = SP_RTS_ON;
2070 config->cts = SP_CTS_IGNORE;
2073 if (flowcontrol == SP_FLOWCONTROL_DTRDSR) {
2074 config->dtr = SP_DTR_FLOW_CONTROL;
2075 config->dsr = SP_DSR_FLOW_CONTROL;
2077 if (config->dtr == SP_DTR_FLOW_CONTROL)
2078 config->dtr = SP_DTR_ON;
2079 config->dsr = SP_DSR_IGNORE;
2085 enum sp_return sp_set_flowcontrol(struct sp_port *port, enum sp_flowcontrol flowcontrol)
2087 struct port_data data;
2088 struct sp_port_config config;
2090 TRACE("%p, %d", port, flowcontrol);
2094 TRY(get_config(port, &data, &config));
2096 TRY(sp_set_config_flowcontrol(&config, flowcontrol));
2098 TRY(set_config(port, &data, &config));
2103 enum sp_return sp_get_signals(struct sp_port *port, enum sp_signal *signals)
2105 TRACE("%p, %p", port, signals);
2110 RETURN_ERROR(SP_ERR_ARG, "Null result pointer");
2112 DEBUG("Getting control signals for port %s", port->name);
2117 if (GetCommModemStatus(port->hdl, &bits) == 0)
2118 RETURN_FAIL("GetCommModemStatus() failed");
2119 if (bits & MS_CTS_ON)
2120 *signals |= SP_SIG_CTS;
2121 if (bits & MS_DSR_ON)
2122 *signals |= SP_SIG_DSR;
2123 if (bits & MS_RLSD_ON)
2124 *signals |= SP_SIG_DCD;
2125 if (bits & MS_RING_ON)
2126 *signals |= SP_SIG_RI;
2129 if (ioctl(port->fd, TIOCMGET, &bits) < 0)
2130 RETURN_FAIL("TIOCMGET ioctl failed");
2131 if (bits & TIOCM_CTS)
2132 *signals |= SP_SIG_CTS;
2133 if (bits & TIOCM_DSR)
2134 *signals |= SP_SIG_DSR;
2135 if (bits & TIOCM_CAR)
2136 *signals |= SP_SIG_DCD;
2137 if (bits & TIOCM_RNG)
2138 *signals |= SP_SIG_RI;
2143 enum sp_return sp_start_break(struct sp_port *port)
2149 if (SetCommBreak(port->hdl) == 0)
2150 RETURN_FAIL("SetCommBreak() failed");
2152 if (ioctl(port->fd, TIOCSBRK, 1) < 0)
2153 RETURN_FAIL("TIOCSBRK ioctl failed");
2159 enum sp_return sp_end_break(struct sp_port *port)
2165 if (ClearCommBreak(port->hdl) == 0)
2166 RETURN_FAIL("ClearCommBreak() failed");
2168 if (ioctl(port->fd, TIOCCBRK, 1) < 0)
2169 RETURN_FAIL("TIOCCBRK ioctl failed");
2175 int sp_last_error_code(void)
2179 RETURN_VALUE("%d", GetLastError());
2181 RETURN_VALUE("%d", errno);
2185 char *sp_last_error_message(void)
2191 DWORD error = GetLastError();
2194 FORMAT_MESSAGE_ALLOCATE_BUFFER |
2195 FORMAT_MESSAGE_FROM_SYSTEM |
2196 FORMAT_MESSAGE_IGNORE_INSERTS,
2199 MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
2203 RETURN_VALUE("%s", message);
2205 RETURN_VALUE("%s", strerror(errno));
2209 void sp_free_error_message(char *message)
2211 TRACE("%s", message);
2222 void sp_set_debug_handler(void (*handler)(const char *format, ...))
2224 TRACE("%p", handler);
2226 sp_debug_handler = handler;
2231 void sp_default_debug_handler(const char *format, ...)
2234 va_start(args, format);
2235 if (getenv("LIBSERIALPORT_DEBUG")) {
2236 fputs("sp: ", stderr);
2237 vfprintf(stderr, format, args);