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>
45 #include <IOKit/IOKitLib.h>
46 #include <IOKit/serial/IOSerialKeys.h>
47 #include <IOKit/serial/ioss.h>
48 #include <sys/syslimits.h>
55 #include "linux/serial.h"
57 #include "linux_termios.h"
59 /* TCGETX/TCSETX is not available everywhere. */
60 #if defined(TCGETX) && defined(TCSETX) && defined(HAVE_TERMIOX)
65 /* TIOCINQ/TIOCOUTQ is not available everywhere. */
66 #if !defined(TIOCINQ) && defined(FIONREAD)
67 #define TIOCINQ FIONREAD
69 #if !defined(TIOCOUTQ) && defined(FIONWRITE)
70 #define TIOCOUTQ FIONWRITE
73 /* Non-standard baudrates are not available everywhere. */
74 #if defined(HAVE_TERMIOS_SPEED) || defined(HAVE_TERMIOS2_SPEED)
75 #define USE_TERMIOS_SPEED
78 #include "libserialport.h"
84 COMMTIMEOUTS timeouts;
96 struct sp_port_config {
99 enum sp_parity parity;
105 enum sp_xonxoff xon_xoff;
114 int termiox_supported;
123 typedef HANDLE event_handle;
125 typedef int event_handle;
128 /* Standard baud rates. */
130 #define BAUD_TYPE DWORD
131 #define BAUD(n) {CBR_##n, n}
133 #define BAUD_TYPE speed_t
134 #define BAUD(n) {B##n, n}
137 struct std_baudrate {
142 const struct std_baudrate std_baudrates[] = {
145 * The baudrates 50/75/134/150/200/1800/230400/460800 do not seem to
146 * have documented CBR_* macros.
148 BAUD(110), BAUD(300), BAUD(600), BAUD(1200), BAUD(2400), BAUD(4800),
149 BAUD(9600), BAUD(14400), BAUD(19200), BAUD(38400), BAUD(57600),
150 BAUD(115200), BAUD(128000), BAUD(256000),
152 BAUD(50), BAUD(75), BAUD(110), BAUD(134), BAUD(150), BAUD(200),
153 BAUD(300), BAUD(600), BAUD(1200), BAUD(1800), BAUD(2400), BAUD(4800),
154 BAUD(9600), BAUD(19200), BAUD(38400), BAUD(57600), BAUD(115200),
156 #if !defined(__APPLE__) && !defined(__OpenBSD__)
162 void (*sp_debug_handler)(const char *format, ...) = sp_default_debug_handler;
164 #define ARRAY_SIZE(x) (sizeof(x) / sizeof(x[0]))
165 #define NUM_STD_BAUDRATES ARRAY_SIZE(std_baudrates)
167 /* Debug output macros. */
168 #define DEBUG(fmt, ...) do { if (sp_debug_handler) sp_debug_handler(fmt ".\n", ##__VA_ARGS__); } while (0)
169 #define DEBUG_ERROR(err, msg) DEBUG("%s returning " #err ": " msg, __func__)
170 #define DEBUG_FAIL(msg) do { \
171 char *errmsg = sp_last_error_message(); \
172 DEBUG("%s returning SP_ERR_FAIL: " msg ": %s", __func__, errmsg); \
173 sp_free_error_message(errmsg); \
175 #define RETURN() do { DEBUG("%s returning", __func__); return; } while(0)
176 #define RETURN_CODE(x) do { DEBUG("%s returning " #x, __func__); return x; } while (0)
177 #define RETURN_CODEVAL(x) do { \
179 case SP_OK: RETURN_CODE(SP_OK); \
180 case SP_ERR_ARG: RETURN_CODE(SP_ERR_ARG); \
181 case SP_ERR_FAIL: RETURN_CODE(SP_ERR_FAIL); \
182 case SP_ERR_MEM: RETURN_CODE(SP_ERR_MEM); \
183 case SP_ERR_SUPP: RETURN_CODE(SP_ERR_SUPP); \
186 #define RETURN_OK() RETURN_CODE(SP_OK);
187 #define RETURN_ERROR(err, msg) do { DEBUG_ERROR(err, msg); return err; } while (0)
188 #define RETURN_FAIL(msg) do { DEBUG_FAIL(msg); return SP_ERR_FAIL; } while (0)
189 #define RETURN_VALUE(fmt, x) do { \
191 DEBUG("%s returning " fmt, __func__, _x); \
194 #define SET_ERROR(val, err, msg) do { DEBUG_ERROR(err, msg); val = err; } while (0)
195 #define SET_FAIL(val, msg) do { DEBUG_FAIL(msg); val = SP_ERR_FAIL; } while (0)
196 #define TRACE(fmt, ...) DEBUG("%s(" fmt ") called", __func__, ##__VA_ARGS__)
198 #define TRY(x) do { int ret = x; if (ret != SP_OK) RETURN_CODEVAL(ret); } while (0)
200 /* Helper functions. */
201 static struct sp_port **list_append(struct sp_port **list, const char *portname);
202 static enum sp_return get_config(struct sp_port *port, struct port_data *data,
203 struct sp_port_config *config);
204 static enum sp_return set_config(struct sp_port *port, struct port_data *data,
205 const struct sp_port_config *config);
207 enum sp_return sp_get_port_by_name(const char *portname, struct sp_port **port_ptr)
209 struct sp_port *port;
212 TRACE("%s, %p", portname, port_ptr);
215 RETURN_ERROR(SP_ERR_ARG, "Null result pointer");
220 RETURN_ERROR(SP_ERR_ARG, "Null port name");
222 DEBUG("Building structure for port %s", portname);
224 if (!(port = malloc(sizeof(struct sp_port))))
225 RETURN_ERROR(SP_ERR_MEM, "Port structure malloc failed");
227 len = strlen(portname) + 1;
229 if (!(port->name = malloc(len))) {
231 RETURN_ERROR(SP_ERR_MEM, "Port name malloc failed");
234 memcpy(port->name, portname, len);
237 port->hdl = INVALID_HANDLE_VALUE;
247 char *sp_get_port_name(const struct sp_port *port)
254 RETURN_VALUE("%s", port->name);
257 enum sp_return sp_get_port_handle(const struct sp_port *port, void *result_ptr)
259 TRACE("%p, %p", port, result_ptr);
262 RETURN_ERROR(SP_ERR_ARG, "Null port");
265 HANDLE *handle_ptr = result_ptr;
266 *handle_ptr = port->hdl;
268 int *fd_ptr = result_ptr;
275 enum sp_return sp_copy_port(const struct sp_port *port, struct sp_port **copy_ptr)
277 TRACE("%p, %p", port, copy_ptr);
280 RETURN_ERROR(SP_ERR_ARG, "Null result pointer");
285 RETURN_ERROR(SP_ERR_ARG, "Null port");
288 RETURN_ERROR(SP_ERR_ARG, "Null port name");
290 DEBUG("Copying port structure");
292 RETURN_VALUE("%p", sp_get_port_by_name(port->name, copy_ptr));
295 void sp_free_port(struct sp_port *port)
304 DEBUG("Freeing port structure");
314 static struct sp_port **list_append(struct sp_port **list, const char *portname)
319 for (count = 0; list[count]; count++);
320 if (!(tmp = realloc(list, sizeof(struct sp_port *) * (count + 2))))
323 if (sp_get_port_by_name(portname, &list[count]) != SP_OK)
325 list[count + 1] = NULL;
329 sp_free_port_list(list);
333 enum sp_return sp_list_ports(struct sp_port ***list_ptr)
335 struct sp_port **list;
336 int ret = SP_ERR_SUPP;
338 TRACE("%p", list_ptr);
341 RETURN_ERROR(SP_ERR_ARG, "Null result pointer");
343 DEBUG("Enumerating ports");
345 if (!(list = malloc(sizeof(struct sp_port **))))
346 RETURN_ERROR(SP_ERR_MEM, "Port list malloc failed");
353 DWORD max_value_len, max_data_size, max_data_len;
354 DWORD value_len, data_size, data_len;
355 DWORD type, index = 0;
361 DEBUG("Opening registry key");
362 if (RegOpenKeyEx(HKEY_LOCAL_MACHINE, _T("HARDWARE\\DEVICEMAP\\SERIALCOMM"),
363 0, KEY_QUERY_VALUE, &key) != ERROR_SUCCESS) {
364 SET_FAIL(ret, "RegOpenKeyEx() failed");
367 DEBUG("Querying registry key value and data sizes");
368 if (RegQueryInfoKey(key, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
369 &max_value_len, &max_data_size, NULL, NULL) != ERROR_SUCCESS) {
370 SET_FAIL(ret, "RegQueryInfoKey() failed");
373 max_data_len = max_data_size / sizeof(TCHAR);
374 if (!(value = malloc((max_value_len + 1) * sizeof(TCHAR)))) {
375 SET_ERROR(ret, SP_ERR_MEM, "registry value malloc failed");
378 if (!(data = malloc((max_data_len + 1) * sizeof(TCHAR)))) {
379 SET_ERROR(ret, SP_ERR_MEM, "registry data malloc failed");
382 DEBUG("Iterating over values");
384 value_len = max_value_len + 1,
385 data_size = max_data_size,
386 RegEnumValue(key, index, value, &value_len,
387 NULL, &type, (LPBYTE)data, &data_size) == ERROR_SUCCESS)
389 data_len = data_size / sizeof(TCHAR);
390 data[data_len] = '\0';
392 name_len = WideCharToMultiByte(CP_ACP, 0, data, -1, NULL, 0, NULL, NULL);
394 name_len = data_len + 1;
396 if (!(name = malloc(name_len))) {
397 SET_ERROR(ret, SP_ERR_MEM, "registry port name malloc failed");
401 WideCharToMultiByte(CP_ACP, 0, data, -1, name, name_len, NULL, NULL);
405 if (type == REG_SZ) {
406 DEBUG("Found port %s", name);
407 if (!(list = list_append(list, name))) {
408 SET_ERROR(ret, SP_ERR_MEM, "list append failed");
424 CFMutableDictionaryRef classes;
433 DEBUG("Getting IOKit master port");
434 if (IOMasterPort(MACH_PORT_NULL, &master) != KERN_SUCCESS) {
435 SET_FAIL(ret, "IOMasterPort() failed");
439 DEBUG("Creating matching dictionary");
440 if (!(classes = IOServiceMatching(kIOSerialBSDServiceValue))) {
441 SET_FAIL(ret, "IOServiceMatching() failed");
445 CFDictionarySetValue(classes,
446 CFSTR(kIOSerialBSDTypeKey), CFSTR(kIOSerialBSDAllTypes));
448 DEBUG("Getting matching services");
449 if (IOServiceGetMatchingServices(master, classes, &iter) != KERN_SUCCESS) {
450 SET_FAIL(ret, "IOServiceGetMatchingServices() failed");
454 if (!(path = malloc(PATH_MAX))) {
455 SET_ERROR(ret, SP_ERR_MEM, "device path malloc failed");
459 DEBUG("Iterating over results");
460 while ((port = IOIteratorNext(iter))) {
461 cf_path = IORegistryEntryCreateCFProperty(port,
462 CFSTR(kIOCalloutDeviceKey), kCFAllocatorDefault, 0);
464 result = CFStringGetCString(cf_path,
465 path, PATH_MAX, kCFStringEncodingASCII);
468 DEBUG("Found port %s", path);
469 if (!(list = list_append(list, path))) {
470 SET_ERROR(ret, SP_ERR_MEM, "list append failed");
471 IOObjectRelease(port);
476 IOObjectRelease(port);
481 IOObjectRelease(iter);
484 #if defined(__linux__) && defined(HAVE_LIBUDEV)
486 struct udev_enumerate *ud_enumerate;
487 struct udev_list_entry *ud_list;
488 struct udev_list_entry *ud_entry;
490 struct udev_device *ud_dev, *ud_parent;
493 int fd, ioctl_result;
494 struct serial_struct serial_info;
498 DEBUG("Enumerating tty devices");
500 ud_enumerate = udev_enumerate_new(ud);
501 udev_enumerate_add_match_subsystem(ud_enumerate, "tty");
502 udev_enumerate_scan_devices(ud_enumerate);
503 ud_list = udev_enumerate_get_list_entry(ud_enumerate);
504 DEBUG("Iterating over results");
505 udev_list_entry_foreach(ud_entry, ud_list) {
506 path = udev_list_entry_get_name(ud_entry);
507 DEBUG("Found device %s", path);
508 ud_dev = udev_device_new_from_syspath(ud, path);
509 /* If there is no parent device, this is a virtual tty. */
510 ud_parent = udev_device_get_parent(ud_dev);
511 if (ud_parent == NULL) {
512 DEBUG("No parent device, assuming virtual tty");
513 udev_device_unref(ud_dev);
516 name = udev_device_get_devnode(ud_dev);
517 /* The serial8250 driver has a hardcoded number of ports.
518 * The only way to tell which actually exist on a given system
519 * is to try to open them and make an ioctl call. */
520 driver = udev_device_get_driver(ud_parent);
521 if (driver && !strcmp(driver, "serial8250")) {
522 DEBUG("serial8250 device, attempting to open");
523 if ((fd = open(name, O_RDWR | O_NONBLOCK | O_NOCTTY)) < 0) {
524 DEBUG("open failed, skipping");
527 ioctl_result = ioctl(fd, TIOCGSERIAL, &serial_info);
529 if (ioctl_result != 0) {
530 DEBUG("ioctl failed, skipping");
533 if (serial_info.type == PORT_UNKNOWN) {
534 DEBUG("port type is unknown, skipping");
538 DEBUG("Found port %s", name);
539 list = list_append(list, name);
541 udev_device_unref(ud_dev);
543 SET_ERROR(ret, SP_ERR_MEM, "list append failed");
548 udev_enumerate_unref(ud_enumerate);
557 DEBUG_ERROR(SP_ERR_SUPP, "Enumeration not supported on this platform");
560 sp_free_port_list(list);
566 void sp_free_port_list(struct sp_port **list)
577 DEBUG("Freeing port list");
579 for (i = 0; list[i]; i++)
580 sp_free_port(list[i]);
586 #define CHECK_PORT() do { \
588 RETURN_ERROR(SP_ERR_ARG, "Null port"); \
589 if (port->name == NULL) \
590 RETURN_ERROR(SP_ERR_ARG, "Null port name"); \
593 #define CHECK_PORT_HANDLE() do { \
594 if (port->hdl == INVALID_HANDLE_VALUE) \
595 RETURN_ERROR(SP_ERR_ARG, "Invalid port handle"); \
598 #define CHECK_PORT_HANDLE() do { \
600 RETURN_ERROR(SP_ERR_ARG, "Invalid port fd"); \
603 #define CHECK_OPEN_PORT() do { \
605 CHECK_PORT_HANDLE(); \
608 enum sp_return sp_open(struct sp_port *port, enum sp_mode flags)
610 struct port_data data;
611 struct sp_port_config config;
614 TRACE("%p, 0x%x", port, flags);
618 if (flags > (SP_MODE_READ | SP_MODE_WRITE))
619 RETURN_ERROR(SP_ERR_ARG, "Invalid flags");
621 DEBUG("Opening port %s", port->name);
624 DWORD desired_access = 0, flags_and_attributes = 0, errors;
625 char *escaped_port_name;
628 /* Prefix port name with '\\.\' to work with ports above COM9. */
629 if (!(escaped_port_name = malloc(strlen(port->name) + 5)))
630 RETURN_ERROR(SP_ERR_MEM, "Escaped port name malloc failed");
631 sprintf(escaped_port_name, "\\\\.\\%s", port->name);
633 /* Map 'flags' to the OS-specific settings. */
634 flags_and_attributes = FILE_ATTRIBUTE_NORMAL | FILE_FLAG_OVERLAPPED;
635 if (flags & SP_MODE_READ)
636 desired_access |= GENERIC_READ;
637 if (flags & SP_MODE_WRITE)
638 desired_access |= GENERIC_WRITE;
640 port->hdl = CreateFile(escaped_port_name, desired_access, 0, 0,
641 OPEN_EXISTING, flags_and_attributes, 0);
643 free(escaped_port_name);
645 if (port->hdl == INVALID_HANDLE_VALUE)
646 RETURN_FAIL("port CreateFile() failed");
648 /* All timeouts initially disabled. */
649 port->timeouts.ReadIntervalTimeout = 0;
650 port->timeouts.ReadTotalTimeoutMultiplier = 0;
651 port->timeouts.ReadTotalTimeoutConstant = 0;
652 port->timeouts.WriteTotalTimeoutMultiplier = 0;
653 port->timeouts.WriteTotalTimeoutConstant = 0;
655 if (SetCommTimeouts(port->hdl, &port->timeouts) == 0) {
657 RETURN_FAIL("SetCommTimeouts() failed");
660 /* Prepare OVERLAPPED structures. */
661 #define INIT_OVERLAPPED(ovl) do { \
662 memset(&port->ovl, 0, sizeof(port->ovl)); \
663 port->ovl.hEvent = INVALID_HANDLE_VALUE; \
664 if ((port->ovl.hEvent = CreateEvent(NULL, TRUE, TRUE, NULL)) \
665 == INVALID_HANDLE_VALUE) { \
667 RETURN_FAIL(#ovl "CreateEvent() failed"); \
671 INIT_OVERLAPPED(read_ovl);
672 INIT_OVERLAPPED(write_ovl);
673 INIT_OVERLAPPED(wait_ovl);
675 /* Set event mask for RX and error events. */
676 if (SetCommMask(port->hdl, EV_RXCHAR | EV_ERR) == 0) {
678 RETURN_FAIL("SetCommMask() failed");
681 /* Start background operation for RX and error events. */
682 if (WaitCommEvent(port->hdl, &port->events, &port->wait_ovl) == 0) {
683 if (GetLastError() != ERROR_IO_PENDING) {
685 RETURN_FAIL("WaitCommEvent() failed");
689 port->writing = FALSE;
692 int flags_local = O_NONBLOCK | O_NOCTTY;
694 /* Map 'flags' to the OS-specific settings. */
695 if (flags & (SP_MODE_READ | SP_MODE_WRITE))
696 flags_local |= O_RDWR;
697 else if (flags & SP_MODE_READ)
698 flags_local |= O_RDONLY;
699 else if (flags & SP_MODE_WRITE)
700 flags_local |= O_WRONLY;
702 if ((port->fd = open(port->name, flags_local)) < 0)
703 RETURN_FAIL("open() failed");
706 ret = get_config(port, &data, &config);
713 /* Set sane port settings. */
715 data.dcb.fBinary = TRUE;
716 data.dcb.fDsrSensitivity = FALSE;
717 data.dcb.fErrorChar = FALSE;
718 data.dcb.fNull = FALSE;
719 data.dcb.fAbortOnError = TRUE;
721 /* Turn off all fancy termios tricks, give us a raw channel. */
722 data.term.c_iflag &= ~(IGNBRK | BRKINT | PARMRK | ISTRIP | INLCR | IGNCR | ICRNL | IMAXBEL);
724 data.term.c_iflag &= ~IUCLC;
726 data.term.c_oflag &= ~(OPOST | ONLCR | OCRNL | ONOCR | ONLRET);
728 data.term.c_oflag &= ~OLCUC;
731 data.term.c_oflag &= ~NLDLY;
734 data.term.c_oflag &= ~CRDLY;
737 data.term.c_oflag &= ~TABDLY;
740 data.term.c_oflag &= ~BSDLY;
743 data.term.c_oflag &= ~VTDLY;
746 data.term.c_oflag &= ~FFDLY;
749 data.term.c_oflag &= ~OFILL;
751 data.term.c_lflag &= ~(ISIG | ICANON | ECHO | IEXTEN);
752 data.term.c_cc[VMIN] = 0;
753 data.term.c_cc[VTIME] = 0;
755 /* Ignore modem status lines; enable receiver; leave control lines alone on close. */
756 data.term.c_cflag |= (CLOCAL | CREAD | HUPCL);
760 if (ClearCommError(port->hdl, &errors, &status) == 0)
761 RETURN_FAIL("ClearCommError() failed");
764 ret = set_config(port, &data, &config);
774 enum sp_return sp_close(struct sp_port *port)
780 DEBUG("Closing port %s", port->name);
783 /* Returns non-zero upon success, 0 upon failure. */
784 if (CloseHandle(port->hdl) == 0)
785 RETURN_FAIL("port CloseHandle() failed");
786 port->hdl = INVALID_HANDLE_VALUE;
788 /* Close event handles for overlapped structures. */
789 #define CLOSE_OVERLAPPED(ovl) do { \
790 if (port->ovl.hEvent != INVALID_HANDLE_VALUE && \
791 CloseHandle(port->ovl.hEvent) == 0) \
792 RETURN_FAIL(# ovl "event CloseHandle() failed"); \
794 CLOSE_OVERLAPPED(read_ovl);
795 CLOSE_OVERLAPPED(write_ovl);
796 CLOSE_OVERLAPPED(wait_ovl);
799 /* Returns 0 upon success, -1 upon failure. */
800 if (close(port->fd) == -1)
801 RETURN_FAIL("close() failed");
808 enum sp_return sp_flush(struct sp_port *port, enum sp_buffer buffers)
810 TRACE("%p, 0x%x", port, buffers);
814 if (buffers > SP_BUF_BOTH)
815 RETURN_ERROR(SP_ERR_ARG, "Invalid buffer selection");
817 const char *buffer_names[] = {"no", "input", "output", "both"};
819 DEBUG("Flushing %s buffers on port %s", buffer_names[buffers], port->name);
823 if (buffers & SP_BUF_INPUT)
824 flags |= PURGE_RXCLEAR;
825 if (buffers & SP_BUF_OUTPUT)
826 flags |= PURGE_TXCLEAR;
828 /* Returns non-zero upon success, 0 upon failure. */
829 if (PurgeComm(port->hdl, flags) == 0)
830 RETURN_FAIL("PurgeComm() failed");
833 if (buffers & SP_BUF_BOTH)
835 else if (buffers & SP_BUF_INPUT)
837 else if (buffers & SP_BUF_OUTPUT)
840 /* Returns 0 upon success, -1 upon failure. */
841 if (tcflush(port->fd, flags) < 0)
842 RETURN_FAIL("tcflush() failed");
847 enum sp_return sp_drain(struct sp_port *port)
853 DEBUG("Draining port %s", port->name);
856 /* Returns non-zero upon success, 0 upon failure. */
857 if (FlushFileBuffers(port->hdl) == 0)
858 RETURN_FAIL("FlushFileBuffers() failed");
865 result = ioctl(port->fd, TCSBRK, &arg);
867 result = tcdrain(port->fd);
870 if (errno == EINTR) {
871 DEBUG("tcdrain() was interrupted");
874 RETURN_FAIL("tcdrain() failed");
883 enum sp_return sp_blocking_write(struct sp_port *port, const void *buf, size_t count, unsigned int timeout)
885 TRACE("%p, %p, %d, %d", port, buf, count, timeout);
890 RETURN_ERROR(SP_ERR_ARG, "Null buffer");
893 DEBUG("Writing %d bytes to port %s, timeout %d ms", count, port->name, timeout);
895 DEBUG("Writing %d bytes to port %s, no timeout", count, port->name);
898 RETURN_VALUE("0", 0);
901 DWORD bytes_written = 0;
904 /* Wait for previous non-blocking write to complete, if any. */
906 DEBUG("Waiting for previous write to complete");
907 result = GetOverlappedResult(port->hdl, &port->write_ovl, &bytes_written, TRUE);
910 RETURN_FAIL("Previous write failed to complete");
911 DEBUG("Previous write completed");
915 port->timeouts.WriteTotalTimeoutConstant = timeout;
916 if (SetCommTimeouts(port->hdl, &port->timeouts) == 0)
917 RETURN_FAIL("SetCommTimeouts() failed");
920 if (WriteFile(port->hdl, buf, count, NULL, &port->write_ovl) == 0) {
921 if (GetLastError() == ERROR_IO_PENDING) {
922 DEBUG("Waiting for write to complete");
923 GetOverlappedResult(port->hdl, &port->write_ovl, &bytes_written, TRUE);
924 DEBUG("Write completed, %d/%d bytes written", bytes_written, count);
925 RETURN_VALUE("%d", bytes_written);
927 RETURN_FAIL("WriteFile() failed");
930 DEBUG("Write completed immediately");
931 RETURN_VALUE("%d", count);
934 size_t bytes_written = 0;
935 unsigned char *ptr = (unsigned char *) buf;
936 struct timeval start, delta, now, end = {0, 0};
941 /* Get time at start of operation. */
942 gettimeofday(&start, NULL);
943 /* Define duration of timeout. */
944 delta.tv_sec = timeout / 1000;
945 delta.tv_usec = (timeout % 1000) * 1000;
946 /* Calculate time at which we should give up. */
947 timeradd(&start, &delta, &end);
950 /* Loop until we have written the requested number of bytes. */
951 while (bytes_written < count)
953 /* Wait until space is available. */
955 FD_SET(port->fd, &fds);
957 gettimeofday(&now, NULL);
958 if (timercmp(&now, &end, >)) {
959 DEBUG("write timed out");
960 RETURN_VALUE("%d", bytes_written);
962 timersub(&end, &now, &delta);
964 result = select(port->fd + 1, NULL, &fds, NULL, timeout ? &delta : NULL);
966 if (errno == EINTR) {
967 DEBUG("select() call was interrupted, repeating");
970 RETURN_FAIL("select() failed");
972 } else if (result == 0) {
973 DEBUG("write timed out");
974 RETURN_VALUE("%d", bytes_written);
978 result = write(port->fd, ptr, count - bytes_written);
982 /* This shouldn't happen because we did a select() first, but handle anyway. */
985 /* This is an actual failure. */
986 RETURN_FAIL("write() failed");
989 bytes_written += result;
993 RETURN_VALUE("%d", bytes_written);
997 enum sp_return sp_nonblocking_write(struct sp_port *port, const void *buf, size_t count)
999 TRACE("%p, %p, %d", port, buf, count);
1004 RETURN_ERROR(SP_ERR_ARG, "Null buffer");
1006 DEBUG("Writing up to %d bytes to port %s", count, port->name);
1009 RETURN_VALUE("0", 0);
1013 BYTE *ptr = (BYTE *) buf;
1015 /* Check whether previous write is complete. */
1016 if (port->writing) {
1017 if (HasOverlappedIoCompleted(&port->write_ovl)) {
1018 DEBUG("Previous write completed");
1021 DEBUG("Previous write not complete");
1022 /* Can't take a new write until the previous one finishes. */
1023 RETURN_VALUE("0", 0);
1028 port->timeouts.WriteTotalTimeoutConstant = 0;
1029 if (SetCommTimeouts(port->hdl, &port->timeouts) == 0)
1030 RETURN_FAIL("SetCommTimeouts() failed");
1032 /* Keep writing data until the OS has to actually start an async IO for it.
1033 * At that point we know the buffer is full. */
1034 while (written < count)
1036 /* Copy first byte of user buffer. */
1037 port->pending_byte = *ptr++;
1039 /* Start asynchronous write. */
1040 if (WriteFile(port->hdl, &port->pending_byte, 1, NULL, &port->write_ovl) == 0) {
1041 if (GetLastError() == ERROR_IO_PENDING) {
1042 if (HasOverlappedIoCompleted(&port->write_ovl)) {
1043 DEBUG("Asynchronous write completed immediately");
1048 DEBUG("Asynchronous write running");
1050 RETURN_VALUE("%d", ++written);
1053 /* Actual failure of some kind. */
1054 RETURN_FAIL("WriteFile() failed");
1057 DEBUG("Single byte written immediately");
1062 DEBUG("All bytes written immediately");
1064 RETURN_VALUE("%d", written);
1066 /* Returns the number of bytes written, or -1 upon failure. */
1067 ssize_t written = write(port->fd, buf, count);
1070 RETURN_FAIL("write() failed");
1072 RETURN_VALUE("%d", written);
1076 enum sp_return sp_blocking_read(struct sp_port *port, void *buf, size_t count, unsigned int timeout)
1078 TRACE("%p, %p, %d, %d", port, buf, count, timeout);
1083 RETURN_ERROR(SP_ERR_ARG, "Null buffer");
1086 DEBUG("Reading %d bytes from port %s, timeout %d ms", count, port->name, timeout);
1088 DEBUG("Reading %d bytes from port %s, no timeout", count, port->name);
1091 RETURN_VALUE("0", 0);
1094 DWORD bytes_read = 0;
1097 port->timeouts.ReadIntervalTimeout = 0;
1098 port->timeouts.ReadTotalTimeoutConstant = timeout;
1099 if (SetCommTimeouts(port->hdl, &port->timeouts) == 0)
1100 RETURN_FAIL("SetCommTimeouts() failed");
1103 if (ReadFile(port->hdl, buf, count, NULL, &port->read_ovl) == 0) {
1104 if (GetLastError() == ERROR_IO_PENDING) {
1105 DEBUG("Waiting for read to complete");
1106 GetOverlappedResult(port->hdl, &port->read_ovl, &bytes_read, TRUE);
1107 DEBUG("Read completed, %d/%d bytes read", bytes_read, count);
1109 RETURN_FAIL("ReadFile() failed");
1112 DEBUG("Read completed immediately");
1116 /* Start background operation for subsequent events. */
1117 if (WaitCommEvent(port->hdl, &port->events, &port->wait_ovl) == 0) {
1118 if (GetLastError() != ERROR_IO_PENDING)
1119 RETURN_FAIL("WaitCommEvent() failed");
1122 RETURN_VALUE("%d", bytes_read);
1125 size_t bytes_read = 0;
1126 unsigned char *ptr = (unsigned char *) buf;
1127 struct timeval start, delta, now, end = {0, 0};
1132 /* Get time at start of operation. */
1133 gettimeofday(&start, NULL);
1134 /* Define duration of timeout. */
1135 delta.tv_sec = timeout / 1000;
1136 delta.tv_usec = (timeout % 1000) * 1000;
1137 /* Calculate time at which we should give up. */
1138 timeradd(&start, &delta, &end);
1141 /* Loop until we have the requested number of bytes. */
1142 while (bytes_read < count)
1144 /* Wait until data is available. */
1146 FD_SET(port->fd, &fds);
1148 gettimeofday(&now, NULL);
1149 if (timercmp(&now, &end, >))
1150 /* Timeout has expired. */
1151 RETURN_VALUE("%d", bytes_read);
1152 timersub(&end, &now, &delta);
1154 result = select(port->fd + 1, &fds, NULL, NULL, timeout ? &delta : NULL);
1156 if (errno == EINTR) {
1157 DEBUG("select() call was interrupted, repeating");
1160 RETURN_FAIL("select() failed");
1162 } else if (result == 0) {
1163 DEBUG("read timed out");
1164 RETURN_VALUE("%d", bytes_read);
1168 result = read(port->fd, ptr, count - bytes_read);
1171 if (errno == EAGAIN)
1172 /* This shouldn't happen because we did a select() first, but handle anyway. */
1175 /* This is an actual failure. */
1176 RETURN_FAIL("read() failed");
1179 bytes_read += result;
1183 RETURN_VALUE("%d", bytes_read);
1187 enum sp_return sp_nonblocking_read(struct sp_port *port, void *buf, size_t count)
1189 TRACE("%p, %p, %d", port, buf, count);
1194 RETURN_ERROR(SP_ERR_ARG, "Null buffer");
1196 DEBUG("Reading up to %d bytes from port %s", count, port->name);
1202 port->timeouts.ReadIntervalTimeout = MAXDWORD;
1203 port->timeouts.ReadTotalTimeoutConstant = 0;
1204 if (SetCommTimeouts(port->hdl, &port->timeouts) == 0)
1205 RETURN_FAIL("SetCommTimeouts() failed");
1208 if (ReadFile(port->hdl, buf, count, NULL, &port->read_ovl) == 0)
1209 RETURN_FAIL("ReadFile() failed");
1211 /* Get number of bytes read. */
1212 if (GetOverlappedResult(port->hdl, &port->read_ovl, &bytes_read, TRUE) == 0)
1213 RETURN_FAIL("GetOverlappedResult() failed");
1215 if (bytes_read > 0) {
1216 /* Start background operation for subsequent events. */
1217 if (WaitCommEvent(port->hdl, &port->events, &port->wait_ovl) == 0) {
1218 if (GetLastError() != ERROR_IO_PENDING)
1219 RETURN_FAIL("WaitCommEvent() failed");
1223 RETURN_VALUE("%d", bytes_read);
1227 /* Returns the number of bytes read, or -1 upon failure. */
1228 if ((bytes_read = read(port->fd, buf, count)) < 0) {
1229 if (errno == EAGAIN)
1230 /* No bytes available. */
1233 /* This is an actual failure. */
1234 RETURN_FAIL("read() failed");
1236 RETURN_VALUE("%d", bytes_read);
1240 enum sp_return sp_input_waiting(struct sp_port *port)
1246 DEBUG("Checking input bytes waiting on port %s", port->name);
1252 if (ClearCommError(port->hdl, &errors, &comstat) == 0)
1253 RETURN_FAIL("ClearCommError() failed");
1254 RETURN_VALUE("%d", comstat.cbInQue);
1257 if (ioctl(port->fd, TIOCINQ, &bytes_waiting) < 0)
1258 RETURN_FAIL("TIOCINQ ioctl failed");
1259 RETURN_VALUE("%d", bytes_waiting);
1263 enum sp_return sp_output_waiting(struct sp_port *port)
1269 DEBUG("Checking output bytes waiting on port %s", port->name);
1275 if (ClearCommError(port->hdl, &errors, &comstat) == 0)
1276 RETURN_FAIL("ClearCommError() failed");
1277 RETURN_VALUE("%d", comstat.cbOutQue);
1280 if (ioctl(port->fd, TIOCOUTQ, &bytes_waiting) < 0)
1281 RETURN_FAIL("TIOCOUTQ ioctl failed");
1282 RETURN_VALUE("%d", bytes_waiting);
1286 enum sp_return sp_new_event_set(struct sp_event_set **result_ptr)
1288 struct sp_event_set *result;
1290 TRACE("%p", result_ptr);
1293 RETURN_ERROR(SP_ERR_ARG, "Null result");
1297 if (!(result = malloc(sizeof(struct sp_event_set))))
1298 RETURN_ERROR(SP_ERR_MEM, "sp_event_set malloc() failed");
1300 memset(result, 0, sizeof(struct sp_event_set));
1302 *result_ptr = result;
1307 static enum sp_return add_handle(struct sp_event_set *event_set,
1308 event_handle handle, enum sp_event mask)
1311 enum sp_event *new_masks;
1313 TRACE("%p, %d, %d", event_set, handle, mask);
1315 if (!(new_handles = realloc(event_set->handles,
1316 sizeof(event_handle) * (event_set->count + 1))))
1317 RETURN_ERROR(SP_ERR_MEM, "handle array realloc() failed");
1319 if (!(new_masks = realloc(event_set->masks,
1320 sizeof(enum sp_event) * (event_set->count + 1))))
1321 RETURN_ERROR(SP_ERR_MEM, "mask array realloc() failed");
1323 event_set->handles = new_handles;
1324 event_set->masks = new_masks;
1326 ((event_handle *) event_set->handles)[event_set->count] = handle;
1327 event_set->masks[event_set->count] = mask;
1334 enum sp_return sp_add_port_events(struct sp_event_set *event_set,
1335 const struct sp_port *port, enum sp_event mask)
1337 TRACE("%p, %p, %d", event_set, port, mask);
1340 RETURN_ERROR(SP_ERR_ARG, "Null event set");
1343 RETURN_ERROR(SP_ERR_ARG, "Null port");
1345 if (mask > (SP_EVENT_RX_READY | SP_EVENT_TX_READY | SP_EVENT_ERROR))
1346 RETURN_ERROR(SP_ERR_ARG, "Invalid event mask");
1352 enum sp_event handle_mask;
1353 if ((handle_mask = mask & SP_EVENT_TX_READY))
1354 TRY(add_handle(event_set, port->write_ovl.hEvent, handle_mask));
1355 if ((handle_mask = mask & (SP_EVENT_RX_READY | SP_EVENT_ERROR)))
1356 TRY(add_handle(event_set, port->wait_ovl.hEvent, handle_mask));
1358 TRY(add_handle(event_set, port->fd, mask));
1364 void sp_free_event_set(struct sp_event_set *event_set)
1366 TRACE("%p", event_set);
1369 DEBUG("Null event set");
1373 DEBUG("Freeing event set");
1375 if (event_set->handles)
1376 free(event_set->handles);
1377 if (event_set->masks)
1378 free(event_set->masks);
1385 enum sp_return sp_wait(struct sp_event_set *event_set, unsigned int timeout)
1387 TRACE("%p, %d", event_set, timeout);
1390 RETURN_ERROR(SP_ERR_ARG, "Null event set");
1393 if (WaitForMultipleObjects(event_set->count, event_set->handles, FALSE,
1394 timeout ? timeout : INFINITE) == WAIT_FAILED)
1395 RETURN_FAIL("WaitForMultipleObjects() failed");
1399 struct timeval start, delta, now, end = {0, 0};
1400 int result, timeout_remaining;
1401 struct pollfd *pollfds;
1404 if (!(pollfds = malloc(sizeof(struct pollfd) * event_set->count)))
1405 RETURN_ERROR(SP_ERR_MEM, "pollfds malloc() failed");
1407 for (i = 0; i < event_set->count; i++) {
1408 pollfds[i].fd = ((int *) event_set->handles)[i];
1409 pollfds[i].events = 0;
1410 pollfds[i].revents = 0;
1411 if (event_set->masks[i] & SP_EVENT_RX_READY)
1412 pollfds[i].events |= POLLIN;
1413 if (event_set->masks[i] & SP_EVENT_TX_READY)
1414 pollfds[i].events |= POLLOUT;
1415 if (event_set->masks[i] & SP_EVENT_ERROR)
1416 pollfds[i].events |= POLLERR;
1420 /* Get time at start of operation. */
1421 gettimeofday(&start, NULL);
1422 /* Define duration of timeout. */
1423 delta.tv_sec = timeout / 1000;
1424 delta.tv_usec = (timeout % 1000) * 1000;
1425 /* Calculate time at which we should give up. */
1426 timeradd(&start, &delta, &end);
1429 /* Loop until an event occurs. */
1433 gettimeofday(&now, NULL);
1434 if (timercmp(&now, &end, >)) {
1435 DEBUG("wait timed out");
1438 timersub(&end, &now, &delta);
1439 timeout_remaining = delta.tv_sec * 1000 + delta.tv_usec / 1000;
1442 result = poll(pollfds, event_set->count, timeout ? timeout_remaining : -1);
1445 if (errno == EINTR) {
1446 DEBUG("poll() call was interrupted, repeating");
1450 RETURN_FAIL("poll() failed");
1452 } else if (result == 0) {
1453 DEBUG("poll() timed out");
1456 DEBUG("poll() completed");
1466 #ifdef USE_TERMIOS_SPEED
1467 static enum sp_return get_baudrate(int fd, int *baudrate)
1471 TRACE("%d, %p", fd, baudrate);
1473 DEBUG("Getting baud rate");
1475 if (!(data = malloc(get_termios_size())))
1476 RETURN_ERROR(SP_ERR_MEM, "termios malloc failed");
1478 if (ioctl(fd, get_termios_get_ioctl(), data) < 0) {
1480 RETURN_FAIL("getting termios failed");
1483 *baudrate = get_termios_speed(data);
1490 static enum sp_return set_baudrate(int fd, int baudrate)
1494 TRACE("%d, %d", fd, baudrate);
1496 DEBUG("Getting baud rate");
1498 if (!(data = malloc(get_termios_size())))
1499 RETURN_ERROR(SP_ERR_MEM, "termios malloc failed");
1501 if (ioctl(fd, get_termios_get_ioctl(), data) < 0) {
1503 RETURN_FAIL("getting termios failed");
1506 DEBUG("Setting baud rate");
1508 set_termios_speed(data, baudrate);
1510 if (ioctl(fd, get_termios_set_ioctl(), data) < 0) {
1512 RETURN_FAIL("setting termios failed");
1519 #endif /* USE_TERMIOS_SPEED */
1522 static enum sp_return get_flow(int fd, struct port_data *data)
1526 TRACE("%d, %p", fd, data);
1528 DEBUG("Getting advanced flow control");
1530 if (!(termx = malloc(get_termiox_size())))
1531 RETURN_ERROR(SP_ERR_MEM, "termiox malloc failed");
1533 if (ioctl(fd, TCGETX, termx) < 0) {
1535 RETURN_FAIL("getting termiox failed");
1538 get_termiox_flow(termx, &data->rts_flow, &data->cts_flow,
1539 &data->dtr_flow, &data->dsr_flow);
1546 static enum sp_return set_flow(int fd, struct port_data *data)
1550 TRACE("%d, %p", fd, data);
1552 DEBUG("Getting advanced flow control");
1554 if (!(termx = malloc(get_termiox_size())))
1555 RETURN_ERROR(SP_ERR_MEM, "termiox malloc failed");
1557 if (ioctl(fd, TCGETX, termx) < 0) {
1559 RETURN_FAIL("getting termiox failed");
1562 DEBUG("Setting advanced flow control");
1564 set_termiox_flow(termx, data->rts_flow, data->cts_flow,
1565 data->dtr_flow, data->dsr_flow);
1567 if (ioctl(fd, TCSETX, termx) < 0) {
1569 RETURN_FAIL("setting termiox failed");
1576 #endif /* USE_TERMIOX */
1578 static enum sp_return get_config(struct sp_port *port, struct port_data *data,
1579 struct sp_port_config *config)
1583 TRACE("%p, %p, %p", port, data, config);
1585 DEBUG("Getting configuration for port %s", port->name);
1588 if (!GetCommState(port->hdl, &data->dcb))
1589 RETURN_FAIL("GetCommState() failed");
1591 for (i = 0; i < NUM_STD_BAUDRATES; i++) {
1592 if (data->dcb.BaudRate == std_baudrates[i].index) {
1593 config->baudrate = std_baudrates[i].value;
1598 if (i == NUM_STD_BAUDRATES)
1599 /* BaudRate field can be either an index or a custom baud rate. */
1600 config->baudrate = data->dcb.BaudRate;
1602 config->bits = data->dcb.ByteSize;
1604 if (data->dcb.fParity)
1605 switch (data->dcb.Parity) {
1607 config->parity = SP_PARITY_NONE;
1610 config->parity = SP_PARITY_ODD;
1613 config->parity = SP_PARITY_EVEN;
1616 config->parity = SP_PARITY_MARK;
1619 config->parity = SP_PARITY_SPACE;
1622 config->parity = -1;
1625 config->parity = SP_PARITY_NONE;
1627 switch (data->dcb.StopBits) {
1629 config->stopbits = 1;
1632 config->stopbits = 2;
1635 config->stopbits = -1;
1638 switch (data->dcb.fRtsControl) {
1639 case RTS_CONTROL_DISABLE:
1640 config->rts = SP_RTS_OFF;
1642 case RTS_CONTROL_ENABLE:
1643 config->rts = SP_RTS_ON;
1645 case RTS_CONTROL_HANDSHAKE:
1646 config->rts = SP_RTS_FLOW_CONTROL;
1652 config->cts = data->dcb.fOutxCtsFlow ? SP_CTS_FLOW_CONTROL : SP_CTS_IGNORE;
1654 switch (data->dcb.fDtrControl) {
1655 case DTR_CONTROL_DISABLE:
1656 config->dtr = SP_DTR_OFF;
1658 case DTR_CONTROL_ENABLE:
1659 config->dtr = SP_DTR_ON;
1661 case DTR_CONTROL_HANDSHAKE:
1662 config->dtr = SP_DTR_FLOW_CONTROL;
1668 config->dsr = data->dcb.fOutxDsrFlow ? SP_DSR_FLOW_CONTROL : SP_DSR_IGNORE;
1670 if (data->dcb.fInX) {
1671 if (data->dcb.fOutX)
1672 config->xon_xoff = SP_XONXOFF_INOUT;
1674 config->xon_xoff = SP_XONXOFF_IN;
1676 if (data->dcb.fOutX)
1677 config->xon_xoff = SP_XONXOFF_OUT;
1679 config->xon_xoff = SP_XONXOFF_DISABLED;
1684 if (tcgetattr(port->fd, &data->term) < 0)
1685 RETURN_FAIL("tcgetattr() failed");
1687 if (ioctl(port->fd, TIOCMGET, &data->controlbits) < 0)
1688 RETURN_FAIL("TIOCMGET ioctl failed");
1691 int ret = get_flow(port->fd, data);
1693 if (ret == SP_ERR_FAIL && errno == EINVAL)
1694 data->termiox_supported = 0;
1696 RETURN_CODEVAL(ret);
1698 data->termiox_supported = 1;
1700 data->termiox_supported = 0;
1703 for (i = 0; i < NUM_STD_BAUDRATES; i++) {
1704 if (cfgetispeed(&data->term) == std_baudrates[i].index) {
1705 config->baudrate = std_baudrates[i].value;
1710 if (i == NUM_STD_BAUDRATES) {
1712 config->baudrate = (int)data->term.c_ispeed;
1713 #elif defined(USE_TERMIOS_SPEED)
1714 TRY(get_baudrate(port->fd, &config->baudrate));
1716 config->baudrate = -1;
1720 switch (data->term.c_cflag & CSIZE) {
1737 if (!(data->term.c_cflag & PARENB) && (data->term.c_iflag & IGNPAR))
1738 config->parity = SP_PARITY_NONE;
1739 else if (!(data->term.c_cflag & PARENB) || (data->term.c_iflag & IGNPAR))
1740 config->parity = -1;
1742 else if (data->term.c_cflag & CMSPAR)
1743 config->parity = (data->term.c_cflag & PARODD) ? SP_PARITY_MARK : SP_PARITY_SPACE;
1746 config->parity = (data->term.c_cflag & PARODD) ? SP_PARITY_ODD : SP_PARITY_EVEN;
1748 config->stopbits = (data->term.c_cflag & CSTOPB) ? 2 : 1;
1750 if (data->term.c_cflag & CRTSCTS) {
1751 config->rts = SP_RTS_FLOW_CONTROL;
1752 config->cts = SP_CTS_FLOW_CONTROL;
1754 if (data->termiox_supported && data->rts_flow)
1755 config->rts = SP_RTS_FLOW_CONTROL;
1757 config->rts = (data->controlbits & TIOCM_RTS) ? SP_RTS_ON : SP_RTS_OFF;
1759 config->cts = (data->termiox_supported && data->cts_flow) ?
1760 SP_CTS_FLOW_CONTROL : SP_CTS_IGNORE;
1763 if (data->termiox_supported && data->dtr_flow)
1764 config->dtr = SP_DTR_FLOW_CONTROL;
1766 config->dtr = (data->controlbits & TIOCM_DTR) ? SP_DTR_ON : SP_DTR_OFF;
1768 config->dsr = (data->termiox_supported && data->dsr_flow) ?
1769 SP_DSR_FLOW_CONTROL : SP_DSR_IGNORE;
1771 if (data->term.c_iflag & IXOFF) {
1772 if (data->term.c_iflag & IXON)
1773 config->xon_xoff = SP_XONXOFF_INOUT;
1775 config->xon_xoff = SP_XONXOFF_IN;
1777 if (data->term.c_iflag & IXON)
1778 config->xon_xoff = SP_XONXOFF_OUT;
1780 config->xon_xoff = SP_XONXOFF_DISABLED;
1787 static enum sp_return set_config(struct sp_port *port, struct port_data *data,
1788 const struct sp_port_config *config)
1792 BAUD_TYPE baud_nonstd;
1796 #ifdef USE_TERMIOS_SPEED
1797 int baud_nonstd = 0;
1800 TRACE("%p, %p, %p", port, data, config);
1802 DEBUG("Setting configuration for port %s", port->name);
1805 if (config->baudrate >= 0) {
1806 for (i = 0; i < NUM_STD_BAUDRATES; i++) {
1807 if (config->baudrate == std_baudrates[i].value) {
1808 data->dcb.BaudRate = std_baudrates[i].index;
1813 if (i == NUM_STD_BAUDRATES)
1814 data->dcb.BaudRate = config->baudrate;
1817 if (config->bits >= 0)
1818 data->dcb.ByteSize = config->bits;
1820 if (config->parity >= 0) {
1821 switch (config->parity) {
1822 case SP_PARITY_NONE:
1823 data->dcb.Parity = NOPARITY;
1826 data->dcb.Parity = ODDPARITY;
1828 case SP_PARITY_EVEN:
1829 data->dcb.Parity = EVENPARITY;
1831 case SP_PARITY_MARK:
1832 data->dcb.Parity = MARKPARITY;
1834 case SP_PARITY_SPACE:
1835 data->dcb.Parity = SPACEPARITY;
1838 RETURN_ERROR(SP_ERR_ARG, "Invalid parity setting");
1842 if (config->stopbits >= 0) {
1843 switch (config->stopbits) {
1844 /* Note: There's also ONE5STOPBITS == 1.5 (unneeded so far). */
1846 data->dcb.StopBits = ONESTOPBIT;
1849 data->dcb.StopBits = TWOSTOPBITS;
1852 RETURN_ERROR(SP_ERR_ARG, "Invalid stop bit setting");
1856 if (config->rts >= 0) {
1857 switch (config->rts) {
1859 data->dcb.fRtsControl = RTS_CONTROL_DISABLE;
1862 data->dcb.fRtsControl = RTS_CONTROL_ENABLE;
1864 case SP_RTS_FLOW_CONTROL:
1865 data->dcb.fRtsControl = RTS_CONTROL_HANDSHAKE;
1868 RETURN_ERROR(SP_ERR_ARG, "Invalid RTS setting");
1872 if (config->cts >= 0) {
1873 switch (config->cts) {
1875 data->dcb.fOutxCtsFlow = FALSE;
1877 case SP_CTS_FLOW_CONTROL:
1878 data->dcb.fOutxCtsFlow = TRUE;
1881 RETURN_ERROR(SP_ERR_ARG, "Invalid CTS setting");
1885 if (config->dtr >= 0) {
1886 switch (config->dtr) {
1888 data->dcb.fDtrControl = DTR_CONTROL_DISABLE;
1891 data->dcb.fDtrControl = DTR_CONTROL_ENABLE;
1893 case SP_DTR_FLOW_CONTROL:
1894 data->dcb.fDtrControl = DTR_CONTROL_HANDSHAKE;
1897 RETURN_ERROR(SP_ERR_ARG, "Invalid DTR setting");
1901 if (config->dsr >= 0) {
1902 switch (config->dsr) {
1904 data->dcb.fOutxDsrFlow = FALSE;
1906 case SP_DSR_FLOW_CONTROL:
1907 data->dcb.fOutxDsrFlow = TRUE;
1910 RETURN_ERROR(SP_ERR_ARG, "Invalid DSR setting");
1914 if (config->xon_xoff >= 0) {
1915 switch (config->xon_xoff) {
1916 case SP_XONXOFF_DISABLED:
1917 data->dcb.fInX = FALSE;
1918 data->dcb.fOutX = FALSE;
1921 data->dcb.fInX = TRUE;
1922 data->dcb.fOutX = FALSE;
1924 case SP_XONXOFF_OUT:
1925 data->dcb.fInX = FALSE;
1926 data->dcb.fOutX = TRUE;
1928 case SP_XONXOFF_INOUT:
1929 data->dcb.fInX = TRUE;
1930 data->dcb.fOutX = TRUE;
1933 RETURN_ERROR(SP_ERR_ARG, "Invalid XON/XOFF setting");
1937 if (!SetCommState(port->hdl, &data->dcb))
1938 RETURN_FAIL("SetCommState() failed");
1944 if (config->baudrate >= 0) {
1945 for (i = 0; i < NUM_STD_BAUDRATES; i++) {
1946 if (config->baudrate == std_baudrates[i].value) {
1947 if (cfsetospeed(&data->term, std_baudrates[i].index) < 0)
1948 RETURN_FAIL("cfsetospeed() failed");
1950 if (cfsetispeed(&data->term, std_baudrates[i].index) < 0)
1951 RETURN_FAIL("cfsetispeed() failed");
1956 /* Non-standard baud rate */
1957 if (i == NUM_STD_BAUDRATES) {
1959 /* Set "dummy" baud rate. */
1960 if (cfsetspeed(&data->term, B9600) < 0)
1961 RETURN_FAIL("cfsetspeed() failed");
1962 baud_nonstd = config->baudrate;
1963 #elif defined(USE_TERMIOS_SPEED)
1966 RETURN_ERROR(SP_ERR_SUPP, "Non-standard baudrate not supported");
1971 if (config->bits >= 0) {
1972 data->term.c_cflag &= ~CSIZE;
1973 switch (config->bits) {
1975 data->term.c_cflag |= CS8;
1978 data->term.c_cflag |= CS7;
1981 data->term.c_cflag |= CS6;
1984 data->term.c_cflag |= CS5;
1987 RETURN_ERROR(SP_ERR_ARG, "Invalid data bits setting");
1991 if (config->parity >= 0) {
1992 data->term.c_iflag &= ~IGNPAR;
1993 data->term.c_cflag &= ~(PARENB | PARODD);
1995 data->term.c_cflag &= ~CMSPAR;
1997 switch (config->parity) {
1998 case SP_PARITY_NONE:
1999 data->term.c_iflag |= IGNPAR;
2001 case SP_PARITY_EVEN:
2002 data->term.c_cflag |= PARENB;
2005 data->term.c_cflag |= PARENB | PARODD;
2008 case SP_PARITY_MARK:
2009 data->term.c_cflag |= PARENB | PARODD;
2010 data->term.c_cflag |= CMSPAR;
2012 case SP_PARITY_SPACE:
2013 data->term.c_cflag |= PARENB;
2014 data->term.c_cflag |= CMSPAR;
2017 case SP_PARITY_MARK:
2018 case SP_PARITY_SPACE:
2019 RETURN_ERROR(SP_ERR_SUPP, "Mark/space parity not supported");
2022 RETURN_ERROR(SP_ERR_ARG, "Invalid parity setting");
2026 if (config->stopbits >= 0) {
2027 data->term.c_cflag &= ~CSTOPB;
2028 switch (config->stopbits) {
2030 data->term.c_cflag &= ~CSTOPB;
2033 data->term.c_cflag |= CSTOPB;
2036 RETURN_ERROR(SP_ERR_ARG, "Invalid stop bits setting");
2040 if (config->rts >= 0 || config->cts >= 0) {
2041 if (data->termiox_supported) {
2042 data->rts_flow = data->cts_flow = 0;
2043 switch (config->rts) {
2046 controlbits = TIOCM_RTS;
2047 if (ioctl(port->fd, config->rts == SP_RTS_ON ? TIOCMBIS : TIOCMBIC, &controlbits) < 0)
2048 RETURN_FAIL("Setting RTS signal level failed");
2050 case SP_RTS_FLOW_CONTROL:
2056 if (config->cts == SP_CTS_FLOW_CONTROL)
2059 if (data->rts_flow && data->cts_flow)
2060 data->term.c_iflag |= CRTSCTS;
2062 data->term.c_iflag &= ~CRTSCTS;
2064 /* Asymmetric use of RTS/CTS not supported. */
2065 if (data->term.c_iflag & CRTSCTS) {
2066 /* Flow control can only be disabled for both RTS & CTS together. */
2067 if (config->rts >= 0 && config->rts != SP_RTS_FLOW_CONTROL) {
2068 if (config->cts != SP_CTS_IGNORE)
2069 RETURN_ERROR(SP_ERR_SUPP, "RTS & CTS flow control must be disabled together");
2071 if (config->cts >= 0 && config->cts != SP_CTS_FLOW_CONTROL) {
2072 if (config->rts <= 0 || config->rts == SP_RTS_FLOW_CONTROL)
2073 RETURN_ERROR(SP_ERR_SUPP, "RTS & CTS flow control must be disabled together");
2076 /* Flow control can only be enabled for both RTS & CTS together. */
2077 if (((config->rts == SP_RTS_FLOW_CONTROL) && (config->cts != SP_CTS_FLOW_CONTROL)) ||
2078 ((config->cts == SP_CTS_FLOW_CONTROL) && (config->rts != SP_RTS_FLOW_CONTROL)))
2079 RETURN_ERROR(SP_ERR_SUPP, "RTS & CTS flow control must be enabled together");
2082 if (config->rts >= 0) {
2083 if (config->rts == SP_RTS_FLOW_CONTROL) {
2084 data->term.c_iflag |= CRTSCTS;
2086 controlbits = TIOCM_RTS;
2087 if (ioctl(port->fd, config->rts == SP_RTS_ON ? TIOCMBIS : TIOCMBIC,
2089 RETURN_FAIL("Setting RTS signal level failed");
2095 if (config->dtr >= 0 || config->dsr >= 0) {
2096 if (data->termiox_supported) {
2097 data->dtr_flow = data->dsr_flow = 0;
2098 switch (config->dtr) {
2101 controlbits = TIOCM_DTR;
2102 if (ioctl(port->fd, config->dtr == SP_DTR_ON ? TIOCMBIS : TIOCMBIC, &controlbits) < 0)
2103 RETURN_FAIL("Setting DTR signal level failed");
2105 case SP_DTR_FLOW_CONTROL:
2111 if (config->dsr == SP_DSR_FLOW_CONTROL)
2114 /* DTR/DSR flow control not supported. */
2115 if (config->dtr == SP_DTR_FLOW_CONTROL || config->dsr == SP_DSR_FLOW_CONTROL)
2116 RETURN_ERROR(SP_ERR_SUPP, "DTR/DSR flow control not supported");
2118 if (config->dtr >= 0) {
2119 controlbits = TIOCM_DTR;
2120 if (ioctl(port->fd, config->dtr == SP_DTR_ON ? TIOCMBIS : TIOCMBIC,
2122 RETURN_FAIL("Setting DTR signal level failed");
2127 if (config->xon_xoff >= 0) {
2128 data->term.c_iflag &= ~(IXON | IXOFF | IXANY);
2129 switch (config->xon_xoff) {
2130 case SP_XONXOFF_DISABLED:
2133 data->term.c_iflag |= IXOFF;
2135 case SP_XONXOFF_OUT:
2136 data->term.c_iflag |= IXON | IXANY;
2138 case SP_XONXOFF_INOUT:
2139 data->term.c_iflag |= IXON | IXOFF | IXANY;
2142 RETURN_ERROR(SP_ERR_ARG, "Invalid XON/XOFF setting");
2146 if (tcsetattr(port->fd, TCSANOW, &data->term) < 0)
2147 RETURN_FAIL("tcsetattr() failed");
2150 if (baud_nonstd != B0) {
2151 if (ioctl(port->fd, IOSSIOSPEED, &baud_nonstd) == -1)
2152 RETURN_FAIL("IOSSIOSPEED ioctl failed");
2153 /* Set baud rates in data->term to correct, but incompatible
2154 * with tcsetattr() value, same as delivered by tcgetattr(). */
2155 if (cfsetspeed(&data->term, baud_nonstd) < 0)
2156 RETURN_FAIL("cfsetspeed() failed");
2158 #elif defined(__linux__)
2159 #ifdef USE_TERMIOS_SPEED
2161 TRY(set_baudrate(port->fd, config->baudrate));
2164 if (data->termiox_supported)
2165 TRY(set_flow(port->fd, data));
2169 #endif /* !_WIN32 */
2174 enum sp_return sp_new_config(struct sp_port_config **config_ptr)
2176 struct sp_port_config *config;
2178 TRACE("%p", config_ptr);
2181 RETURN_ERROR(SP_ERR_ARG, "Null result pointer");
2185 if (!(config = malloc(sizeof(struct sp_port_config))))
2186 RETURN_ERROR(SP_ERR_MEM, "config malloc failed");
2188 config->baudrate = -1;
2190 config->parity = -1;
2191 config->stopbits = -1;
2197 *config_ptr = config;
2202 void sp_free_config(struct sp_port_config *config)
2204 TRACE("%p", config);
2207 DEBUG("Null config");
2214 enum sp_return sp_get_config(struct sp_port *port, struct sp_port_config *config)
2216 struct port_data data;
2218 TRACE("%p, %p", port, config);
2223 RETURN_ERROR(SP_ERR_ARG, "Null config");
2225 TRY(get_config(port, &data, config));
2230 enum sp_return sp_set_config(struct sp_port *port, const struct sp_port_config *config)
2232 struct port_data data;
2233 struct sp_port_config prev_config;
2235 TRACE("%p, %p", port, config);
2240 RETURN_ERROR(SP_ERR_ARG, "Null config");
2242 TRY(get_config(port, &data, &prev_config));
2243 TRY(set_config(port, &data, config));
2248 #define CREATE_ACCESSORS(x, type) \
2249 enum sp_return sp_set_##x(struct sp_port *port, type x) { \
2250 struct port_data data; \
2251 struct sp_port_config config; \
2252 TRACE("%p, %d", port, x); \
2253 CHECK_OPEN_PORT(); \
2254 TRY(get_config(port, &data, &config)); \
2256 TRY(set_config(port, &data, &config)); \
2259 enum sp_return sp_get_config_##x(const struct sp_port_config *config, type *x) { \
2260 TRACE("%p, %p", config, x); \
2262 RETURN_ERROR(SP_ERR_ARG, "Null config"); \
2266 enum sp_return sp_set_config_##x(struct sp_port_config *config, type x) { \
2267 TRACE("%p, %d", config, x); \
2269 RETURN_ERROR(SP_ERR_ARG, "Null config"); \
2274 CREATE_ACCESSORS(baudrate, int)
2275 CREATE_ACCESSORS(bits, int)
2276 CREATE_ACCESSORS(parity, enum sp_parity)
2277 CREATE_ACCESSORS(stopbits, int)
2278 CREATE_ACCESSORS(rts, enum sp_rts)
2279 CREATE_ACCESSORS(cts, enum sp_cts)
2280 CREATE_ACCESSORS(dtr, enum sp_dtr)
2281 CREATE_ACCESSORS(dsr, enum sp_dsr)
2282 CREATE_ACCESSORS(xon_xoff, enum sp_xonxoff)
2284 enum sp_return sp_set_config_flowcontrol(struct sp_port_config *config, enum sp_flowcontrol flowcontrol)
2287 RETURN_ERROR(SP_ERR_ARG, "Null configuration");
2289 if (flowcontrol > SP_FLOWCONTROL_DTRDSR)
2290 RETURN_ERROR(SP_ERR_ARG, "Invalid flow control setting");
2292 if (flowcontrol == SP_FLOWCONTROL_XONXOFF)
2293 config->xon_xoff = SP_XONXOFF_INOUT;
2295 config->xon_xoff = SP_XONXOFF_DISABLED;
2297 if (flowcontrol == SP_FLOWCONTROL_RTSCTS) {
2298 config->rts = SP_RTS_FLOW_CONTROL;
2299 config->cts = SP_CTS_FLOW_CONTROL;
2301 if (config->rts == SP_RTS_FLOW_CONTROL)
2302 config->rts = SP_RTS_ON;
2303 config->cts = SP_CTS_IGNORE;
2306 if (flowcontrol == SP_FLOWCONTROL_DTRDSR) {
2307 config->dtr = SP_DTR_FLOW_CONTROL;
2308 config->dsr = SP_DSR_FLOW_CONTROL;
2310 if (config->dtr == SP_DTR_FLOW_CONTROL)
2311 config->dtr = SP_DTR_ON;
2312 config->dsr = SP_DSR_IGNORE;
2318 enum sp_return sp_set_flowcontrol(struct sp_port *port, enum sp_flowcontrol flowcontrol)
2320 struct port_data data;
2321 struct sp_port_config config;
2323 TRACE("%p, %d", port, flowcontrol);
2327 TRY(get_config(port, &data, &config));
2329 TRY(sp_set_config_flowcontrol(&config, flowcontrol));
2331 TRY(set_config(port, &data, &config));
2336 enum sp_return sp_get_signals(struct sp_port *port, enum sp_signal *signals)
2338 TRACE("%p, %p", port, signals);
2343 RETURN_ERROR(SP_ERR_ARG, "Null result pointer");
2345 DEBUG("Getting control signals for port %s", port->name);
2350 if (GetCommModemStatus(port->hdl, &bits) == 0)
2351 RETURN_FAIL("GetCommModemStatus() failed");
2352 if (bits & MS_CTS_ON)
2353 *signals |= SP_SIG_CTS;
2354 if (bits & MS_DSR_ON)
2355 *signals |= SP_SIG_DSR;
2356 if (bits & MS_RLSD_ON)
2357 *signals |= SP_SIG_DCD;
2358 if (bits & MS_RING_ON)
2359 *signals |= SP_SIG_RI;
2362 if (ioctl(port->fd, TIOCMGET, &bits) < 0)
2363 RETURN_FAIL("TIOCMGET ioctl failed");
2364 if (bits & TIOCM_CTS)
2365 *signals |= SP_SIG_CTS;
2366 if (bits & TIOCM_DSR)
2367 *signals |= SP_SIG_DSR;
2368 if (bits & TIOCM_CAR)
2369 *signals |= SP_SIG_DCD;
2370 if (bits & TIOCM_RNG)
2371 *signals |= SP_SIG_RI;
2376 enum sp_return sp_start_break(struct sp_port *port)
2382 if (SetCommBreak(port->hdl) == 0)
2383 RETURN_FAIL("SetCommBreak() failed");
2385 if (ioctl(port->fd, TIOCSBRK, 1) < 0)
2386 RETURN_FAIL("TIOCSBRK ioctl failed");
2392 enum sp_return sp_end_break(struct sp_port *port)
2398 if (ClearCommBreak(port->hdl) == 0)
2399 RETURN_FAIL("ClearCommBreak() failed");
2401 if (ioctl(port->fd, TIOCCBRK, 1) < 0)
2402 RETURN_FAIL("TIOCCBRK ioctl failed");
2408 int sp_last_error_code(void)
2412 RETURN_VALUE("%d", GetLastError());
2414 RETURN_VALUE("%d", errno);
2418 char *sp_last_error_message(void)
2424 DWORD error = GetLastError();
2427 FORMAT_MESSAGE_ALLOCATE_BUFFER |
2428 FORMAT_MESSAGE_FROM_SYSTEM |
2429 FORMAT_MESSAGE_IGNORE_INSERTS,
2432 MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
2436 RETURN_VALUE("%s", message);
2438 RETURN_VALUE("%s", strerror(errno));
2442 void sp_free_error_message(char *message)
2444 TRACE("%s", message);
2455 void sp_set_debug_handler(void (*handler)(const char *format, ...))
2457 TRACE("%p", handler);
2459 sp_debug_handler = handler;
2464 void sp_default_debug_handler(const char *format, ...)
2467 va_start(args, format);
2468 if (getenv("LIBSERIALPORT_DEBUG")) {
2469 fputs("sp: ", stderr);
2470 vfprintf(stderr, format, args);
2475 int sp_get_major_package_version(void)
2477 return SP_PACKAGE_VERSION_MAJOR;
2480 int sp_get_minor_package_version(void)
2482 return SP_PACKAGE_VERSION_MINOR;
2485 int sp_get_micro_package_version(void)
2487 return SP_PACKAGE_VERSION_MICRO;
2490 const char *sp_get_package_version_string(void)
2492 return SP_PACKAGE_VERSION_STRING;
2495 int sp_get_current_lib_version(void)
2497 return SP_LIB_VERSION_CURRENT;
2500 int sp_get_revision_lib_version(void)
2502 return SP_LIB_VERSION_REVISION;
2505 int sp_get_age_lib_version(void)
2507 return SP_LIB_VERSION_AGE;
2510 const char *sp_get_lib_version_string(void)
2512 return SP_LIB_VERSION_STRING;