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 { DEBUG("%s returning " fmt, __func__, x); return x; } while (0)
177 #define SET_ERROR(val, err, msg) do { DEBUG_ERROR(err, msg); val = err; } while (0)
178 #define SET_FAIL(val, msg) do { DEBUG_FAIL(msg); val = SP_ERR_FAIL; } while (0)
179 #define TRACE(fmt, ...) DEBUG("%s(" fmt ") called", __func__, ##__VA_ARGS__)
181 #define TRY(x) do { int ret = x; if (ret != SP_OK) RETURN_CODEVAL(ret); } while (0)
183 /* Helper functions. */
184 static struct sp_port **list_append(struct sp_port **list, const char *portname);
185 static enum sp_return get_config(struct sp_port *port, struct port_data *data,
186 struct sp_port_config *config);
187 static enum sp_return set_config(struct sp_port *port, struct port_data *data,
188 const struct sp_port_config *config);
190 enum sp_return sp_get_port_by_name(const char *portname, struct sp_port **port_ptr)
192 struct sp_port *port;
195 TRACE("%s, %p", portname, port_ptr);
198 RETURN_ERROR(SP_ERR_ARG, "Null result pointer");
203 RETURN_ERROR(SP_ERR_ARG, "Null port name");
205 DEBUG("Building structure for port %s", portname);
207 if (!(port = malloc(sizeof(struct sp_port))))
208 RETURN_ERROR(SP_ERR_MEM, "Port structure malloc failed");
210 len = strlen(portname) + 1;
212 if (!(port->name = malloc(len))) {
214 RETURN_ERROR(SP_ERR_MEM, "Port name malloc failed");
217 memcpy(port->name, portname, len);
220 port->hdl = INVALID_HANDLE_VALUE;
230 char *sp_get_port_name(const struct sp_port *port)
237 RETURN_VALUE("%s", port->name);
240 enum sp_return sp_get_port_handle(const struct sp_port *port, void *result_ptr)
242 TRACE("%p, %p", port, result_ptr);
245 RETURN_ERROR(SP_ERR_ARG, "Null port");
248 HANDLE *handle_ptr = result_ptr;
249 *handle_ptr = port->hdl;
251 int *fd_ptr = result_ptr;
258 enum sp_return sp_copy_port(const struct sp_port *port, struct sp_port **copy_ptr)
260 TRACE("%p, %p", port, copy_ptr);
263 RETURN_ERROR(SP_ERR_ARG, "Null result pointer");
268 RETURN_ERROR(SP_ERR_ARG, "Null port");
271 RETURN_ERROR(SP_ERR_ARG, "Null port name");
273 DEBUG("Copying port structure");
275 RETURN_VALUE("%p", sp_get_port_by_name(port->name, copy_ptr));
278 void sp_free_port(struct sp_port *port)
287 DEBUG("Freeing port structure");
297 static struct sp_port **list_append(struct sp_port **list, const char *portname)
302 for (count = 0; list[count]; count++);
303 if (!(tmp = realloc(list, sizeof(struct sp_port *) * (count + 2))))
306 if (sp_get_port_by_name(portname, &list[count]) != SP_OK)
308 list[count + 1] = NULL;
312 sp_free_port_list(list);
316 enum sp_return sp_list_ports(struct sp_port ***list_ptr)
318 struct sp_port **list;
319 int ret = SP_ERR_SUPP;
321 TRACE("%p", list_ptr);
324 RETURN_ERROR(SP_ERR_ARG, "Null result pointer");
326 DEBUG("Enumerating ports");
328 if (!(list = malloc(sizeof(struct sp_port **))))
329 RETURN_ERROR(SP_ERR_MEM, "Port list malloc failed");
336 DWORD max_value_len, max_data_size, max_data_len;
337 DWORD value_len, data_size, data_len;
338 DWORD type, index = 0;
344 DEBUG("Opening registry key");
345 if (RegOpenKeyEx(HKEY_LOCAL_MACHINE, _T("HARDWARE\\DEVICEMAP\\SERIALCOMM"),
346 0, KEY_QUERY_VALUE, &key) != ERROR_SUCCESS) {
347 SET_FAIL(ret, "RegOpenKeyEx() failed");
350 DEBUG("Querying registry key value and data sizes");
351 if (RegQueryInfoKey(key, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
352 &max_value_len, &max_data_size, NULL, NULL) != ERROR_SUCCESS) {
353 SET_FAIL(ret, "RegQueryInfoKey() failed");
356 max_data_len = max_data_size / sizeof(TCHAR);
357 if (!(value = malloc((max_value_len + 1) * sizeof(TCHAR)))) {
358 SET_ERROR(ret, SP_ERR_MEM, "registry value malloc failed");
361 if (!(data = malloc((max_data_len + 1) * sizeof(TCHAR)))) {
362 SET_ERROR(ret, SP_ERR_MEM, "registry data malloc failed");
365 DEBUG("Iterating over values");
367 value_len = max_value_len + 1,
368 data_size = max_data_size,
369 RegEnumValue(key, index, value, &value_len,
370 NULL, &type, (LPBYTE)data, &data_size) == ERROR_SUCCESS)
372 data_len = data_size / sizeof(TCHAR);
373 data[data_len] = '\0';
375 name_len = WideCharToMultiByte(CP_ACP, 0, data, -1, NULL, 0, NULL, NULL)
377 name_len = data_len + 1;
379 if (!(name = malloc(name_len))) {
380 SET_ERROR(ret, SP_ERR_MEM, "registry port name malloc failed");
384 WideCharToMultiByte(CP_ACP, 0, data, -1, name, name_len, NULL, NULL);
388 if (type == REG_SZ) {
389 DEBUG("Found port %s", name);
390 if (!(list = list_append(list, name))) {
391 SET_ERROR(ret, SP_ERR_MEM, "list append failed");
407 CFMutableDictionaryRef classes;
416 DEBUG("Getting IOKit master port");
417 if (IOMasterPort(MACH_PORT_NULL, &master) != KERN_SUCCESS) {
418 SET_FAIL(ret, "IOMasterPort() failed");
422 DEBUG("Creating matching dictionary");
423 if (!(classes = IOServiceMatching(kIOSerialBSDServiceValue))) {
424 SET_FAIL(ret, "IOServiceMatching() failed");
428 CFDictionarySetValue(classes,
429 CFSTR(kIOSerialBSDTypeKey), CFSTR(kIOSerialBSDAllTypes));
431 DEBUG("Getting matching services");
432 if (IOServiceGetMatchingServices(master, classes, &iter) != KERN_SUCCESS) {
433 SET_FAIL(ret, "IOServiceGetMatchingServices() failed");
437 if (!(path = malloc(PATH_MAX))) {
438 SET_ERROR(ret, SP_ERR_MEM, "device path malloc failed");
442 DEBUG("Iterating over results");
443 while ((port = IOIteratorNext(iter))) {
444 cf_path = IORegistryEntryCreateCFProperty(port,
445 CFSTR(kIOCalloutDeviceKey), kCFAllocatorDefault, 0);
447 result = CFStringGetCString(cf_path,
448 path, PATH_MAX, kCFStringEncodingASCII);
451 DEBUG("Found port %s", path);
452 if (!(list = list_append(list, path))) {
453 SET_ERROR(ret, SP_ERR_MEM, "list append failed");
454 IOObjectRelease(port);
459 IOObjectRelease(port);
464 IOObjectRelease(iter);
467 #if defined(__linux__) && defined(HAVE_LIBUDEV)
469 struct udev_enumerate *ud_enumerate;
470 struct udev_list_entry *ud_list;
471 struct udev_list_entry *ud_entry;
473 struct udev_device *ud_dev, *ud_parent;
476 int fd, ioctl_result;
477 struct serial_struct serial_info;
481 DEBUG("Enumerating tty devices");
483 ud_enumerate = udev_enumerate_new(ud);
484 udev_enumerate_add_match_subsystem(ud_enumerate, "tty");
485 udev_enumerate_scan_devices(ud_enumerate);
486 ud_list = udev_enumerate_get_list_entry(ud_enumerate);
487 DEBUG("Iterating over results");
488 udev_list_entry_foreach(ud_entry, ud_list) {
489 path = udev_list_entry_get_name(ud_entry);
490 DEBUG("Found device %s", path);
491 ud_dev = udev_device_new_from_syspath(ud, path);
492 /* If there is no parent device, this is a virtual tty. */
493 ud_parent = udev_device_get_parent(ud_dev);
494 if (ud_parent == NULL) {
495 DEBUG("No parent device, assuming virtual tty");
496 udev_device_unref(ud_dev);
499 name = udev_device_get_devnode(ud_dev);
500 /* The serial8250 driver has a hardcoded number of ports.
501 * The only way to tell which actually exist on a given system
502 * is to try to open them and make an ioctl call. */
503 driver = udev_device_get_driver(ud_parent);
504 if (driver && !strcmp(driver, "serial8250")) {
505 DEBUG("serial8250 device, attempting to open");
506 if ((fd = open(name, O_RDWR | O_NONBLOCK | O_NOCTTY)) < 0) {
507 DEBUG("open failed, skipping");
510 ioctl_result = ioctl(fd, TIOCGSERIAL, &serial_info);
512 if (ioctl_result != 0) {
513 DEBUG("ioctl failed, skipping");
516 if (serial_info.type == PORT_UNKNOWN) {
517 DEBUG("port type is unknown, skipping");
521 DEBUG("Found port %s", name);
522 list = list_append(list, name);
524 udev_device_unref(ud_dev);
526 SET_ERROR(ret, SP_ERR_MEM, "list append failed");
531 udev_enumerate_unref(ud_enumerate);
540 DEBUG_ERROR(SP_ERR_SUPP, "Enumeration not supported on this platform.");
543 sp_free_port_list(list);
549 void sp_free_port_list(struct sp_port **list)
560 DEBUG("Freeing port list");
562 for (i = 0; list[i]; i++)
563 sp_free_port(list[i]);
569 #define CHECK_PORT() do { \
571 RETURN_ERROR(SP_ERR_ARG, "Null port"); \
572 if (port->name == NULL) \
573 RETURN_ERROR(SP_ERR_ARG, "Null port name"); \
576 #define CHECK_PORT_HANDLE() do { \
577 if (port->hdl == INVALID_HANDLE_VALUE) \
578 RETURN_ERROR(SP_ERR_ARG, "Invalid port handle"); \
581 #define CHECK_PORT_HANDLE() do { \
583 RETURN_ERROR(SP_ERR_ARG, "Invalid port fd"); \
586 #define CHECK_OPEN_PORT() do { \
588 CHECK_PORT_HANDLE(); \
591 enum sp_return sp_open(struct sp_port *port, enum sp_mode flags)
593 struct port_data data;
594 struct sp_port_config config;
597 TRACE("%p, 0x%x", port, flags);
601 if (flags > (SP_MODE_READ | SP_MODE_WRITE))
602 RETURN_ERROR(SP_ERR_ARG, "Invalid flags");
604 DEBUG("Opening port %s", port->name);
607 DWORD desired_access = 0, flags_and_attributes = 0;
608 char *escaped_port_name;
610 /* Prefix port name with '\\.\' to work with ports above COM9. */
611 if (!(escaped_port_name = malloc(strlen(port->name + 5))))
612 RETURN_ERROR(SP_ERR_MEM, "Escaped port name malloc failed");
613 sprintf(escaped_port_name, "\\\\.\\%s", port->name);
615 /* Map 'flags' to the OS-specific settings. */
616 flags_and_attributes = FILE_ATTRIBUTE_NORMAL | FILE_FLAG_OVERLAPPED;
617 if (flags & SP_MODE_READ)
618 desired_access |= GENERIC_READ;
619 if (flags & SP_MODE_WRITE)
620 desired_access |= GENERIC_WRITE;
622 port->hdl = CreateFile(escaped_port_name, desired_access, 0, 0,
623 OPEN_EXISTING, flags_and_attributes, 0);
625 free(escaped_port_name);
627 if (port->hdl == INVALID_HANDLE_VALUE)
628 RETURN_FAIL("port CreateFile() failed");
630 /* All timeouts initially disabled. */
631 port->timeouts.ReadIntervalTimeout = 0;
632 port->timeouts.ReadTotalTimeoutMultiplier = 0;
633 port->timeouts.ReadTotalTimeoutConstant = 0;
634 port->timeouts.WriteTotalTimeoutMultiplier = 0;
635 port->timeouts.WriteTotalTimeoutConstant = 0;
637 if (SetCommTimeouts(port->hdl, &port->timeouts) == 0) {
639 RETURN_FAIL("SetCommTimeouts() failed");
642 /* Prepare OVERLAPPED structures. */
643 memset(&port->read_ovl, 0, sizeof(port->read_ovl));
644 memset(&port->write_ovl, 0, sizeof(port->write_ovl));
645 port->read_ovl.hEvent = INVALID_HANDLE_VALUE;
646 port->write_ovl.hEvent = INVALID_HANDLE_VALUE;
647 if ((port->read_ovl.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL)) == INVALID_HANDLE_VALUE) {
649 RETURN_FAIL("read event CreateEvent() failed");
651 if ((port->write_ovl.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL)) == INVALID_HANDLE_VALUE) {
653 RETURN_FAIL("write event CreateEvent() failed");
656 port->writing = FALSE;
659 int flags_local = O_NONBLOCK | O_NOCTTY;
661 /* Map 'flags' to the OS-specific settings. */
662 if (flags & (SP_MODE_READ | SP_MODE_WRITE))
663 flags_local |= O_RDWR;
664 else if (flags & SP_MODE_READ)
665 flags_local |= O_RDONLY;
666 else if (flags & SP_MODE_WRITE)
667 flags_local |= O_WRONLY;
669 if ((port->fd = open(port->name, flags_local)) < 0)
670 RETURN_FAIL("open() failed");
673 ret = get_config(port, &data, &config);
680 /* Set sane port settings. */
682 data.dcb.fBinary = TRUE;
683 data.dcb.fDsrSensitivity = FALSE;
684 data.dcb.fErrorChar = FALSE;
685 data.dcb.fNull = FALSE;
686 data.dcb.fAbortOnError = TRUE;
688 /* Turn off all fancy termios tricks, give us a raw channel. */
689 data.term.c_iflag &= ~(IGNBRK | BRKINT | PARMRK | ISTRIP | INLCR | IGNCR | ICRNL | IMAXBEL);
691 data.term.c_iflag &= ~IUCLC;
693 data.term.c_oflag &= ~(OPOST | ONLCR | OCRNL | ONOCR | ONLRET);
695 data.term.c_oflag &= ~OLCUC;
698 data.term.c_oflag &= ~NLDLY;
701 data.term.c_oflag &= ~CRDLY;
704 data.term.c_oflag &= ~TABDLY;
707 data.term.c_oflag &= ~BSDLY;
710 data.term.c_oflag &= ~VTDLY;
713 data.term.c_oflag &= ~FFDLY;
716 data.term.c_oflag &= ~OFILL;
718 data.term.c_lflag &= ~(ISIG | ICANON | ECHO | IEXTEN);
719 data.term.c_cc[VMIN] = 0;
720 data.term.c_cc[VTIME] = 0;
722 /* Ignore modem status lines; enable receiver; leave control lines alone on close. */
723 data.term.c_cflag |= (CLOCAL | CREAD | HUPCL);
726 ret = set_config(port, &data, &config);
736 enum sp_return sp_close(struct sp_port *port)
742 DEBUG("Closing port %s", port->name);
745 /* Returns non-zero upon success, 0 upon failure. */
746 if (CloseHandle(port->hdl) == 0)
747 RETURN_FAIL("port CloseHandle() failed");
748 port->hdl = INVALID_HANDLE_VALUE;
749 /* Close event handle created for overlapped reads. */
750 if (port->read_ovl.hEvent != INVALID_HANDLE_VALUE && CloseHandle(port->read_ovl.hEvent) == 0)
751 RETURN_FAIL("read event CloseHandle() failed");
752 /* Close event handle created for overlapped writes. */
753 if (port->write_ovl.hEvent != INVALID_HANDLE_VALUE && CloseHandle(port->write_ovl.hEvent) == 0)
754 RETURN_FAIL("write event CloseHandle() failed");
756 /* Returns 0 upon success, -1 upon failure. */
757 if (close(port->fd) == -1)
758 RETURN_FAIL("close() failed");
765 enum sp_return sp_flush(struct sp_port *port, enum sp_buffer buffers)
767 TRACE("%p, 0x%x", port, buffers);
771 if (buffers > SP_BUF_BOTH)
772 RETURN_ERROR(SP_ERR_ARG, "Invalid buffer selection");
774 const char *buffer_names[] = {"no", "input", "output", "both"};
776 DEBUG("Flushing %s buffers on port %s", buffer_names[buffers], port->name);
780 if (buffers & SP_BUF_INPUT)
781 flags |= PURGE_RXCLEAR;
782 if (buffers & SP_BUF_OUTPUT)
783 flags |= PURGE_TXCLEAR;
785 /* Returns non-zero upon success, 0 upon failure. */
786 if (PurgeComm(port->hdl, flags) == 0)
787 RETURN_FAIL("PurgeComm() failed");
790 if (buffers & SP_BUF_BOTH)
792 else if (buffers & SP_BUF_INPUT)
794 else if (buffers & SP_BUF_OUTPUT)
797 /* Returns 0 upon success, -1 upon failure. */
798 if (tcflush(port->fd, flags) < 0)
799 RETURN_FAIL("tcflush() failed");
804 enum sp_return sp_drain(struct sp_port *port)
810 DEBUG("Draining port %s", port->name);
813 /* Returns non-zero upon success, 0 upon failure. */
814 if (FlushFileBuffers(port->hdl) == 0)
815 RETURN_FAIL("FlushFileBuffers() failed");
822 result = ioctl(port->fd, TCSBRK, &arg);
824 result = tcdrain(port->fd);
827 if (errno == EINTR) {
828 DEBUG("tcdrain() was interrupted");
831 RETURN_FAIL("tcdrain() failed");
840 enum sp_return sp_blocking_write(struct sp_port *port, const void *buf, size_t count, unsigned int timeout)
842 TRACE("%p, %p, %d, %d", port, buf, count, timeout);
847 RETURN_ERROR(SP_ERR_ARG, "Null buffer");
850 DEBUG("Writing %d bytes to port %s, timeout %d ms", count, port->name, timeout);
852 DEBUG("Writing %d bytes to port %s, no timeout", count, port->name);
855 RETURN_VALUE("0", 0);
858 DWORD bytes_written = 0;
861 /* Wait for previous non-blocking write to complete, if any. */
863 DEBUG("Waiting for previous write to complete");
864 result = GetOverlappedResult(port->hdl, &port->write_ovl, &bytes_written, TRUE);
867 RETURN_FAIL("Previous write failed to complete");
868 DEBUG("Previous write completed");
872 port->timeouts.WriteTotalTimeoutConstant = timeout;
873 if (SetCommTimeouts(port->hdl, &port->timeouts) == 0)
874 RETURN_FAIL("SetCommTimeouts() failed");
877 if (WriteFile(port->hdl, buf, count, NULL, &port->write_ovl) == 0) {
878 if (GetLastError() == ERROR_IO_PENDING) {
879 DEBUG("Waiting for write to complete");
880 GetOverlappedResult(port->hdl, &port->write_ovl, &bytes_written, TRUE);
881 DEBUG("Write completed, %d/%d bytes written", bytes_written, count);
882 RETURN_VALUE("%d", bytes_written);
884 RETURN_FAIL("WriteFile() failed");
887 DEBUG("Write completed immediately");
888 RETURN_VALUE("%d", count);
891 size_t bytes_written = 0;
892 unsigned char *ptr = (unsigned char *) buf;
893 struct timeval start, delta, now, end = {0, 0};
898 /* Get time at start of operation. */
899 gettimeofday(&start, NULL);
900 /* Define duration of timeout. */
901 delta.tv_sec = timeout / 1000;
902 delta.tv_usec = (timeout % 1000) * 1000;
903 /* Calculate time at which we should give up. */
904 timeradd(&start, &delta, &end);
907 /* Loop until we have written the requested number of bytes. */
908 while (bytes_written < count)
910 /* Wait until space is available. */
912 FD_SET(port->fd, &fds);
914 gettimeofday(&now, NULL);
915 if (timercmp(&now, &end, >)) {
916 DEBUG("write timed out");
917 RETURN_VALUE("%d", bytes_written);
919 timersub(&end, &now, &delta);
921 result = select(port->fd + 1, NULL, &fds, NULL, timeout ? &delta : NULL);
923 if (errno == EINTR) {
924 DEBUG("select() call was interrupted, repeating");
927 RETURN_FAIL("select() failed");
929 } else if (result == 0) {
930 DEBUG("write timed out");
931 RETURN_VALUE("%d", bytes_written);
935 result = write(port->fd, ptr, count - bytes_written);
939 /* This shouldn't happen because we did a select() first, but handle anyway. */
942 /* This is an actual failure. */
943 RETURN_FAIL("write() failed");
946 bytes_written += result;
950 RETURN_VALUE("%d", bytes_written);
954 enum sp_return sp_nonblocking_write(struct sp_port *port, const void *buf, size_t count)
956 TRACE("%p, %p, %d", port, buf, count);
961 RETURN_ERROR(SP_ERR_ARG, "Null buffer");
963 DEBUG("Writing up to %d bytes to port %s", count, port->name);
966 RETURN_VALUE("0", 0);
970 BYTE *ptr = (BYTE *) buf;
972 /* Check whether previous write is complete. */
974 if (HasOverlappedIoCompleted(&port->write_ovl)) {
975 DEBUG("Previous write completed");
978 DEBUG("Previous write not complete");
979 /* Can't take a new write until the previous one finishes. */
980 RETURN_VALUE("0", 0);
985 port->timeouts.WriteTotalTimeoutConstant = 0;
986 if (SetCommTimeouts(port->hdl, &port->timeouts) == 0)
987 RETURN_FAIL("SetCommTimeouts() failed");
989 /* Keep writing data until the OS has to actually start an async IO for it.
990 * At that point we know the buffer is full. */
991 while (written < count)
993 /* Copy first byte of user buffer. */
994 port->pending_byte = *ptr++;
996 /* Start asynchronous write. */
997 if (WriteFile(port->hdl, &port->pending_byte, 1, NULL, &port->write_ovl) == 0) {
998 if (GetLastError() == ERROR_IO_PENDING) {
999 DEBUG("Asynchronous write started");
1001 RETURN_VALUE("%d", ++written);
1003 /* Actual failure of some kind. */
1004 RETURN_FAIL("WriteFile() failed");
1007 DEBUG("Single byte written immediately.");
1012 DEBUG("All bytes written immediately.");
1014 RETURN_VALUE("%d", written);
1016 /* Returns the number of bytes written, or -1 upon failure. */
1017 ssize_t written = write(port->fd, buf, count);
1020 RETURN_FAIL("write() failed");
1022 RETURN_VALUE("%d", written);
1026 enum sp_return sp_blocking_read(struct sp_port *port, void *buf, size_t count, unsigned int timeout)
1028 TRACE("%p, %p, %d, %d", port, buf, count, timeout);
1033 RETURN_ERROR(SP_ERR_ARG, "Null buffer");
1036 DEBUG("Reading %d bytes from port %s, timeout %d ms", count, port->name, timeout);
1038 DEBUG("Reading %d bytes from port %s, no timeout", count, port->name);
1041 RETURN_VALUE("0", 0);
1044 DWORD bytes_read = 0;
1047 port->timeouts.ReadIntervalTimeout = 0;
1048 port->timeouts.ReadTotalTimeoutConstant = timeout;
1049 if (SetCommTimeouts(port->hdl, &port->timeouts) == 0)
1050 RETURN_FAIL("SetCommTimeouts() failed");
1053 if (ReadFile(port->hdl, buf, count, NULL, &port->read_ovl) == 0) {
1054 if (GetLastError() == ERROR_IO_PENDING) {
1055 DEBUG("Waiting for read to complete");
1056 GetOverlappedResult(port->hdl, &port->read_ovl, &bytes_read, TRUE);
1057 DEBUG("Read completed, %d/%d bytes read", bytes_read, count);
1058 RETURN_VALUE("%d", bytes_read);
1060 RETURN_FAIL("ReadFile() failed");
1063 DEBUG("Read completed immediately");
1064 RETURN_VALUE("%d", count);
1067 size_t bytes_read = 0;
1068 unsigned char *ptr = (unsigned char *) buf;
1069 struct timeval start, delta, now, end = {0, 0};
1074 /* Get time at start of operation. */
1075 gettimeofday(&start, NULL);
1076 /* Define duration of timeout. */
1077 delta.tv_sec = timeout / 1000;
1078 delta.tv_usec = (timeout % 1000) * 1000;
1079 /* Calculate time at which we should give up. */
1080 timeradd(&start, &delta, &end);
1083 /* Loop until we have the requested number of bytes. */
1084 while (bytes_read < count)
1086 /* Wait until data is available. */
1088 FD_SET(port->fd, &fds);
1090 gettimeofday(&now, NULL);
1091 if (timercmp(&now, &end, >))
1092 /* Timeout has expired. */
1093 RETURN_VALUE("%d", bytes_read);
1094 timersub(&end, &now, &delta);
1096 result = select(port->fd + 1, &fds, NULL, NULL, timeout ? &delta : NULL);
1098 if (errno == EINTR) {
1099 DEBUG("select() call was interrupted, repeating");
1102 RETURN_FAIL("select() failed");
1104 } else if (result == 0) {
1105 DEBUG("read timed out");
1106 RETURN_VALUE("%d", bytes_read);
1110 result = read(port->fd, ptr, count - bytes_read);
1113 if (errno == EAGAIN)
1114 /* This shouldn't happen because we did a select() first, but handle anyway. */
1117 /* This is an actual failure. */
1118 RETURN_FAIL("read() failed");
1121 bytes_read += result;
1125 RETURN_VALUE("%d", bytes_read);
1129 enum sp_return sp_nonblocking_read(struct sp_port *port, void *buf, size_t count)
1131 TRACE("%p, %p, %d", port, buf, count);
1136 RETURN_ERROR(SP_ERR_ARG, "Null buffer");
1138 DEBUG("Reading up to %d bytes from port %s", count, port->name);
1144 port->timeouts.ReadIntervalTimeout = MAXDWORD;
1145 port->timeouts.ReadTotalTimeoutConstant = 0;
1146 if (SetCommTimeouts(port->hdl, &port->timeouts) == 0)
1147 RETURN_FAIL("SetCommTimeouts() failed");
1150 if (ReadFile(port->hdl, buf, count, NULL, &port->read_ovl) == 0)
1151 RETURN_FAIL("ReadFile() failed");
1153 /* Get number of bytes read. */
1154 GetOverlappedResult(port->hdl, &port->read_ovl, &bytes_read, TRUE);
1156 RETURN_VALUE("%d", bytes_read);
1160 /* Returns the number of bytes read, or -1 upon failure. */
1161 if ((bytes_read = read(port->fd, buf, count)) < 0) {
1162 if (errno == EAGAIN)
1163 /* No bytes available. */
1166 /* This is an actual failure. */
1167 RETURN_FAIL("read() failed");
1169 RETURN_VALUE("%d", bytes_read);
1173 enum sp_return sp_input_waiting(struct sp_port *port)
1179 DEBUG("Checking input bytes waiting on port %s", port->name);
1185 if (ClearCommError(port->hdl, &errors, &comstat) == 0)
1186 RETURN_FAIL("ClearComError() failed");
1187 RETURN_VALUE("%d", comstat.cbInQue);
1190 if (ioctl(port->fd, TIOCINQ, &bytes_waiting) < 0)
1191 RETURN_FAIL("TIOCINQ ioctl failed");
1192 RETURN_VALUE("%d", bytes_waiting);
1196 enum sp_return sp_output_waiting(struct sp_port *port)
1202 DEBUG("Checking output bytes waiting on port %s", port->name);
1208 if (ClearCommError(port->hdl, &errors, &comstat) == 0)
1209 RETURN_FAIL("ClearComError() failed");
1210 RETURN_VALUE("%d", comstat.cbOutQue);
1213 if (ioctl(port->fd, TIOCOUTQ, &bytes_waiting) < 0)
1214 RETURN_FAIL("TIOCOUTQ ioctl failed");
1215 RETURN_VALUE("%d", bytes_waiting);
1220 static enum sp_return get_baudrate(int fd, int *baudrate)
1224 TRACE("%d, %p", fd, baudrate);
1226 DEBUG("Getting baud rate");
1228 if (!(data = malloc(get_termios_size())))
1229 RETURN_ERROR(SP_ERR_MEM, "termios malloc failed");
1231 if (ioctl(fd, get_termios_get_ioctl(), data) < 0) {
1233 RETURN_FAIL("getting termios failed");
1236 *baudrate = get_termios_speed(data);
1243 static enum sp_return set_baudrate(int fd, int baudrate)
1247 TRACE("%d, %d", fd, baudrate);
1249 DEBUG("Getting baud rate");
1251 if (!(data = malloc(get_termios_size())))
1252 RETURN_ERROR(SP_ERR_MEM, "termios malloc failed");
1254 if (ioctl(fd, get_termios_get_ioctl(), data) < 0) {
1256 RETURN_FAIL("getting termios failed");
1259 DEBUG("Setting baud rate");
1261 set_termios_speed(data, baudrate);
1263 if (ioctl(fd, get_termios_set_ioctl(), data) < 0) {
1265 RETURN_FAIL("setting termios failed");
1274 static enum sp_return get_flow(int fd, int *flow)
1278 TRACE("%d, %p", fd, flow);
1280 DEBUG("Getting advanced flow control");
1282 if (!(data = malloc(get_termiox_size())))
1283 RETURN_ERROR(SP_ERR_MEM, "termiox malloc failed");
1285 if (ioctl(fd, TCGETX, data) < 0) {
1287 RETURN_FAIL("getting termiox failed");
1290 *flow = get_termiox_flow(data);
1297 static enum sp_return set_flow(int fd, int flow)
1301 TRACE("%d, %d", fd, flow);
1303 DEBUG("Getting advanced flow control");
1305 if (!(data = malloc(get_termiox_size())))
1306 RETURN_ERROR(SP_ERR_MEM, "termiox malloc failed");
1308 if (ioctl(fd, TCGETX, data) < 0) {
1310 RETURN_FAIL("getting termiox failed");
1313 DEBUG("Setting advanced flow control");
1315 set_termiox_flow(data, flow);
1317 if (ioctl(fd, TCSETX, data) < 0) {
1319 RETURN_FAIL("setting termiox failed");
1326 #endif /* USE_TERMIOX */
1327 #endif /* __linux__ */
1329 static enum sp_return get_config(struct sp_port *port, struct port_data *data,
1330 struct sp_port_config *config)
1334 TRACE("%p, %p, %p", port, data, config);
1336 DEBUG("Getting configuration for port %s", port->name);
1339 if (!GetCommState(port->hdl, &data->dcb))
1340 RETURN_FAIL("GetCommState() failed");
1342 for (i = 0; i < NUM_STD_BAUDRATES; i++) {
1343 if (data->dcb.BaudRate == std_baudrates[i].index) {
1344 config->baudrate = std_baudrates[i].value;
1349 if (i == NUM_STD_BAUDRATES)
1350 /* BaudRate field can be either an index or a custom baud rate. */
1351 config->baudrate = data->dcb.BaudRate;
1353 config->bits = data->dcb.ByteSize;
1355 if (data->dcb.fParity)
1356 switch (data->dcb.Parity) {
1358 config->parity = SP_PARITY_NONE;
1361 config->parity = SP_PARITY_ODD;
1364 config->parity = SP_PARITY_EVEN;
1367 config->parity = SP_PARITY_MARK;
1370 config->parity = SP_PARITY_SPACE;
1373 config->parity = -1;
1376 config->parity = SP_PARITY_NONE;
1378 switch (data->dcb.StopBits) {
1380 config->stopbits = 1;
1383 config->stopbits = 2;
1386 config->stopbits = -1;
1389 switch (data->dcb.fRtsControl) {
1390 case RTS_CONTROL_DISABLE:
1391 config->rts = SP_RTS_OFF;
1393 case RTS_CONTROL_ENABLE:
1394 config->rts = SP_RTS_ON;
1396 case RTS_CONTROL_HANDSHAKE:
1397 config->rts = SP_RTS_FLOW_CONTROL;
1403 config->cts = data->dcb.fOutxCtsFlow ? SP_CTS_FLOW_CONTROL : SP_CTS_IGNORE;
1405 switch (data->dcb.fDtrControl) {
1406 case DTR_CONTROL_DISABLE:
1407 config->dtr = SP_DTR_OFF;
1409 case DTR_CONTROL_ENABLE:
1410 config->dtr = SP_DTR_ON;
1412 case DTR_CONTROL_HANDSHAKE:
1413 config->dtr = SP_DTR_FLOW_CONTROL;
1419 config->dsr = data->dcb.fOutxDsrFlow ? SP_DSR_FLOW_CONTROL : SP_DSR_IGNORE;
1421 if (data->dcb.fInX) {
1422 if (data->dcb.fOutX)
1423 config->xon_xoff = SP_XONXOFF_INOUT;
1425 config->xon_xoff = SP_XONXOFF_IN;
1427 if (data->dcb.fOutX)
1428 config->xon_xoff = SP_XONXOFF_OUT;
1430 config->xon_xoff = SP_XONXOFF_DISABLED;
1435 if (tcgetattr(port->fd, &data->term) < 0)
1436 RETURN_FAIL("tcgetattr() failed");
1438 if (ioctl(port->fd, TIOCMGET, &data->controlbits) < 0)
1439 RETURN_FAIL("TIOCMGET ioctl failed");
1442 int ret = get_flow(port->fd, &data->flow);
1444 if (ret == SP_ERR_FAIL && errno == EINVAL)
1445 data->termiox_supported = 0;
1447 RETURN_CODEVAL(ret);
1449 data->termiox_supported = 1;
1451 data->termiox_supported = 0;
1454 for (i = 0; i < NUM_STD_BAUDRATES; i++) {
1455 if (cfgetispeed(&data->term) == std_baudrates[i].index) {
1456 config->baudrate = std_baudrates[i].value;
1461 if (i == NUM_STD_BAUDRATES) {
1463 config->baudrate = (int)data->term.c_ispeed;
1464 #elif defined(__linux__)
1465 TRY(get_baudrate(port->fd, &config->baudrate));
1467 config->baudrate = -1;
1471 switch (data->term.c_cflag & CSIZE) {
1488 if (!(data->term.c_cflag & PARENB) && (data->term.c_iflag & IGNPAR))
1489 config->parity = SP_PARITY_NONE;
1490 else if (!(data->term.c_cflag & PARENB) || (data->term.c_iflag & IGNPAR))
1491 config->parity = -1;
1493 else if (data->term.c_cflag & CMSPAR)
1494 config->parity = (data->term.c_cflag & PARODD) ? SP_PARITY_MARK : SP_PARITY_SPACE;
1497 config->parity = (data->term.c_cflag & PARODD) ? SP_PARITY_ODD : SP_PARITY_EVEN;
1499 config->stopbits = (data->term.c_cflag & CSTOPB) ? 2 : 1;
1501 if (data->term.c_cflag & CRTSCTS) {
1502 config->rts = SP_RTS_FLOW_CONTROL;
1503 config->cts = SP_CTS_FLOW_CONTROL;
1505 if (data->termiox_supported && data->flow & RTS_FLOW)
1506 config->rts = SP_RTS_FLOW_CONTROL;
1508 config->rts = (data->controlbits & TIOCM_RTS) ? SP_RTS_ON : SP_RTS_OFF;
1510 config->cts = (data->termiox_supported && data->flow & CTS_FLOW) ?
1511 SP_CTS_FLOW_CONTROL : SP_CTS_IGNORE;
1514 if (data->termiox_supported && data->flow & DTR_FLOW)
1515 config->dtr = SP_DTR_FLOW_CONTROL;
1517 config->dtr = (data->controlbits & TIOCM_DTR) ? SP_DTR_ON : SP_DTR_OFF;
1519 config->dsr = (data->termiox_supported && data->flow & DSR_FLOW) ?
1520 SP_DSR_FLOW_CONTROL : SP_DSR_IGNORE;
1522 if (data->term.c_iflag & IXOFF) {
1523 if (data->term.c_iflag & IXON)
1524 config->xon_xoff = SP_XONXOFF_INOUT;
1526 config->xon_xoff = SP_XONXOFF_IN;
1528 if (data->term.c_iflag & IXON)
1529 config->xon_xoff = SP_XONXOFF_OUT;
1531 config->xon_xoff = SP_XONXOFF_DISABLED;
1538 static enum sp_return set_config(struct sp_port *port, struct port_data *data,
1539 const struct sp_port_config *config)
1543 BAUD_TYPE baud_nonstd;
1548 int baud_nonstd = 0;
1551 TRACE("%p, %p, %p", port, data, config);
1553 DEBUG("Setting configuration for port %s", port->name);
1556 if (config->baudrate >= 0) {
1557 for (i = 0; i < NUM_STD_BAUDRATES; i++) {
1558 if (config->baudrate == std_baudrates[i].value) {
1559 data->dcb.BaudRate = std_baudrates[i].index;
1564 if (i == NUM_STD_BAUDRATES)
1565 data->dcb.BaudRate = config->baudrate;
1568 if (config->bits >= 0)
1569 data->dcb.ByteSize = config->bits;
1571 if (config->parity >= 0) {
1572 switch (config->parity) {
1573 /* Note: There's also SPACEPARITY, MARKPARITY (unneeded so far). */
1574 case SP_PARITY_NONE:
1575 data->dcb.Parity = NOPARITY;
1578 data->dcb.Parity = ODDPARITY;
1580 case SP_PARITY_EVEN:
1581 data->dcb.Parity = EVENPARITY;
1583 case SP_PARITY_MARK:
1584 data->dcb.Parity = MARKPARITY;
1586 case SP_PARITY_SPACE:
1587 data->dcb.Parity = SPACEPARITY;
1590 RETURN_ERROR(SP_ERR_ARG, "Invalid parity setting");
1594 if (config->stopbits >= 0) {
1595 switch (config->stopbits) {
1596 /* Note: There's also ONE5STOPBITS == 1.5 (unneeded so far). */
1598 data->dcb.StopBits = ONESTOPBIT;
1601 data->dcb.StopBits = TWOSTOPBITS;
1604 RETURN_ERROR(SP_ERR_ARG, "Invalid stop bit setting");
1608 if (config->rts >= 0) {
1609 switch (config->rts) {
1611 data->dcb.fRtsControl = RTS_CONTROL_DISABLE;
1614 data->dcb.fRtsControl = RTS_CONTROL_ENABLE;
1616 case SP_RTS_FLOW_CONTROL:
1617 data->dcb.fRtsControl = RTS_CONTROL_HANDSHAKE;
1620 RETURN_ERROR(SP_ERR_ARG, "Invalid RTS setting");
1624 if (config->cts >= 0) {
1625 switch (config->cts) {
1627 data->dcb.fOutxCtsFlow = FALSE;
1629 case SP_CTS_FLOW_CONTROL:
1630 data->dcb.fOutxCtsFlow = TRUE;
1633 RETURN_ERROR(SP_ERR_ARG, "Invalid CTS setting");
1637 if (config->dtr >= 0) {
1638 switch (config->dtr) {
1640 data->dcb.fDtrControl = DTR_CONTROL_DISABLE;
1643 data->dcb.fDtrControl = DTR_CONTROL_ENABLE;
1645 case SP_DTR_FLOW_CONTROL:
1646 data->dcb.fDtrControl = DTR_CONTROL_HANDSHAKE;
1649 RETURN_ERROR(SP_ERR_ARG, "Invalid DTR setting");
1653 if (config->dsr >= 0) {
1654 switch (config->dsr) {
1656 data->dcb.fOutxDsrFlow = FALSE;
1658 case SP_DSR_FLOW_CONTROL:
1659 data->dcb.fOutxDsrFlow = TRUE;
1662 RETURN_ERROR(SP_ERR_ARG, "Invalid DSR setting");
1666 if (config->xon_xoff >= 0) {
1667 switch (config->xon_xoff) {
1668 case SP_XONXOFF_DISABLED:
1669 data->dcb.fInX = FALSE;
1670 data->dcb.fOutX = FALSE;
1673 data->dcb.fInX = TRUE;
1674 data->dcb.fOutX = FALSE;
1676 case SP_XONXOFF_OUT:
1677 data->dcb.fInX = FALSE;
1678 data->dcb.fOutX = TRUE;
1680 case SP_XONXOFF_INOUT:
1681 data->dcb.fInX = TRUE;
1682 data->dcb.fOutX = TRUE;
1685 RETURN_ERROR(SP_ERR_ARG, "Invalid XON/XOFF setting");
1689 if (!SetCommState(port->hdl, &data->dcb))
1690 RETURN_FAIL("SetCommState() failed");
1696 if (config->baudrate >= 0) {
1697 for (i = 0; i < NUM_STD_BAUDRATES; i++) {
1698 if (config->baudrate == std_baudrates[i].value) {
1699 if (cfsetospeed(&data->term, std_baudrates[i].index) < 0)
1700 RETURN_FAIL("cfsetospeed() failed");
1702 if (cfsetispeed(&data->term, std_baudrates[i].index) < 0)
1703 RETURN_FAIL("cfsetispeed() failed");
1708 /* Non-standard baud rate */
1709 if (i == NUM_STD_BAUDRATES) {
1711 /* Set "dummy" baud rate. */
1712 if (cfsetspeed(&data->term, B9600) < 0)
1713 RETURN_FAIL("cfsetspeed() failed");
1714 baud_nonstd = config->baudrate;
1715 #elif defined(__linux__)
1718 RETURN_ERROR(SP_ERR_SUPP, "Non-standard baudrate not supported");
1723 if (config->bits >= 0) {
1724 data->term.c_cflag &= ~CSIZE;
1725 switch (config->bits) {
1727 data->term.c_cflag |= CS8;
1730 data->term.c_cflag |= CS7;
1733 data->term.c_cflag |= CS6;
1736 data->term.c_cflag |= CS5;
1739 RETURN_ERROR(SP_ERR_ARG, "Invalid data bits setting");
1743 if (config->parity >= 0) {
1744 data->term.c_iflag &= ~IGNPAR;
1745 data->term.c_cflag &= ~(PARENB | PARODD);
1747 data->term.c_cflag &= ~CMSPAR;
1749 switch (config->parity) {
1750 case SP_PARITY_NONE:
1751 data->term.c_iflag |= IGNPAR;
1753 case SP_PARITY_EVEN:
1754 data->term.c_cflag |= PARENB;
1757 data->term.c_cflag |= PARENB | PARODD;
1760 case SP_PARITY_MARK:
1761 data->term.c_cflag |= PARENB | PARODD;
1762 data->term.c_cflag |= CMSPAR;
1764 case SP_PARITY_SPACE:
1765 data->term.c_cflag |= PARENB;
1766 data->term.c_cflag |= CMSPAR;
1769 case SP_PARITY_MARK:
1770 case SP_PARITY_SPACE:
1771 RETURN_ERROR(SP_ERR_SUPP, "Mark/space parity not supported");
1774 RETURN_ERROR(SP_ERR_ARG, "Invalid parity setting");
1778 if (config->stopbits >= 0) {
1779 data->term.c_cflag &= ~CSTOPB;
1780 switch (config->stopbits) {
1782 data->term.c_cflag &= ~CSTOPB;
1785 data->term.c_cflag |= CSTOPB;
1788 RETURN_ERROR(SP_ERR_ARG, "Invalid stop bits setting");
1792 if (config->rts >= 0 || config->cts >= 0) {
1793 if (data->termiox_supported) {
1794 data->flow &= ~(RTS_FLOW | CTS_FLOW);
1795 switch (config->rts) {
1798 controlbits = TIOCM_RTS;
1799 if (ioctl(port->fd, config->rts == SP_RTS_ON ? TIOCMBIS : TIOCMBIC, &controlbits) < 0)
1800 RETURN_FAIL("Setting RTS signal level failed");
1802 case SP_RTS_FLOW_CONTROL:
1803 data->flow |= RTS_FLOW;
1808 if (config->cts == SP_CTS_FLOW_CONTROL)
1809 data->flow |= CTS_FLOW;
1811 if (data->flow & (RTS_FLOW | CTS_FLOW))
1812 data->term.c_iflag |= CRTSCTS;
1814 data->term.c_iflag &= ~CRTSCTS;
1816 /* Asymmetric use of RTS/CTS not supported. */
1817 if (data->term.c_iflag & CRTSCTS) {
1818 /* Flow control can only be disabled for both RTS & CTS together. */
1819 if (config->rts >= 0 && config->rts != SP_RTS_FLOW_CONTROL) {
1820 if (config->cts != SP_CTS_IGNORE)
1821 RETURN_ERROR(SP_ERR_SUPP, "RTS & CTS flow control must be disabled together");
1823 if (config->cts >= 0 && config->cts != SP_CTS_FLOW_CONTROL) {
1824 if (config->rts <= 0 || config->rts == SP_RTS_FLOW_CONTROL)
1825 RETURN_ERROR(SP_ERR_SUPP, "RTS & CTS flow control must be disabled together");
1828 /* Flow control can only be enabled for both RTS & CTS together. */
1829 if (((config->rts == SP_RTS_FLOW_CONTROL) && (config->cts != SP_CTS_FLOW_CONTROL)) ||
1830 ((config->cts == SP_CTS_FLOW_CONTROL) && (config->rts != SP_RTS_FLOW_CONTROL)))
1831 RETURN_ERROR(SP_ERR_SUPP, "RTS & CTS flow control must be enabled together");
1834 if (config->rts >= 0) {
1835 if (config->rts == SP_RTS_FLOW_CONTROL) {
1836 data->term.c_iflag |= CRTSCTS;
1838 controlbits = TIOCM_RTS;
1839 if (ioctl(port->fd, config->rts == SP_RTS_ON ? TIOCMBIS : TIOCMBIC,
1841 RETURN_FAIL("Setting RTS signal level failed");
1847 if (config->dtr >= 0 || config->dsr >= 0) {
1848 if (data->termiox_supported) {
1849 data->flow &= ~(DTR_FLOW | DSR_FLOW);
1850 switch (config->dtr) {
1853 controlbits = TIOCM_DTR;
1854 if (ioctl(port->fd, config->dtr == SP_DTR_ON ? TIOCMBIS : TIOCMBIC, &controlbits) < 0)
1855 RETURN_FAIL("Setting DTR signal level failed");
1857 case SP_DTR_FLOW_CONTROL:
1858 data->flow |= DTR_FLOW;
1863 if (config->dsr == SP_DSR_FLOW_CONTROL)
1864 data->flow |= DSR_FLOW;
1866 /* DTR/DSR flow control not supported. */
1867 if (config->dtr == SP_DTR_FLOW_CONTROL || config->dsr == SP_DSR_FLOW_CONTROL)
1868 RETURN_ERROR(SP_ERR_SUPP, "DTR/DSR flow control not supported");
1870 if (config->dtr >= 0) {
1871 controlbits = TIOCM_DTR;
1872 if (ioctl(port->fd, config->dtr == SP_DTR_ON ? TIOCMBIS : TIOCMBIC,
1874 RETURN_FAIL("Setting DTR signal level failed");
1879 if (config->xon_xoff >= 0) {
1880 data->term.c_iflag &= ~(IXON | IXOFF | IXANY);
1881 switch (config->xon_xoff) {
1882 case SP_XONXOFF_DISABLED:
1885 data->term.c_iflag |= IXOFF;
1887 case SP_XONXOFF_OUT:
1888 data->term.c_iflag |= IXON | IXANY;
1890 case SP_XONXOFF_INOUT:
1891 data->term.c_iflag |= IXON | IXOFF | IXANY;
1894 RETURN_ERROR(SP_ERR_ARG, "Invalid XON/XOFF setting");
1898 if (tcsetattr(port->fd, TCSANOW, &data->term) < 0)
1899 RETURN_FAIL("tcsetattr() failed");
1902 if (baud_nonstd != B0) {
1903 if (ioctl(port->fd, IOSSIOSPEED, &baud_nonstd) == -1)
1904 RETURN_FAIL("IOSSIOSPEED ioctl failed");
1905 /* Set baud rates in data->term to correct, but incompatible
1906 * with tcsetattr() value, same as delivered by tcgetattr(). */
1907 if (cfsetspeed(&data->term, baud_nonstd) < 0)
1908 RETURN_FAIL("cfsetspeed() failed");
1910 #elif defined(__linux__)
1912 TRY(set_baudrate(port->fd, config->baudrate));
1914 if (data->termiox_supported)
1915 TRY(set_flow(port->fd, data->flow));
1919 #endif /* !_WIN32 */
1924 enum sp_return sp_new_config(struct sp_port_config **config_ptr)
1926 struct sp_port_config *config;
1928 TRACE("%p", config_ptr);
1931 RETURN_ERROR(SP_ERR_ARG, "Null result pointer");
1935 if (!(config = malloc(sizeof(struct sp_port_config))))
1936 RETURN_ERROR(SP_ERR_MEM, "config malloc failed");
1938 config->baudrate = -1;
1940 config->parity = -1;
1941 config->stopbits = -1;
1947 *config_ptr = config;
1952 void sp_free_config(struct sp_port_config *config)
1954 TRACE("%p", config);
1957 DEBUG("Null config");
1964 enum sp_return sp_get_config(struct sp_port *port, struct sp_port_config *config)
1966 struct port_data data;
1968 TRACE("%p, %p", port, config);
1973 RETURN_ERROR(SP_ERR_ARG, "Null config");
1975 TRY(get_config(port, &data, config));
1980 enum sp_return sp_set_config(struct sp_port *port, const struct sp_port_config *config)
1982 struct port_data data;
1983 struct sp_port_config prev_config;
1985 TRACE("%p, %p", port, config);
1990 RETURN_ERROR(SP_ERR_ARG, "Null config");
1992 TRY(get_config(port, &data, &prev_config));
1993 TRY(set_config(port, &data, config));
1998 #define CREATE_ACCESSORS(x, type) \
1999 enum sp_return sp_set_##x(struct sp_port *port, type x) { \
2000 struct port_data data; \
2001 struct sp_port_config config; \
2002 TRACE("%p, %d", port, x); \
2003 CHECK_OPEN_PORT(); \
2004 TRY(get_config(port, &data, &config)); \
2006 TRY(set_config(port, &data, &config)); \
2009 enum sp_return sp_get_config_##x(const struct sp_port_config *config, type *x) { \
2010 TRACE("%p, %p", config, x); \
2012 RETURN_ERROR(SP_ERR_ARG, "Null config"); \
2016 enum sp_return sp_set_config_##x(struct sp_port_config *config, type x) { \
2017 TRACE("%p, %d", config, x); \
2019 RETURN_ERROR(SP_ERR_ARG, "Null config"); \
2024 CREATE_ACCESSORS(baudrate, int)
2025 CREATE_ACCESSORS(bits, int)
2026 CREATE_ACCESSORS(parity, enum sp_parity)
2027 CREATE_ACCESSORS(stopbits, int)
2028 CREATE_ACCESSORS(rts, enum sp_rts)
2029 CREATE_ACCESSORS(cts, enum sp_cts)
2030 CREATE_ACCESSORS(dtr, enum sp_dtr)
2031 CREATE_ACCESSORS(dsr, enum sp_dsr)
2032 CREATE_ACCESSORS(xon_xoff, enum sp_xonxoff)
2034 enum sp_return sp_set_config_flowcontrol(struct sp_port_config *config, enum sp_flowcontrol flowcontrol)
2037 RETURN_ERROR(SP_ERR_ARG, "Null configuration");
2039 if (flowcontrol > SP_FLOWCONTROL_DTRDSR)
2040 RETURN_ERROR(SP_ERR_ARG, "Invalid flow control setting");
2042 if (flowcontrol == SP_FLOWCONTROL_XONXOFF)
2043 config->xon_xoff = SP_XONXOFF_INOUT;
2045 config->xon_xoff = SP_XONXOFF_DISABLED;
2047 if (flowcontrol == SP_FLOWCONTROL_RTSCTS) {
2048 config->rts = SP_RTS_FLOW_CONTROL;
2049 config->cts = SP_CTS_FLOW_CONTROL;
2051 if (config->rts == SP_RTS_FLOW_CONTROL)
2052 config->rts = SP_RTS_ON;
2053 config->cts = SP_CTS_IGNORE;
2056 if (flowcontrol == SP_FLOWCONTROL_DTRDSR) {
2057 config->dtr = SP_DTR_FLOW_CONTROL;
2058 config->dsr = SP_DSR_FLOW_CONTROL;
2060 if (config->dtr == SP_DTR_FLOW_CONTROL)
2061 config->dtr = SP_DTR_ON;
2062 config->dsr = SP_DSR_IGNORE;
2068 enum sp_return sp_set_flowcontrol(struct sp_port *port, enum sp_flowcontrol flowcontrol)
2070 struct port_data data;
2071 struct sp_port_config config;
2073 TRACE("%p, %d", port, flowcontrol);
2077 TRY(get_config(port, &data, &config));
2079 TRY(sp_set_config_flowcontrol(&config, flowcontrol));
2081 TRY(set_config(port, &data, &config));
2086 enum sp_return sp_get_signals(struct sp_port *port, enum sp_signal *signals)
2088 TRACE("%p, %p", port, signals);
2093 RETURN_ERROR(SP_ERR_ARG, "Null result pointer");
2095 DEBUG("Getting control signals for port %s", port->name);
2100 if (GetCommModemStatus(port->hdl, &bits) == 0)
2101 RETURN_FAIL("GetCommModemStatus() failed");
2102 if (bits & MS_CTS_ON)
2103 *signals |= SP_SIG_CTS;
2104 if (bits & MS_DSR_ON)
2105 *signals |= SP_SIG_DSR;
2106 if (bits & MS_RLSD_ON)
2107 *signals |= SP_SIG_DCD;
2108 if (bits & MS_RING_ON)
2109 *signals |= SP_SIG_RI;
2112 if (ioctl(port->fd, TIOCMGET, &bits) < 0)
2113 RETURN_FAIL("TIOCMGET ioctl failed");
2114 if (bits & TIOCM_CTS)
2115 *signals |= SP_SIG_CTS;
2116 if (bits & TIOCM_DSR)
2117 *signals |= SP_SIG_DSR;
2118 if (bits & TIOCM_CAR)
2119 *signals |= SP_SIG_DCD;
2120 if (bits & TIOCM_RNG)
2121 *signals |= SP_SIG_RI;
2126 enum sp_return sp_start_break(struct sp_port *port)
2132 if (SetCommBreak(port->hdl) == 0)
2133 RETURN_FAIL("SetCommBreak() failed");
2135 if (ioctl(port->fd, TIOCSBRK, 1) < 0)
2136 RETURN_FAIL("TIOCSBRK ioctl failed");
2142 enum sp_return sp_end_break(struct sp_port *port)
2148 if (ClearCommBreak(port->hdl) == 0)
2149 RETURN_FAIL("ClearCommBreak() failed");
2151 if (ioctl(port->fd, TIOCCBRK, 1) < 0)
2152 RETURN_FAIL("TIOCCBRK ioctl failed");
2158 int sp_last_error_code(void)
2162 RETURN_VALUE("%d", GetLastError());
2164 RETURN_VALUE("%d", errno);
2168 char *sp_last_error_message(void)
2174 DWORD error = GetLastError();
2177 FORMAT_MESSAGE_ALLOCATE_BUFFER |
2178 FORMAT_MESSAGE_FROM_SYSTEM |
2179 FORMAT_MESSAGE_IGNORE_INSERTS,
2182 MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
2186 RETURN_VALUE("%s", message);
2188 RETURN_VALUE("%s", strerror(errno));
2192 void sp_free_error_message(char *message)
2194 TRACE("%s", message);
2205 void sp_set_debug_handler(void (*handler)(const char *format, ...))
2207 TRACE("%p", handler);
2209 sp_debug_handler = handler;
2214 void sp_default_debug_handler(const char *format, ...)
2217 va_start(args, format);
2218 if (getenv("LIBSERIALPORT_DEBUG")) {
2219 fputs("sp: ", stderr);
2220 vfprintf(stderr, format, args);