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>
38 #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
72 /* Non-standard baudrates are not available everywhere. */
73 #if defined(HAVE_TERMIOS_SPEED) || defined(HAVE_TERMIOS2_SPEED)
74 #define USE_TERMIOS_SPEED
77 #include "libserialport.h"
83 COMMTIMEOUTS timeouts;
95 struct sp_port_config {
98 enum sp_parity parity;
104 enum sp_xonxoff xon_xoff;
113 int termiox_supported;
122 typedef HANDLE event_handle;
124 typedef int event_handle;
127 /* Standard baud rates. */
129 #define BAUD_TYPE DWORD
130 #define BAUD(n) {CBR_##n, n}
132 #define BAUD_TYPE speed_t
133 #define BAUD(n) {B##n, n}
136 struct std_baudrate {
141 const struct std_baudrate std_baudrates[] = {
144 * The baudrates 50/75/134/150/200/1800/230400/460800 do not seem to
145 * have documented CBR_* macros.
147 BAUD(110), BAUD(300), BAUD(600), BAUD(1200), BAUD(2400), BAUD(4800),
148 BAUD(9600), BAUD(14400), BAUD(19200), BAUD(38400), BAUD(57600),
149 BAUD(115200), BAUD(128000), BAUD(256000),
151 BAUD(50), BAUD(75), BAUD(110), BAUD(134), BAUD(150), BAUD(200),
152 BAUD(300), BAUD(600), BAUD(1200), BAUD(1800), BAUD(2400), BAUD(4800),
153 BAUD(9600), BAUD(19200), BAUD(38400), BAUD(57600), BAUD(115200),
155 #if !defined(__APPLE__) && !defined(__OpenBSD__)
161 void (*sp_debug_handler)(const char *format, ...) = sp_default_debug_handler;
163 #define ARRAY_SIZE(x) (sizeof(x) / sizeof(x[0]))
164 #define NUM_STD_BAUDRATES ARRAY_SIZE(std_baudrates)
166 /* Debug output macros. */
167 #define DEBUG(fmt, ...) do { if (sp_debug_handler) sp_debug_handler(fmt ".\n", ##__VA_ARGS__); } while (0)
168 #define DEBUG_ERROR(err, fmt, ...) DEBUG("%s returning " #err ": " fmt, __func__, ##__VA_ARGS__)
169 #define DEBUG_FAIL(fmt, ...) do { \
170 char *errmsg = sp_last_error_message(); \
171 DEBUG("%s returning SP_ERR_FAIL: "fmt": %s", __func__,##__VA_ARGS__,errmsg); \
172 sp_free_error_message(errmsg); \
174 #define RETURN() do { DEBUG("%s returning", __func__); return; } while(0)
175 #define RETURN_CODE(x) do { DEBUG("%s returning " #x, __func__); return x; } while (0)
176 #define RETURN_CODEVAL(x) do { \
178 case SP_OK: RETURN_CODE(SP_OK); \
179 case SP_ERR_ARG: RETURN_CODE(SP_ERR_ARG); \
180 case SP_ERR_FAIL: RETURN_CODE(SP_ERR_FAIL); \
181 case SP_ERR_MEM: RETURN_CODE(SP_ERR_MEM); \
182 case SP_ERR_SUPP: RETURN_CODE(SP_ERR_SUPP); \
185 #define RETURN_OK() RETURN_CODE(SP_OK);
186 #define RETURN_ERROR(err, ...) do { DEBUG_ERROR(err, __VA_ARGS__); return err; } while (0)
187 #define RETURN_FAIL(...) do { DEBUG_FAIL(__VA_ARGS__); return SP_ERR_FAIL; } while (0)
188 #define RETURN_VALUE(fmt, x) do { \
190 DEBUG("%s returning " fmt, __func__, _x); \
193 #define SET_ERROR(val, err, msg) do { DEBUG_ERROR(err, msg); val = err; } while (0)
194 #define SET_FAIL(val, msg) do { DEBUG_FAIL(msg); val = SP_ERR_FAIL; } while (0)
195 #define TRACE(fmt, ...) DEBUG("%s(" fmt ") called", __func__, ##__VA_ARGS__)
197 #define TRY(x) do { int ret = x; if (ret != SP_OK) RETURN_CODEVAL(ret); } while (0)
199 /* Helper functions. */
200 static struct sp_port **list_append(struct sp_port **list, const char *portname);
201 static enum sp_return get_config(struct sp_port *port, struct port_data *data,
202 struct sp_port_config *config);
203 static enum sp_return set_config(struct sp_port *port, struct port_data *data,
204 const struct sp_port_config *config);
206 enum sp_return sp_get_port_by_name(const char *portname, struct sp_port **port_ptr)
208 struct sp_port *port;
211 TRACE("%s, %p", portname, port_ptr);
214 RETURN_ERROR(SP_ERR_ARG, "Null result pointer");
219 RETURN_ERROR(SP_ERR_ARG, "Null port name");
221 DEBUG("Building structure for port %s", portname);
223 if (!(port = malloc(sizeof(struct sp_port))))
224 RETURN_ERROR(SP_ERR_MEM, "Port structure malloc failed");
226 len = strlen(portname) + 1;
228 if (!(port->name = malloc(len))) {
230 RETURN_ERROR(SP_ERR_MEM, "Port name malloc failed");
233 memcpy(port->name, portname, len);
236 port->hdl = INVALID_HANDLE_VALUE;
246 char *sp_get_port_name(const struct sp_port *port)
253 RETURN_VALUE("%s", port->name);
256 enum sp_return sp_get_port_handle(const struct sp_port *port, void *result_ptr)
258 TRACE("%p, %p", port, result_ptr);
261 RETURN_ERROR(SP_ERR_ARG, "Null port");
264 HANDLE *handle_ptr = result_ptr;
265 *handle_ptr = port->hdl;
267 int *fd_ptr = result_ptr;
274 enum sp_return sp_copy_port(const struct sp_port *port, struct sp_port **copy_ptr)
276 TRACE("%p, %p", port, copy_ptr);
279 RETURN_ERROR(SP_ERR_ARG, "Null result pointer");
284 RETURN_ERROR(SP_ERR_ARG, "Null port");
287 RETURN_ERROR(SP_ERR_ARG, "Null port name");
289 DEBUG("Copying port structure");
291 RETURN_VALUE("%p", sp_get_port_by_name(port->name, copy_ptr));
294 void sp_free_port(struct sp_port *port)
303 DEBUG("Freeing port structure");
313 static struct sp_port **list_append(struct sp_port **list, const char *portname)
318 for (count = 0; list[count]; count++);
319 if (!(tmp = realloc(list, sizeof(struct sp_port *) * (count + 2))))
322 if (sp_get_port_by_name(portname, &list[count]) != SP_OK)
324 list[count + 1] = NULL;
328 sp_free_port_list(list);
332 enum sp_return sp_list_ports(struct sp_port ***list_ptr)
334 struct sp_port **list;
335 int ret = SP_ERR_SUPP;
337 TRACE("%p", list_ptr);
340 RETURN_ERROR(SP_ERR_ARG, "Null result pointer");
342 DEBUG("Enumerating ports");
344 if (!(list = malloc(sizeof(struct sp_port **))))
345 RETURN_ERROR(SP_ERR_MEM, "Port list malloc failed");
352 DWORD max_value_len, max_data_size, max_data_len;
353 DWORD value_len, data_size, data_len;
354 DWORD type, index = 0;
360 DEBUG("Opening registry key");
361 if (RegOpenKeyEx(HKEY_LOCAL_MACHINE, _T("HARDWARE\\DEVICEMAP\\SERIALCOMM"),
362 0, KEY_QUERY_VALUE, &key) != ERROR_SUCCESS) {
363 SET_FAIL(ret, "RegOpenKeyEx() failed");
366 DEBUG("Querying registry key value and data sizes");
367 if (RegQueryInfoKey(key, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
368 &max_value_len, &max_data_size, NULL, NULL) != ERROR_SUCCESS) {
369 SET_FAIL(ret, "RegQueryInfoKey() failed");
372 max_data_len = max_data_size / sizeof(TCHAR);
373 if (!(value = malloc((max_value_len + 1) * sizeof(TCHAR)))) {
374 SET_ERROR(ret, SP_ERR_MEM, "registry value malloc failed");
377 if (!(data = malloc((max_data_len + 1) * sizeof(TCHAR)))) {
378 SET_ERROR(ret, SP_ERR_MEM, "registry data malloc failed");
381 DEBUG("Iterating over values");
383 value_len = max_value_len + 1,
384 data_size = max_data_size,
385 RegEnumValue(key, index, value, &value_len,
386 NULL, &type, (LPBYTE)data, &data_size) == ERROR_SUCCESS)
388 data_len = data_size / sizeof(TCHAR);
389 data[data_len] = '\0';
391 name_len = WideCharToMultiByte(CP_ACP, 0, data, -1, NULL, 0, NULL, NULL);
393 name_len = data_len + 1;
395 if (!(name = malloc(name_len))) {
396 SET_ERROR(ret, SP_ERR_MEM, "registry port name malloc failed");
400 WideCharToMultiByte(CP_ACP, 0, data, -1, name, name_len, NULL, NULL);
404 if (type == REG_SZ) {
405 DEBUG("Found port %s", name);
406 if (!(list = list_append(list, name))) {
407 SET_ERROR(ret, SP_ERR_MEM, "list append failed");
423 CFMutableDictionaryRef classes;
432 DEBUG("Getting IOKit master port");
433 if (IOMasterPort(MACH_PORT_NULL, &master) != KERN_SUCCESS) {
434 SET_FAIL(ret, "IOMasterPort() failed");
438 DEBUG("Creating matching dictionary");
439 if (!(classes = IOServiceMatching(kIOSerialBSDServiceValue))) {
440 SET_FAIL(ret, "IOServiceMatching() failed");
444 CFDictionarySetValue(classes,
445 CFSTR(kIOSerialBSDTypeKey), CFSTR(kIOSerialBSDAllTypes));
447 DEBUG("Getting matching services");
448 if (IOServiceGetMatchingServices(master, classes, &iter) != KERN_SUCCESS) {
449 SET_FAIL(ret, "IOServiceGetMatchingServices() failed");
453 if (!(path = malloc(PATH_MAX))) {
454 SET_ERROR(ret, SP_ERR_MEM, "device path malloc failed");
458 DEBUG("Iterating over results");
459 while ((port = IOIteratorNext(iter))) {
460 cf_path = IORegistryEntryCreateCFProperty(port,
461 CFSTR(kIOCalloutDeviceKey), kCFAllocatorDefault, 0);
463 result = CFStringGetCString(cf_path,
464 path, PATH_MAX, kCFStringEncodingASCII);
467 DEBUG("Found port %s", path);
468 if (!(list = list_append(list, path))) {
469 SET_ERROR(ret, SP_ERR_MEM, "list append failed");
470 IOObjectRelease(port);
475 IOObjectRelease(port);
480 IOObjectRelease(iter);
483 #if defined(__linux__) && defined(HAVE_LIBUDEV)
485 struct udev_enumerate *ud_enumerate;
486 struct udev_list_entry *ud_list;
487 struct udev_list_entry *ud_entry;
489 struct udev_device *ud_dev, *ud_parent;
492 int fd, ioctl_result;
493 struct serial_struct serial_info;
497 DEBUG("Enumerating tty devices");
499 ud_enumerate = udev_enumerate_new(ud);
500 udev_enumerate_add_match_subsystem(ud_enumerate, "tty");
501 udev_enumerate_scan_devices(ud_enumerate);
502 ud_list = udev_enumerate_get_list_entry(ud_enumerate);
503 DEBUG("Iterating over results");
504 udev_list_entry_foreach(ud_entry, ud_list) {
505 path = udev_list_entry_get_name(ud_entry);
506 DEBUG("Found device %s", path);
507 ud_dev = udev_device_new_from_syspath(ud, path);
508 /* If there is no parent device, this is a virtual tty. */
509 ud_parent = udev_device_get_parent(ud_dev);
510 if (ud_parent == NULL) {
511 DEBUG("No parent device, assuming virtual tty");
512 udev_device_unref(ud_dev);
515 name = udev_device_get_devnode(ud_dev);
516 /* The serial8250 driver has a hardcoded number of ports.
517 * The only way to tell which actually exist on a given system
518 * is to try to open them and make an ioctl call. */
519 driver = udev_device_get_driver(ud_parent);
520 if (driver && !strcmp(driver, "serial8250")) {
521 DEBUG("serial8250 device, attempting to open");
522 if ((fd = open(name, O_RDWR | O_NONBLOCK | O_NOCTTY)) < 0) {
523 DEBUG("open failed, skipping");
526 ioctl_result = ioctl(fd, TIOCGSERIAL, &serial_info);
528 if (ioctl_result != 0) {
529 DEBUG("ioctl failed, skipping");
532 if (serial_info.type == PORT_UNKNOWN) {
533 DEBUG("port type is unknown, skipping");
537 DEBUG("Found port %s", name);
538 list = list_append(list, name);
540 udev_device_unref(ud_dev);
542 SET_ERROR(ret, SP_ERR_MEM, "list append failed");
547 udev_enumerate_unref(ud_enumerate);
556 DEBUG_ERROR(SP_ERR_SUPP, "Enumeration not supported on this platform");
559 sp_free_port_list(list);
565 void sp_free_port_list(struct sp_port **list)
576 DEBUG("Freeing port list");
578 for (i = 0; list[i]; i++)
579 sp_free_port(list[i]);
585 #define CHECK_PORT() do { \
587 RETURN_ERROR(SP_ERR_ARG, "Null port"); \
588 if (port->name == NULL) \
589 RETURN_ERROR(SP_ERR_ARG, "Null port name"); \
592 #define CHECK_PORT_HANDLE() do { \
593 if (port->hdl == INVALID_HANDLE_VALUE) \
594 RETURN_ERROR(SP_ERR_ARG, "Invalid port handle"); \
597 #define CHECK_PORT_HANDLE() do { \
599 RETURN_ERROR(SP_ERR_ARG, "Invalid port fd"); \
602 #define CHECK_OPEN_PORT() do { \
604 CHECK_PORT_HANDLE(); \
607 enum sp_return sp_open(struct sp_port *port, enum sp_mode flags)
609 struct port_data data;
610 struct sp_port_config config;
613 TRACE("%p, 0x%x", port, flags);
617 if (flags > (SP_MODE_READ | SP_MODE_WRITE))
618 RETURN_ERROR(SP_ERR_ARG, "Invalid flags");
620 DEBUG("Opening port %s", port->name);
623 DWORD desired_access = 0, flags_and_attributes = 0, errors;
624 char *escaped_port_name;
627 /* Prefix port name with '\\.\' to work with ports above COM9. */
628 if (!(escaped_port_name = malloc(strlen(port->name) + 5)))
629 RETURN_ERROR(SP_ERR_MEM, "Escaped port name malloc failed");
630 sprintf(escaped_port_name, "\\\\.\\%s", port->name);
632 /* Map 'flags' to the OS-specific settings. */
633 flags_and_attributes = FILE_ATTRIBUTE_NORMAL | FILE_FLAG_OVERLAPPED;
634 if (flags & SP_MODE_READ)
635 desired_access |= GENERIC_READ;
636 if (flags & SP_MODE_WRITE)
637 desired_access |= GENERIC_WRITE;
639 port->hdl = CreateFile(escaped_port_name, desired_access, 0, 0,
640 OPEN_EXISTING, flags_and_attributes, 0);
642 free(escaped_port_name);
644 if (port->hdl == INVALID_HANDLE_VALUE)
645 RETURN_FAIL("port CreateFile() failed");
647 /* All timeouts initially disabled. */
648 port->timeouts.ReadIntervalTimeout = 0;
649 port->timeouts.ReadTotalTimeoutMultiplier = 0;
650 port->timeouts.ReadTotalTimeoutConstant = 0;
651 port->timeouts.WriteTotalTimeoutMultiplier = 0;
652 port->timeouts.WriteTotalTimeoutConstant = 0;
654 if (SetCommTimeouts(port->hdl, &port->timeouts) == 0) {
656 RETURN_FAIL("SetCommTimeouts() failed");
659 /* Prepare OVERLAPPED structures. */
660 #define INIT_OVERLAPPED(ovl) do { \
661 memset(&port->ovl, 0, sizeof(port->ovl)); \
662 port->ovl.hEvent = INVALID_HANDLE_VALUE; \
663 if ((port->ovl.hEvent = CreateEvent(NULL, TRUE, TRUE, NULL)) \
664 == INVALID_HANDLE_VALUE) { \
666 RETURN_FAIL(#ovl "CreateEvent() failed"); \
670 INIT_OVERLAPPED(read_ovl);
671 INIT_OVERLAPPED(write_ovl);
672 INIT_OVERLAPPED(wait_ovl);
674 /* Set event mask for RX and error events. */
675 if (SetCommMask(port->hdl, EV_RXCHAR | EV_ERR) == 0) {
677 RETURN_FAIL("SetCommMask() failed");
680 /* Start background operation for RX and error events. */
681 if (WaitCommEvent(port->hdl, &port->events, &port->wait_ovl) == 0) {
682 if (GetLastError() != ERROR_IO_PENDING) {
684 RETURN_FAIL("WaitCommEvent() failed");
688 port->writing = FALSE;
691 int flags_local = O_NONBLOCK | O_NOCTTY;
693 /* Map 'flags' to the OS-specific settings. */
694 if (flags & (SP_MODE_READ | SP_MODE_WRITE))
695 flags_local |= O_RDWR;
696 else if (flags & SP_MODE_READ)
697 flags_local |= O_RDONLY;
698 else if (flags & SP_MODE_WRITE)
699 flags_local |= O_WRONLY;
701 if ((port->fd = open(port->name, flags_local)) < 0)
702 RETURN_FAIL("open() failed");
705 ret = get_config(port, &data, &config);
712 /* Set sane port settings. */
714 data.dcb.fBinary = TRUE;
715 data.dcb.fDsrSensitivity = FALSE;
716 data.dcb.fErrorChar = FALSE;
717 data.dcb.fNull = FALSE;
718 data.dcb.fAbortOnError = TRUE;
720 /* Turn off all fancy termios tricks, give us a raw channel. */
721 data.term.c_iflag &= ~(IGNBRK | BRKINT | PARMRK | ISTRIP | INLCR | IGNCR | ICRNL | IMAXBEL);
723 data.term.c_iflag &= ~IUCLC;
725 data.term.c_oflag &= ~(OPOST | ONLCR | OCRNL | ONOCR | ONLRET);
727 data.term.c_oflag &= ~OLCUC;
730 data.term.c_oflag &= ~NLDLY;
733 data.term.c_oflag &= ~CRDLY;
736 data.term.c_oflag &= ~TABDLY;
739 data.term.c_oflag &= ~BSDLY;
742 data.term.c_oflag &= ~VTDLY;
745 data.term.c_oflag &= ~FFDLY;
748 data.term.c_oflag &= ~OFILL;
750 data.term.c_lflag &= ~(ISIG | ICANON | ECHO | IEXTEN);
751 data.term.c_cc[VMIN] = 0;
752 data.term.c_cc[VTIME] = 0;
754 /* Ignore modem status lines; enable receiver; leave control lines alone on close. */
755 data.term.c_cflag |= (CLOCAL | CREAD | HUPCL);
759 if (ClearCommError(port->hdl, &errors, &status) == 0)
760 RETURN_FAIL("ClearCommError() failed");
763 ret = set_config(port, &data, &config);
773 enum sp_return sp_close(struct sp_port *port)
779 DEBUG("Closing port %s", port->name);
782 /* Returns non-zero upon success, 0 upon failure. */
783 if (CloseHandle(port->hdl) == 0)
784 RETURN_FAIL("port CloseHandle() failed");
785 port->hdl = INVALID_HANDLE_VALUE;
787 /* Close event handles for overlapped structures. */
788 #define CLOSE_OVERLAPPED(ovl) do { \
789 if (port->ovl.hEvent != INVALID_HANDLE_VALUE && \
790 CloseHandle(port->ovl.hEvent) == 0) \
791 RETURN_FAIL(# ovl "event CloseHandle() failed"); \
793 CLOSE_OVERLAPPED(read_ovl);
794 CLOSE_OVERLAPPED(write_ovl);
795 CLOSE_OVERLAPPED(wait_ovl);
798 /* Returns 0 upon success, -1 upon failure. */
799 if (close(port->fd) == -1)
800 RETURN_FAIL("close() failed");
807 enum sp_return sp_flush(struct sp_port *port, enum sp_buffer buffers)
809 TRACE("%p, 0x%x", port, buffers);
813 if (buffers > SP_BUF_BOTH)
814 RETURN_ERROR(SP_ERR_ARG, "Invalid buffer selection");
816 const char *buffer_names[] = {"no", "input", "output", "both"};
818 DEBUG("Flushing %s buffers on port %s", buffer_names[buffers], port->name);
822 if (buffers & SP_BUF_INPUT)
823 flags |= PURGE_RXCLEAR;
824 if (buffers & SP_BUF_OUTPUT)
825 flags |= PURGE_TXCLEAR;
827 /* Returns non-zero upon success, 0 upon failure. */
828 if (PurgeComm(port->hdl, flags) == 0)
829 RETURN_FAIL("PurgeComm() failed");
832 if (buffers & SP_BUF_BOTH)
834 else if (buffers & SP_BUF_INPUT)
836 else if (buffers & SP_BUF_OUTPUT)
839 /* Returns 0 upon success, -1 upon failure. */
840 if (tcflush(port->fd, flags) < 0)
841 RETURN_FAIL("tcflush() failed");
846 enum sp_return sp_drain(struct sp_port *port)
852 DEBUG("Draining port %s", port->name);
855 /* Returns non-zero upon success, 0 upon failure. */
856 if (FlushFileBuffers(port->hdl) == 0)
857 RETURN_FAIL("FlushFileBuffers() failed");
864 result = ioctl(port->fd, TCSBRK, &arg);
866 result = tcdrain(port->fd);
869 if (errno == EINTR) {
870 DEBUG("tcdrain() was interrupted");
873 RETURN_FAIL("tcdrain() failed");
882 enum sp_return sp_blocking_write(struct sp_port *port, const void *buf, size_t count, unsigned int timeout)
884 TRACE("%p, %p, %d, %d", port, buf, count, timeout);
889 RETURN_ERROR(SP_ERR_ARG, "Null buffer");
892 DEBUG("Writing %d bytes to port %s, timeout %d ms", count, port->name, timeout);
894 DEBUG("Writing %d bytes to port %s, no timeout", count, port->name);
897 RETURN_VALUE("0", 0);
900 DWORD bytes_written = 0;
903 /* Wait for previous non-blocking write to complete, if any. */
905 DEBUG("Waiting for previous write to complete");
906 result = GetOverlappedResult(port->hdl, &port->write_ovl, &bytes_written, TRUE);
909 RETURN_FAIL("Previous write failed to complete");
910 DEBUG("Previous write completed");
914 port->timeouts.WriteTotalTimeoutConstant = timeout;
915 if (SetCommTimeouts(port->hdl, &port->timeouts) == 0)
916 RETURN_FAIL("SetCommTimeouts() failed");
919 if (WriteFile(port->hdl, buf, count, NULL, &port->write_ovl) == 0) {
920 if (GetLastError() == ERROR_IO_PENDING) {
921 DEBUG("Waiting for write to complete");
922 GetOverlappedResult(port->hdl, &port->write_ovl, &bytes_written, TRUE);
923 DEBUG("Write completed, %d/%d bytes written", bytes_written, count);
924 RETURN_VALUE("%d", bytes_written);
926 RETURN_FAIL("WriteFile() failed");
929 DEBUG("Write completed immediately");
930 RETURN_VALUE("%d", count);
933 size_t bytes_written = 0;
934 unsigned char *ptr = (unsigned char *) buf;
935 struct timeval start, delta, now, end = {0, 0};
940 /* Get time at start of operation. */
941 gettimeofday(&start, NULL);
942 /* Define duration of timeout. */
943 delta.tv_sec = timeout / 1000;
944 delta.tv_usec = (timeout % 1000) * 1000;
945 /* Calculate time at which we should give up. */
946 timeradd(&start, &delta, &end);
949 /* Loop until we have written the requested number of bytes. */
950 while (bytes_written < count)
952 /* Wait until space is available. */
954 FD_SET(port->fd, &fds);
956 gettimeofday(&now, NULL);
957 if (timercmp(&now, &end, >)) {
958 DEBUG("write timed out");
959 RETURN_VALUE("%d", bytes_written);
961 timersub(&end, &now, &delta);
963 result = select(port->fd + 1, NULL, &fds, NULL, timeout ? &delta : NULL);
965 if (errno == EINTR) {
966 DEBUG("select() call was interrupted, repeating");
969 RETURN_FAIL("select() failed");
971 } else if (result == 0) {
972 DEBUG("write timed out");
973 RETURN_VALUE("%d", bytes_written);
977 result = write(port->fd, ptr, count - bytes_written);
981 /* This shouldn't happen because we did a select() first, but handle anyway. */
984 /* This is an actual failure. */
985 RETURN_FAIL("write() failed");
988 bytes_written += result;
992 RETURN_VALUE("%d", bytes_written);
996 enum sp_return sp_nonblocking_write(struct sp_port *port, const void *buf, size_t count)
998 TRACE("%p, %p, %d", port, buf, count);
1003 RETURN_ERROR(SP_ERR_ARG, "Null buffer");
1005 DEBUG("Writing up to %d bytes to port %s", count, port->name);
1008 RETURN_VALUE("0", 0);
1012 BYTE *ptr = (BYTE *) buf;
1014 /* Check whether previous write is complete. */
1015 if (port->writing) {
1016 if (HasOverlappedIoCompleted(&port->write_ovl)) {
1017 DEBUG("Previous write completed");
1020 DEBUG("Previous write not complete");
1021 /* Can't take a new write until the previous one finishes. */
1022 RETURN_VALUE("0", 0);
1027 port->timeouts.WriteTotalTimeoutConstant = 0;
1028 if (SetCommTimeouts(port->hdl, &port->timeouts) == 0)
1029 RETURN_FAIL("SetCommTimeouts() failed");
1031 /* Keep writing data until the OS has to actually start an async IO for it.
1032 * At that point we know the buffer is full. */
1033 while (written < count)
1035 /* Copy first byte of user buffer. */
1036 port->pending_byte = *ptr++;
1038 /* Start asynchronous write. */
1039 if (WriteFile(port->hdl, &port->pending_byte, 1, NULL, &port->write_ovl) == 0) {
1040 if (GetLastError() == ERROR_IO_PENDING) {
1041 if (HasOverlappedIoCompleted(&port->write_ovl)) {
1042 DEBUG("Asynchronous write completed immediately");
1047 DEBUG("Asynchronous write running");
1049 RETURN_VALUE("%d", ++written);
1052 /* Actual failure of some kind. */
1053 RETURN_FAIL("WriteFile() failed");
1056 DEBUG("Single byte written immediately");
1061 DEBUG("All bytes written immediately");
1063 RETURN_VALUE("%d", written);
1065 /* Returns the number of bytes written, or -1 upon failure. */
1066 ssize_t written = write(port->fd, buf, count);
1069 RETURN_FAIL("write() failed");
1071 RETURN_VALUE("%d", written);
1075 enum sp_return sp_blocking_read(struct sp_port *port, void *buf, size_t count, unsigned int timeout)
1077 TRACE("%p, %p, %d, %d", port, buf, count, timeout);
1082 RETURN_ERROR(SP_ERR_ARG, "Null buffer");
1085 DEBUG("Reading %d bytes from port %s, timeout %d ms", count, port->name, timeout);
1087 DEBUG("Reading %d bytes from port %s, no timeout", count, port->name);
1090 RETURN_VALUE("0", 0);
1093 DWORD bytes_read = 0;
1096 port->timeouts.ReadIntervalTimeout = 0;
1097 port->timeouts.ReadTotalTimeoutConstant = timeout;
1098 if (SetCommTimeouts(port->hdl, &port->timeouts) == 0)
1099 RETURN_FAIL("SetCommTimeouts() failed");
1102 if (ReadFile(port->hdl, buf, count, NULL, &port->read_ovl) == 0) {
1103 if (GetLastError() == ERROR_IO_PENDING) {
1104 DEBUG("Waiting for read to complete");
1105 GetOverlappedResult(port->hdl, &port->read_ovl, &bytes_read, TRUE);
1106 DEBUG("Read completed, %d/%d bytes read", bytes_read, count);
1108 RETURN_FAIL("ReadFile() failed");
1111 DEBUG("Read completed immediately");
1115 /* Start background operation for subsequent events. */
1116 if (WaitCommEvent(port->hdl, &port->events, &port->wait_ovl) == 0) {
1117 if (GetLastError() != ERROR_IO_PENDING)
1118 RETURN_FAIL("WaitCommEvent() failed");
1121 RETURN_VALUE("%d", bytes_read);
1124 size_t bytes_read = 0;
1125 unsigned char *ptr = (unsigned char *) buf;
1126 struct timeval start, delta, now, end = {0, 0};
1131 /* Get time at start of operation. */
1132 gettimeofday(&start, NULL);
1133 /* Define duration of timeout. */
1134 delta.tv_sec = timeout / 1000;
1135 delta.tv_usec = (timeout % 1000) * 1000;
1136 /* Calculate time at which we should give up. */
1137 timeradd(&start, &delta, &end);
1140 /* Loop until we have the requested number of bytes. */
1141 while (bytes_read < count)
1143 /* Wait until data is available. */
1145 FD_SET(port->fd, &fds);
1147 gettimeofday(&now, NULL);
1148 if (timercmp(&now, &end, >))
1149 /* Timeout has expired. */
1150 RETURN_VALUE("%d", bytes_read);
1151 timersub(&end, &now, &delta);
1153 result = select(port->fd + 1, &fds, NULL, NULL, timeout ? &delta : NULL);
1155 if (errno == EINTR) {
1156 DEBUG("select() call was interrupted, repeating");
1159 RETURN_FAIL("select() failed");
1161 } else if (result == 0) {
1162 DEBUG("read timed out");
1163 RETURN_VALUE("%d", bytes_read);
1167 result = read(port->fd, ptr, count - bytes_read);
1170 if (errno == EAGAIN)
1171 /* This shouldn't happen because we did a select() first, but handle anyway. */
1174 /* This is an actual failure. */
1175 RETURN_FAIL("read() failed");
1178 bytes_read += result;
1182 RETURN_VALUE("%d", bytes_read);
1186 enum sp_return sp_nonblocking_read(struct sp_port *port, void *buf, size_t count)
1188 TRACE("%p, %p, %d", port, buf, count);
1193 RETURN_ERROR(SP_ERR_ARG, "Null buffer");
1195 DEBUG("Reading up to %d bytes from port %s", count, port->name);
1201 port->timeouts.ReadIntervalTimeout = MAXDWORD;
1202 port->timeouts.ReadTotalTimeoutConstant = 0;
1203 if (SetCommTimeouts(port->hdl, &port->timeouts) == 0)
1204 RETURN_FAIL("SetCommTimeouts() failed");
1207 if (ReadFile(port->hdl, buf, count, NULL, &port->read_ovl) == 0)
1208 RETURN_FAIL("ReadFile() failed");
1210 /* Get number of bytes read. */
1211 if (GetOverlappedResult(port->hdl, &port->read_ovl, &bytes_read, TRUE) == 0)
1212 RETURN_FAIL("GetOverlappedResult() failed");
1214 if (bytes_read > 0) {
1215 /* Start background operation for subsequent events. */
1216 if (WaitCommEvent(port->hdl, &port->events, &port->wait_ovl) == 0) {
1217 if (GetLastError() != ERROR_IO_PENDING)
1218 RETURN_FAIL("WaitCommEvent() failed");
1222 RETURN_VALUE("%d", bytes_read);
1226 /* Returns the number of bytes read, or -1 upon failure. */
1227 if ((bytes_read = read(port->fd, buf, count)) < 0) {
1228 if (errno == EAGAIN)
1229 /* No bytes available. */
1232 /* This is an actual failure. */
1233 RETURN_FAIL("read() failed");
1235 RETURN_VALUE("%d", bytes_read);
1239 enum sp_return sp_input_waiting(struct sp_port *port)
1245 DEBUG("Checking input bytes waiting on port %s", port->name);
1251 if (ClearCommError(port->hdl, &errors, &comstat) == 0)
1252 RETURN_FAIL("ClearCommError() failed");
1253 RETURN_VALUE("%d", comstat.cbInQue);
1256 if (ioctl(port->fd, TIOCINQ, &bytes_waiting) < 0)
1257 RETURN_FAIL("TIOCINQ ioctl failed");
1258 RETURN_VALUE("%d", bytes_waiting);
1262 enum sp_return sp_output_waiting(struct sp_port *port)
1268 DEBUG("Checking output bytes waiting on port %s", port->name);
1274 if (ClearCommError(port->hdl, &errors, &comstat) == 0)
1275 RETURN_FAIL("ClearCommError() failed");
1276 RETURN_VALUE("%d", comstat.cbOutQue);
1279 if (ioctl(port->fd, TIOCOUTQ, &bytes_waiting) < 0)
1280 RETURN_FAIL("TIOCOUTQ ioctl failed");
1281 RETURN_VALUE("%d", bytes_waiting);
1285 enum sp_return sp_new_event_set(struct sp_event_set **result_ptr)
1287 struct sp_event_set *result;
1289 TRACE("%p", result_ptr);
1292 RETURN_ERROR(SP_ERR_ARG, "Null result");
1296 if (!(result = malloc(sizeof(struct sp_event_set))))
1297 RETURN_ERROR(SP_ERR_MEM, "sp_event_set malloc() failed");
1299 memset(result, 0, sizeof(struct sp_event_set));
1301 *result_ptr = result;
1306 static enum sp_return add_handle(struct sp_event_set *event_set,
1307 event_handle handle, enum sp_event mask)
1310 enum sp_event *new_masks;
1312 TRACE("%p, %d, %d", event_set, handle, mask);
1314 if (!(new_handles = realloc(event_set->handles,
1315 sizeof(event_handle) * (event_set->count + 1))))
1316 RETURN_ERROR(SP_ERR_MEM, "handle array realloc() failed");
1318 if (!(new_masks = realloc(event_set->masks,
1319 sizeof(enum sp_event) * (event_set->count + 1))))
1320 RETURN_ERROR(SP_ERR_MEM, "mask array realloc() failed");
1322 event_set->handles = new_handles;
1323 event_set->masks = new_masks;
1325 ((event_handle *) event_set->handles)[event_set->count] = handle;
1326 event_set->masks[event_set->count] = mask;
1333 enum sp_return sp_add_port_events(struct sp_event_set *event_set,
1334 const struct sp_port *port, enum sp_event mask)
1336 TRACE("%p, %p, %d", event_set, port, mask);
1339 RETURN_ERROR(SP_ERR_ARG, "Null event set");
1342 RETURN_ERROR(SP_ERR_ARG, "Null port");
1344 if (mask > (SP_EVENT_RX_READY | SP_EVENT_TX_READY | SP_EVENT_ERROR))
1345 RETURN_ERROR(SP_ERR_ARG, "Invalid event mask");
1351 enum sp_event handle_mask;
1352 if ((handle_mask = mask & SP_EVENT_TX_READY))
1353 TRY(add_handle(event_set, port->write_ovl.hEvent, handle_mask));
1354 if ((handle_mask = mask & (SP_EVENT_RX_READY | SP_EVENT_ERROR)))
1355 TRY(add_handle(event_set, port->wait_ovl.hEvent, handle_mask));
1357 TRY(add_handle(event_set, port->fd, mask));
1363 void sp_free_event_set(struct sp_event_set *event_set)
1365 TRACE("%p", event_set);
1368 DEBUG("Null event set");
1372 DEBUG("Freeing event set");
1374 if (event_set->handles)
1375 free(event_set->handles);
1376 if (event_set->masks)
1377 free(event_set->masks);
1384 enum sp_return sp_wait(struct sp_event_set *event_set, unsigned int timeout)
1386 TRACE("%p, %d", event_set, timeout);
1389 RETURN_ERROR(SP_ERR_ARG, "Null event set");
1392 if (WaitForMultipleObjects(event_set->count, event_set->handles, FALSE,
1393 timeout ? timeout : INFINITE) == WAIT_FAILED)
1394 RETURN_FAIL("WaitForMultipleObjects() failed");
1398 struct timeval start, delta, now, end = {0, 0};
1399 int result, timeout_remaining;
1400 struct pollfd *pollfds;
1403 if (!(pollfds = malloc(sizeof(struct pollfd) * event_set->count)))
1404 RETURN_ERROR(SP_ERR_MEM, "pollfds malloc() failed");
1406 for (i = 0; i < event_set->count; i++) {
1407 pollfds[i].fd = ((int *) event_set->handles)[i];
1408 pollfds[i].events = 0;
1409 pollfds[i].revents = 0;
1410 if (event_set->masks[i] & SP_EVENT_RX_READY)
1411 pollfds[i].events |= POLLIN;
1412 if (event_set->masks[i] & SP_EVENT_TX_READY)
1413 pollfds[i].events |= POLLOUT;
1414 if (event_set->masks[i] & SP_EVENT_ERROR)
1415 pollfds[i].events |= POLLERR;
1419 /* Get time at start of operation. */
1420 gettimeofday(&start, NULL);
1421 /* Define duration of timeout. */
1422 delta.tv_sec = timeout / 1000;
1423 delta.tv_usec = (timeout % 1000) * 1000;
1424 /* Calculate time at which we should give up. */
1425 timeradd(&start, &delta, &end);
1428 /* Loop until an event occurs. */
1432 gettimeofday(&now, NULL);
1433 if (timercmp(&now, &end, >)) {
1434 DEBUG("wait timed out");
1437 timersub(&end, &now, &delta);
1438 timeout_remaining = delta.tv_sec * 1000 + delta.tv_usec / 1000;
1441 result = poll(pollfds, event_set->count, timeout ? timeout_remaining : -1);
1444 if (errno == EINTR) {
1445 DEBUG("poll() call was interrupted, repeating");
1449 RETURN_FAIL("poll() failed");
1451 } else if (result == 0) {
1452 DEBUG("poll() timed out");
1455 DEBUG("poll() completed");
1465 #ifdef USE_TERMIOS_SPEED
1466 static enum sp_return get_baudrate(int fd, int *baudrate)
1470 TRACE("%d, %p", fd, baudrate);
1472 DEBUG("Getting baud rate");
1474 if (!(data = malloc(get_termios_size())))
1475 RETURN_ERROR(SP_ERR_MEM, "termios malloc failed");
1477 if (ioctl(fd, get_termios_get_ioctl(), data) < 0) {
1479 RETURN_FAIL("getting termios failed");
1482 *baudrate = get_termios_speed(data);
1489 static enum sp_return set_baudrate(int fd, int baudrate)
1493 TRACE("%d, %d", fd, baudrate);
1495 DEBUG("Getting baud rate");
1497 if (!(data = malloc(get_termios_size())))
1498 RETURN_ERROR(SP_ERR_MEM, "termios malloc failed");
1500 if (ioctl(fd, get_termios_get_ioctl(), data) < 0) {
1502 RETURN_FAIL("getting termios failed");
1505 DEBUG("Setting baud rate");
1507 set_termios_speed(data, baudrate);
1509 if (ioctl(fd, get_termios_set_ioctl(), data) < 0) {
1511 RETURN_FAIL("setting termios failed");
1518 #endif /* USE_TERMIOS_SPEED */
1521 static enum sp_return get_flow(int fd, struct port_data *data)
1525 TRACE("%d, %p", fd, data);
1527 DEBUG("Getting advanced flow control");
1529 if (!(termx = malloc(get_termiox_size())))
1530 RETURN_ERROR(SP_ERR_MEM, "termiox malloc failed");
1532 if (ioctl(fd, TCGETX, termx) < 0) {
1534 RETURN_FAIL("getting termiox failed");
1537 get_termiox_flow(termx, &data->rts_flow, &data->cts_flow,
1538 &data->dtr_flow, &data->dsr_flow);
1545 static enum sp_return set_flow(int fd, struct port_data *data)
1549 TRACE("%d, %p", fd, data);
1551 DEBUG("Getting advanced flow control");
1553 if (!(termx = malloc(get_termiox_size())))
1554 RETURN_ERROR(SP_ERR_MEM, "termiox malloc failed");
1556 if (ioctl(fd, TCGETX, termx) < 0) {
1558 RETURN_FAIL("getting termiox failed");
1561 DEBUG("Setting advanced flow control");
1563 set_termiox_flow(termx, data->rts_flow, data->cts_flow,
1564 data->dtr_flow, data->dsr_flow);
1566 if (ioctl(fd, TCSETX, termx) < 0) {
1568 RETURN_FAIL("setting termiox failed");
1575 #endif /* USE_TERMIOX */
1577 static enum sp_return get_config(struct sp_port *port, struct port_data *data,
1578 struct sp_port_config *config)
1582 TRACE("%p, %p, %p", port, data, config);
1584 DEBUG("Getting configuration for port %s", port->name);
1587 if (!GetCommState(port->hdl, &data->dcb))
1588 RETURN_FAIL("GetCommState() failed");
1590 for (i = 0; i < NUM_STD_BAUDRATES; i++) {
1591 if (data->dcb.BaudRate == std_baudrates[i].index) {
1592 config->baudrate = std_baudrates[i].value;
1597 if (i == NUM_STD_BAUDRATES)
1598 /* BaudRate field can be either an index or a custom baud rate. */
1599 config->baudrate = data->dcb.BaudRate;
1601 config->bits = data->dcb.ByteSize;
1603 if (data->dcb.fParity)
1604 switch (data->dcb.Parity) {
1606 config->parity = SP_PARITY_NONE;
1609 config->parity = SP_PARITY_ODD;
1612 config->parity = SP_PARITY_EVEN;
1615 config->parity = SP_PARITY_MARK;
1618 config->parity = SP_PARITY_SPACE;
1621 config->parity = -1;
1624 config->parity = SP_PARITY_NONE;
1626 switch (data->dcb.StopBits) {
1628 config->stopbits = 1;
1631 config->stopbits = 2;
1634 config->stopbits = -1;
1637 switch (data->dcb.fRtsControl) {
1638 case RTS_CONTROL_DISABLE:
1639 config->rts = SP_RTS_OFF;
1641 case RTS_CONTROL_ENABLE:
1642 config->rts = SP_RTS_ON;
1644 case RTS_CONTROL_HANDSHAKE:
1645 config->rts = SP_RTS_FLOW_CONTROL;
1651 config->cts = data->dcb.fOutxCtsFlow ? SP_CTS_FLOW_CONTROL : SP_CTS_IGNORE;
1653 switch (data->dcb.fDtrControl) {
1654 case DTR_CONTROL_DISABLE:
1655 config->dtr = SP_DTR_OFF;
1657 case DTR_CONTROL_ENABLE:
1658 config->dtr = SP_DTR_ON;
1660 case DTR_CONTROL_HANDSHAKE:
1661 config->dtr = SP_DTR_FLOW_CONTROL;
1667 config->dsr = data->dcb.fOutxDsrFlow ? SP_DSR_FLOW_CONTROL : SP_DSR_IGNORE;
1669 if (data->dcb.fInX) {
1670 if (data->dcb.fOutX)
1671 config->xon_xoff = SP_XONXOFF_INOUT;
1673 config->xon_xoff = SP_XONXOFF_IN;
1675 if (data->dcb.fOutX)
1676 config->xon_xoff = SP_XONXOFF_OUT;
1678 config->xon_xoff = SP_XONXOFF_DISABLED;
1683 if (tcgetattr(port->fd, &data->term) < 0)
1684 RETURN_FAIL("tcgetattr() failed");
1686 if (ioctl(port->fd, TIOCMGET, &data->controlbits) < 0)
1687 RETURN_FAIL("TIOCMGET ioctl failed");
1690 int ret = get_flow(port->fd, data);
1692 if (ret == SP_ERR_FAIL && errno == EINVAL)
1693 data->termiox_supported = 0;
1695 RETURN_CODEVAL(ret);
1697 data->termiox_supported = 1;
1699 data->termiox_supported = 0;
1702 for (i = 0; i < NUM_STD_BAUDRATES; i++) {
1703 if (cfgetispeed(&data->term) == std_baudrates[i].index) {
1704 config->baudrate = std_baudrates[i].value;
1709 if (i == NUM_STD_BAUDRATES) {
1711 config->baudrate = (int)data->term.c_ispeed;
1712 #elif defined(USE_TERMIOS_SPEED)
1713 TRY(get_baudrate(port->fd, &config->baudrate));
1715 config->baudrate = -1;
1719 switch (data->term.c_cflag & CSIZE) {
1736 if (!(data->term.c_cflag & PARENB) && (data->term.c_iflag & IGNPAR))
1737 config->parity = SP_PARITY_NONE;
1738 else if (!(data->term.c_cflag & PARENB) || (data->term.c_iflag & IGNPAR))
1739 config->parity = -1;
1741 else if (data->term.c_cflag & CMSPAR)
1742 config->parity = (data->term.c_cflag & PARODD) ? SP_PARITY_MARK : SP_PARITY_SPACE;
1745 config->parity = (data->term.c_cflag & PARODD) ? SP_PARITY_ODD : SP_PARITY_EVEN;
1747 config->stopbits = (data->term.c_cflag & CSTOPB) ? 2 : 1;
1749 if (data->term.c_cflag & CRTSCTS) {
1750 config->rts = SP_RTS_FLOW_CONTROL;
1751 config->cts = SP_CTS_FLOW_CONTROL;
1753 if (data->termiox_supported && data->rts_flow)
1754 config->rts = SP_RTS_FLOW_CONTROL;
1756 config->rts = (data->controlbits & TIOCM_RTS) ? SP_RTS_ON : SP_RTS_OFF;
1758 config->cts = (data->termiox_supported && data->cts_flow) ?
1759 SP_CTS_FLOW_CONTROL : SP_CTS_IGNORE;
1762 if (data->termiox_supported && data->dtr_flow)
1763 config->dtr = SP_DTR_FLOW_CONTROL;
1765 config->dtr = (data->controlbits & TIOCM_DTR) ? SP_DTR_ON : SP_DTR_OFF;
1767 config->dsr = (data->termiox_supported && data->dsr_flow) ?
1768 SP_DSR_FLOW_CONTROL : SP_DSR_IGNORE;
1770 if (data->term.c_iflag & IXOFF) {
1771 if (data->term.c_iflag & IXON)
1772 config->xon_xoff = SP_XONXOFF_INOUT;
1774 config->xon_xoff = SP_XONXOFF_IN;
1776 if (data->term.c_iflag & IXON)
1777 config->xon_xoff = SP_XONXOFF_OUT;
1779 config->xon_xoff = SP_XONXOFF_DISABLED;
1786 static enum sp_return set_config(struct sp_port *port, struct port_data *data,
1787 const struct sp_port_config *config)
1791 BAUD_TYPE baud_nonstd;
1795 #ifdef USE_TERMIOS_SPEED
1796 int baud_nonstd = 0;
1799 TRACE("%p, %p, %p", port, data, config);
1801 DEBUG("Setting configuration for port %s", port->name);
1804 if (config->baudrate >= 0) {
1805 for (i = 0; i < NUM_STD_BAUDRATES; i++) {
1806 if (config->baudrate == std_baudrates[i].value) {
1807 data->dcb.BaudRate = std_baudrates[i].index;
1812 if (i == NUM_STD_BAUDRATES)
1813 data->dcb.BaudRate = config->baudrate;
1816 if (config->bits >= 0)
1817 data->dcb.ByteSize = config->bits;
1819 if (config->parity >= 0) {
1820 switch (config->parity) {
1821 case SP_PARITY_NONE:
1822 data->dcb.Parity = NOPARITY;
1825 data->dcb.Parity = ODDPARITY;
1827 case SP_PARITY_EVEN:
1828 data->dcb.Parity = EVENPARITY;
1830 case SP_PARITY_MARK:
1831 data->dcb.Parity = MARKPARITY;
1833 case SP_PARITY_SPACE:
1834 data->dcb.Parity = SPACEPARITY;
1837 RETURN_ERROR(SP_ERR_ARG, "Invalid parity setting");
1841 if (config->stopbits >= 0) {
1842 switch (config->stopbits) {
1843 /* Note: There's also ONE5STOPBITS == 1.5 (unneeded so far). */
1845 data->dcb.StopBits = ONESTOPBIT;
1848 data->dcb.StopBits = TWOSTOPBITS;
1851 RETURN_ERROR(SP_ERR_ARG, "Invalid stop bit setting");
1855 if (config->rts >= 0) {
1856 switch (config->rts) {
1858 data->dcb.fRtsControl = RTS_CONTROL_DISABLE;
1861 data->dcb.fRtsControl = RTS_CONTROL_ENABLE;
1863 case SP_RTS_FLOW_CONTROL:
1864 data->dcb.fRtsControl = RTS_CONTROL_HANDSHAKE;
1867 RETURN_ERROR(SP_ERR_ARG, "Invalid RTS setting");
1871 if (config->cts >= 0) {
1872 switch (config->cts) {
1874 data->dcb.fOutxCtsFlow = FALSE;
1876 case SP_CTS_FLOW_CONTROL:
1877 data->dcb.fOutxCtsFlow = TRUE;
1880 RETURN_ERROR(SP_ERR_ARG, "Invalid CTS setting");
1884 if (config->dtr >= 0) {
1885 switch (config->dtr) {
1887 data->dcb.fDtrControl = DTR_CONTROL_DISABLE;
1890 data->dcb.fDtrControl = DTR_CONTROL_ENABLE;
1892 case SP_DTR_FLOW_CONTROL:
1893 data->dcb.fDtrControl = DTR_CONTROL_HANDSHAKE;
1896 RETURN_ERROR(SP_ERR_ARG, "Invalid DTR setting");
1900 if (config->dsr >= 0) {
1901 switch (config->dsr) {
1903 data->dcb.fOutxDsrFlow = FALSE;
1905 case SP_DSR_FLOW_CONTROL:
1906 data->dcb.fOutxDsrFlow = TRUE;
1909 RETURN_ERROR(SP_ERR_ARG, "Invalid DSR setting");
1913 if (config->xon_xoff >= 0) {
1914 switch (config->xon_xoff) {
1915 case SP_XONXOFF_DISABLED:
1916 data->dcb.fInX = FALSE;
1917 data->dcb.fOutX = FALSE;
1920 data->dcb.fInX = TRUE;
1921 data->dcb.fOutX = FALSE;
1923 case SP_XONXOFF_OUT:
1924 data->dcb.fInX = FALSE;
1925 data->dcb.fOutX = TRUE;
1927 case SP_XONXOFF_INOUT:
1928 data->dcb.fInX = TRUE;
1929 data->dcb.fOutX = TRUE;
1932 RETURN_ERROR(SP_ERR_ARG, "Invalid XON/XOFF setting");
1936 if (!SetCommState(port->hdl, &data->dcb))
1937 RETURN_FAIL("SetCommState() failed");
1943 if (config->baudrate >= 0) {
1944 for (i = 0; i < NUM_STD_BAUDRATES; i++) {
1945 if (config->baudrate == std_baudrates[i].value) {
1946 if (cfsetospeed(&data->term, std_baudrates[i].index) < 0)
1947 RETURN_FAIL("cfsetospeed() failed");
1949 if (cfsetispeed(&data->term, std_baudrates[i].index) < 0)
1950 RETURN_FAIL("cfsetispeed() failed");
1955 /* Non-standard baud rate */
1956 if (i == NUM_STD_BAUDRATES) {
1958 /* Set "dummy" baud rate. */
1959 if (cfsetspeed(&data->term, B9600) < 0)
1960 RETURN_FAIL("cfsetspeed() failed");
1961 baud_nonstd = config->baudrate;
1962 #elif defined(USE_TERMIOS_SPEED)
1965 RETURN_ERROR(SP_ERR_SUPP, "Non-standard baudrate not supported");
1970 if (config->bits >= 0) {
1971 data->term.c_cflag &= ~CSIZE;
1972 switch (config->bits) {
1974 data->term.c_cflag |= CS8;
1977 data->term.c_cflag |= CS7;
1980 data->term.c_cflag |= CS6;
1983 data->term.c_cflag |= CS5;
1986 RETURN_ERROR(SP_ERR_ARG, "Invalid data bits setting");
1990 if (config->parity >= 0) {
1991 data->term.c_iflag &= ~IGNPAR;
1992 data->term.c_cflag &= ~(PARENB | PARODD);
1994 data->term.c_cflag &= ~CMSPAR;
1996 switch (config->parity) {
1997 case SP_PARITY_NONE:
1998 data->term.c_iflag |= IGNPAR;
2000 case SP_PARITY_EVEN:
2001 data->term.c_cflag |= PARENB;
2004 data->term.c_cflag |= PARENB | PARODD;
2007 case SP_PARITY_MARK:
2008 data->term.c_cflag |= PARENB | PARODD;
2009 data->term.c_cflag |= CMSPAR;
2011 case SP_PARITY_SPACE:
2012 data->term.c_cflag |= PARENB;
2013 data->term.c_cflag |= CMSPAR;
2016 case SP_PARITY_MARK:
2017 case SP_PARITY_SPACE:
2018 RETURN_ERROR(SP_ERR_SUPP, "Mark/space parity not supported");
2021 RETURN_ERROR(SP_ERR_ARG, "Invalid parity setting");
2025 if (config->stopbits >= 0) {
2026 data->term.c_cflag &= ~CSTOPB;
2027 switch (config->stopbits) {
2029 data->term.c_cflag &= ~CSTOPB;
2032 data->term.c_cflag |= CSTOPB;
2035 RETURN_ERROR(SP_ERR_ARG, "Invalid stop bits setting");
2039 if (config->rts >= 0 || config->cts >= 0) {
2040 if (data->termiox_supported) {
2041 data->rts_flow = data->cts_flow = 0;
2042 switch (config->rts) {
2045 controlbits = TIOCM_RTS;
2046 if (ioctl(port->fd, config->rts == SP_RTS_ON ? TIOCMBIS : TIOCMBIC, &controlbits) < 0)
2047 RETURN_FAIL("Setting RTS signal level failed");
2049 case SP_RTS_FLOW_CONTROL:
2055 if (config->cts == SP_CTS_FLOW_CONTROL)
2058 if (data->rts_flow && data->cts_flow)
2059 data->term.c_iflag |= CRTSCTS;
2061 data->term.c_iflag &= ~CRTSCTS;
2063 /* Asymmetric use of RTS/CTS not supported. */
2064 if (data->term.c_iflag & CRTSCTS) {
2065 /* Flow control can only be disabled for both RTS & CTS together. */
2066 if (config->rts >= 0 && config->rts != SP_RTS_FLOW_CONTROL) {
2067 if (config->cts != SP_CTS_IGNORE)
2068 RETURN_ERROR(SP_ERR_SUPP, "RTS & CTS flow control must be disabled together");
2070 if (config->cts >= 0 && config->cts != SP_CTS_FLOW_CONTROL) {
2071 if (config->rts <= 0 || config->rts == SP_RTS_FLOW_CONTROL)
2072 RETURN_ERROR(SP_ERR_SUPP, "RTS & CTS flow control must be disabled together");
2075 /* Flow control can only be enabled for both RTS & CTS together. */
2076 if (((config->rts == SP_RTS_FLOW_CONTROL) && (config->cts != SP_CTS_FLOW_CONTROL)) ||
2077 ((config->cts == SP_CTS_FLOW_CONTROL) && (config->rts != SP_RTS_FLOW_CONTROL)))
2078 RETURN_ERROR(SP_ERR_SUPP, "RTS & CTS flow control must be enabled together");
2081 if (config->rts >= 0) {
2082 if (config->rts == SP_RTS_FLOW_CONTROL) {
2083 data->term.c_iflag |= CRTSCTS;
2085 controlbits = TIOCM_RTS;
2086 if (ioctl(port->fd, config->rts == SP_RTS_ON ? TIOCMBIS : TIOCMBIC,
2088 RETURN_FAIL("Setting RTS signal level failed");
2094 if (config->dtr >= 0 || config->dsr >= 0) {
2095 if (data->termiox_supported) {
2096 data->dtr_flow = data->dsr_flow = 0;
2097 switch (config->dtr) {
2100 controlbits = TIOCM_DTR;
2101 if (ioctl(port->fd, config->dtr == SP_DTR_ON ? TIOCMBIS : TIOCMBIC, &controlbits) < 0)
2102 RETURN_FAIL("Setting DTR signal level failed");
2104 case SP_DTR_FLOW_CONTROL:
2110 if (config->dsr == SP_DSR_FLOW_CONTROL)
2113 /* DTR/DSR flow control not supported. */
2114 if (config->dtr == SP_DTR_FLOW_CONTROL || config->dsr == SP_DSR_FLOW_CONTROL)
2115 RETURN_ERROR(SP_ERR_SUPP, "DTR/DSR flow control not supported");
2117 if (config->dtr >= 0) {
2118 controlbits = TIOCM_DTR;
2119 if (ioctl(port->fd, config->dtr == SP_DTR_ON ? TIOCMBIS : TIOCMBIC,
2121 RETURN_FAIL("Setting DTR signal level failed");
2126 if (config->xon_xoff >= 0) {
2127 data->term.c_iflag &= ~(IXON | IXOFF | IXANY);
2128 switch (config->xon_xoff) {
2129 case SP_XONXOFF_DISABLED:
2132 data->term.c_iflag |= IXOFF;
2134 case SP_XONXOFF_OUT:
2135 data->term.c_iflag |= IXON | IXANY;
2137 case SP_XONXOFF_INOUT:
2138 data->term.c_iflag |= IXON | IXOFF | IXANY;
2141 RETURN_ERROR(SP_ERR_ARG, "Invalid XON/XOFF setting");
2145 if (tcsetattr(port->fd, TCSANOW, &data->term) < 0)
2146 RETURN_FAIL("tcsetattr() failed");
2149 if (baud_nonstd != B0) {
2150 if (ioctl(port->fd, IOSSIOSPEED, &baud_nonstd) == -1)
2151 RETURN_FAIL("IOSSIOSPEED ioctl failed");
2152 /* Set baud rates in data->term to correct, but incompatible
2153 * with tcsetattr() value, same as delivered by tcgetattr(). */
2154 if (cfsetspeed(&data->term, baud_nonstd) < 0)
2155 RETURN_FAIL("cfsetspeed() failed");
2157 #elif defined(__linux__)
2158 #ifdef USE_TERMIOS_SPEED
2160 TRY(set_baudrate(port->fd, config->baudrate));
2163 if (data->termiox_supported)
2164 TRY(set_flow(port->fd, data));
2168 #endif /* !_WIN32 */
2173 enum sp_return sp_new_config(struct sp_port_config **config_ptr)
2175 struct sp_port_config *config;
2177 TRACE("%p", config_ptr);
2180 RETURN_ERROR(SP_ERR_ARG, "Null result pointer");
2184 if (!(config = malloc(sizeof(struct sp_port_config))))
2185 RETURN_ERROR(SP_ERR_MEM, "config malloc failed");
2187 config->baudrate = -1;
2189 config->parity = -1;
2190 config->stopbits = -1;
2196 *config_ptr = config;
2201 void sp_free_config(struct sp_port_config *config)
2203 TRACE("%p", config);
2206 DEBUG("Null config");
2213 enum sp_return sp_get_config(struct sp_port *port, struct sp_port_config *config)
2215 struct port_data data;
2217 TRACE("%p, %p", port, config);
2222 RETURN_ERROR(SP_ERR_ARG, "Null config");
2224 TRY(get_config(port, &data, config));
2229 enum sp_return sp_set_config(struct sp_port *port, const struct sp_port_config *config)
2231 struct port_data data;
2232 struct sp_port_config prev_config;
2234 TRACE("%p, %p", port, config);
2239 RETURN_ERROR(SP_ERR_ARG, "Null config");
2241 TRY(get_config(port, &data, &prev_config));
2242 TRY(set_config(port, &data, config));
2247 #define CREATE_ACCESSORS(x, type) \
2248 enum sp_return sp_set_##x(struct sp_port *port, type x) { \
2249 struct port_data data; \
2250 struct sp_port_config config; \
2251 TRACE("%p, %d", port, x); \
2252 CHECK_OPEN_PORT(); \
2253 TRY(get_config(port, &data, &config)); \
2255 TRY(set_config(port, &data, &config)); \
2258 enum sp_return sp_get_config_##x(const struct sp_port_config *config, type *x) { \
2259 TRACE("%p, %p", config, x); \
2261 RETURN_ERROR(SP_ERR_ARG, "Null config"); \
2265 enum sp_return sp_set_config_##x(struct sp_port_config *config, type x) { \
2266 TRACE("%p, %d", config, x); \
2268 RETURN_ERROR(SP_ERR_ARG, "Null config"); \
2273 CREATE_ACCESSORS(baudrate, int)
2274 CREATE_ACCESSORS(bits, int)
2275 CREATE_ACCESSORS(parity, enum sp_parity)
2276 CREATE_ACCESSORS(stopbits, int)
2277 CREATE_ACCESSORS(rts, enum sp_rts)
2278 CREATE_ACCESSORS(cts, enum sp_cts)
2279 CREATE_ACCESSORS(dtr, enum sp_dtr)
2280 CREATE_ACCESSORS(dsr, enum sp_dsr)
2281 CREATE_ACCESSORS(xon_xoff, enum sp_xonxoff)
2283 enum sp_return sp_set_config_flowcontrol(struct sp_port_config *config, enum sp_flowcontrol flowcontrol)
2286 RETURN_ERROR(SP_ERR_ARG, "Null configuration");
2288 if (flowcontrol > SP_FLOWCONTROL_DTRDSR)
2289 RETURN_ERROR(SP_ERR_ARG, "Invalid flow control setting");
2291 if (flowcontrol == SP_FLOWCONTROL_XONXOFF)
2292 config->xon_xoff = SP_XONXOFF_INOUT;
2294 config->xon_xoff = SP_XONXOFF_DISABLED;
2296 if (flowcontrol == SP_FLOWCONTROL_RTSCTS) {
2297 config->rts = SP_RTS_FLOW_CONTROL;
2298 config->cts = SP_CTS_FLOW_CONTROL;
2300 if (config->rts == SP_RTS_FLOW_CONTROL)
2301 config->rts = SP_RTS_ON;
2302 config->cts = SP_CTS_IGNORE;
2305 if (flowcontrol == SP_FLOWCONTROL_DTRDSR) {
2306 config->dtr = SP_DTR_FLOW_CONTROL;
2307 config->dsr = SP_DSR_FLOW_CONTROL;
2309 if (config->dtr == SP_DTR_FLOW_CONTROL)
2310 config->dtr = SP_DTR_ON;
2311 config->dsr = SP_DSR_IGNORE;
2317 enum sp_return sp_set_flowcontrol(struct sp_port *port, enum sp_flowcontrol flowcontrol)
2319 struct port_data data;
2320 struct sp_port_config config;
2322 TRACE("%p, %d", port, flowcontrol);
2326 TRY(get_config(port, &data, &config));
2328 TRY(sp_set_config_flowcontrol(&config, flowcontrol));
2330 TRY(set_config(port, &data, &config));
2335 enum sp_return sp_get_signals(struct sp_port *port, enum sp_signal *signals)
2337 TRACE("%p, %p", port, signals);
2342 RETURN_ERROR(SP_ERR_ARG, "Null result pointer");
2344 DEBUG("Getting control signals for port %s", port->name);
2349 if (GetCommModemStatus(port->hdl, &bits) == 0)
2350 RETURN_FAIL("GetCommModemStatus() failed");
2351 if (bits & MS_CTS_ON)
2352 *signals |= SP_SIG_CTS;
2353 if (bits & MS_DSR_ON)
2354 *signals |= SP_SIG_DSR;
2355 if (bits & MS_RLSD_ON)
2356 *signals |= SP_SIG_DCD;
2357 if (bits & MS_RING_ON)
2358 *signals |= SP_SIG_RI;
2361 if (ioctl(port->fd, TIOCMGET, &bits) < 0)
2362 RETURN_FAIL("TIOCMGET ioctl failed");
2363 if (bits & TIOCM_CTS)
2364 *signals |= SP_SIG_CTS;
2365 if (bits & TIOCM_DSR)
2366 *signals |= SP_SIG_DSR;
2367 if (bits & TIOCM_CAR)
2368 *signals |= SP_SIG_DCD;
2369 if (bits & TIOCM_RNG)
2370 *signals |= SP_SIG_RI;
2375 enum sp_return sp_start_break(struct sp_port *port)
2381 if (SetCommBreak(port->hdl) == 0)
2382 RETURN_FAIL("SetCommBreak() failed");
2384 if (ioctl(port->fd, TIOCSBRK, 1) < 0)
2385 RETURN_FAIL("TIOCSBRK ioctl failed");
2391 enum sp_return sp_end_break(struct sp_port *port)
2397 if (ClearCommBreak(port->hdl) == 0)
2398 RETURN_FAIL("ClearCommBreak() failed");
2400 if (ioctl(port->fd, TIOCCBRK, 1) < 0)
2401 RETURN_FAIL("TIOCCBRK ioctl failed");
2407 int sp_last_error_code(void)
2411 RETURN_VALUE("%d", GetLastError());
2413 RETURN_VALUE("%d", errno);
2417 char *sp_last_error_message(void)
2423 DWORD error = GetLastError();
2426 FORMAT_MESSAGE_ALLOCATE_BUFFER |
2427 FORMAT_MESSAGE_FROM_SYSTEM |
2428 FORMAT_MESSAGE_IGNORE_INSERTS,
2431 MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
2435 RETURN_VALUE("%s", message);
2437 RETURN_VALUE("%s", strerror(errno));
2441 void sp_free_error_message(char *message)
2443 TRACE("%s", message);
2454 void sp_set_debug_handler(void (*handler)(const char *format, ...))
2456 TRACE("%p", handler);
2458 sp_debug_handler = handler;
2463 void sp_default_debug_handler(const char *format, ...)
2466 va_start(args, format);
2467 if (getenv("LIBSERIALPORT_DEBUG")) {
2468 fputs("sp: ", stderr);
2469 vfprintf(stderr, format, args);
2474 int sp_get_major_package_version(void)
2476 return SP_PACKAGE_VERSION_MAJOR;
2479 int sp_get_minor_package_version(void)
2481 return SP_PACKAGE_VERSION_MINOR;
2484 int sp_get_micro_package_version(void)
2486 return SP_PACKAGE_VERSION_MICRO;
2489 const char *sp_get_package_version_string(void)
2491 return SP_PACKAGE_VERSION_STRING;
2494 int sp_get_current_lib_version(void)
2496 return SP_LIB_VERSION_CURRENT;
2499 int sp_get_revision_lib_version(void)
2501 return SP_LIB_VERSION_REVISION;
2504 int sp_get_age_lib_version(void)
2506 return SP_LIB_VERSION_AGE;
2509 const char *sp_get_lib_version_string(void)
2511 return SP_LIB_VERSION_STRING;