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;
612 char *escaped_port_name;
614 /* Prefix port name with '\\.\' to work with ports above COM9. */
615 if (!(escaped_port_name = malloc(strlen(port->name + 5))))
616 RETURN_ERROR(SP_ERR_MEM, "Escaped port name malloc failed");
617 sprintf(escaped_port_name, "\\\\.\\%s", port->name);
619 /* Map 'flags' to the OS-specific settings. */
620 flags_and_attributes = FILE_ATTRIBUTE_NORMAL | FILE_FLAG_OVERLAPPED;
621 if (flags & SP_MODE_READ)
622 desired_access |= GENERIC_READ;
623 if (flags & SP_MODE_WRITE)
624 desired_access |= GENERIC_WRITE;
626 port->hdl = CreateFile(escaped_port_name, desired_access, 0, 0,
627 OPEN_EXISTING, flags_and_attributes, 0);
629 free(escaped_port_name);
631 if (port->hdl == INVALID_HANDLE_VALUE)
632 RETURN_FAIL("port CreateFile() failed");
634 /* All timeouts initially disabled. */
635 port->timeouts.ReadIntervalTimeout = 0;
636 port->timeouts.ReadTotalTimeoutMultiplier = 0;
637 port->timeouts.ReadTotalTimeoutConstant = 0;
638 port->timeouts.WriteTotalTimeoutMultiplier = 0;
639 port->timeouts.WriteTotalTimeoutConstant = 0;
641 if (SetCommTimeouts(port->hdl, &port->timeouts) == 0) {
643 RETURN_FAIL("SetCommTimeouts() failed");
646 /* Prepare OVERLAPPED structures. */
647 memset(&port->read_ovl, 0, sizeof(port->read_ovl));
648 memset(&port->write_ovl, 0, sizeof(port->write_ovl));
649 port->read_ovl.hEvent = INVALID_HANDLE_VALUE;
650 port->write_ovl.hEvent = INVALID_HANDLE_VALUE;
651 if ((port->read_ovl.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL)) == INVALID_HANDLE_VALUE) {
653 RETURN_FAIL("read event CreateEvent() failed");
655 if ((port->write_ovl.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL)) == INVALID_HANDLE_VALUE) {
657 RETURN_FAIL("write event CreateEvent() failed");
660 port->writing = FALSE;
663 int flags_local = O_NONBLOCK | O_NOCTTY;
665 /* Map 'flags' to the OS-specific settings. */
666 if (flags & (SP_MODE_READ | SP_MODE_WRITE))
667 flags_local |= O_RDWR;
668 else if (flags & SP_MODE_READ)
669 flags_local |= O_RDONLY;
670 else if (flags & SP_MODE_WRITE)
671 flags_local |= O_WRONLY;
673 if ((port->fd = open(port->name, flags_local)) < 0)
674 RETURN_FAIL("open() failed");
677 ret = get_config(port, &data, &config);
684 /* Set sane port settings. */
686 data.dcb.fBinary = TRUE;
687 data.dcb.fDsrSensitivity = FALSE;
688 data.dcb.fErrorChar = FALSE;
689 data.dcb.fNull = FALSE;
690 data.dcb.fAbortOnError = TRUE;
692 /* Turn off all fancy termios tricks, give us a raw channel. */
693 data.term.c_iflag &= ~(IGNBRK | BRKINT | PARMRK | ISTRIP | INLCR | IGNCR | ICRNL | IMAXBEL);
695 data.term.c_iflag &= ~IUCLC;
697 data.term.c_oflag &= ~(OPOST | ONLCR | OCRNL | ONOCR | ONLRET);
699 data.term.c_oflag &= ~OLCUC;
702 data.term.c_oflag &= ~NLDLY;
705 data.term.c_oflag &= ~CRDLY;
708 data.term.c_oflag &= ~TABDLY;
711 data.term.c_oflag &= ~BSDLY;
714 data.term.c_oflag &= ~VTDLY;
717 data.term.c_oflag &= ~FFDLY;
720 data.term.c_oflag &= ~OFILL;
722 data.term.c_lflag &= ~(ISIG | ICANON | ECHO | IEXTEN);
723 data.term.c_cc[VMIN] = 0;
724 data.term.c_cc[VTIME] = 0;
726 /* Ignore modem status lines; enable receiver; leave control lines alone on close. */
727 data.term.c_cflag |= (CLOCAL | CREAD | HUPCL);
730 ret = set_config(port, &data, &config);
740 enum sp_return sp_close(struct sp_port *port)
746 DEBUG("Closing port %s", port->name);
749 /* Returns non-zero upon success, 0 upon failure. */
750 if (CloseHandle(port->hdl) == 0)
751 RETURN_FAIL("port CloseHandle() failed");
752 port->hdl = INVALID_HANDLE_VALUE;
753 /* Close event handle created for overlapped reads. */
754 if (port->read_ovl.hEvent != INVALID_HANDLE_VALUE && CloseHandle(port->read_ovl.hEvent) == 0)
755 RETURN_FAIL("read event CloseHandle() failed");
756 /* Close event handle created for overlapped writes. */
757 if (port->write_ovl.hEvent != INVALID_HANDLE_VALUE && CloseHandle(port->write_ovl.hEvent) == 0)
758 RETURN_FAIL("write event CloseHandle() failed");
760 /* Returns 0 upon success, -1 upon failure. */
761 if (close(port->fd) == -1)
762 RETURN_FAIL("close() failed");
769 enum sp_return sp_flush(struct sp_port *port, enum sp_buffer buffers)
771 TRACE("%p, 0x%x", port, buffers);
775 if (buffers > SP_BUF_BOTH)
776 RETURN_ERROR(SP_ERR_ARG, "Invalid buffer selection");
778 const char *buffer_names[] = {"no", "input", "output", "both"};
780 DEBUG("Flushing %s buffers on port %s", buffer_names[buffers], port->name);
784 if (buffers & SP_BUF_INPUT)
785 flags |= PURGE_RXCLEAR;
786 if (buffers & SP_BUF_OUTPUT)
787 flags |= PURGE_TXCLEAR;
789 /* Returns non-zero upon success, 0 upon failure. */
790 if (PurgeComm(port->hdl, flags) == 0)
791 RETURN_FAIL("PurgeComm() failed");
794 if (buffers & SP_BUF_BOTH)
796 else if (buffers & SP_BUF_INPUT)
798 else if (buffers & SP_BUF_OUTPUT)
801 /* Returns 0 upon success, -1 upon failure. */
802 if (tcflush(port->fd, flags) < 0)
803 RETURN_FAIL("tcflush() failed");
808 enum sp_return sp_drain(struct sp_port *port)
814 DEBUG("Draining port %s", port->name);
817 /* Returns non-zero upon success, 0 upon failure. */
818 if (FlushFileBuffers(port->hdl) == 0)
819 RETURN_FAIL("FlushFileBuffers() failed");
826 result = ioctl(port->fd, TCSBRK, &arg);
828 result = tcdrain(port->fd);
831 if (errno == EINTR) {
832 DEBUG("tcdrain() was interrupted");
835 RETURN_FAIL("tcdrain() failed");
844 enum sp_return sp_blocking_write(struct sp_port *port, const void *buf, size_t count, unsigned int timeout)
846 TRACE("%p, %p, %d, %d", port, buf, count, timeout);
851 RETURN_ERROR(SP_ERR_ARG, "Null buffer");
854 DEBUG("Writing %d bytes to port %s, timeout %d ms", count, port->name, timeout);
856 DEBUG("Writing %d bytes to port %s, no timeout", count, port->name);
859 RETURN_VALUE("0", 0);
862 DWORD bytes_written = 0;
865 /* Wait for previous non-blocking write to complete, if any. */
867 DEBUG("Waiting for previous write to complete");
868 result = GetOverlappedResult(port->hdl, &port->write_ovl, &bytes_written, TRUE);
871 RETURN_FAIL("Previous write failed to complete");
872 DEBUG("Previous write completed");
876 port->timeouts.WriteTotalTimeoutConstant = timeout;
877 if (SetCommTimeouts(port->hdl, &port->timeouts) == 0)
878 RETURN_FAIL("SetCommTimeouts() failed");
881 if (WriteFile(port->hdl, buf, count, NULL, &port->write_ovl) == 0) {
882 if (GetLastError() == ERROR_IO_PENDING) {
883 DEBUG("Waiting for write to complete");
884 GetOverlappedResult(port->hdl, &port->write_ovl, &bytes_written, TRUE);
885 DEBUG("Write completed, %d/%d bytes written", bytes_written, count);
886 RETURN_VALUE("%d", bytes_written);
888 RETURN_FAIL("WriteFile() failed");
891 DEBUG("Write completed immediately");
892 RETURN_VALUE("%d", count);
895 size_t bytes_written = 0;
896 unsigned char *ptr = (unsigned char *) buf;
897 struct timeval start, delta, now, end = {0, 0};
902 /* Get time at start of operation. */
903 gettimeofday(&start, NULL);
904 /* Define duration of timeout. */
905 delta.tv_sec = timeout / 1000;
906 delta.tv_usec = (timeout % 1000) * 1000;
907 /* Calculate time at which we should give up. */
908 timeradd(&start, &delta, &end);
911 /* Loop until we have written the requested number of bytes. */
912 while (bytes_written < count)
914 /* Wait until space is available. */
916 FD_SET(port->fd, &fds);
918 gettimeofday(&now, NULL);
919 if (timercmp(&now, &end, >)) {
920 DEBUG("write timed out");
921 RETURN_VALUE("%d", bytes_written);
923 timersub(&end, &now, &delta);
925 result = select(port->fd + 1, NULL, &fds, NULL, timeout ? &delta : NULL);
927 if (errno == EINTR) {
928 DEBUG("select() call was interrupted, repeating");
931 RETURN_FAIL("select() failed");
933 } else if (result == 0) {
934 DEBUG("write timed out");
935 RETURN_VALUE("%d", bytes_written);
939 result = write(port->fd, ptr, count - bytes_written);
943 /* This shouldn't happen because we did a select() first, but handle anyway. */
946 /* This is an actual failure. */
947 RETURN_FAIL("write() failed");
950 bytes_written += result;
954 RETURN_VALUE("%d", bytes_written);
958 enum sp_return sp_nonblocking_write(struct sp_port *port, const void *buf, size_t count)
960 TRACE("%p, %p, %d", port, buf, count);
965 RETURN_ERROR(SP_ERR_ARG, "Null buffer");
967 DEBUG("Writing up to %d bytes to port %s", count, port->name);
970 RETURN_VALUE("0", 0);
974 BYTE *ptr = (BYTE *) buf;
976 /* Check whether previous write is complete. */
978 if (HasOverlappedIoCompleted(&port->write_ovl)) {
979 DEBUG("Previous write completed");
982 DEBUG("Previous write not complete");
983 /* Can't take a new write until the previous one finishes. */
984 RETURN_VALUE("0", 0);
989 port->timeouts.WriteTotalTimeoutConstant = 0;
990 if (SetCommTimeouts(port->hdl, &port->timeouts) == 0)
991 RETURN_FAIL("SetCommTimeouts() failed");
993 /* Keep writing data until the OS has to actually start an async IO for it.
994 * At that point we know the buffer is full. */
995 while (written < count)
997 /* Copy first byte of user buffer. */
998 port->pending_byte = *ptr++;
1000 /* Start asynchronous write. */
1001 if (WriteFile(port->hdl, &port->pending_byte, 1, NULL, &port->write_ovl) == 0) {
1002 if (GetLastError() == ERROR_IO_PENDING) {
1003 if (HasOverlappedIoCompleted(&port->write_ovl)) {
1004 DEBUG("Asynchronous write completed immediately");
1009 DEBUG("Asynchronous write running");
1011 RETURN_VALUE("%d", ++written);
1014 /* Actual failure of some kind. */
1015 RETURN_FAIL("WriteFile() failed");
1018 DEBUG("Single byte written immediately.");
1023 DEBUG("All bytes written immediately.");
1025 RETURN_VALUE("%d", written);
1027 /* Returns the number of bytes written, or -1 upon failure. */
1028 ssize_t written = write(port->fd, buf, count);
1031 RETURN_FAIL("write() failed");
1033 RETURN_VALUE("%d", written);
1037 enum sp_return sp_blocking_read(struct sp_port *port, void *buf, size_t count, unsigned int timeout)
1039 TRACE("%p, %p, %d, %d", port, buf, count, timeout);
1044 RETURN_ERROR(SP_ERR_ARG, "Null buffer");
1047 DEBUG("Reading %d bytes from port %s, timeout %d ms", count, port->name, timeout);
1049 DEBUG("Reading %d bytes from port %s, no timeout", count, port->name);
1052 RETURN_VALUE("0", 0);
1055 DWORD bytes_read = 0;
1058 port->timeouts.ReadIntervalTimeout = 0;
1059 port->timeouts.ReadTotalTimeoutConstant = timeout;
1060 if (SetCommTimeouts(port->hdl, &port->timeouts) == 0)
1061 RETURN_FAIL("SetCommTimeouts() failed");
1064 if (ReadFile(port->hdl, buf, count, NULL, &port->read_ovl) == 0) {
1065 if (GetLastError() == ERROR_IO_PENDING) {
1066 DEBUG("Waiting for read to complete");
1067 GetOverlappedResult(port->hdl, &port->read_ovl, &bytes_read, TRUE);
1068 DEBUG("Read completed, %d/%d bytes read", bytes_read, count);
1069 RETURN_VALUE("%d", bytes_read);
1071 RETURN_FAIL("ReadFile() failed");
1074 DEBUG("Read completed immediately");
1075 RETURN_VALUE("%d", count);
1078 size_t bytes_read = 0;
1079 unsigned char *ptr = (unsigned char *) buf;
1080 struct timeval start, delta, now, end = {0, 0};
1085 /* Get time at start of operation. */
1086 gettimeofday(&start, NULL);
1087 /* Define duration of timeout. */
1088 delta.tv_sec = timeout / 1000;
1089 delta.tv_usec = (timeout % 1000) * 1000;
1090 /* Calculate time at which we should give up. */
1091 timeradd(&start, &delta, &end);
1094 /* Loop until we have the requested number of bytes. */
1095 while (bytes_read < count)
1097 /* Wait until data is available. */
1099 FD_SET(port->fd, &fds);
1101 gettimeofday(&now, NULL);
1102 if (timercmp(&now, &end, >))
1103 /* Timeout has expired. */
1104 RETURN_VALUE("%d", bytes_read);
1105 timersub(&end, &now, &delta);
1107 result = select(port->fd + 1, &fds, NULL, NULL, timeout ? &delta : NULL);
1109 if (errno == EINTR) {
1110 DEBUG("select() call was interrupted, repeating");
1113 RETURN_FAIL("select() failed");
1115 } else if (result == 0) {
1116 DEBUG("read timed out");
1117 RETURN_VALUE("%d", bytes_read);
1121 result = read(port->fd, ptr, count - bytes_read);
1124 if (errno == EAGAIN)
1125 /* This shouldn't happen because we did a select() first, but handle anyway. */
1128 /* This is an actual failure. */
1129 RETURN_FAIL("read() failed");
1132 bytes_read += result;
1136 RETURN_VALUE("%d", bytes_read);
1140 enum sp_return sp_nonblocking_read(struct sp_port *port, void *buf, size_t count)
1142 TRACE("%p, %p, %d", port, buf, count);
1147 RETURN_ERROR(SP_ERR_ARG, "Null buffer");
1149 DEBUG("Reading up to %d bytes from port %s", count, port->name);
1155 port->timeouts.ReadIntervalTimeout = MAXDWORD;
1156 port->timeouts.ReadTotalTimeoutConstant = 0;
1157 if (SetCommTimeouts(port->hdl, &port->timeouts) == 0)
1158 RETURN_FAIL("SetCommTimeouts() failed");
1161 if (ReadFile(port->hdl, buf, count, NULL, &port->read_ovl) == 0)
1162 RETURN_FAIL("ReadFile() failed");
1164 /* Get number of bytes read. */
1165 if (GetOverlappedResult(port->hdl, &port->read_ovl, &bytes_read, TRUE) == 0)
1166 RETURN_FAIL("GetOverlappedResult() failed");
1168 RETURN_VALUE("%d", bytes_read);
1172 /* Returns the number of bytes read, or -1 upon failure. */
1173 if ((bytes_read = read(port->fd, buf, count)) < 0) {
1174 if (errno == EAGAIN)
1175 /* No bytes available. */
1178 /* This is an actual failure. */
1179 RETURN_FAIL("read() failed");
1181 RETURN_VALUE("%d", bytes_read);
1185 enum sp_return sp_input_waiting(struct sp_port *port)
1191 DEBUG("Checking input bytes waiting on port %s", port->name);
1197 if (ClearCommError(port->hdl, &errors, &comstat) == 0)
1198 RETURN_FAIL("ClearComError() failed");
1199 RETURN_VALUE("%d", comstat.cbInQue);
1202 if (ioctl(port->fd, TIOCINQ, &bytes_waiting) < 0)
1203 RETURN_FAIL("TIOCINQ ioctl failed");
1204 RETURN_VALUE("%d", bytes_waiting);
1208 enum sp_return sp_output_waiting(struct sp_port *port)
1214 DEBUG("Checking output bytes waiting on port %s", port->name);
1220 if (ClearCommError(port->hdl, &errors, &comstat) == 0)
1221 RETURN_FAIL("ClearComError() failed");
1222 RETURN_VALUE("%d", comstat.cbOutQue);
1225 if (ioctl(port->fd, TIOCOUTQ, &bytes_waiting) < 0)
1226 RETURN_FAIL("TIOCOUTQ ioctl failed");
1227 RETURN_VALUE("%d", bytes_waiting);
1232 static enum sp_return get_baudrate(int fd, int *baudrate)
1236 TRACE("%d, %p", fd, baudrate);
1238 DEBUG("Getting baud rate");
1240 if (!(data = malloc(get_termios_size())))
1241 RETURN_ERROR(SP_ERR_MEM, "termios malloc failed");
1243 if (ioctl(fd, get_termios_get_ioctl(), data) < 0) {
1245 RETURN_FAIL("getting termios failed");
1248 *baudrate = get_termios_speed(data);
1255 static enum sp_return set_baudrate(int fd, int baudrate)
1259 TRACE("%d, %d", fd, baudrate);
1261 DEBUG("Getting baud rate");
1263 if (!(data = malloc(get_termios_size())))
1264 RETURN_ERROR(SP_ERR_MEM, "termios malloc failed");
1266 if (ioctl(fd, get_termios_get_ioctl(), data) < 0) {
1268 RETURN_FAIL("getting termios failed");
1271 DEBUG("Setting baud rate");
1273 set_termios_speed(data, baudrate);
1275 if (ioctl(fd, get_termios_set_ioctl(), data) < 0) {
1277 RETURN_FAIL("setting termios failed");
1286 static enum sp_return get_flow(int fd, int *flow)
1290 TRACE("%d, %p", fd, flow);
1292 DEBUG("Getting advanced flow control");
1294 if (!(data = malloc(get_termiox_size())))
1295 RETURN_ERROR(SP_ERR_MEM, "termiox malloc failed");
1297 if (ioctl(fd, TCGETX, data) < 0) {
1299 RETURN_FAIL("getting termiox failed");
1302 *flow = get_termiox_flow(data);
1309 static enum sp_return set_flow(int fd, int flow)
1313 TRACE("%d, %d", fd, flow);
1315 DEBUG("Getting advanced flow control");
1317 if (!(data = malloc(get_termiox_size())))
1318 RETURN_ERROR(SP_ERR_MEM, "termiox malloc failed");
1320 if (ioctl(fd, TCGETX, data) < 0) {
1322 RETURN_FAIL("getting termiox failed");
1325 DEBUG("Setting advanced flow control");
1327 set_termiox_flow(data, flow);
1329 if (ioctl(fd, TCSETX, data) < 0) {
1331 RETURN_FAIL("setting termiox failed");
1338 #endif /* USE_TERMIOX */
1339 #endif /* __linux__ */
1341 static enum sp_return get_config(struct sp_port *port, struct port_data *data,
1342 struct sp_port_config *config)
1346 TRACE("%p, %p, %p", port, data, config);
1348 DEBUG("Getting configuration for port %s", port->name);
1351 if (!GetCommState(port->hdl, &data->dcb))
1352 RETURN_FAIL("GetCommState() failed");
1354 for (i = 0; i < NUM_STD_BAUDRATES; i++) {
1355 if (data->dcb.BaudRate == std_baudrates[i].index) {
1356 config->baudrate = std_baudrates[i].value;
1361 if (i == NUM_STD_BAUDRATES)
1362 /* BaudRate field can be either an index or a custom baud rate. */
1363 config->baudrate = data->dcb.BaudRate;
1365 config->bits = data->dcb.ByteSize;
1367 if (data->dcb.fParity)
1368 switch (data->dcb.Parity) {
1370 config->parity = SP_PARITY_NONE;
1373 config->parity = SP_PARITY_ODD;
1376 config->parity = SP_PARITY_EVEN;
1379 config->parity = SP_PARITY_MARK;
1382 config->parity = SP_PARITY_SPACE;
1385 config->parity = -1;
1388 config->parity = SP_PARITY_NONE;
1390 switch (data->dcb.StopBits) {
1392 config->stopbits = 1;
1395 config->stopbits = 2;
1398 config->stopbits = -1;
1401 switch (data->dcb.fRtsControl) {
1402 case RTS_CONTROL_DISABLE:
1403 config->rts = SP_RTS_OFF;
1405 case RTS_CONTROL_ENABLE:
1406 config->rts = SP_RTS_ON;
1408 case RTS_CONTROL_HANDSHAKE:
1409 config->rts = SP_RTS_FLOW_CONTROL;
1415 config->cts = data->dcb.fOutxCtsFlow ? SP_CTS_FLOW_CONTROL : SP_CTS_IGNORE;
1417 switch (data->dcb.fDtrControl) {
1418 case DTR_CONTROL_DISABLE:
1419 config->dtr = SP_DTR_OFF;
1421 case DTR_CONTROL_ENABLE:
1422 config->dtr = SP_DTR_ON;
1424 case DTR_CONTROL_HANDSHAKE:
1425 config->dtr = SP_DTR_FLOW_CONTROL;
1431 config->dsr = data->dcb.fOutxDsrFlow ? SP_DSR_FLOW_CONTROL : SP_DSR_IGNORE;
1433 if (data->dcb.fInX) {
1434 if (data->dcb.fOutX)
1435 config->xon_xoff = SP_XONXOFF_INOUT;
1437 config->xon_xoff = SP_XONXOFF_IN;
1439 if (data->dcb.fOutX)
1440 config->xon_xoff = SP_XONXOFF_OUT;
1442 config->xon_xoff = SP_XONXOFF_DISABLED;
1447 if (tcgetattr(port->fd, &data->term) < 0)
1448 RETURN_FAIL("tcgetattr() failed");
1450 if (ioctl(port->fd, TIOCMGET, &data->controlbits) < 0)
1451 RETURN_FAIL("TIOCMGET ioctl failed");
1454 int ret = get_flow(port->fd, &data->flow);
1456 if (ret == SP_ERR_FAIL && errno == EINVAL)
1457 data->termiox_supported = 0;
1459 RETURN_CODEVAL(ret);
1461 data->termiox_supported = 1;
1463 data->termiox_supported = 0;
1466 for (i = 0; i < NUM_STD_BAUDRATES; i++) {
1467 if (cfgetispeed(&data->term) == std_baudrates[i].index) {
1468 config->baudrate = std_baudrates[i].value;
1473 if (i == NUM_STD_BAUDRATES) {
1475 config->baudrate = (int)data->term.c_ispeed;
1476 #elif defined(__linux__)
1477 TRY(get_baudrate(port->fd, &config->baudrate));
1479 config->baudrate = -1;
1483 switch (data->term.c_cflag & CSIZE) {
1500 if (!(data->term.c_cflag & PARENB) && (data->term.c_iflag & IGNPAR))
1501 config->parity = SP_PARITY_NONE;
1502 else if (!(data->term.c_cflag & PARENB) || (data->term.c_iflag & IGNPAR))
1503 config->parity = -1;
1505 else if (data->term.c_cflag & CMSPAR)
1506 config->parity = (data->term.c_cflag & PARODD) ? SP_PARITY_MARK : SP_PARITY_SPACE;
1509 config->parity = (data->term.c_cflag & PARODD) ? SP_PARITY_ODD : SP_PARITY_EVEN;
1511 config->stopbits = (data->term.c_cflag & CSTOPB) ? 2 : 1;
1513 if (data->term.c_cflag & CRTSCTS) {
1514 config->rts = SP_RTS_FLOW_CONTROL;
1515 config->cts = SP_CTS_FLOW_CONTROL;
1517 if (data->termiox_supported && data->flow & RTS_FLOW)
1518 config->rts = SP_RTS_FLOW_CONTROL;
1520 config->rts = (data->controlbits & TIOCM_RTS) ? SP_RTS_ON : SP_RTS_OFF;
1522 config->cts = (data->termiox_supported && data->flow & CTS_FLOW) ?
1523 SP_CTS_FLOW_CONTROL : SP_CTS_IGNORE;
1526 if (data->termiox_supported && data->flow & DTR_FLOW)
1527 config->dtr = SP_DTR_FLOW_CONTROL;
1529 config->dtr = (data->controlbits & TIOCM_DTR) ? SP_DTR_ON : SP_DTR_OFF;
1531 config->dsr = (data->termiox_supported && data->flow & DSR_FLOW) ?
1532 SP_DSR_FLOW_CONTROL : SP_DSR_IGNORE;
1534 if (data->term.c_iflag & IXOFF) {
1535 if (data->term.c_iflag & IXON)
1536 config->xon_xoff = SP_XONXOFF_INOUT;
1538 config->xon_xoff = SP_XONXOFF_IN;
1540 if (data->term.c_iflag & IXON)
1541 config->xon_xoff = SP_XONXOFF_OUT;
1543 config->xon_xoff = SP_XONXOFF_DISABLED;
1550 static enum sp_return set_config(struct sp_port *port, struct port_data *data,
1551 const struct sp_port_config *config)
1555 BAUD_TYPE baud_nonstd;
1560 int baud_nonstd = 0;
1563 TRACE("%p, %p, %p", port, data, config);
1565 DEBUG("Setting configuration for port %s", port->name);
1568 if (config->baudrate >= 0) {
1569 for (i = 0; i < NUM_STD_BAUDRATES; i++) {
1570 if (config->baudrate == std_baudrates[i].value) {
1571 data->dcb.BaudRate = std_baudrates[i].index;
1576 if (i == NUM_STD_BAUDRATES)
1577 data->dcb.BaudRate = config->baudrate;
1580 if (config->bits >= 0)
1581 data->dcb.ByteSize = config->bits;
1583 if (config->parity >= 0) {
1584 switch (config->parity) {
1585 /* Note: There's also SPACEPARITY, MARKPARITY (unneeded so far). */
1586 case SP_PARITY_NONE:
1587 data->dcb.Parity = NOPARITY;
1590 data->dcb.Parity = ODDPARITY;
1592 case SP_PARITY_EVEN:
1593 data->dcb.Parity = EVENPARITY;
1595 case SP_PARITY_MARK:
1596 data->dcb.Parity = MARKPARITY;
1598 case SP_PARITY_SPACE:
1599 data->dcb.Parity = SPACEPARITY;
1602 RETURN_ERROR(SP_ERR_ARG, "Invalid parity setting");
1606 if (config->stopbits >= 0) {
1607 switch (config->stopbits) {
1608 /* Note: There's also ONE5STOPBITS == 1.5 (unneeded so far). */
1610 data->dcb.StopBits = ONESTOPBIT;
1613 data->dcb.StopBits = TWOSTOPBITS;
1616 RETURN_ERROR(SP_ERR_ARG, "Invalid stop bit setting");
1620 if (config->rts >= 0) {
1621 switch (config->rts) {
1623 data->dcb.fRtsControl = RTS_CONTROL_DISABLE;
1626 data->dcb.fRtsControl = RTS_CONTROL_ENABLE;
1628 case SP_RTS_FLOW_CONTROL:
1629 data->dcb.fRtsControl = RTS_CONTROL_HANDSHAKE;
1632 RETURN_ERROR(SP_ERR_ARG, "Invalid RTS setting");
1636 if (config->cts >= 0) {
1637 switch (config->cts) {
1639 data->dcb.fOutxCtsFlow = FALSE;
1641 case SP_CTS_FLOW_CONTROL:
1642 data->dcb.fOutxCtsFlow = TRUE;
1645 RETURN_ERROR(SP_ERR_ARG, "Invalid CTS setting");
1649 if (config->dtr >= 0) {
1650 switch (config->dtr) {
1652 data->dcb.fDtrControl = DTR_CONTROL_DISABLE;
1655 data->dcb.fDtrControl = DTR_CONTROL_ENABLE;
1657 case SP_DTR_FLOW_CONTROL:
1658 data->dcb.fDtrControl = DTR_CONTROL_HANDSHAKE;
1661 RETURN_ERROR(SP_ERR_ARG, "Invalid DTR setting");
1665 if (config->dsr >= 0) {
1666 switch (config->dsr) {
1668 data->dcb.fOutxDsrFlow = FALSE;
1670 case SP_DSR_FLOW_CONTROL:
1671 data->dcb.fOutxDsrFlow = TRUE;
1674 RETURN_ERROR(SP_ERR_ARG, "Invalid DSR setting");
1678 if (config->xon_xoff >= 0) {
1679 switch (config->xon_xoff) {
1680 case SP_XONXOFF_DISABLED:
1681 data->dcb.fInX = FALSE;
1682 data->dcb.fOutX = FALSE;
1685 data->dcb.fInX = TRUE;
1686 data->dcb.fOutX = FALSE;
1688 case SP_XONXOFF_OUT:
1689 data->dcb.fInX = FALSE;
1690 data->dcb.fOutX = TRUE;
1692 case SP_XONXOFF_INOUT:
1693 data->dcb.fInX = TRUE;
1694 data->dcb.fOutX = TRUE;
1697 RETURN_ERROR(SP_ERR_ARG, "Invalid XON/XOFF setting");
1701 if (!SetCommState(port->hdl, &data->dcb))
1702 RETURN_FAIL("SetCommState() failed");
1708 if (config->baudrate >= 0) {
1709 for (i = 0; i < NUM_STD_BAUDRATES; i++) {
1710 if (config->baudrate == std_baudrates[i].value) {
1711 if (cfsetospeed(&data->term, std_baudrates[i].index) < 0)
1712 RETURN_FAIL("cfsetospeed() failed");
1714 if (cfsetispeed(&data->term, std_baudrates[i].index) < 0)
1715 RETURN_FAIL("cfsetispeed() failed");
1720 /* Non-standard baud rate */
1721 if (i == NUM_STD_BAUDRATES) {
1723 /* Set "dummy" baud rate. */
1724 if (cfsetspeed(&data->term, B9600) < 0)
1725 RETURN_FAIL("cfsetspeed() failed");
1726 baud_nonstd = config->baudrate;
1727 #elif defined(__linux__)
1730 RETURN_ERROR(SP_ERR_SUPP, "Non-standard baudrate not supported");
1735 if (config->bits >= 0) {
1736 data->term.c_cflag &= ~CSIZE;
1737 switch (config->bits) {
1739 data->term.c_cflag |= CS8;
1742 data->term.c_cflag |= CS7;
1745 data->term.c_cflag |= CS6;
1748 data->term.c_cflag |= CS5;
1751 RETURN_ERROR(SP_ERR_ARG, "Invalid data bits setting");
1755 if (config->parity >= 0) {
1756 data->term.c_iflag &= ~IGNPAR;
1757 data->term.c_cflag &= ~(PARENB | PARODD);
1759 data->term.c_cflag &= ~CMSPAR;
1761 switch (config->parity) {
1762 case SP_PARITY_NONE:
1763 data->term.c_iflag |= IGNPAR;
1765 case SP_PARITY_EVEN:
1766 data->term.c_cflag |= PARENB;
1769 data->term.c_cflag |= PARENB | PARODD;
1772 case SP_PARITY_MARK:
1773 data->term.c_cflag |= PARENB | PARODD;
1774 data->term.c_cflag |= CMSPAR;
1776 case SP_PARITY_SPACE:
1777 data->term.c_cflag |= PARENB;
1778 data->term.c_cflag |= CMSPAR;
1781 case SP_PARITY_MARK:
1782 case SP_PARITY_SPACE:
1783 RETURN_ERROR(SP_ERR_SUPP, "Mark/space parity not supported");
1786 RETURN_ERROR(SP_ERR_ARG, "Invalid parity setting");
1790 if (config->stopbits >= 0) {
1791 data->term.c_cflag &= ~CSTOPB;
1792 switch (config->stopbits) {
1794 data->term.c_cflag &= ~CSTOPB;
1797 data->term.c_cflag |= CSTOPB;
1800 RETURN_ERROR(SP_ERR_ARG, "Invalid stop bits setting");
1804 if (config->rts >= 0 || config->cts >= 0) {
1805 if (data->termiox_supported) {
1806 data->flow &= ~(RTS_FLOW | CTS_FLOW);
1807 switch (config->rts) {
1810 controlbits = TIOCM_RTS;
1811 if (ioctl(port->fd, config->rts == SP_RTS_ON ? TIOCMBIS : TIOCMBIC, &controlbits) < 0)
1812 RETURN_FAIL("Setting RTS signal level failed");
1814 case SP_RTS_FLOW_CONTROL:
1815 data->flow |= RTS_FLOW;
1820 if (config->cts == SP_CTS_FLOW_CONTROL)
1821 data->flow |= CTS_FLOW;
1823 if (data->flow & (RTS_FLOW | CTS_FLOW))
1824 data->term.c_iflag |= CRTSCTS;
1826 data->term.c_iflag &= ~CRTSCTS;
1828 /* Asymmetric use of RTS/CTS not supported. */
1829 if (data->term.c_iflag & CRTSCTS) {
1830 /* Flow control can only be disabled for both RTS & CTS together. */
1831 if (config->rts >= 0 && config->rts != SP_RTS_FLOW_CONTROL) {
1832 if (config->cts != SP_CTS_IGNORE)
1833 RETURN_ERROR(SP_ERR_SUPP, "RTS & CTS flow control must be disabled together");
1835 if (config->cts >= 0 && config->cts != SP_CTS_FLOW_CONTROL) {
1836 if (config->rts <= 0 || config->rts == SP_RTS_FLOW_CONTROL)
1837 RETURN_ERROR(SP_ERR_SUPP, "RTS & CTS flow control must be disabled together");
1840 /* Flow control can only be enabled for both RTS & CTS together. */
1841 if (((config->rts == SP_RTS_FLOW_CONTROL) && (config->cts != SP_CTS_FLOW_CONTROL)) ||
1842 ((config->cts == SP_CTS_FLOW_CONTROL) && (config->rts != SP_RTS_FLOW_CONTROL)))
1843 RETURN_ERROR(SP_ERR_SUPP, "RTS & CTS flow control must be enabled together");
1846 if (config->rts >= 0) {
1847 if (config->rts == SP_RTS_FLOW_CONTROL) {
1848 data->term.c_iflag |= CRTSCTS;
1850 controlbits = TIOCM_RTS;
1851 if (ioctl(port->fd, config->rts == SP_RTS_ON ? TIOCMBIS : TIOCMBIC,
1853 RETURN_FAIL("Setting RTS signal level failed");
1859 if (config->dtr >= 0 || config->dsr >= 0) {
1860 if (data->termiox_supported) {
1861 data->flow &= ~(DTR_FLOW | DSR_FLOW);
1862 switch (config->dtr) {
1865 controlbits = TIOCM_DTR;
1866 if (ioctl(port->fd, config->dtr == SP_DTR_ON ? TIOCMBIS : TIOCMBIC, &controlbits) < 0)
1867 RETURN_FAIL("Setting DTR signal level failed");
1869 case SP_DTR_FLOW_CONTROL:
1870 data->flow |= DTR_FLOW;
1875 if (config->dsr == SP_DSR_FLOW_CONTROL)
1876 data->flow |= DSR_FLOW;
1878 /* DTR/DSR flow control not supported. */
1879 if (config->dtr == SP_DTR_FLOW_CONTROL || config->dsr == SP_DSR_FLOW_CONTROL)
1880 RETURN_ERROR(SP_ERR_SUPP, "DTR/DSR flow control not supported");
1882 if (config->dtr >= 0) {
1883 controlbits = TIOCM_DTR;
1884 if (ioctl(port->fd, config->dtr == SP_DTR_ON ? TIOCMBIS : TIOCMBIC,
1886 RETURN_FAIL("Setting DTR signal level failed");
1891 if (config->xon_xoff >= 0) {
1892 data->term.c_iflag &= ~(IXON | IXOFF | IXANY);
1893 switch (config->xon_xoff) {
1894 case SP_XONXOFF_DISABLED:
1897 data->term.c_iflag |= IXOFF;
1899 case SP_XONXOFF_OUT:
1900 data->term.c_iflag |= IXON | IXANY;
1902 case SP_XONXOFF_INOUT:
1903 data->term.c_iflag |= IXON | IXOFF | IXANY;
1906 RETURN_ERROR(SP_ERR_ARG, "Invalid XON/XOFF setting");
1910 if (tcsetattr(port->fd, TCSANOW, &data->term) < 0)
1911 RETURN_FAIL("tcsetattr() failed");
1914 if (baud_nonstd != B0) {
1915 if (ioctl(port->fd, IOSSIOSPEED, &baud_nonstd) == -1)
1916 RETURN_FAIL("IOSSIOSPEED ioctl failed");
1917 /* Set baud rates in data->term to correct, but incompatible
1918 * with tcsetattr() value, same as delivered by tcgetattr(). */
1919 if (cfsetspeed(&data->term, baud_nonstd) < 0)
1920 RETURN_FAIL("cfsetspeed() failed");
1922 #elif defined(__linux__)
1924 TRY(set_baudrate(port->fd, config->baudrate));
1926 if (data->termiox_supported)
1927 TRY(set_flow(port->fd, data->flow));
1931 #endif /* !_WIN32 */
1936 enum sp_return sp_new_config(struct sp_port_config **config_ptr)
1938 struct sp_port_config *config;
1940 TRACE("%p", config_ptr);
1943 RETURN_ERROR(SP_ERR_ARG, "Null result pointer");
1947 if (!(config = malloc(sizeof(struct sp_port_config))))
1948 RETURN_ERROR(SP_ERR_MEM, "config malloc failed");
1950 config->baudrate = -1;
1952 config->parity = -1;
1953 config->stopbits = -1;
1959 *config_ptr = config;
1964 void sp_free_config(struct sp_port_config *config)
1966 TRACE("%p", config);
1969 DEBUG("Null config");
1976 enum sp_return sp_get_config(struct sp_port *port, struct sp_port_config *config)
1978 struct port_data data;
1980 TRACE("%p, %p", port, config);
1985 RETURN_ERROR(SP_ERR_ARG, "Null config");
1987 TRY(get_config(port, &data, config));
1992 enum sp_return sp_set_config(struct sp_port *port, const struct sp_port_config *config)
1994 struct port_data data;
1995 struct sp_port_config prev_config;
1997 TRACE("%p, %p", port, config);
2002 RETURN_ERROR(SP_ERR_ARG, "Null config");
2004 TRY(get_config(port, &data, &prev_config));
2005 TRY(set_config(port, &data, config));
2010 #define CREATE_ACCESSORS(x, type) \
2011 enum sp_return sp_set_##x(struct sp_port *port, type x) { \
2012 struct port_data data; \
2013 struct sp_port_config config; \
2014 TRACE("%p, %d", port, x); \
2015 CHECK_OPEN_PORT(); \
2016 TRY(get_config(port, &data, &config)); \
2018 TRY(set_config(port, &data, &config)); \
2021 enum sp_return sp_get_config_##x(const struct sp_port_config *config, type *x) { \
2022 TRACE("%p, %p", config, x); \
2024 RETURN_ERROR(SP_ERR_ARG, "Null config"); \
2028 enum sp_return sp_set_config_##x(struct sp_port_config *config, type x) { \
2029 TRACE("%p, %d", config, x); \
2031 RETURN_ERROR(SP_ERR_ARG, "Null config"); \
2036 CREATE_ACCESSORS(baudrate, int)
2037 CREATE_ACCESSORS(bits, int)
2038 CREATE_ACCESSORS(parity, enum sp_parity)
2039 CREATE_ACCESSORS(stopbits, int)
2040 CREATE_ACCESSORS(rts, enum sp_rts)
2041 CREATE_ACCESSORS(cts, enum sp_cts)
2042 CREATE_ACCESSORS(dtr, enum sp_dtr)
2043 CREATE_ACCESSORS(dsr, enum sp_dsr)
2044 CREATE_ACCESSORS(xon_xoff, enum sp_xonxoff)
2046 enum sp_return sp_set_config_flowcontrol(struct sp_port_config *config, enum sp_flowcontrol flowcontrol)
2049 RETURN_ERROR(SP_ERR_ARG, "Null configuration");
2051 if (flowcontrol > SP_FLOWCONTROL_DTRDSR)
2052 RETURN_ERROR(SP_ERR_ARG, "Invalid flow control setting");
2054 if (flowcontrol == SP_FLOWCONTROL_XONXOFF)
2055 config->xon_xoff = SP_XONXOFF_INOUT;
2057 config->xon_xoff = SP_XONXOFF_DISABLED;
2059 if (flowcontrol == SP_FLOWCONTROL_RTSCTS) {
2060 config->rts = SP_RTS_FLOW_CONTROL;
2061 config->cts = SP_CTS_FLOW_CONTROL;
2063 if (config->rts == SP_RTS_FLOW_CONTROL)
2064 config->rts = SP_RTS_ON;
2065 config->cts = SP_CTS_IGNORE;
2068 if (flowcontrol == SP_FLOWCONTROL_DTRDSR) {
2069 config->dtr = SP_DTR_FLOW_CONTROL;
2070 config->dsr = SP_DSR_FLOW_CONTROL;
2072 if (config->dtr == SP_DTR_FLOW_CONTROL)
2073 config->dtr = SP_DTR_ON;
2074 config->dsr = SP_DSR_IGNORE;
2080 enum sp_return sp_set_flowcontrol(struct sp_port *port, enum sp_flowcontrol flowcontrol)
2082 struct port_data data;
2083 struct sp_port_config config;
2085 TRACE("%p, %d", port, flowcontrol);
2089 TRY(get_config(port, &data, &config));
2091 TRY(sp_set_config_flowcontrol(&config, flowcontrol));
2093 TRY(set_config(port, &data, &config));
2098 enum sp_return sp_get_signals(struct sp_port *port, enum sp_signal *signals)
2100 TRACE("%p, %p", port, signals);
2105 RETURN_ERROR(SP_ERR_ARG, "Null result pointer");
2107 DEBUG("Getting control signals for port %s", port->name);
2112 if (GetCommModemStatus(port->hdl, &bits) == 0)
2113 RETURN_FAIL("GetCommModemStatus() failed");
2114 if (bits & MS_CTS_ON)
2115 *signals |= SP_SIG_CTS;
2116 if (bits & MS_DSR_ON)
2117 *signals |= SP_SIG_DSR;
2118 if (bits & MS_RLSD_ON)
2119 *signals |= SP_SIG_DCD;
2120 if (bits & MS_RING_ON)
2121 *signals |= SP_SIG_RI;
2124 if (ioctl(port->fd, TIOCMGET, &bits) < 0)
2125 RETURN_FAIL("TIOCMGET ioctl failed");
2126 if (bits & TIOCM_CTS)
2127 *signals |= SP_SIG_CTS;
2128 if (bits & TIOCM_DSR)
2129 *signals |= SP_SIG_DSR;
2130 if (bits & TIOCM_CAR)
2131 *signals |= SP_SIG_DCD;
2132 if (bits & TIOCM_RNG)
2133 *signals |= SP_SIG_RI;
2138 enum sp_return sp_start_break(struct sp_port *port)
2144 if (SetCommBreak(port->hdl) == 0)
2145 RETURN_FAIL("SetCommBreak() failed");
2147 if (ioctl(port->fd, TIOCSBRK, 1) < 0)
2148 RETURN_FAIL("TIOCSBRK ioctl failed");
2154 enum sp_return sp_end_break(struct sp_port *port)
2160 if (ClearCommBreak(port->hdl) == 0)
2161 RETURN_FAIL("ClearCommBreak() failed");
2163 if (ioctl(port->fd, TIOCCBRK, 1) < 0)
2164 RETURN_FAIL("TIOCCBRK ioctl failed");
2170 int sp_last_error_code(void)
2174 RETURN_VALUE("%d", GetLastError());
2176 RETURN_VALUE("%d", errno);
2180 char *sp_last_error_message(void)
2186 DWORD error = GetLastError();
2189 FORMAT_MESSAGE_ALLOCATE_BUFFER |
2190 FORMAT_MESSAGE_FROM_SYSTEM |
2191 FORMAT_MESSAGE_IGNORE_INSERTS,
2194 MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
2198 RETURN_VALUE("%s", message);
2200 RETURN_VALUE("%s", strerror(errno));
2204 void sp_free_error_message(char *message)
2206 TRACE("%s", message);
2217 void sp_set_debug_handler(void (*handler)(const char *format, ...))
2219 TRACE("%p", handler);
2221 sp_debug_handler = handler;
2226 void sp_default_debug_handler(const char *format, ...)
2229 va_start(args, format);
2230 if (getenv("LIBSERIALPORT_DEBUG")) {
2231 fputs("sp: ", stderr);
2232 vfprintf(stderr, format, args);