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 #include "libserialport.h"
79 COMMTIMEOUTS timeouts;
91 struct sp_port_config {
94 enum sp_parity parity;
100 enum sp_xonxoff xon_xoff;
109 int termiox_supported;
118 typedef HANDLE event_handle;
120 typedef int event_handle;
123 /* Standard baud rates. */
125 #define BAUD_TYPE DWORD
126 #define BAUD(n) {CBR_##n, n}
128 #define BAUD_TYPE speed_t
129 #define BAUD(n) {B##n, n}
132 struct std_baudrate {
137 const struct std_baudrate std_baudrates[] = {
140 * The baudrates 50/75/134/150/200/1800/230400/460800 do not seem to
141 * have documented CBR_* macros.
143 BAUD(110), BAUD(300), BAUD(600), BAUD(1200), BAUD(2400), BAUD(4800),
144 BAUD(9600), BAUD(14400), BAUD(19200), BAUD(38400), BAUD(57600),
145 BAUD(115200), BAUD(128000), BAUD(256000),
147 BAUD(50), BAUD(75), BAUD(110), BAUD(134), BAUD(150), BAUD(200),
148 BAUD(300), BAUD(600), BAUD(1200), BAUD(1800), BAUD(2400), BAUD(4800),
149 BAUD(9600), BAUD(19200), BAUD(38400), BAUD(57600), BAUD(115200),
151 #if !defined(__APPLE__) && !defined(__OpenBSD__)
157 void (*sp_debug_handler)(const char *format, ...) = sp_default_debug_handler;
159 #define ARRAY_SIZE(x) (sizeof(x) / sizeof(x[0]))
160 #define NUM_STD_BAUDRATES ARRAY_SIZE(std_baudrates)
162 /* Debug output macros. */
163 #define DEBUG(fmt, ...) do { if (sp_debug_handler) sp_debug_handler(fmt ".\n", ##__VA_ARGS__); } while (0)
164 #define DEBUG_ERROR(err, msg) DEBUG("%s returning " #err ": " msg, __func__)
165 #define DEBUG_FAIL(msg) do { \
166 char *errmsg = sp_last_error_message(); \
167 DEBUG("%s returning SP_ERR_FAIL: " msg ": %s", __func__, errmsg); \
168 sp_free_error_message(errmsg); \
170 #define RETURN() do { DEBUG("%s returning", __func__); return; } while(0)
171 #define RETURN_CODE(x) do { DEBUG("%s returning " #x, __func__); return x; } while (0)
172 #define RETURN_CODEVAL(x) do { \
174 case SP_OK: RETURN_CODE(SP_OK); \
175 case SP_ERR_ARG: RETURN_CODE(SP_ERR_ARG); \
176 case SP_ERR_FAIL: RETURN_CODE(SP_ERR_FAIL); \
177 case SP_ERR_MEM: RETURN_CODE(SP_ERR_MEM); \
178 case SP_ERR_SUPP: RETURN_CODE(SP_ERR_SUPP); \
181 #define RETURN_OK() RETURN_CODE(SP_OK);
182 #define RETURN_ERROR(err, msg) do { DEBUG_ERROR(err, msg); return err; } while (0)
183 #define RETURN_FAIL(msg) do { DEBUG_FAIL(msg); return SP_ERR_FAIL; } while (0)
184 #define RETURN_VALUE(fmt, x) do { \
186 DEBUG("%s returning " fmt, __func__, _x); \
189 #define SET_ERROR(val, err, msg) do { DEBUG_ERROR(err, msg); val = err; } while (0)
190 #define SET_FAIL(val, msg) do { DEBUG_FAIL(msg); val = SP_ERR_FAIL; } while (0)
191 #define TRACE(fmt, ...) DEBUG("%s(" fmt ") called", __func__, ##__VA_ARGS__)
193 #define TRY(x) do { int ret = x; if (ret != SP_OK) RETURN_CODEVAL(ret); } while (0)
195 /* Helper functions. */
196 static struct sp_port **list_append(struct sp_port **list, const char *portname);
197 static enum sp_return get_config(struct sp_port *port, struct port_data *data,
198 struct sp_port_config *config);
199 static enum sp_return set_config(struct sp_port *port, struct port_data *data,
200 const struct sp_port_config *config);
202 enum sp_return sp_get_port_by_name(const char *portname, struct sp_port **port_ptr)
204 struct sp_port *port;
207 TRACE("%s, %p", portname, port_ptr);
210 RETURN_ERROR(SP_ERR_ARG, "Null result pointer");
215 RETURN_ERROR(SP_ERR_ARG, "Null port name");
217 DEBUG("Building structure for port %s", portname);
219 if (!(port = malloc(sizeof(struct sp_port))))
220 RETURN_ERROR(SP_ERR_MEM, "Port structure malloc failed");
222 len = strlen(portname) + 1;
224 if (!(port->name = malloc(len))) {
226 RETURN_ERROR(SP_ERR_MEM, "Port name malloc failed");
229 memcpy(port->name, portname, len);
232 port->hdl = INVALID_HANDLE_VALUE;
242 char *sp_get_port_name(const struct sp_port *port)
249 RETURN_VALUE("%s", port->name);
252 enum sp_return sp_get_port_handle(const struct sp_port *port, void *result_ptr)
254 TRACE("%p, %p", port, result_ptr);
257 RETURN_ERROR(SP_ERR_ARG, "Null port");
260 HANDLE *handle_ptr = result_ptr;
261 *handle_ptr = port->hdl;
263 int *fd_ptr = result_ptr;
270 enum sp_return sp_copy_port(const struct sp_port *port, struct sp_port **copy_ptr)
272 TRACE("%p, %p", port, copy_ptr);
275 RETURN_ERROR(SP_ERR_ARG, "Null result pointer");
280 RETURN_ERROR(SP_ERR_ARG, "Null port");
283 RETURN_ERROR(SP_ERR_ARG, "Null port name");
285 DEBUG("Copying port structure");
287 RETURN_VALUE("%p", sp_get_port_by_name(port->name, copy_ptr));
290 void sp_free_port(struct sp_port *port)
299 DEBUG("Freeing port structure");
309 static struct sp_port **list_append(struct sp_port **list, const char *portname)
314 for (count = 0; list[count]; count++);
315 if (!(tmp = realloc(list, sizeof(struct sp_port *) * (count + 2))))
318 if (sp_get_port_by_name(portname, &list[count]) != SP_OK)
320 list[count + 1] = NULL;
324 sp_free_port_list(list);
328 enum sp_return sp_list_ports(struct sp_port ***list_ptr)
330 struct sp_port **list;
331 int ret = SP_ERR_SUPP;
333 TRACE("%p", list_ptr);
336 RETURN_ERROR(SP_ERR_ARG, "Null result pointer");
338 DEBUG("Enumerating ports");
340 if (!(list = malloc(sizeof(struct sp_port **))))
341 RETURN_ERROR(SP_ERR_MEM, "Port list malloc failed");
348 DWORD max_value_len, max_data_size, max_data_len;
349 DWORD value_len, data_size, data_len;
350 DWORD type, index = 0;
356 DEBUG("Opening registry key");
357 if (RegOpenKeyEx(HKEY_LOCAL_MACHINE, _T("HARDWARE\\DEVICEMAP\\SERIALCOMM"),
358 0, KEY_QUERY_VALUE, &key) != ERROR_SUCCESS) {
359 SET_FAIL(ret, "RegOpenKeyEx() failed");
362 DEBUG("Querying registry key value and data sizes");
363 if (RegQueryInfoKey(key, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
364 &max_value_len, &max_data_size, NULL, NULL) != ERROR_SUCCESS) {
365 SET_FAIL(ret, "RegQueryInfoKey() failed");
368 max_data_len = max_data_size / sizeof(TCHAR);
369 if (!(value = malloc((max_value_len + 1) * sizeof(TCHAR)))) {
370 SET_ERROR(ret, SP_ERR_MEM, "registry value malloc failed");
373 if (!(data = malloc((max_data_len + 1) * sizeof(TCHAR)))) {
374 SET_ERROR(ret, SP_ERR_MEM, "registry data malloc failed");
377 DEBUG("Iterating over values");
379 value_len = max_value_len + 1,
380 data_size = max_data_size,
381 RegEnumValue(key, index, value, &value_len,
382 NULL, &type, (LPBYTE)data, &data_size) == ERROR_SUCCESS)
384 data_len = data_size / sizeof(TCHAR);
385 data[data_len] = '\0';
387 name_len = WideCharToMultiByte(CP_ACP, 0, data, -1, NULL, 0, NULL, NULL)
389 name_len = data_len + 1;
391 if (!(name = malloc(name_len))) {
392 SET_ERROR(ret, SP_ERR_MEM, "registry port name malloc failed");
396 WideCharToMultiByte(CP_ACP, 0, data, -1, name, name_len, NULL, NULL);
400 if (type == REG_SZ) {
401 DEBUG("Found port %s", name);
402 if (!(list = list_append(list, name))) {
403 SET_ERROR(ret, SP_ERR_MEM, "list append failed");
419 CFMutableDictionaryRef classes;
428 DEBUG("Getting IOKit master port");
429 if (IOMasterPort(MACH_PORT_NULL, &master) != KERN_SUCCESS) {
430 SET_FAIL(ret, "IOMasterPort() failed");
434 DEBUG("Creating matching dictionary");
435 if (!(classes = IOServiceMatching(kIOSerialBSDServiceValue))) {
436 SET_FAIL(ret, "IOServiceMatching() failed");
440 CFDictionarySetValue(classes,
441 CFSTR(kIOSerialBSDTypeKey), CFSTR(kIOSerialBSDAllTypes));
443 DEBUG("Getting matching services");
444 if (IOServiceGetMatchingServices(master, classes, &iter) != KERN_SUCCESS) {
445 SET_FAIL(ret, "IOServiceGetMatchingServices() failed");
449 if (!(path = malloc(PATH_MAX))) {
450 SET_ERROR(ret, SP_ERR_MEM, "device path malloc failed");
454 DEBUG("Iterating over results");
455 while ((port = IOIteratorNext(iter))) {
456 cf_path = IORegistryEntryCreateCFProperty(port,
457 CFSTR(kIOCalloutDeviceKey), kCFAllocatorDefault, 0);
459 result = CFStringGetCString(cf_path,
460 path, PATH_MAX, kCFStringEncodingASCII);
463 DEBUG("Found port %s", path);
464 if (!(list = list_append(list, path))) {
465 SET_ERROR(ret, SP_ERR_MEM, "list append failed");
466 IOObjectRelease(port);
471 IOObjectRelease(port);
476 IOObjectRelease(iter);
479 #if defined(__linux__) && defined(HAVE_LIBUDEV)
481 struct udev_enumerate *ud_enumerate;
482 struct udev_list_entry *ud_list;
483 struct udev_list_entry *ud_entry;
485 struct udev_device *ud_dev, *ud_parent;
488 int fd, ioctl_result;
489 struct serial_struct serial_info;
493 DEBUG("Enumerating tty devices");
495 ud_enumerate = udev_enumerate_new(ud);
496 udev_enumerate_add_match_subsystem(ud_enumerate, "tty");
497 udev_enumerate_scan_devices(ud_enumerate);
498 ud_list = udev_enumerate_get_list_entry(ud_enumerate);
499 DEBUG("Iterating over results");
500 udev_list_entry_foreach(ud_entry, ud_list) {
501 path = udev_list_entry_get_name(ud_entry);
502 DEBUG("Found device %s", path);
503 ud_dev = udev_device_new_from_syspath(ud, path);
504 /* If there is no parent device, this is a virtual tty. */
505 ud_parent = udev_device_get_parent(ud_dev);
506 if (ud_parent == NULL) {
507 DEBUG("No parent device, assuming virtual tty");
508 udev_device_unref(ud_dev);
511 name = udev_device_get_devnode(ud_dev);
512 /* The serial8250 driver has a hardcoded number of ports.
513 * The only way to tell which actually exist on a given system
514 * is to try to open them and make an ioctl call. */
515 driver = udev_device_get_driver(ud_parent);
516 if (driver && !strcmp(driver, "serial8250")) {
517 DEBUG("serial8250 device, attempting to open");
518 if ((fd = open(name, O_RDWR | O_NONBLOCK | O_NOCTTY)) < 0) {
519 DEBUG("open failed, skipping");
522 ioctl_result = ioctl(fd, TIOCGSERIAL, &serial_info);
524 if (ioctl_result != 0) {
525 DEBUG("ioctl failed, skipping");
528 if (serial_info.type == PORT_UNKNOWN) {
529 DEBUG("port type is unknown, skipping");
533 DEBUG("Found port %s", name);
534 list = list_append(list, name);
536 udev_device_unref(ud_dev);
538 SET_ERROR(ret, SP_ERR_MEM, "list append failed");
543 udev_enumerate_unref(ud_enumerate);
552 DEBUG_ERROR(SP_ERR_SUPP, "Enumeration not supported on this platform");
555 sp_free_port_list(list);
561 void sp_free_port_list(struct sp_port **list)
572 DEBUG("Freeing port list");
574 for (i = 0; list[i]; i++)
575 sp_free_port(list[i]);
581 #define CHECK_PORT() do { \
583 RETURN_ERROR(SP_ERR_ARG, "Null port"); \
584 if (port->name == NULL) \
585 RETURN_ERROR(SP_ERR_ARG, "Null port name"); \
588 #define CHECK_PORT_HANDLE() do { \
589 if (port->hdl == INVALID_HANDLE_VALUE) \
590 RETURN_ERROR(SP_ERR_ARG, "Invalid port handle"); \
593 #define CHECK_PORT_HANDLE() do { \
595 RETURN_ERROR(SP_ERR_ARG, "Invalid port fd"); \
598 #define CHECK_OPEN_PORT() do { \
600 CHECK_PORT_HANDLE(); \
603 enum sp_return sp_open(struct sp_port *port, enum sp_mode flags)
605 struct port_data data;
606 struct sp_port_config config;
609 TRACE("%p, 0x%x", port, flags);
613 if (flags > (SP_MODE_READ | SP_MODE_WRITE))
614 RETURN_ERROR(SP_ERR_ARG, "Invalid flags");
616 DEBUG("Opening port %s", port->name);
619 DWORD desired_access = 0, flags_and_attributes = 0, errors;
620 char *escaped_port_name;
623 /* Prefix port name with '\\.\' to work with ports above COM9. */
624 if (!(escaped_port_name = malloc(strlen(port->name + 5))))
625 RETURN_ERROR(SP_ERR_MEM, "Escaped port name malloc failed");
626 sprintf(escaped_port_name, "\\\\.\\%s", port->name);
628 /* Map 'flags' to the OS-specific settings. */
629 flags_and_attributes = FILE_ATTRIBUTE_NORMAL | FILE_FLAG_OVERLAPPED;
630 if (flags & SP_MODE_READ)
631 desired_access |= GENERIC_READ;
632 if (flags & SP_MODE_WRITE)
633 desired_access |= GENERIC_WRITE;
635 port->hdl = CreateFile(escaped_port_name, desired_access, 0, 0,
636 OPEN_EXISTING, flags_and_attributes, 0);
638 free(escaped_port_name);
640 if (port->hdl == INVALID_HANDLE_VALUE)
641 RETURN_FAIL("port CreateFile() failed");
643 /* All timeouts initially disabled. */
644 port->timeouts.ReadIntervalTimeout = 0;
645 port->timeouts.ReadTotalTimeoutMultiplier = 0;
646 port->timeouts.ReadTotalTimeoutConstant = 0;
647 port->timeouts.WriteTotalTimeoutMultiplier = 0;
648 port->timeouts.WriteTotalTimeoutConstant = 0;
650 if (SetCommTimeouts(port->hdl, &port->timeouts) == 0) {
652 RETURN_FAIL("SetCommTimeouts() failed");
655 /* Prepare OVERLAPPED structures. */
656 #define INIT_OVERLAPPED(ovl) do { \
657 memset(&port->ovl, 0, sizeof(port->ovl)); \
658 port->ovl.hEvent = INVALID_HANDLE_VALUE; \
659 if ((port->ovl.hEvent = CreateEvent(NULL, TRUE, TRUE, NULL)) \
660 == INVALID_HANDLE_VALUE) { \
662 RETURN_FAIL(#ovl "CreateEvent() failed"); \
666 INIT_OVERLAPPED(read_ovl);
667 INIT_OVERLAPPED(write_ovl);
668 INIT_OVERLAPPED(wait_ovl);
670 /* Set event mask for RX and error events. */
671 if (SetCommMask(port->hdl, EV_RXCHAR | EV_ERR) == 0) {
673 RETURN_FAIL("SetCommMask() failed");
676 /* Start background operation for RX and error events. */
677 if (WaitCommEvent(port->hdl, &port->events, &port->wait_ovl) == 0) {
678 if (GetLastError() != ERROR_IO_PENDING) {
680 RETURN_FAIL("WaitCommEvent() failed");
684 port->writing = FALSE;
687 int flags_local = O_NONBLOCK | O_NOCTTY;
689 /* Map 'flags' to the OS-specific settings. */
690 if (flags & (SP_MODE_READ | SP_MODE_WRITE))
691 flags_local |= O_RDWR;
692 else if (flags & SP_MODE_READ)
693 flags_local |= O_RDONLY;
694 else if (flags & SP_MODE_WRITE)
695 flags_local |= O_WRONLY;
697 if ((port->fd = open(port->name, flags_local)) < 0)
698 RETURN_FAIL("open() failed");
701 ret = get_config(port, &data, &config);
708 /* Set sane port settings. */
710 data.dcb.fBinary = TRUE;
711 data.dcb.fDsrSensitivity = FALSE;
712 data.dcb.fErrorChar = FALSE;
713 data.dcb.fNull = FALSE;
714 data.dcb.fAbortOnError = TRUE;
716 /* Turn off all fancy termios tricks, give us a raw channel. */
717 data.term.c_iflag &= ~(IGNBRK | BRKINT | PARMRK | ISTRIP | INLCR | IGNCR | ICRNL | IMAXBEL);
719 data.term.c_iflag &= ~IUCLC;
721 data.term.c_oflag &= ~(OPOST | ONLCR | OCRNL | ONOCR | ONLRET);
723 data.term.c_oflag &= ~OLCUC;
726 data.term.c_oflag &= ~NLDLY;
729 data.term.c_oflag &= ~CRDLY;
732 data.term.c_oflag &= ~TABDLY;
735 data.term.c_oflag &= ~BSDLY;
738 data.term.c_oflag &= ~VTDLY;
741 data.term.c_oflag &= ~FFDLY;
744 data.term.c_oflag &= ~OFILL;
746 data.term.c_lflag &= ~(ISIG | ICANON | ECHO | IEXTEN);
747 data.term.c_cc[VMIN] = 0;
748 data.term.c_cc[VTIME] = 0;
750 /* Ignore modem status lines; enable receiver; leave control lines alone on close. */
751 data.term.c_cflag |= (CLOCAL | CREAD | HUPCL);
755 if (ClearCommError(port->hdl, &errors, &status) == 0)
756 RETURN_FAIL("ClearCommError() failed");
759 ret = set_config(port, &data, &config);
769 enum sp_return sp_close(struct sp_port *port)
775 DEBUG("Closing port %s", port->name);
778 /* Returns non-zero upon success, 0 upon failure. */
779 if (CloseHandle(port->hdl) == 0)
780 RETURN_FAIL("port CloseHandle() failed");
781 port->hdl = INVALID_HANDLE_VALUE;
783 /* Close event handles for overlapped structures. */
784 #define CLOSE_OVERLAPPED(ovl) do { \
785 if (port->ovl.hEvent != INVALID_HANDLE_VALUE && \
786 CloseHandle(port->ovl.hEvent) == 0) \
787 RETURN_FAIL(# ovl "event CloseHandle() failed"); \
789 CLOSE_OVERLAPPED(read_ovl);
790 CLOSE_OVERLAPPED(write_ovl);
791 CLOSE_OVERLAPPED(wait_ovl);
794 /* Returns 0 upon success, -1 upon failure. */
795 if (close(port->fd) == -1)
796 RETURN_FAIL("close() failed");
803 enum sp_return sp_flush(struct sp_port *port, enum sp_buffer buffers)
805 TRACE("%p, 0x%x", port, buffers);
809 if (buffers > SP_BUF_BOTH)
810 RETURN_ERROR(SP_ERR_ARG, "Invalid buffer selection");
812 const char *buffer_names[] = {"no", "input", "output", "both"};
814 DEBUG("Flushing %s buffers on port %s", buffer_names[buffers], port->name);
818 if (buffers & SP_BUF_INPUT)
819 flags |= PURGE_RXCLEAR;
820 if (buffers & SP_BUF_OUTPUT)
821 flags |= PURGE_TXCLEAR;
823 /* Returns non-zero upon success, 0 upon failure. */
824 if (PurgeComm(port->hdl, flags) == 0)
825 RETURN_FAIL("PurgeComm() failed");
828 if (buffers & SP_BUF_BOTH)
830 else if (buffers & SP_BUF_INPUT)
832 else if (buffers & SP_BUF_OUTPUT)
835 /* Returns 0 upon success, -1 upon failure. */
836 if (tcflush(port->fd, flags) < 0)
837 RETURN_FAIL("tcflush() failed");
842 enum sp_return sp_drain(struct sp_port *port)
848 DEBUG("Draining port %s", port->name);
851 /* Returns non-zero upon success, 0 upon failure. */
852 if (FlushFileBuffers(port->hdl) == 0)
853 RETURN_FAIL("FlushFileBuffers() failed");
860 result = ioctl(port->fd, TCSBRK, &arg);
862 result = tcdrain(port->fd);
865 if (errno == EINTR) {
866 DEBUG("tcdrain() was interrupted");
869 RETURN_FAIL("tcdrain() failed");
878 enum sp_return sp_blocking_write(struct sp_port *port, const void *buf, size_t count, unsigned int timeout)
880 TRACE("%p, %p, %d, %d", port, buf, count, timeout);
885 RETURN_ERROR(SP_ERR_ARG, "Null buffer");
888 DEBUG("Writing %d bytes to port %s, timeout %d ms", count, port->name, timeout);
890 DEBUG("Writing %d bytes to port %s, no timeout", count, port->name);
893 RETURN_VALUE("0", 0);
896 DWORD bytes_written = 0;
899 /* Wait for previous non-blocking write to complete, if any. */
901 DEBUG("Waiting for previous write to complete");
902 result = GetOverlappedResult(port->hdl, &port->write_ovl, &bytes_written, TRUE);
905 RETURN_FAIL("Previous write failed to complete");
906 DEBUG("Previous write completed");
910 port->timeouts.WriteTotalTimeoutConstant = timeout;
911 if (SetCommTimeouts(port->hdl, &port->timeouts) == 0)
912 RETURN_FAIL("SetCommTimeouts() failed");
915 if (WriteFile(port->hdl, buf, count, NULL, &port->write_ovl) == 0) {
916 if (GetLastError() == ERROR_IO_PENDING) {
917 DEBUG("Waiting for write to complete");
918 GetOverlappedResult(port->hdl, &port->write_ovl, &bytes_written, TRUE);
919 DEBUG("Write completed, %d/%d bytes written", bytes_written, count);
920 RETURN_VALUE("%d", bytes_written);
922 RETURN_FAIL("WriteFile() failed");
925 DEBUG("Write completed immediately");
926 RETURN_VALUE("%d", count);
929 size_t bytes_written = 0;
930 unsigned char *ptr = (unsigned char *) buf;
931 struct timeval start, delta, now, end = {0, 0};
936 /* Get time at start of operation. */
937 gettimeofday(&start, NULL);
938 /* Define duration of timeout. */
939 delta.tv_sec = timeout / 1000;
940 delta.tv_usec = (timeout % 1000) * 1000;
941 /* Calculate time at which we should give up. */
942 timeradd(&start, &delta, &end);
945 /* Loop until we have written the requested number of bytes. */
946 while (bytes_written < count)
948 /* Wait until space is available. */
950 FD_SET(port->fd, &fds);
952 gettimeofday(&now, NULL);
953 if (timercmp(&now, &end, >)) {
954 DEBUG("write timed out");
955 RETURN_VALUE("%d", bytes_written);
957 timersub(&end, &now, &delta);
959 result = select(port->fd + 1, NULL, &fds, NULL, timeout ? &delta : NULL);
961 if (errno == EINTR) {
962 DEBUG("select() call was interrupted, repeating");
965 RETURN_FAIL("select() failed");
967 } else if (result == 0) {
968 DEBUG("write timed out");
969 RETURN_VALUE("%d", bytes_written);
973 result = write(port->fd, ptr, count - bytes_written);
977 /* This shouldn't happen because we did a select() first, but handle anyway. */
980 /* This is an actual failure. */
981 RETURN_FAIL("write() failed");
984 bytes_written += result;
988 RETURN_VALUE("%d", bytes_written);
992 enum sp_return sp_nonblocking_write(struct sp_port *port, const void *buf, size_t count)
994 TRACE("%p, %p, %d", port, buf, count);
999 RETURN_ERROR(SP_ERR_ARG, "Null buffer");
1001 DEBUG("Writing up to %d bytes to port %s", count, port->name);
1004 RETURN_VALUE("0", 0);
1008 BYTE *ptr = (BYTE *) buf;
1010 /* Check whether previous write is complete. */
1011 if (port->writing) {
1012 if (HasOverlappedIoCompleted(&port->write_ovl)) {
1013 DEBUG("Previous write completed");
1016 DEBUG("Previous write not complete");
1017 /* Can't take a new write until the previous one finishes. */
1018 RETURN_VALUE("0", 0);
1023 port->timeouts.WriteTotalTimeoutConstant = 0;
1024 if (SetCommTimeouts(port->hdl, &port->timeouts) == 0)
1025 RETURN_FAIL("SetCommTimeouts() failed");
1027 /* Keep writing data until the OS has to actually start an async IO for it.
1028 * At that point we know the buffer is full. */
1029 while (written < count)
1031 /* Copy first byte of user buffer. */
1032 port->pending_byte = *ptr++;
1034 /* Start asynchronous write. */
1035 if (WriteFile(port->hdl, &port->pending_byte, 1, NULL, &port->write_ovl) == 0) {
1036 if (GetLastError() == ERROR_IO_PENDING) {
1037 if (HasOverlappedIoCompleted(&port->write_ovl)) {
1038 DEBUG("Asynchronous write completed immediately");
1043 DEBUG("Asynchronous write running");
1045 RETURN_VALUE("%d", ++written);
1048 /* Actual failure of some kind. */
1049 RETURN_FAIL("WriteFile() failed");
1052 DEBUG("Single byte written immediately");
1057 DEBUG("All bytes written immediately");
1059 RETURN_VALUE("%d", written);
1061 /* Returns the number of bytes written, or -1 upon failure. */
1062 ssize_t written = write(port->fd, buf, count);
1065 RETURN_FAIL("write() failed");
1067 RETURN_VALUE("%d", written);
1071 enum sp_return sp_blocking_read(struct sp_port *port, void *buf, size_t count, unsigned int timeout)
1073 TRACE("%p, %p, %d, %d", port, buf, count, timeout);
1078 RETURN_ERROR(SP_ERR_ARG, "Null buffer");
1081 DEBUG("Reading %d bytes from port %s, timeout %d ms", count, port->name, timeout);
1083 DEBUG("Reading %d bytes from port %s, no timeout", count, port->name);
1086 RETURN_VALUE("0", 0);
1089 DWORD bytes_read = 0;
1092 port->timeouts.ReadIntervalTimeout = 0;
1093 port->timeouts.ReadTotalTimeoutConstant = timeout;
1094 if (SetCommTimeouts(port->hdl, &port->timeouts) == 0)
1095 RETURN_FAIL("SetCommTimeouts() failed");
1098 if (ReadFile(port->hdl, buf, count, NULL, &port->read_ovl) == 0) {
1099 if (GetLastError() == ERROR_IO_PENDING) {
1100 DEBUG("Waiting for read to complete");
1101 GetOverlappedResult(port->hdl, &port->read_ovl, &bytes_read, TRUE);
1102 DEBUG("Read completed, %d/%d bytes read", bytes_read, count);
1104 RETURN_FAIL("ReadFile() failed");
1107 DEBUG("Read completed immediately");
1111 /* Start background operation for subsequent events. */
1112 if (WaitCommEvent(port->hdl, &port->events, &port->wait_ovl) == 0) {
1113 if (GetLastError() != ERROR_IO_PENDING)
1114 RETURN_FAIL("WaitCommEvent() failed");
1117 RETURN_VALUE("%d", bytes_read);
1120 size_t bytes_read = 0;
1121 unsigned char *ptr = (unsigned char *) buf;
1122 struct timeval start, delta, now, end = {0, 0};
1127 /* Get time at start of operation. */
1128 gettimeofday(&start, NULL);
1129 /* Define duration of timeout. */
1130 delta.tv_sec = timeout / 1000;
1131 delta.tv_usec = (timeout % 1000) * 1000;
1132 /* Calculate time at which we should give up. */
1133 timeradd(&start, &delta, &end);
1136 /* Loop until we have the requested number of bytes. */
1137 while (bytes_read < count)
1139 /* Wait until data is available. */
1141 FD_SET(port->fd, &fds);
1143 gettimeofday(&now, NULL);
1144 if (timercmp(&now, &end, >))
1145 /* Timeout has expired. */
1146 RETURN_VALUE("%d", bytes_read);
1147 timersub(&end, &now, &delta);
1149 result = select(port->fd + 1, &fds, NULL, NULL, timeout ? &delta : NULL);
1151 if (errno == EINTR) {
1152 DEBUG("select() call was interrupted, repeating");
1155 RETURN_FAIL("select() failed");
1157 } else if (result == 0) {
1158 DEBUG("read timed out");
1159 RETURN_VALUE("%d", bytes_read);
1163 result = read(port->fd, ptr, count - bytes_read);
1166 if (errno == EAGAIN)
1167 /* This shouldn't happen because we did a select() first, but handle anyway. */
1170 /* This is an actual failure. */
1171 RETURN_FAIL("read() failed");
1174 bytes_read += result;
1178 RETURN_VALUE("%d", bytes_read);
1182 enum sp_return sp_nonblocking_read(struct sp_port *port, void *buf, size_t count)
1184 TRACE("%p, %p, %d", port, buf, count);
1189 RETURN_ERROR(SP_ERR_ARG, "Null buffer");
1191 DEBUG("Reading up to %d bytes from port %s", count, port->name);
1197 port->timeouts.ReadIntervalTimeout = MAXDWORD;
1198 port->timeouts.ReadTotalTimeoutConstant = 0;
1199 if (SetCommTimeouts(port->hdl, &port->timeouts) == 0)
1200 RETURN_FAIL("SetCommTimeouts() failed");
1203 if (ReadFile(port->hdl, buf, count, NULL, &port->read_ovl) == 0)
1204 RETURN_FAIL("ReadFile() failed");
1206 /* Get number of bytes read. */
1207 if (GetOverlappedResult(port->hdl, &port->read_ovl, &bytes_read, TRUE) == 0)
1208 RETURN_FAIL("GetOverlappedResult() failed");
1210 if (bytes_read > 0) {
1211 /* Start background operation for subsequent events. */
1212 if (WaitCommEvent(port->hdl, &port->events, &port->wait_ovl) == 0) {
1213 if (GetLastError() != ERROR_IO_PENDING)
1214 RETURN_FAIL("WaitCommEvent() failed");
1218 RETURN_VALUE("%d", bytes_read);
1222 /* Returns the number of bytes read, or -1 upon failure. */
1223 if ((bytes_read = read(port->fd, buf, count)) < 0) {
1224 if (errno == EAGAIN)
1225 /* No bytes available. */
1228 /* This is an actual failure. */
1229 RETURN_FAIL("read() failed");
1231 RETURN_VALUE("%d", bytes_read);
1235 enum sp_return sp_input_waiting(struct sp_port *port)
1241 DEBUG("Checking input bytes waiting on port %s", port->name);
1247 if (ClearCommError(port->hdl, &errors, &comstat) == 0)
1248 RETURN_FAIL("ClearCommError() failed");
1249 RETURN_VALUE("%d", comstat.cbInQue);
1252 if (ioctl(port->fd, TIOCINQ, &bytes_waiting) < 0)
1253 RETURN_FAIL("TIOCINQ ioctl failed");
1254 RETURN_VALUE("%d", bytes_waiting);
1258 enum sp_return sp_output_waiting(struct sp_port *port)
1264 DEBUG("Checking output bytes waiting on port %s", port->name);
1270 if (ClearCommError(port->hdl, &errors, &comstat) == 0)
1271 RETURN_FAIL("ClearCommError() failed");
1272 RETURN_VALUE("%d", comstat.cbOutQue);
1275 if (ioctl(port->fd, TIOCOUTQ, &bytes_waiting) < 0)
1276 RETURN_FAIL("TIOCOUTQ ioctl failed");
1277 RETURN_VALUE("%d", bytes_waiting);
1281 enum sp_return sp_new_event_set(struct sp_event_set **result_ptr)
1283 struct sp_event_set *result;
1285 TRACE("%p", result_ptr);
1288 RETURN_ERROR(SP_ERR_ARG, "Null result");
1292 if (!(result = malloc(sizeof(struct sp_event_set))))
1293 RETURN_ERROR(SP_ERR_MEM, "sp_event_set malloc() failed");
1295 memset(result, 0, sizeof(struct sp_event_set));
1297 *result_ptr = result;
1302 static enum sp_return add_handle(struct sp_event_set *event_set,
1303 event_handle handle, enum sp_event mask)
1306 enum sp_event *new_masks;
1308 TRACE("%p, %d, %d", event_set, handle, mask);
1310 if (!(new_handles = realloc(event_set->handles,
1311 sizeof(event_handle) * (event_set->count + 1))))
1312 RETURN_ERROR(SP_ERR_MEM, "handle array realloc() failed");
1314 if (!(new_masks = realloc(event_set->masks,
1315 sizeof(enum sp_event) * (event_set->count + 1))))
1316 RETURN_ERROR(SP_ERR_MEM, "mask array realloc() failed");
1318 event_set->handles = new_handles;
1319 event_set->masks = new_masks;
1321 ((event_handle *) event_set->handles)[event_set->count] = handle;
1322 event_set->masks[event_set->count] = mask;
1329 enum sp_return sp_add_port_events(struct sp_event_set *event_set,
1330 const struct sp_port *port, enum sp_event mask)
1332 TRACE("%p, %p, %d", event_set, port, mask);
1335 RETURN_ERROR(SP_ERR_ARG, "Null event set");
1338 RETURN_ERROR(SP_ERR_ARG, "Null port");
1340 if (mask > (SP_EVENT_RX_READY | SP_EVENT_TX_READY | SP_EVENT_ERROR))
1341 RETURN_ERROR(SP_ERR_ARG, "Invalid event mask");
1347 enum sp_event handle_mask;
1348 if ((handle_mask = mask & SP_EVENT_TX_READY))
1349 TRY(add_handle(event_set, port->write_ovl.hEvent, handle_mask));
1350 if ((handle_mask = mask & (SP_EVENT_RX_READY | SP_EVENT_ERROR)))
1351 TRY(add_handle(event_set, port->wait_ovl.hEvent, handle_mask));
1353 TRY(add_handle(event_set, port->fd, mask));
1359 void sp_free_event_set(struct sp_event_set *event_set)
1361 TRACE("%p", event_set);
1364 DEBUG("Null event set");
1368 DEBUG("Freeing event set");
1370 if (event_set->handles)
1371 free(event_set->handles);
1372 if (event_set->masks)
1373 free(event_set->masks);
1380 enum sp_return sp_wait(struct sp_event_set *event_set, unsigned int timeout)
1382 TRACE("%p, %d", event_set, timeout);
1385 RETURN_ERROR(SP_ERR_ARG, "Null event set");
1388 if (WaitForMultipleObjects(event_set->count, event_set->handles, FALSE,
1389 timeout ? timeout : INFINITE) == WAIT_FAILED)
1390 RETURN_FAIL("WaitForMultipleObjects() failed");
1394 struct timeval start, delta, now, end = {0, 0};
1395 int result, timeout_remaining;
1396 struct pollfd *pollfds;
1399 if (!(pollfds = malloc(sizeof(struct pollfd) * event_set->count)))
1400 RETURN_ERROR(SP_ERR_MEM, "pollfds malloc() failed");
1402 for (i = 0; i < event_set->count; i++) {
1403 pollfds[i].fd = ((int *) event_set->handles)[i];
1404 pollfds[i].events = 0;
1405 pollfds[i].revents = 0;
1406 if (event_set->masks[i] & SP_EVENT_RX_READY)
1407 pollfds[i].events |= POLLIN;
1408 if (event_set->masks[i] & SP_EVENT_TX_READY)
1409 pollfds[i].events |= POLLOUT;
1410 if (event_set->masks[i] & SP_EVENT_ERROR)
1411 pollfds[i].events |= POLLERR;
1415 /* Get time at start of operation. */
1416 gettimeofday(&start, NULL);
1417 /* Define duration of timeout. */
1418 delta.tv_sec = timeout / 1000;
1419 delta.tv_usec = (timeout % 1000) * 1000;
1420 /* Calculate time at which we should give up. */
1421 timeradd(&start, &delta, &end);
1424 /* Loop until an event occurs. */
1428 gettimeofday(&now, NULL);
1429 if (timercmp(&now, &end, >)) {
1430 DEBUG("wait timed out");
1433 timersub(&end, &now, &delta);
1434 timeout_remaining = delta.tv_sec * 1000 + delta.tv_usec / 1000;
1437 result = poll(pollfds, event_set->count, timeout ? timeout_remaining : -1);
1440 if (errno == EINTR) {
1441 DEBUG("poll() call was interrupted, repeating");
1445 RETURN_FAIL("poll() failed");
1447 } else if (result == 0) {
1448 DEBUG("poll() timed out");
1451 DEBUG("poll() completed");
1462 static enum sp_return get_baudrate(int fd, int *baudrate)
1466 TRACE("%d, %p", fd, baudrate);
1468 DEBUG("Getting baud rate");
1470 if (!(data = malloc(get_termios_size())))
1471 RETURN_ERROR(SP_ERR_MEM, "termios malloc failed");
1473 if (ioctl(fd, get_termios_get_ioctl(), data) < 0) {
1475 RETURN_FAIL("getting termios failed");
1478 *baudrate = get_termios_speed(data);
1485 static enum sp_return set_baudrate(int fd, int baudrate)
1489 TRACE("%d, %d", fd, baudrate);
1491 DEBUG("Getting baud rate");
1493 if (!(data = malloc(get_termios_size())))
1494 RETURN_ERROR(SP_ERR_MEM, "termios malloc failed");
1496 if (ioctl(fd, get_termios_get_ioctl(), data) < 0) {
1498 RETURN_FAIL("getting termios failed");
1501 DEBUG("Setting baud rate");
1503 set_termios_speed(data, baudrate);
1505 if (ioctl(fd, get_termios_set_ioctl(), data) < 0) {
1507 RETURN_FAIL("setting termios failed");
1516 static enum sp_return get_flow(int fd, struct port_data *data)
1520 TRACE("%d, %p", fd, data);
1522 DEBUG("Getting advanced flow control");
1524 if (!(termx = malloc(get_termiox_size())))
1525 RETURN_ERROR(SP_ERR_MEM, "termiox malloc failed");
1527 if (ioctl(fd, TCGETX, termx) < 0) {
1529 RETURN_FAIL("getting termiox failed");
1532 get_termiox_flow(termx, &data->rts_flow, &data->cts_flow,
1533 &data->dtr_flow, &data->dsr_flow);
1540 static enum sp_return set_flow(int fd, struct port_data *data)
1544 TRACE("%d, %p", fd, data);
1546 DEBUG("Getting advanced flow control");
1548 if (!(termx = malloc(get_termiox_size())))
1549 RETURN_ERROR(SP_ERR_MEM, "termiox malloc failed");
1551 if (ioctl(fd, TCGETX, termx) < 0) {
1553 RETURN_FAIL("getting termiox failed");
1556 DEBUG("Setting advanced flow control");
1558 set_termiox_flow(termx, data->rts_flow, data->cts_flow,
1559 data->dtr_flow, data->dsr_flow);
1561 if (ioctl(fd, TCSETX, termx) < 0) {
1563 RETURN_FAIL("setting termiox failed");
1570 #endif /* USE_TERMIOX */
1571 #endif /* __linux__ */
1573 static enum sp_return get_config(struct sp_port *port, struct port_data *data,
1574 struct sp_port_config *config)
1578 TRACE("%p, %p, %p", port, data, config);
1580 DEBUG("Getting configuration for port %s", port->name);
1583 if (!GetCommState(port->hdl, &data->dcb))
1584 RETURN_FAIL("GetCommState() failed");
1586 for (i = 0; i < NUM_STD_BAUDRATES; i++) {
1587 if (data->dcb.BaudRate == std_baudrates[i].index) {
1588 config->baudrate = std_baudrates[i].value;
1593 if (i == NUM_STD_BAUDRATES)
1594 /* BaudRate field can be either an index or a custom baud rate. */
1595 config->baudrate = data->dcb.BaudRate;
1597 config->bits = data->dcb.ByteSize;
1599 if (data->dcb.fParity)
1600 switch (data->dcb.Parity) {
1602 config->parity = SP_PARITY_NONE;
1605 config->parity = SP_PARITY_ODD;
1608 config->parity = SP_PARITY_EVEN;
1611 config->parity = SP_PARITY_MARK;
1614 config->parity = SP_PARITY_SPACE;
1617 config->parity = -1;
1620 config->parity = SP_PARITY_NONE;
1622 switch (data->dcb.StopBits) {
1624 config->stopbits = 1;
1627 config->stopbits = 2;
1630 config->stopbits = -1;
1633 switch (data->dcb.fRtsControl) {
1634 case RTS_CONTROL_DISABLE:
1635 config->rts = SP_RTS_OFF;
1637 case RTS_CONTROL_ENABLE:
1638 config->rts = SP_RTS_ON;
1640 case RTS_CONTROL_HANDSHAKE:
1641 config->rts = SP_RTS_FLOW_CONTROL;
1647 config->cts = data->dcb.fOutxCtsFlow ? SP_CTS_FLOW_CONTROL : SP_CTS_IGNORE;
1649 switch (data->dcb.fDtrControl) {
1650 case DTR_CONTROL_DISABLE:
1651 config->dtr = SP_DTR_OFF;
1653 case DTR_CONTROL_ENABLE:
1654 config->dtr = SP_DTR_ON;
1656 case DTR_CONTROL_HANDSHAKE:
1657 config->dtr = SP_DTR_FLOW_CONTROL;
1663 config->dsr = data->dcb.fOutxDsrFlow ? SP_DSR_FLOW_CONTROL : SP_DSR_IGNORE;
1665 if (data->dcb.fInX) {
1666 if (data->dcb.fOutX)
1667 config->xon_xoff = SP_XONXOFF_INOUT;
1669 config->xon_xoff = SP_XONXOFF_IN;
1671 if (data->dcb.fOutX)
1672 config->xon_xoff = SP_XONXOFF_OUT;
1674 config->xon_xoff = SP_XONXOFF_DISABLED;
1679 if (tcgetattr(port->fd, &data->term) < 0)
1680 RETURN_FAIL("tcgetattr() failed");
1682 if (ioctl(port->fd, TIOCMGET, &data->controlbits) < 0)
1683 RETURN_FAIL("TIOCMGET ioctl failed");
1686 int ret = get_flow(port->fd, data);
1688 if (ret == SP_ERR_FAIL && errno == EINVAL)
1689 data->termiox_supported = 0;
1691 RETURN_CODEVAL(ret);
1693 data->termiox_supported = 1;
1695 data->termiox_supported = 0;
1698 for (i = 0; i < NUM_STD_BAUDRATES; i++) {
1699 if (cfgetispeed(&data->term) == std_baudrates[i].index) {
1700 config->baudrate = std_baudrates[i].value;
1705 if (i == NUM_STD_BAUDRATES) {
1707 config->baudrate = (int)data->term.c_ispeed;
1708 #elif defined(__linux__)
1709 TRY(get_baudrate(port->fd, &config->baudrate));
1711 config->baudrate = -1;
1715 switch (data->term.c_cflag & CSIZE) {
1732 if (!(data->term.c_cflag & PARENB) && (data->term.c_iflag & IGNPAR))
1733 config->parity = SP_PARITY_NONE;
1734 else if (!(data->term.c_cflag & PARENB) || (data->term.c_iflag & IGNPAR))
1735 config->parity = -1;
1737 else if (data->term.c_cflag & CMSPAR)
1738 config->parity = (data->term.c_cflag & PARODD) ? SP_PARITY_MARK : SP_PARITY_SPACE;
1741 config->parity = (data->term.c_cflag & PARODD) ? SP_PARITY_ODD : SP_PARITY_EVEN;
1743 config->stopbits = (data->term.c_cflag & CSTOPB) ? 2 : 1;
1745 if (data->term.c_cflag & CRTSCTS) {
1746 config->rts = SP_RTS_FLOW_CONTROL;
1747 config->cts = SP_CTS_FLOW_CONTROL;
1749 if (data->termiox_supported && data->rts_flow)
1750 config->rts = SP_RTS_FLOW_CONTROL;
1752 config->rts = (data->controlbits & TIOCM_RTS) ? SP_RTS_ON : SP_RTS_OFF;
1754 config->cts = (data->termiox_supported && data->cts_flow) ?
1755 SP_CTS_FLOW_CONTROL : SP_CTS_IGNORE;
1758 if (data->termiox_supported && data->dtr_flow)
1759 config->dtr = SP_DTR_FLOW_CONTROL;
1761 config->dtr = (data->controlbits & TIOCM_DTR) ? SP_DTR_ON : SP_DTR_OFF;
1763 config->dsr = (data->termiox_supported && data->dsr_flow) ?
1764 SP_DSR_FLOW_CONTROL : SP_DSR_IGNORE;
1766 if (data->term.c_iflag & IXOFF) {
1767 if (data->term.c_iflag & IXON)
1768 config->xon_xoff = SP_XONXOFF_INOUT;
1770 config->xon_xoff = SP_XONXOFF_IN;
1772 if (data->term.c_iflag & IXON)
1773 config->xon_xoff = SP_XONXOFF_OUT;
1775 config->xon_xoff = SP_XONXOFF_DISABLED;
1782 static enum sp_return set_config(struct sp_port *port, struct port_data *data,
1783 const struct sp_port_config *config)
1787 BAUD_TYPE baud_nonstd;
1792 int baud_nonstd = 0;
1795 TRACE("%p, %p, %p", port, data, config);
1797 DEBUG("Setting configuration for port %s", port->name);
1800 if (config->baudrate >= 0) {
1801 for (i = 0; i < NUM_STD_BAUDRATES; i++) {
1802 if (config->baudrate == std_baudrates[i].value) {
1803 data->dcb.BaudRate = std_baudrates[i].index;
1808 if (i == NUM_STD_BAUDRATES)
1809 data->dcb.BaudRate = config->baudrate;
1812 if (config->bits >= 0)
1813 data->dcb.ByteSize = config->bits;
1815 if (config->parity >= 0) {
1816 switch (config->parity) {
1817 case SP_PARITY_NONE:
1818 data->dcb.Parity = NOPARITY;
1821 data->dcb.Parity = ODDPARITY;
1823 case SP_PARITY_EVEN:
1824 data->dcb.Parity = EVENPARITY;
1826 case SP_PARITY_MARK:
1827 data->dcb.Parity = MARKPARITY;
1829 case SP_PARITY_SPACE:
1830 data->dcb.Parity = SPACEPARITY;
1833 RETURN_ERROR(SP_ERR_ARG, "Invalid parity setting");
1837 if (config->stopbits >= 0) {
1838 switch (config->stopbits) {
1839 /* Note: There's also ONE5STOPBITS == 1.5 (unneeded so far). */
1841 data->dcb.StopBits = ONESTOPBIT;
1844 data->dcb.StopBits = TWOSTOPBITS;
1847 RETURN_ERROR(SP_ERR_ARG, "Invalid stop bit setting");
1851 if (config->rts >= 0) {
1852 switch (config->rts) {
1854 data->dcb.fRtsControl = RTS_CONTROL_DISABLE;
1857 data->dcb.fRtsControl = RTS_CONTROL_ENABLE;
1859 case SP_RTS_FLOW_CONTROL:
1860 data->dcb.fRtsControl = RTS_CONTROL_HANDSHAKE;
1863 RETURN_ERROR(SP_ERR_ARG, "Invalid RTS setting");
1867 if (config->cts >= 0) {
1868 switch (config->cts) {
1870 data->dcb.fOutxCtsFlow = FALSE;
1872 case SP_CTS_FLOW_CONTROL:
1873 data->dcb.fOutxCtsFlow = TRUE;
1876 RETURN_ERROR(SP_ERR_ARG, "Invalid CTS setting");
1880 if (config->dtr >= 0) {
1881 switch (config->dtr) {
1883 data->dcb.fDtrControl = DTR_CONTROL_DISABLE;
1886 data->dcb.fDtrControl = DTR_CONTROL_ENABLE;
1888 case SP_DTR_FLOW_CONTROL:
1889 data->dcb.fDtrControl = DTR_CONTROL_HANDSHAKE;
1892 RETURN_ERROR(SP_ERR_ARG, "Invalid DTR setting");
1896 if (config->dsr >= 0) {
1897 switch (config->dsr) {
1899 data->dcb.fOutxDsrFlow = FALSE;
1901 case SP_DSR_FLOW_CONTROL:
1902 data->dcb.fOutxDsrFlow = TRUE;
1905 RETURN_ERROR(SP_ERR_ARG, "Invalid DSR setting");
1909 if (config->xon_xoff >= 0) {
1910 switch (config->xon_xoff) {
1911 case SP_XONXOFF_DISABLED:
1912 data->dcb.fInX = FALSE;
1913 data->dcb.fOutX = FALSE;
1916 data->dcb.fInX = TRUE;
1917 data->dcb.fOutX = FALSE;
1919 case SP_XONXOFF_OUT:
1920 data->dcb.fInX = FALSE;
1921 data->dcb.fOutX = TRUE;
1923 case SP_XONXOFF_INOUT:
1924 data->dcb.fInX = TRUE;
1925 data->dcb.fOutX = TRUE;
1928 RETURN_ERROR(SP_ERR_ARG, "Invalid XON/XOFF setting");
1932 if (!SetCommState(port->hdl, &data->dcb))
1933 RETURN_FAIL("SetCommState() failed");
1939 if (config->baudrate >= 0) {
1940 for (i = 0; i < NUM_STD_BAUDRATES; i++) {
1941 if (config->baudrate == std_baudrates[i].value) {
1942 if (cfsetospeed(&data->term, std_baudrates[i].index) < 0)
1943 RETURN_FAIL("cfsetospeed() failed");
1945 if (cfsetispeed(&data->term, std_baudrates[i].index) < 0)
1946 RETURN_FAIL("cfsetispeed() failed");
1951 /* Non-standard baud rate */
1952 if (i == NUM_STD_BAUDRATES) {
1954 /* Set "dummy" baud rate. */
1955 if (cfsetspeed(&data->term, B9600) < 0)
1956 RETURN_FAIL("cfsetspeed() failed");
1957 baud_nonstd = config->baudrate;
1958 #elif defined(__linux__)
1961 RETURN_ERROR(SP_ERR_SUPP, "Non-standard baudrate not supported");
1966 if (config->bits >= 0) {
1967 data->term.c_cflag &= ~CSIZE;
1968 switch (config->bits) {
1970 data->term.c_cflag |= CS8;
1973 data->term.c_cflag |= CS7;
1976 data->term.c_cflag |= CS6;
1979 data->term.c_cflag |= CS5;
1982 RETURN_ERROR(SP_ERR_ARG, "Invalid data bits setting");
1986 if (config->parity >= 0) {
1987 data->term.c_iflag &= ~IGNPAR;
1988 data->term.c_cflag &= ~(PARENB | PARODD);
1990 data->term.c_cflag &= ~CMSPAR;
1992 switch (config->parity) {
1993 case SP_PARITY_NONE:
1994 data->term.c_iflag |= IGNPAR;
1996 case SP_PARITY_EVEN:
1997 data->term.c_cflag |= PARENB;
2000 data->term.c_cflag |= PARENB | PARODD;
2003 case SP_PARITY_MARK:
2004 data->term.c_cflag |= PARENB | PARODD;
2005 data->term.c_cflag |= CMSPAR;
2007 case SP_PARITY_SPACE:
2008 data->term.c_cflag |= PARENB;
2009 data->term.c_cflag |= CMSPAR;
2012 case SP_PARITY_MARK:
2013 case SP_PARITY_SPACE:
2014 RETURN_ERROR(SP_ERR_SUPP, "Mark/space parity not supported");
2017 RETURN_ERROR(SP_ERR_ARG, "Invalid parity setting");
2021 if (config->stopbits >= 0) {
2022 data->term.c_cflag &= ~CSTOPB;
2023 switch (config->stopbits) {
2025 data->term.c_cflag &= ~CSTOPB;
2028 data->term.c_cflag |= CSTOPB;
2031 RETURN_ERROR(SP_ERR_ARG, "Invalid stop bits setting");
2035 if (config->rts >= 0 || config->cts >= 0) {
2036 if (data->termiox_supported) {
2037 data->rts_flow = data->cts_flow = 0;
2038 switch (config->rts) {
2041 controlbits = TIOCM_RTS;
2042 if (ioctl(port->fd, config->rts == SP_RTS_ON ? TIOCMBIS : TIOCMBIC, &controlbits) < 0)
2043 RETURN_FAIL("Setting RTS signal level failed");
2045 case SP_RTS_FLOW_CONTROL:
2051 if (config->cts == SP_CTS_FLOW_CONTROL)
2054 if (data->rts_flow && data->cts_flow)
2055 data->term.c_iflag |= CRTSCTS;
2057 data->term.c_iflag &= ~CRTSCTS;
2059 /* Asymmetric use of RTS/CTS not supported. */
2060 if (data->term.c_iflag & CRTSCTS) {
2061 /* Flow control can only be disabled for both RTS & CTS together. */
2062 if (config->rts >= 0 && config->rts != SP_RTS_FLOW_CONTROL) {
2063 if (config->cts != SP_CTS_IGNORE)
2064 RETURN_ERROR(SP_ERR_SUPP, "RTS & CTS flow control must be disabled together");
2066 if (config->cts >= 0 && config->cts != SP_CTS_FLOW_CONTROL) {
2067 if (config->rts <= 0 || config->rts == SP_RTS_FLOW_CONTROL)
2068 RETURN_ERROR(SP_ERR_SUPP, "RTS & CTS flow control must be disabled together");
2071 /* Flow control can only be enabled for both RTS & CTS together. */
2072 if (((config->rts == SP_RTS_FLOW_CONTROL) && (config->cts != SP_CTS_FLOW_CONTROL)) ||
2073 ((config->cts == SP_CTS_FLOW_CONTROL) && (config->rts != SP_RTS_FLOW_CONTROL)))
2074 RETURN_ERROR(SP_ERR_SUPP, "RTS & CTS flow control must be enabled together");
2077 if (config->rts >= 0) {
2078 if (config->rts == SP_RTS_FLOW_CONTROL) {
2079 data->term.c_iflag |= CRTSCTS;
2081 controlbits = TIOCM_RTS;
2082 if (ioctl(port->fd, config->rts == SP_RTS_ON ? TIOCMBIS : TIOCMBIC,
2084 RETURN_FAIL("Setting RTS signal level failed");
2090 if (config->dtr >= 0 || config->dsr >= 0) {
2091 if (data->termiox_supported) {
2092 data->dtr_flow = data->dsr_flow = 0;
2093 switch (config->dtr) {
2096 controlbits = TIOCM_DTR;
2097 if (ioctl(port->fd, config->dtr == SP_DTR_ON ? TIOCMBIS : TIOCMBIC, &controlbits) < 0)
2098 RETURN_FAIL("Setting DTR signal level failed");
2100 case SP_DTR_FLOW_CONTROL:
2106 if (config->dsr == SP_DSR_FLOW_CONTROL)
2109 /* DTR/DSR flow control not supported. */
2110 if (config->dtr == SP_DTR_FLOW_CONTROL || config->dsr == SP_DSR_FLOW_CONTROL)
2111 RETURN_ERROR(SP_ERR_SUPP, "DTR/DSR flow control not supported");
2113 if (config->dtr >= 0) {
2114 controlbits = TIOCM_DTR;
2115 if (ioctl(port->fd, config->dtr == SP_DTR_ON ? TIOCMBIS : TIOCMBIC,
2117 RETURN_FAIL("Setting DTR signal level failed");
2122 if (config->xon_xoff >= 0) {
2123 data->term.c_iflag &= ~(IXON | IXOFF | IXANY);
2124 switch (config->xon_xoff) {
2125 case SP_XONXOFF_DISABLED:
2128 data->term.c_iflag |= IXOFF;
2130 case SP_XONXOFF_OUT:
2131 data->term.c_iflag |= IXON | IXANY;
2133 case SP_XONXOFF_INOUT:
2134 data->term.c_iflag |= IXON | IXOFF | IXANY;
2137 RETURN_ERROR(SP_ERR_ARG, "Invalid XON/XOFF setting");
2141 if (tcsetattr(port->fd, TCSANOW, &data->term) < 0)
2142 RETURN_FAIL("tcsetattr() failed");
2145 if (baud_nonstd != B0) {
2146 if (ioctl(port->fd, IOSSIOSPEED, &baud_nonstd) == -1)
2147 RETURN_FAIL("IOSSIOSPEED ioctl failed");
2148 /* Set baud rates in data->term to correct, but incompatible
2149 * with tcsetattr() value, same as delivered by tcgetattr(). */
2150 if (cfsetspeed(&data->term, baud_nonstd) < 0)
2151 RETURN_FAIL("cfsetspeed() failed");
2153 #elif defined(__linux__)
2155 TRY(set_baudrate(port->fd, config->baudrate));
2157 if (data->termiox_supported)
2158 TRY(set_flow(port->fd, data));
2162 #endif /* !_WIN32 */
2167 enum sp_return sp_new_config(struct sp_port_config **config_ptr)
2169 struct sp_port_config *config;
2171 TRACE("%p", config_ptr);
2174 RETURN_ERROR(SP_ERR_ARG, "Null result pointer");
2178 if (!(config = malloc(sizeof(struct sp_port_config))))
2179 RETURN_ERROR(SP_ERR_MEM, "config malloc failed");
2181 config->baudrate = -1;
2183 config->parity = -1;
2184 config->stopbits = -1;
2190 *config_ptr = config;
2195 void sp_free_config(struct sp_port_config *config)
2197 TRACE("%p", config);
2200 DEBUG("Null config");
2207 enum sp_return sp_get_config(struct sp_port *port, struct sp_port_config *config)
2209 struct port_data data;
2211 TRACE("%p, %p", port, config);
2216 RETURN_ERROR(SP_ERR_ARG, "Null config");
2218 TRY(get_config(port, &data, config));
2223 enum sp_return sp_set_config(struct sp_port *port, const struct sp_port_config *config)
2225 struct port_data data;
2226 struct sp_port_config prev_config;
2228 TRACE("%p, %p", port, config);
2233 RETURN_ERROR(SP_ERR_ARG, "Null config");
2235 TRY(get_config(port, &data, &prev_config));
2236 TRY(set_config(port, &data, config));
2241 #define CREATE_ACCESSORS(x, type) \
2242 enum sp_return sp_set_##x(struct sp_port *port, type x) { \
2243 struct port_data data; \
2244 struct sp_port_config config; \
2245 TRACE("%p, %d", port, x); \
2246 CHECK_OPEN_PORT(); \
2247 TRY(get_config(port, &data, &config)); \
2249 TRY(set_config(port, &data, &config)); \
2252 enum sp_return sp_get_config_##x(const struct sp_port_config *config, type *x) { \
2253 TRACE("%p, %p", config, x); \
2255 RETURN_ERROR(SP_ERR_ARG, "Null config"); \
2259 enum sp_return sp_set_config_##x(struct sp_port_config *config, type x) { \
2260 TRACE("%p, %d", config, x); \
2262 RETURN_ERROR(SP_ERR_ARG, "Null config"); \
2267 CREATE_ACCESSORS(baudrate, int)
2268 CREATE_ACCESSORS(bits, int)
2269 CREATE_ACCESSORS(parity, enum sp_parity)
2270 CREATE_ACCESSORS(stopbits, int)
2271 CREATE_ACCESSORS(rts, enum sp_rts)
2272 CREATE_ACCESSORS(cts, enum sp_cts)
2273 CREATE_ACCESSORS(dtr, enum sp_dtr)
2274 CREATE_ACCESSORS(dsr, enum sp_dsr)
2275 CREATE_ACCESSORS(xon_xoff, enum sp_xonxoff)
2277 enum sp_return sp_set_config_flowcontrol(struct sp_port_config *config, enum sp_flowcontrol flowcontrol)
2280 RETURN_ERROR(SP_ERR_ARG, "Null configuration");
2282 if (flowcontrol > SP_FLOWCONTROL_DTRDSR)
2283 RETURN_ERROR(SP_ERR_ARG, "Invalid flow control setting");
2285 if (flowcontrol == SP_FLOWCONTROL_XONXOFF)
2286 config->xon_xoff = SP_XONXOFF_INOUT;
2288 config->xon_xoff = SP_XONXOFF_DISABLED;
2290 if (flowcontrol == SP_FLOWCONTROL_RTSCTS) {
2291 config->rts = SP_RTS_FLOW_CONTROL;
2292 config->cts = SP_CTS_FLOW_CONTROL;
2294 if (config->rts == SP_RTS_FLOW_CONTROL)
2295 config->rts = SP_RTS_ON;
2296 config->cts = SP_CTS_IGNORE;
2299 if (flowcontrol == SP_FLOWCONTROL_DTRDSR) {
2300 config->dtr = SP_DTR_FLOW_CONTROL;
2301 config->dsr = SP_DSR_FLOW_CONTROL;
2303 if (config->dtr == SP_DTR_FLOW_CONTROL)
2304 config->dtr = SP_DTR_ON;
2305 config->dsr = SP_DSR_IGNORE;
2311 enum sp_return sp_set_flowcontrol(struct sp_port *port, enum sp_flowcontrol flowcontrol)
2313 struct port_data data;
2314 struct sp_port_config config;
2316 TRACE("%p, %d", port, flowcontrol);
2320 TRY(get_config(port, &data, &config));
2322 TRY(sp_set_config_flowcontrol(&config, flowcontrol));
2324 TRY(set_config(port, &data, &config));
2329 enum sp_return sp_get_signals(struct sp_port *port, enum sp_signal *signals)
2331 TRACE("%p, %p", port, signals);
2336 RETURN_ERROR(SP_ERR_ARG, "Null result pointer");
2338 DEBUG("Getting control signals for port %s", port->name);
2343 if (GetCommModemStatus(port->hdl, &bits) == 0)
2344 RETURN_FAIL("GetCommModemStatus() failed");
2345 if (bits & MS_CTS_ON)
2346 *signals |= SP_SIG_CTS;
2347 if (bits & MS_DSR_ON)
2348 *signals |= SP_SIG_DSR;
2349 if (bits & MS_RLSD_ON)
2350 *signals |= SP_SIG_DCD;
2351 if (bits & MS_RING_ON)
2352 *signals |= SP_SIG_RI;
2355 if (ioctl(port->fd, TIOCMGET, &bits) < 0)
2356 RETURN_FAIL("TIOCMGET ioctl failed");
2357 if (bits & TIOCM_CTS)
2358 *signals |= SP_SIG_CTS;
2359 if (bits & TIOCM_DSR)
2360 *signals |= SP_SIG_DSR;
2361 if (bits & TIOCM_CAR)
2362 *signals |= SP_SIG_DCD;
2363 if (bits & TIOCM_RNG)
2364 *signals |= SP_SIG_RI;
2369 enum sp_return sp_start_break(struct sp_port *port)
2375 if (SetCommBreak(port->hdl) == 0)
2376 RETURN_FAIL("SetCommBreak() failed");
2378 if (ioctl(port->fd, TIOCSBRK, 1) < 0)
2379 RETURN_FAIL("TIOCSBRK ioctl failed");
2385 enum sp_return sp_end_break(struct sp_port *port)
2391 if (ClearCommBreak(port->hdl) == 0)
2392 RETURN_FAIL("ClearCommBreak() failed");
2394 if (ioctl(port->fd, TIOCCBRK, 1) < 0)
2395 RETURN_FAIL("TIOCCBRK ioctl failed");
2401 int sp_last_error_code(void)
2405 RETURN_VALUE("%d", GetLastError());
2407 RETURN_VALUE("%d", errno);
2411 char *sp_last_error_message(void)
2417 DWORD error = GetLastError();
2420 FORMAT_MESSAGE_ALLOCATE_BUFFER |
2421 FORMAT_MESSAGE_FROM_SYSTEM |
2422 FORMAT_MESSAGE_IGNORE_INSERTS,
2425 MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
2429 RETURN_VALUE("%s", message);
2431 RETURN_VALUE("%s", strerror(errno));
2435 void sp_free_error_message(char *message)
2437 TRACE("%s", message);
2448 void sp_set_debug_handler(void (*handler)(const char *format, ...))
2450 TRACE("%p", handler);
2452 sp_debug_handler = handler;
2457 void sp_default_debug_handler(const char *format, ...)
2460 va_start(args, format);
2461 if (getenv("LIBSERIALPORT_DEBUG")) {
2462 fputs("sp: ", stderr);
2463 vfprintf(stderr, format, args);