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 enum sp_return get_config(struct sp_port *port, struct port_data *data,
201 struct sp_port_config *config);
202 static enum sp_return set_config(struct sp_port *port, struct port_data *data,
203 const struct sp_port_config *config);
205 enum sp_return sp_get_port_by_name(const char *portname, struct sp_port **port_ptr)
207 struct sp_port *port;
210 TRACE("%s, %p", portname, port_ptr);
213 RETURN_ERROR(SP_ERR_ARG, "Null result pointer");
218 RETURN_ERROR(SP_ERR_ARG, "Null port name");
220 DEBUG("Building structure for port %s", portname);
222 if (!(port = malloc(sizeof(struct sp_port))))
223 RETURN_ERROR(SP_ERR_MEM, "Port structure malloc failed");
225 len = strlen(portname) + 1;
227 if (!(port->name = malloc(len))) {
229 RETURN_ERROR(SP_ERR_MEM, "Port name malloc failed");
232 memcpy(port->name, portname, len);
235 port->hdl = INVALID_HANDLE_VALUE;
245 char *sp_get_port_name(const struct sp_port *port)
252 RETURN_VALUE("%s", port->name);
255 enum sp_return sp_get_port_handle(const struct sp_port *port, void *result_ptr)
257 TRACE("%p, %p", port, result_ptr);
260 RETURN_ERROR(SP_ERR_ARG, "Null port");
263 HANDLE *handle_ptr = result_ptr;
264 *handle_ptr = port->hdl;
266 int *fd_ptr = result_ptr;
273 enum sp_return sp_copy_port(const struct sp_port *port, struct sp_port **copy_ptr)
275 TRACE("%p, %p", port, copy_ptr);
278 RETURN_ERROR(SP_ERR_ARG, "Null result pointer");
283 RETURN_ERROR(SP_ERR_ARG, "Null port");
286 RETURN_ERROR(SP_ERR_ARG, "Null port name");
288 DEBUG("Copying port structure");
290 RETURN_VALUE("%p", sp_get_port_by_name(port->name, copy_ptr));
293 void sp_free_port(struct sp_port *port)
302 DEBUG("Freeing port structure");
312 static struct sp_port **list_append(struct sp_port **list, const char *portname)
317 for (count = 0; list[count]; count++);
318 if (!(tmp = realloc(list, sizeof(struct sp_port *) * (count + 2))))
321 if (sp_get_port_by_name(portname, &list[count]) != SP_OK)
323 list[count + 1] = NULL;
327 sp_free_port_list(list);
331 enum sp_return sp_list_ports(struct sp_port ***list_ptr)
333 struct sp_port **list;
334 int ret = SP_ERR_SUPP;
336 TRACE("%p", list_ptr);
339 RETURN_ERROR(SP_ERR_ARG, "Null result pointer");
341 DEBUG("Enumerating ports");
343 if (!(list = malloc(sizeof(struct sp_port **))))
344 RETURN_ERROR(SP_ERR_MEM, "Port list malloc failed");
351 DWORD max_value_len, max_data_size, max_data_len;
352 DWORD value_len, data_size, data_len;
353 DWORD type, index = 0;
359 DEBUG("Opening registry key");
360 if (RegOpenKeyEx(HKEY_LOCAL_MACHINE, _T("HARDWARE\\DEVICEMAP\\SERIALCOMM"),
361 0, KEY_QUERY_VALUE, &key) != ERROR_SUCCESS) {
362 SET_FAIL(ret, "RegOpenKeyEx() failed");
365 DEBUG("Querying registry key value and data sizes");
366 if (RegQueryInfoKey(key, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
367 &max_value_len, &max_data_size, NULL, NULL) != ERROR_SUCCESS) {
368 SET_FAIL(ret, "RegQueryInfoKey() failed");
371 max_data_len = max_data_size / sizeof(TCHAR);
372 if (!(value = malloc((max_value_len + 1) * sizeof(TCHAR)))) {
373 SET_ERROR(ret, SP_ERR_MEM, "registry value malloc failed");
376 if (!(data = malloc((max_data_len + 1) * sizeof(TCHAR)))) {
377 SET_ERROR(ret, SP_ERR_MEM, "registry data malloc failed");
380 DEBUG("Iterating over values");
382 value_len = max_value_len + 1,
383 data_size = max_data_size,
384 RegEnumValue(key, index, value, &value_len,
385 NULL, &type, (LPBYTE)data, &data_size) == ERROR_SUCCESS)
387 data_len = data_size / sizeof(TCHAR);
388 data[data_len] = '\0';
390 name_len = WideCharToMultiByte(CP_ACP, 0, data, -1, NULL, 0, NULL, NULL);
392 name_len = data_len + 1;
394 if (!(name = malloc(name_len))) {
395 SET_ERROR(ret, SP_ERR_MEM, "registry port name malloc failed");
399 WideCharToMultiByte(CP_ACP, 0, data, -1, name, name_len, NULL, NULL);
403 if (type == REG_SZ) {
404 DEBUG("Found port %s", name);
405 if (!(list = list_append(list, name))) {
406 SET_ERROR(ret, SP_ERR_MEM, "list append failed");
421 CFMutableDictionaryRef classes;
430 DEBUG("Creating matching dictionary");
431 if (!(classes = IOServiceMatching(kIOSerialBSDServiceValue))) {
432 SET_FAIL(ret, "IOServiceMatching() failed");
436 DEBUG("Getting matching services");
437 if (IOServiceGetMatchingServices(kIOMasterPortDefault, classes,
438 &iter) != KERN_SUCCESS) {
439 SET_FAIL(ret, "IOServiceGetMatchingServices() failed");
443 DEBUG("Iterating over results");
444 while ((port = IOIteratorNext(iter))) {
445 cf_path = IORegistryEntryCreateCFProperty(port,
446 CFSTR(kIOCalloutDeviceKey), kCFAllocatorDefault, 0);
448 result = CFStringGetCString(cf_path, path, sizeof(path),
449 kCFStringEncodingASCII);
452 DEBUG("Found port %s", path);
453 if (!(list = list_append(list, path))) {
454 SET_ERROR(ret, SP_ERR_MEM, "list append failed");
455 IOObjectRelease(port);
460 IOObjectRelease(port);
463 IOObjectRelease(iter);
466 #if defined(__linux__) && defined(HAVE_LIBUDEV)
468 struct udev_enumerate *ud_enumerate;
469 struct udev_list_entry *ud_list;
470 struct udev_list_entry *ud_entry;
472 struct udev_device *ud_dev, *ud_parent;
475 int fd, ioctl_result;
476 struct serial_struct serial_info;
480 DEBUG("Enumerating tty devices");
482 ud_enumerate = udev_enumerate_new(ud);
483 udev_enumerate_add_match_subsystem(ud_enumerate, "tty");
484 udev_enumerate_scan_devices(ud_enumerate);
485 ud_list = udev_enumerate_get_list_entry(ud_enumerate);
486 DEBUG("Iterating over results");
487 udev_list_entry_foreach(ud_entry, ud_list) {
488 path = udev_list_entry_get_name(ud_entry);
489 DEBUG("Found device %s", path);
490 ud_dev = udev_device_new_from_syspath(ud, path);
491 /* If there is no parent device, this is a virtual tty. */
492 ud_parent = udev_device_get_parent(ud_dev);
493 if (ud_parent == NULL) {
494 DEBUG("No parent device, assuming virtual tty");
495 udev_device_unref(ud_dev);
498 name = udev_device_get_devnode(ud_dev);
499 /* The serial8250 driver has a hardcoded number of ports.
500 * The only way to tell which actually exist on a given system
501 * is to try to open them and make an ioctl call. */
502 driver = udev_device_get_driver(ud_parent);
503 if (driver && !strcmp(driver, "serial8250")) {
504 DEBUG("serial8250 device, attempting to open");
505 if ((fd = open(name, O_RDWR | O_NONBLOCK | O_NOCTTY)) < 0) {
506 DEBUG("open failed, skipping");
509 ioctl_result = ioctl(fd, TIOCGSERIAL, &serial_info);
511 if (ioctl_result != 0) {
512 DEBUG("ioctl failed, skipping");
515 if (serial_info.type == PORT_UNKNOWN) {
516 DEBUG("port type is unknown, skipping");
520 DEBUG("Found port %s", name);
521 list = list_append(list, name);
523 udev_device_unref(ud_dev);
525 SET_ERROR(ret, SP_ERR_MEM, "list append failed");
530 udev_enumerate_unref(ud_enumerate);
539 DEBUG_ERROR(SP_ERR_SUPP, "Enumeration not supported on this platform");
542 sp_free_port_list(list);
548 void sp_free_port_list(struct sp_port **list)
559 DEBUG("Freeing port list");
561 for (i = 0; list[i]; i++)
562 sp_free_port(list[i]);
568 #define CHECK_PORT() do { \
570 RETURN_ERROR(SP_ERR_ARG, "Null port"); \
571 if (port->name == NULL) \
572 RETURN_ERROR(SP_ERR_ARG, "Null port name"); \
575 #define CHECK_PORT_HANDLE() do { \
576 if (port->hdl == INVALID_HANDLE_VALUE) \
577 RETURN_ERROR(SP_ERR_ARG, "Invalid port handle"); \
580 #define CHECK_PORT_HANDLE() do { \
582 RETURN_ERROR(SP_ERR_ARG, "Invalid port fd"); \
585 #define CHECK_OPEN_PORT() do { \
587 CHECK_PORT_HANDLE(); \
590 enum sp_return sp_open(struct sp_port *port, enum sp_mode flags)
592 struct port_data data;
593 struct sp_port_config config;
596 TRACE("%p, 0x%x", port, flags);
600 if (flags > (SP_MODE_READ | SP_MODE_WRITE))
601 RETURN_ERROR(SP_ERR_ARG, "Invalid flags");
603 DEBUG("Opening port %s", port->name);
606 DWORD desired_access = 0, flags_and_attributes = 0, errors;
607 char *escaped_port_name;
610 /* Prefix port name with '\\.\' to work with ports above COM9. */
611 if (!(escaped_port_name = malloc(strlen(port->name) + 5)))
612 RETURN_ERROR(SP_ERR_MEM, "Escaped port name malloc failed");
613 sprintf(escaped_port_name, "\\\\.\\%s", port->name);
615 /* Map 'flags' to the OS-specific settings. */
616 flags_and_attributes = FILE_ATTRIBUTE_NORMAL | FILE_FLAG_OVERLAPPED;
617 if (flags & SP_MODE_READ)
618 desired_access |= GENERIC_READ;
619 if (flags & SP_MODE_WRITE)
620 desired_access |= GENERIC_WRITE;
622 port->hdl = CreateFile(escaped_port_name, desired_access, 0, 0,
623 OPEN_EXISTING, flags_and_attributes, 0);
625 free(escaped_port_name);
627 if (port->hdl == INVALID_HANDLE_VALUE)
628 RETURN_FAIL("port CreateFile() failed");
630 /* All timeouts initially disabled. */
631 port->timeouts.ReadIntervalTimeout = 0;
632 port->timeouts.ReadTotalTimeoutMultiplier = 0;
633 port->timeouts.ReadTotalTimeoutConstant = 0;
634 port->timeouts.WriteTotalTimeoutMultiplier = 0;
635 port->timeouts.WriteTotalTimeoutConstant = 0;
637 if (SetCommTimeouts(port->hdl, &port->timeouts) == 0) {
639 RETURN_FAIL("SetCommTimeouts() failed");
642 /* Prepare OVERLAPPED structures. */
643 #define INIT_OVERLAPPED(ovl) do { \
644 memset(&port->ovl, 0, sizeof(port->ovl)); \
645 port->ovl.hEvent = INVALID_HANDLE_VALUE; \
646 if ((port->ovl.hEvent = CreateEvent(NULL, TRUE, TRUE, NULL)) \
647 == INVALID_HANDLE_VALUE) { \
649 RETURN_FAIL(#ovl "CreateEvent() failed"); \
653 INIT_OVERLAPPED(read_ovl);
654 INIT_OVERLAPPED(write_ovl);
655 INIT_OVERLAPPED(wait_ovl);
657 /* Set event mask for RX and error events. */
658 if (SetCommMask(port->hdl, EV_RXCHAR | EV_ERR) == 0) {
660 RETURN_FAIL("SetCommMask() failed");
663 /* Start background operation for RX and error events. */
664 if (WaitCommEvent(port->hdl, &port->events, &port->wait_ovl) == 0) {
665 if (GetLastError() != ERROR_IO_PENDING) {
667 RETURN_FAIL("WaitCommEvent() failed");
671 port->writing = FALSE;
674 int flags_local = O_NONBLOCK | O_NOCTTY;
676 /* Map 'flags' to the OS-specific settings. */
677 if (flags & (SP_MODE_READ | SP_MODE_WRITE))
678 flags_local |= O_RDWR;
679 else if (flags & SP_MODE_READ)
680 flags_local |= O_RDONLY;
681 else if (flags & SP_MODE_WRITE)
682 flags_local |= O_WRONLY;
684 if ((port->fd = open(port->name, flags_local)) < 0)
685 RETURN_FAIL("open() failed");
688 ret = get_config(port, &data, &config);
695 /* Set sane port settings. */
697 data.dcb.fBinary = TRUE;
698 data.dcb.fDsrSensitivity = FALSE;
699 data.dcb.fErrorChar = FALSE;
700 data.dcb.fNull = FALSE;
701 data.dcb.fAbortOnError = TRUE;
703 /* Turn off all fancy termios tricks, give us a raw channel. */
704 data.term.c_iflag &= ~(IGNBRK | BRKINT | PARMRK | ISTRIP | INLCR | IGNCR | ICRNL | IMAXBEL);
706 data.term.c_iflag &= ~IUCLC;
708 data.term.c_oflag &= ~(OPOST | ONLCR | OCRNL | ONOCR | ONLRET);
710 data.term.c_oflag &= ~OLCUC;
713 data.term.c_oflag &= ~NLDLY;
716 data.term.c_oflag &= ~CRDLY;
719 data.term.c_oflag &= ~TABDLY;
722 data.term.c_oflag &= ~BSDLY;
725 data.term.c_oflag &= ~VTDLY;
728 data.term.c_oflag &= ~FFDLY;
731 data.term.c_oflag &= ~OFILL;
733 data.term.c_lflag &= ~(ISIG | ICANON | ECHO | IEXTEN);
734 data.term.c_cc[VMIN] = 0;
735 data.term.c_cc[VTIME] = 0;
737 /* Ignore modem status lines; enable receiver; leave control lines alone on close. */
738 data.term.c_cflag |= (CLOCAL | CREAD | HUPCL);
742 if (ClearCommError(port->hdl, &errors, &status) == 0)
743 RETURN_FAIL("ClearCommError() failed");
746 ret = set_config(port, &data, &config);
756 enum sp_return sp_close(struct sp_port *port)
762 DEBUG("Closing port %s", port->name);
765 /* Returns non-zero upon success, 0 upon failure. */
766 if (CloseHandle(port->hdl) == 0)
767 RETURN_FAIL("port CloseHandle() failed");
768 port->hdl = INVALID_HANDLE_VALUE;
770 /* Close event handles for overlapped structures. */
771 #define CLOSE_OVERLAPPED(ovl) do { \
772 if (port->ovl.hEvent != INVALID_HANDLE_VALUE && \
773 CloseHandle(port->ovl.hEvent) == 0) \
774 RETURN_FAIL(# ovl "event CloseHandle() failed"); \
776 CLOSE_OVERLAPPED(read_ovl);
777 CLOSE_OVERLAPPED(write_ovl);
778 CLOSE_OVERLAPPED(wait_ovl);
781 /* Returns 0 upon success, -1 upon failure. */
782 if (close(port->fd) == -1)
783 RETURN_FAIL("close() failed");
790 enum sp_return sp_flush(struct sp_port *port, enum sp_buffer buffers)
792 TRACE("%p, 0x%x", port, buffers);
796 if (buffers > SP_BUF_BOTH)
797 RETURN_ERROR(SP_ERR_ARG, "Invalid buffer selection");
799 const char *buffer_names[] = {"no", "input", "output", "both"};
801 DEBUG("Flushing %s buffers on port %s", buffer_names[buffers], port->name);
805 if (buffers & SP_BUF_INPUT)
806 flags |= PURGE_RXCLEAR;
807 if (buffers & SP_BUF_OUTPUT)
808 flags |= PURGE_TXCLEAR;
810 /* Returns non-zero upon success, 0 upon failure. */
811 if (PurgeComm(port->hdl, flags) == 0)
812 RETURN_FAIL("PurgeComm() failed");
815 if (buffers & SP_BUF_BOTH)
817 else if (buffers & SP_BUF_INPUT)
819 else if (buffers & SP_BUF_OUTPUT)
822 /* Returns 0 upon success, -1 upon failure. */
823 if (tcflush(port->fd, flags) < 0)
824 RETURN_FAIL("tcflush() failed");
829 enum sp_return sp_drain(struct sp_port *port)
835 DEBUG("Draining port %s", port->name);
838 /* Returns non-zero upon success, 0 upon failure. */
839 if (FlushFileBuffers(port->hdl) == 0)
840 RETURN_FAIL("FlushFileBuffers() failed");
847 result = ioctl(port->fd, TCSBRK, &arg);
849 result = tcdrain(port->fd);
852 if (errno == EINTR) {
853 DEBUG("tcdrain() was interrupted");
856 RETURN_FAIL("tcdrain() failed");
865 enum sp_return sp_blocking_write(struct sp_port *port, const void *buf, size_t count, unsigned int timeout)
867 TRACE("%p, %p, %d, %d", port, buf, count, timeout);
872 RETURN_ERROR(SP_ERR_ARG, "Null buffer");
875 DEBUG("Writing %d bytes to port %s, timeout %d ms", count, port->name, timeout);
877 DEBUG("Writing %d bytes to port %s, no timeout", count, port->name);
880 RETURN_VALUE("0", 0);
883 DWORD bytes_written = 0;
886 /* Wait for previous non-blocking write to complete, if any. */
888 DEBUG("Waiting for previous write to complete");
889 result = GetOverlappedResult(port->hdl, &port->write_ovl, &bytes_written, TRUE);
892 RETURN_FAIL("Previous write failed to complete");
893 DEBUG("Previous write completed");
897 port->timeouts.WriteTotalTimeoutConstant = timeout;
898 if (SetCommTimeouts(port->hdl, &port->timeouts) == 0)
899 RETURN_FAIL("SetCommTimeouts() failed");
902 if (WriteFile(port->hdl, buf, count, NULL, &port->write_ovl) == 0) {
903 if (GetLastError() == ERROR_IO_PENDING) {
904 DEBUG("Waiting for write to complete");
905 GetOverlappedResult(port->hdl, &port->write_ovl, &bytes_written, TRUE);
906 DEBUG("Write completed, %d/%d bytes written", bytes_written, count);
907 RETURN_VALUE("%d", bytes_written);
909 RETURN_FAIL("WriteFile() failed");
912 DEBUG("Write completed immediately");
913 RETURN_VALUE("%d", count);
916 size_t bytes_written = 0;
917 unsigned char *ptr = (unsigned char *) buf;
918 struct timeval start, delta, now, end = {0, 0};
923 /* Get time at start of operation. */
924 gettimeofday(&start, NULL);
925 /* Define duration of timeout. */
926 delta.tv_sec = timeout / 1000;
927 delta.tv_usec = (timeout % 1000) * 1000;
928 /* Calculate time at which we should give up. */
929 timeradd(&start, &delta, &end);
932 /* Loop until we have written the requested number of bytes. */
933 while (bytes_written < count)
935 /* Wait until space is available. */
937 FD_SET(port->fd, &fds);
939 gettimeofday(&now, NULL);
940 if (timercmp(&now, &end, >)) {
941 DEBUG("write timed out");
942 RETURN_VALUE("%d", bytes_written);
944 timersub(&end, &now, &delta);
946 result = select(port->fd + 1, NULL, &fds, NULL, timeout ? &delta : NULL);
948 if (errno == EINTR) {
949 DEBUG("select() call was interrupted, repeating");
952 RETURN_FAIL("select() failed");
954 } else if (result == 0) {
955 DEBUG("write timed out");
956 RETURN_VALUE("%d", bytes_written);
960 result = write(port->fd, ptr, count - bytes_written);
964 /* This shouldn't happen because we did a select() first, but handle anyway. */
967 /* This is an actual failure. */
968 RETURN_FAIL("write() failed");
971 bytes_written += result;
975 RETURN_VALUE("%d", bytes_written);
979 enum sp_return sp_nonblocking_write(struct sp_port *port, const void *buf, size_t count)
981 TRACE("%p, %p, %d", port, buf, count);
986 RETURN_ERROR(SP_ERR_ARG, "Null buffer");
988 DEBUG("Writing up to %d bytes to port %s", count, port->name);
991 RETURN_VALUE("0", 0);
995 BYTE *ptr = (BYTE *) buf;
997 /* Check whether previous write is complete. */
999 if (HasOverlappedIoCompleted(&port->write_ovl)) {
1000 DEBUG("Previous write completed");
1003 DEBUG("Previous write not complete");
1004 /* Can't take a new write until the previous one finishes. */
1005 RETURN_VALUE("0", 0);
1010 port->timeouts.WriteTotalTimeoutConstant = 0;
1011 if (SetCommTimeouts(port->hdl, &port->timeouts) == 0)
1012 RETURN_FAIL("SetCommTimeouts() failed");
1014 /* Keep writing data until the OS has to actually start an async IO for it.
1015 * At that point we know the buffer is full. */
1016 while (written < count)
1018 /* Copy first byte of user buffer. */
1019 port->pending_byte = *ptr++;
1021 /* Start asynchronous write. */
1022 if (WriteFile(port->hdl, &port->pending_byte, 1, NULL, &port->write_ovl) == 0) {
1023 if (GetLastError() == ERROR_IO_PENDING) {
1024 if (HasOverlappedIoCompleted(&port->write_ovl)) {
1025 DEBUG("Asynchronous write completed immediately");
1030 DEBUG("Asynchronous write running");
1032 RETURN_VALUE("%d", ++written);
1035 /* Actual failure of some kind. */
1036 RETURN_FAIL("WriteFile() failed");
1039 DEBUG("Single byte written immediately");
1044 DEBUG("All bytes written immediately");
1046 RETURN_VALUE("%d", written);
1048 /* Returns the number of bytes written, or -1 upon failure. */
1049 ssize_t written = write(port->fd, buf, count);
1052 RETURN_FAIL("write() failed");
1054 RETURN_VALUE("%d", written);
1058 enum sp_return sp_blocking_read(struct sp_port *port, void *buf, size_t count, unsigned int timeout)
1060 TRACE("%p, %p, %d, %d", port, buf, count, timeout);
1065 RETURN_ERROR(SP_ERR_ARG, "Null buffer");
1068 DEBUG("Reading %d bytes from port %s, timeout %d ms", count, port->name, timeout);
1070 DEBUG("Reading %d bytes from port %s, no timeout", count, port->name);
1073 RETURN_VALUE("0", 0);
1076 DWORD bytes_read = 0;
1079 port->timeouts.ReadIntervalTimeout = 0;
1080 port->timeouts.ReadTotalTimeoutConstant = timeout;
1081 if (SetCommTimeouts(port->hdl, &port->timeouts) == 0)
1082 RETURN_FAIL("SetCommTimeouts() failed");
1085 if (ReadFile(port->hdl, buf, count, NULL, &port->read_ovl) == 0) {
1086 if (GetLastError() == ERROR_IO_PENDING) {
1087 DEBUG("Waiting for read to complete");
1088 GetOverlappedResult(port->hdl, &port->read_ovl, &bytes_read, TRUE);
1089 DEBUG("Read completed, %d/%d bytes read", bytes_read, count);
1091 RETURN_FAIL("ReadFile() failed");
1094 DEBUG("Read completed immediately");
1098 /* Start background operation for subsequent events. */
1099 if (WaitCommEvent(port->hdl, &port->events, &port->wait_ovl) == 0) {
1100 if (GetLastError() != ERROR_IO_PENDING)
1101 RETURN_FAIL("WaitCommEvent() failed");
1104 RETURN_VALUE("%d", bytes_read);
1107 size_t bytes_read = 0;
1108 unsigned char *ptr = (unsigned char *) buf;
1109 struct timeval start, delta, now, end = {0, 0};
1114 /* Get time at start of operation. */
1115 gettimeofday(&start, NULL);
1116 /* Define duration of timeout. */
1117 delta.tv_sec = timeout / 1000;
1118 delta.tv_usec = (timeout % 1000) * 1000;
1119 /* Calculate time at which we should give up. */
1120 timeradd(&start, &delta, &end);
1123 /* Loop until we have the requested number of bytes. */
1124 while (bytes_read < count)
1126 /* Wait until data is available. */
1128 FD_SET(port->fd, &fds);
1130 gettimeofday(&now, NULL);
1131 if (timercmp(&now, &end, >))
1132 /* Timeout has expired. */
1133 RETURN_VALUE("%d", bytes_read);
1134 timersub(&end, &now, &delta);
1136 result = select(port->fd + 1, &fds, NULL, NULL, timeout ? &delta : NULL);
1138 if (errno == EINTR) {
1139 DEBUG("select() call was interrupted, repeating");
1142 RETURN_FAIL("select() failed");
1144 } else if (result == 0) {
1145 DEBUG("read timed out");
1146 RETURN_VALUE("%d", bytes_read);
1150 result = read(port->fd, ptr, count - bytes_read);
1153 if (errno == EAGAIN)
1154 /* This shouldn't happen because we did a select() first, but handle anyway. */
1157 /* This is an actual failure. */
1158 RETURN_FAIL("read() failed");
1161 bytes_read += result;
1165 RETURN_VALUE("%d", bytes_read);
1169 enum sp_return sp_nonblocking_read(struct sp_port *port, void *buf, size_t count)
1171 TRACE("%p, %p, %d", port, buf, count);
1176 RETURN_ERROR(SP_ERR_ARG, "Null buffer");
1178 DEBUG("Reading up to %d bytes from port %s", count, port->name);
1184 port->timeouts.ReadIntervalTimeout = MAXDWORD;
1185 port->timeouts.ReadTotalTimeoutConstant = 0;
1186 if (SetCommTimeouts(port->hdl, &port->timeouts) == 0)
1187 RETURN_FAIL("SetCommTimeouts() failed");
1190 if (ReadFile(port->hdl, buf, count, NULL, &port->read_ovl) == 0)
1191 RETURN_FAIL("ReadFile() failed");
1193 /* Get number of bytes read. */
1194 if (GetOverlappedResult(port->hdl, &port->read_ovl, &bytes_read, TRUE) == 0)
1195 RETURN_FAIL("GetOverlappedResult() failed");
1197 if (bytes_read > 0) {
1198 /* Start background operation for subsequent events. */
1199 if (WaitCommEvent(port->hdl, &port->events, &port->wait_ovl) == 0) {
1200 if (GetLastError() != ERROR_IO_PENDING)
1201 RETURN_FAIL("WaitCommEvent() failed");
1205 RETURN_VALUE("%d", bytes_read);
1209 /* Returns the number of bytes read, or -1 upon failure. */
1210 if ((bytes_read = read(port->fd, buf, count)) < 0) {
1211 if (errno == EAGAIN)
1212 /* No bytes available. */
1215 /* This is an actual failure. */
1216 RETURN_FAIL("read() failed");
1218 RETURN_VALUE("%d", bytes_read);
1222 enum sp_return sp_input_waiting(struct sp_port *port)
1228 DEBUG("Checking input bytes waiting on port %s", port->name);
1234 if (ClearCommError(port->hdl, &errors, &comstat) == 0)
1235 RETURN_FAIL("ClearCommError() failed");
1236 RETURN_VALUE("%d", comstat.cbInQue);
1239 if (ioctl(port->fd, TIOCINQ, &bytes_waiting) < 0)
1240 RETURN_FAIL("TIOCINQ ioctl failed");
1241 RETURN_VALUE("%d", bytes_waiting);
1245 enum sp_return sp_output_waiting(struct sp_port *port)
1251 DEBUG("Checking output bytes waiting on port %s", port->name);
1257 if (ClearCommError(port->hdl, &errors, &comstat) == 0)
1258 RETURN_FAIL("ClearCommError() failed");
1259 RETURN_VALUE("%d", comstat.cbOutQue);
1262 if (ioctl(port->fd, TIOCOUTQ, &bytes_waiting) < 0)
1263 RETURN_FAIL("TIOCOUTQ ioctl failed");
1264 RETURN_VALUE("%d", bytes_waiting);
1268 enum sp_return sp_new_event_set(struct sp_event_set **result_ptr)
1270 struct sp_event_set *result;
1272 TRACE("%p", result_ptr);
1275 RETURN_ERROR(SP_ERR_ARG, "Null result");
1279 if (!(result = malloc(sizeof(struct sp_event_set))))
1280 RETURN_ERROR(SP_ERR_MEM, "sp_event_set malloc() failed");
1282 memset(result, 0, sizeof(struct sp_event_set));
1284 *result_ptr = result;
1289 static enum sp_return add_handle(struct sp_event_set *event_set,
1290 event_handle handle, enum sp_event mask)
1293 enum sp_event *new_masks;
1295 TRACE("%p, %d, %d", event_set, handle, mask);
1297 if (!(new_handles = realloc(event_set->handles,
1298 sizeof(event_handle) * (event_set->count + 1))))
1299 RETURN_ERROR(SP_ERR_MEM, "handle array realloc() failed");
1301 if (!(new_masks = realloc(event_set->masks,
1302 sizeof(enum sp_event) * (event_set->count + 1))))
1303 RETURN_ERROR(SP_ERR_MEM, "mask array realloc() failed");
1305 event_set->handles = new_handles;
1306 event_set->masks = new_masks;
1308 ((event_handle *) event_set->handles)[event_set->count] = handle;
1309 event_set->masks[event_set->count] = mask;
1316 enum sp_return sp_add_port_events(struct sp_event_set *event_set,
1317 const struct sp_port *port, enum sp_event mask)
1319 TRACE("%p, %p, %d", event_set, port, mask);
1322 RETURN_ERROR(SP_ERR_ARG, "Null event set");
1325 RETURN_ERROR(SP_ERR_ARG, "Null port");
1327 if (mask > (SP_EVENT_RX_READY | SP_EVENT_TX_READY | SP_EVENT_ERROR))
1328 RETURN_ERROR(SP_ERR_ARG, "Invalid event mask");
1334 enum sp_event handle_mask;
1335 if ((handle_mask = mask & SP_EVENT_TX_READY))
1336 TRY(add_handle(event_set, port->write_ovl.hEvent, handle_mask));
1337 if ((handle_mask = mask & (SP_EVENT_RX_READY | SP_EVENT_ERROR)))
1338 TRY(add_handle(event_set, port->wait_ovl.hEvent, handle_mask));
1340 TRY(add_handle(event_set, port->fd, mask));
1346 void sp_free_event_set(struct sp_event_set *event_set)
1348 TRACE("%p", event_set);
1351 DEBUG("Null event set");
1355 DEBUG("Freeing event set");
1357 if (event_set->handles)
1358 free(event_set->handles);
1359 if (event_set->masks)
1360 free(event_set->masks);
1367 enum sp_return sp_wait(struct sp_event_set *event_set, unsigned int timeout)
1369 TRACE("%p, %d", event_set, timeout);
1372 RETURN_ERROR(SP_ERR_ARG, "Null event set");
1375 if (WaitForMultipleObjects(event_set->count, event_set->handles, FALSE,
1376 timeout ? timeout : INFINITE) == WAIT_FAILED)
1377 RETURN_FAIL("WaitForMultipleObjects() failed");
1381 struct timeval start, delta, now, end = {0, 0};
1382 int result, timeout_remaining;
1383 struct pollfd *pollfds;
1386 if (!(pollfds = malloc(sizeof(struct pollfd) * event_set->count)))
1387 RETURN_ERROR(SP_ERR_MEM, "pollfds malloc() failed");
1389 for (i = 0; i < event_set->count; i++) {
1390 pollfds[i].fd = ((int *) event_set->handles)[i];
1391 pollfds[i].events = 0;
1392 pollfds[i].revents = 0;
1393 if (event_set->masks[i] & SP_EVENT_RX_READY)
1394 pollfds[i].events |= POLLIN;
1395 if (event_set->masks[i] & SP_EVENT_TX_READY)
1396 pollfds[i].events |= POLLOUT;
1397 if (event_set->masks[i] & SP_EVENT_ERROR)
1398 pollfds[i].events |= POLLERR;
1402 /* Get time at start of operation. */
1403 gettimeofday(&start, NULL);
1404 /* Define duration of timeout. */
1405 delta.tv_sec = timeout / 1000;
1406 delta.tv_usec = (timeout % 1000) * 1000;
1407 /* Calculate time at which we should give up. */
1408 timeradd(&start, &delta, &end);
1411 /* Loop until an event occurs. */
1415 gettimeofday(&now, NULL);
1416 if (timercmp(&now, &end, >)) {
1417 DEBUG("wait timed out");
1420 timersub(&end, &now, &delta);
1421 timeout_remaining = delta.tv_sec * 1000 + delta.tv_usec / 1000;
1424 result = poll(pollfds, event_set->count, timeout ? timeout_remaining : -1);
1427 if (errno == EINTR) {
1428 DEBUG("poll() call was interrupted, repeating");
1432 RETURN_FAIL("poll() failed");
1434 } else if (result == 0) {
1435 DEBUG("poll() timed out");
1438 DEBUG("poll() completed");
1448 #ifdef USE_TERMIOS_SPEED
1449 static enum sp_return get_baudrate(int fd, int *baudrate)
1453 TRACE("%d, %p", fd, baudrate);
1455 DEBUG("Getting baud rate");
1457 if (!(data = malloc(get_termios_size())))
1458 RETURN_ERROR(SP_ERR_MEM, "termios malloc failed");
1460 if (ioctl(fd, get_termios_get_ioctl(), data) < 0) {
1462 RETURN_FAIL("getting termios failed");
1465 *baudrate = get_termios_speed(data);
1472 static enum sp_return set_baudrate(int fd, int baudrate)
1476 TRACE("%d, %d", fd, baudrate);
1478 DEBUG("Getting baud rate");
1480 if (!(data = malloc(get_termios_size())))
1481 RETURN_ERROR(SP_ERR_MEM, "termios malloc failed");
1483 if (ioctl(fd, get_termios_get_ioctl(), data) < 0) {
1485 RETURN_FAIL("getting termios failed");
1488 DEBUG("Setting baud rate");
1490 set_termios_speed(data, baudrate);
1492 if (ioctl(fd, get_termios_set_ioctl(), data) < 0) {
1494 RETURN_FAIL("setting termios failed");
1501 #endif /* USE_TERMIOS_SPEED */
1504 static enum sp_return get_flow(int fd, struct port_data *data)
1508 TRACE("%d, %p", fd, data);
1510 DEBUG("Getting advanced flow control");
1512 if (!(termx = malloc(get_termiox_size())))
1513 RETURN_ERROR(SP_ERR_MEM, "termiox malloc failed");
1515 if (ioctl(fd, TCGETX, termx) < 0) {
1517 RETURN_FAIL("getting termiox failed");
1520 get_termiox_flow(termx, &data->rts_flow, &data->cts_flow,
1521 &data->dtr_flow, &data->dsr_flow);
1528 static enum sp_return set_flow(int fd, struct port_data *data)
1532 TRACE("%d, %p", fd, data);
1534 DEBUG("Getting advanced flow control");
1536 if (!(termx = malloc(get_termiox_size())))
1537 RETURN_ERROR(SP_ERR_MEM, "termiox malloc failed");
1539 if (ioctl(fd, TCGETX, termx) < 0) {
1541 RETURN_FAIL("getting termiox failed");
1544 DEBUG("Setting advanced flow control");
1546 set_termiox_flow(termx, data->rts_flow, data->cts_flow,
1547 data->dtr_flow, data->dsr_flow);
1549 if (ioctl(fd, TCSETX, termx) < 0) {
1551 RETURN_FAIL("setting termiox failed");
1558 #endif /* USE_TERMIOX */
1560 static enum sp_return get_config(struct sp_port *port, struct port_data *data,
1561 struct sp_port_config *config)
1565 TRACE("%p, %p, %p", port, data, config);
1567 DEBUG("Getting configuration for port %s", port->name);
1570 if (!GetCommState(port->hdl, &data->dcb))
1571 RETURN_FAIL("GetCommState() failed");
1573 for (i = 0; i < NUM_STD_BAUDRATES; i++) {
1574 if (data->dcb.BaudRate == std_baudrates[i].index) {
1575 config->baudrate = std_baudrates[i].value;
1580 if (i == NUM_STD_BAUDRATES)
1581 /* BaudRate field can be either an index or a custom baud rate. */
1582 config->baudrate = data->dcb.BaudRate;
1584 config->bits = data->dcb.ByteSize;
1586 if (data->dcb.fParity)
1587 switch (data->dcb.Parity) {
1589 config->parity = SP_PARITY_NONE;
1592 config->parity = SP_PARITY_ODD;
1595 config->parity = SP_PARITY_EVEN;
1598 config->parity = SP_PARITY_MARK;
1601 config->parity = SP_PARITY_SPACE;
1604 config->parity = -1;
1607 config->parity = SP_PARITY_NONE;
1609 switch (data->dcb.StopBits) {
1611 config->stopbits = 1;
1614 config->stopbits = 2;
1617 config->stopbits = -1;
1620 switch (data->dcb.fRtsControl) {
1621 case RTS_CONTROL_DISABLE:
1622 config->rts = SP_RTS_OFF;
1624 case RTS_CONTROL_ENABLE:
1625 config->rts = SP_RTS_ON;
1627 case RTS_CONTROL_HANDSHAKE:
1628 config->rts = SP_RTS_FLOW_CONTROL;
1634 config->cts = data->dcb.fOutxCtsFlow ? SP_CTS_FLOW_CONTROL : SP_CTS_IGNORE;
1636 switch (data->dcb.fDtrControl) {
1637 case DTR_CONTROL_DISABLE:
1638 config->dtr = SP_DTR_OFF;
1640 case DTR_CONTROL_ENABLE:
1641 config->dtr = SP_DTR_ON;
1643 case DTR_CONTROL_HANDSHAKE:
1644 config->dtr = SP_DTR_FLOW_CONTROL;
1650 config->dsr = data->dcb.fOutxDsrFlow ? SP_DSR_FLOW_CONTROL : SP_DSR_IGNORE;
1652 if (data->dcb.fInX) {
1653 if (data->dcb.fOutX)
1654 config->xon_xoff = SP_XONXOFF_INOUT;
1656 config->xon_xoff = SP_XONXOFF_IN;
1658 if (data->dcb.fOutX)
1659 config->xon_xoff = SP_XONXOFF_OUT;
1661 config->xon_xoff = SP_XONXOFF_DISABLED;
1666 if (tcgetattr(port->fd, &data->term) < 0)
1667 RETURN_FAIL("tcgetattr() failed");
1669 if (ioctl(port->fd, TIOCMGET, &data->controlbits) < 0)
1670 RETURN_FAIL("TIOCMGET ioctl failed");
1673 int ret = get_flow(port->fd, data);
1675 if (ret == SP_ERR_FAIL && errno == EINVAL)
1676 data->termiox_supported = 0;
1678 RETURN_CODEVAL(ret);
1680 data->termiox_supported = 1;
1682 data->termiox_supported = 0;
1685 for (i = 0; i < NUM_STD_BAUDRATES; i++) {
1686 if (cfgetispeed(&data->term) == std_baudrates[i].index) {
1687 config->baudrate = std_baudrates[i].value;
1692 if (i == NUM_STD_BAUDRATES) {
1694 config->baudrate = (int)data->term.c_ispeed;
1695 #elif defined(USE_TERMIOS_SPEED)
1696 TRY(get_baudrate(port->fd, &config->baudrate));
1698 config->baudrate = -1;
1702 switch (data->term.c_cflag & CSIZE) {
1719 if (!(data->term.c_cflag & PARENB) && (data->term.c_iflag & IGNPAR))
1720 config->parity = SP_PARITY_NONE;
1721 else if (!(data->term.c_cflag & PARENB) || (data->term.c_iflag & IGNPAR))
1722 config->parity = -1;
1724 else if (data->term.c_cflag & CMSPAR)
1725 config->parity = (data->term.c_cflag & PARODD) ? SP_PARITY_MARK : SP_PARITY_SPACE;
1728 config->parity = (data->term.c_cflag & PARODD) ? SP_PARITY_ODD : SP_PARITY_EVEN;
1730 config->stopbits = (data->term.c_cflag & CSTOPB) ? 2 : 1;
1732 if (data->term.c_cflag & CRTSCTS) {
1733 config->rts = SP_RTS_FLOW_CONTROL;
1734 config->cts = SP_CTS_FLOW_CONTROL;
1736 if (data->termiox_supported && data->rts_flow)
1737 config->rts = SP_RTS_FLOW_CONTROL;
1739 config->rts = (data->controlbits & TIOCM_RTS) ? SP_RTS_ON : SP_RTS_OFF;
1741 config->cts = (data->termiox_supported && data->cts_flow) ?
1742 SP_CTS_FLOW_CONTROL : SP_CTS_IGNORE;
1745 if (data->termiox_supported && data->dtr_flow)
1746 config->dtr = SP_DTR_FLOW_CONTROL;
1748 config->dtr = (data->controlbits & TIOCM_DTR) ? SP_DTR_ON : SP_DTR_OFF;
1750 config->dsr = (data->termiox_supported && data->dsr_flow) ?
1751 SP_DSR_FLOW_CONTROL : SP_DSR_IGNORE;
1753 if (data->term.c_iflag & IXOFF) {
1754 if (data->term.c_iflag & IXON)
1755 config->xon_xoff = SP_XONXOFF_INOUT;
1757 config->xon_xoff = SP_XONXOFF_IN;
1759 if (data->term.c_iflag & IXON)
1760 config->xon_xoff = SP_XONXOFF_OUT;
1762 config->xon_xoff = SP_XONXOFF_DISABLED;
1769 static enum sp_return set_config(struct sp_port *port, struct port_data *data,
1770 const struct sp_port_config *config)
1774 BAUD_TYPE baud_nonstd;
1778 #ifdef USE_TERMIOS_SPEED
1779 int baud_nonstd = 0;
1782 TRACE("%p, %p, %p", port, data, config);
1784 DEBUG("Setting configuration for port %s", port->name);
1787 if (config->baudrate >= 0) {
1788 for (i = 0; i < NUM_STD_BAUDRATES; i++) {
1789 if (config->baudrate == std_baudrates[i].value) {
1790 data->dcb.BaudRate = std_baudrates[i].index;
1795 if (i == NUM_STD_BAUDRATES)
1796 data->dcb.BaudRate = config->baudrate;
1799 if (config->bits >= 0)
1800 data->dcb.ByteSize = config->bits;
1802 if (config->parity >= 0) {
1803 switch (config->parity) {
1804 case SP_PARITY_NONE:
1805 data->dcb.Parity = NOPARITY;
1808 data->dcb.Parity = ODDPARITY;
1810 case SP_PARITY_EVEN:
1811 data->dcb.Parity = EVENPARITY;
1813 case SP_PARITY_MARK:
1814 data->dcb.Parity = MARKPARITY;
1816 case SP_PARITY_SPACE:
1817 data->dcb.Parity = SPACEPARITY;
1820 RETURN_ERROR(SP_ERR_ARG, "Invalid parity setting");
1824 if (config->stopbits >= 0) {
1825 switch (config->stopbits) {
1826 /* Note: There's also ONE5STOPBITS == 1.5 (unneeded so far). */
1828 data->dcb.StopBits = ONESTOPBIT;
1831 data->dcb.StopBits = TWOSTOPBITS;
1834 RETURN_ERROR(SP_ERR_ARG, "Invalid stop bit setting");
1838 if (config->rts >= 0) {
1839 switch (config->rts) {
1841 data->dcb.fRtsControl = RTS_CONTROL_DISABLE;
1844 data->dcb.fRtsControl = RTS_CONTROL_ENABLE;
1846 case SP_RTS_FLOW_CONTROL:
1847 data->dcb.fRtsControl = RTS_CONTROL_HANDSHAKE;
1850 RETURN_ERROR(SP_ERR_ARG, "Invalid RTS setting");
1854 if (config->cts >= 0) {
1855 switch (config->cts) {
1857 data->dcb.fOutxCtsFlow = FALSE;
1859 case SP_CTS_FLOW_CONTROL:
1860 data->dcb.fOutxCtsFlow = TRUE;
1863 RETURN_ERROR(SP_ERR_ARG, "Invalid CTS setting");
1867 if (config->dtr >= 0) {
1868 switch (config->dtr) {
1870 data->dcb.fDtrControl = DTR_CONTROL_DISABLE;
1873 data->dcb.fDtrControl = DTR_CONTROL_ENABLE;
1875 case SP_DTR_FLOW_CONTROL:
1876 data->dcb.fDtrControl = DTR_CONTROL_HANDSHAKE;
1879 RETURN_ERROR(SP_ERR_ARG, "Invalid DTR setting");
1883 if (config->dsr >= 0) {
1884 switch (config->dsr) {
1886 data->dcb.fOutxDsrFlow = FALSE;
1888 case SP_DSR_FLOW_CONTROL:
1889 data->dcb.fOutxDsrFlow = TRUE;
1892 RETURN_ERROR(SP_ERR_ARG, "Invalid DSR setting");
1896 if (config->xon_xoff >= 0) {
1897 switch (config->xon_xoff) {
1898 case SP_XONXOFF_DISABLED:
1899 data->dcb.fInX = FALSE;
1900 data->dcb.fOutX = FALSE;
1903 data->dcb.fInX = TRUE;
1904 data->dcb.fOutX = FALSE;
1906 case SP_XONXOFF_OUT:
1907 data->dcb.fInX = FALSE;
1908 data->dcb.fOutX = TRUE;
1910 case SP_XONXOFF_INOUT:
1911 data->dcb.fInX = TRUE;
1912 data->dcb.fOutX = TRUE;
1915 RETURN_ERROR(SP_ERR_ARG, "Invalid XON/XOFF setting");
1919 if (!SetCommState(port->hdl, &data->dcb))
1920 RETURN_FAIL("SetCommState() failed");
1926 if (config->baudrate >= 0) {
1927 for (i = 0; i < NUM_STD_BAUDRATES; i++) {
1928 if (config->baudrate == std_baudrates[i].value) {
1929 if (cfsetospeed(&data->term, std_baudrates[i].index) < 0)
1930 RETURN_FAIL("cfsetospeed() failed");
1932 if (cfsetispeed(&data->term, std_baudrates[i].index) < 0)
1933 RETURN_FAIL("cfsetispeed() failed");
1938 /* Non-standard baud rate */
1939 if (i == NUM_STD_BAUDRATES) {
1941 /* Set "dummy" baud rate. */
1942 if (cfsetspeed(&data->term, B9600) < 0)
1943 RETURN_FAIL("cfsetspeed() failed");
1944 baud_nonstd = config->baudrate;
1945 #elif defined(USE_TERMIOS_SPEED)
1948 RETURN_ERROR(SP_ERR_SUPP, "Non-standard baudrate not supported");
1953 if (config->bits >= 0) {
1954 data->term.c_cflag &= ~CSIZE;
1955 switch (config->bits) {
1957 data->term.c_cflag |= CS8;
1960 data->term.c_cflag |= CS7;
1963 data->term.c_cflag |= CS6;
1966 data->term.c_cflag |= CS5;
1969 RETURN_ERROR(SP_ERR_ARG, "Invalid data bits setting");
1973 if (config->parity >= 0) {
1974 data->term.c_iflag &= ~IGNPAR;
1975 data->term.c_cflag &= ~(PARENB | PARODD);
1977 data->term.c_cflag &= ~CMSPAR;
1979 switch (config->parity) {
1980 case SP_PARITY_NONE:
1981 data->term.c_iflag |= IGNPAR;
1983 case SP_PARITY_EVEN:
1984 data->term.c_cflag |= PARENB;
1987 data->term.c_cflag |= PARENB | PARODD;
1990 case SP_PARITY_MARK:
1991 data->term.c_cflag |= PARENB | PARODD;
1992 data->term.c_cflag |= CMSPAR;
1994 case SP_PARITY_SPACE:
1995 data->term.c_cflag |= PARENB;
1996 data->term.c_cflag |= CMSPAR;
1999 case SP_PARITY_MARK:
2000 case SP_PARITY_SPACE:
2001 RETURN_ERROR(SP_ERR_SUPP, "Mark/space parity not supported");
2004 RETURN_ERROR(SP_ERR_ARG, "Invalid parity setting");
2008 if (config->stopbits >= 0) {
2009 data->term.c_cflag &= ~CSTOPB;
2010 switch (config->stopbits) {
2012 data->term.c_cflag &= ~CSTOPB;
2015 data->term.c_cflag |= CSTOPB;
2018 RETURN_ERROR(SP_ERR_ARG, "Invalid stop bits setting");
2022 if (config->rts >= 0 || config->cts >= 0) {
2023 if (data->termiox_supported) {
2024 data->rts_flow = data->cts_flow = 0;
2025 switch (config->rts) {
2028 controlbits = TIOCM_RTS;
2029 if (ioctl(port->fd, config->rts == SP_RTS_ON ? TIOCMBIS : TIOCMBIC, &controlbits) < 0)
2030 RETURN_FAIL("Setting RTS signal level failed");
2032 case SP_RTS_FLOW_CONTROL:
2038 if (config->cts == SP_CTS_FLOW_CONTROL)
2041 if (data->rts_flow && data->cts_flow)
2042 data->term.c_iflag |= CRTSCTS;
2044 data->term.c_iflag &= ~CRTSCTS;
2046 /* Asymmetric use of RTS/CTS not supported. */
2047 if (data->term.c_iflag & CRTSCTS) {
2048 /* Flow control can only be disabled for both RTS & CTS together. */
2049 if (config->rts >= 0 && config->rts != SP_RTS_FLOW_CONTROL) {
2050 if (config->cts != SP_CTS_IGNORE)
2051 RETURN_ERROR(SP_ERR_SUPP, "RTS & CTS flow control must be disabled together");
2053 if (config->cts >= 0 && config->cts != SP_CTS_FLOW_CONTROL) {
2054 if (config->rts <= 0 || config->rts == SP_RTS_FLOW_CONTROL)
2055 RETURN_ERROR(SP_ERR_SUPP, "RTS & CTS flow control must be disabled together");
2058 /* Flow control can only be enabled for both RTS & CTS together. */
2059 if (((config->rts == SP_RTS_FLOW_CONTROL) && (config->cts != SP_CTS_FLOW_CONTROL)) ||
2060 ((config->cts == SP_CTS_FLOW_CONTROL) && (config->rts != SP_RTS_FLOW_CONTROL)))
2061 RETURN_ERROR(SP_ERR_SUPP, "RTS & CTS flow control must be enabled together");
2064 if (config->rts >= 0) {
2065 if (config->rts == SP_RTS_FLOW_CONTROL) {
2066 data->term.c_iflag |= CRTSCTS;
2068 controlbits = TIOCM_RTS;
2069 if (ioctl(port->fd, config->rts == SP_RTS_ON ? TIOCMBIS : TIOCMBIC,
2071 RETURN_FAIL("Setting RTS signal level failed");
2077 if (config->dtr >= 0 || config->dsr >= 0) {
2078 if (data->termiox_supported) {
2079 data->dtr_flow = data->dsr_flow = 0;
2080 switch (config->dtr) {
2083 controlbits = TIOCM_DTR;
2084 if (ioctl(port->fd, config->dtr == SP_DTR_ON ? TIOCMBIS : TIOCMBIC, &controlbits) < 0)
2085 RETURN_FAIL("Setting DTR signal level failed");
2087 case SP_DTR_FLOW_CONTROL:
2093 if (config->dsr == SP_DSR_FLOW_CONTROL)
2096 /* DTR/DSR flow control not supported. */
2097 if (config->dtr == SP_DTR_FLOW_CONTROL || config->dsr == SP_DSR_FLOW_CONTROL)
2098 RETURN_ERROR(SP_ERR_SUPP, "DTR/DSR flow control not supported");
2100 if (config->dtr >= 0) {
2101 controlbits = TIOCM_DTR;
2102 if (ioctl(port->fd, config->dtr == SP_DTR_ON ? TIOCMBIS : TIOCMBIC,
2104 RETURN_FAIL("Setting DTR signal level failed");
2109 if (config->xon_xoff >= 0) {
2110 data->term.c_iflag &= ~(IXON | IXOFF | IXANY);
2111 switch (config->xon_xoff) {
2112 case SP_XONXOFF_DISABLED:
2115 data->term.c_iflag |= IXOFF;
2117 case SP_XONXOFF_OUT:
2118 data->term.c_iflag |= IXON | IXANY;
2120 case SP_XONXOFF_INOUT:
2121 data->term.c_iflag |= IXON | IXOFF | IXANY;
2124 RETURN_ERROR(SP_ERR_ARG, "Invalid XON/XOFF setting");
2128 if (tcsetattr(port->fd, TCSANOW, &data->term) < 0)
2129 RETURN_FAIL("tcsetattr() failed");
2132 if (baud_nonstd != B0) {
2133 if (ioctl(port->fd, IOSSIOSPEED, &baud_nonstd) == -1)
2134 RETURN_FAIL("IOSSIOSPEED ioctl failed");
2135 /* Set baud rates in data->term to correct, but incompatible
2136 * with tcsetattr() value, same as delivered by tcgetattr(). */
2137 if (cfsetspeed(&data->term, baud_nonstd) < 0)
2138 RETURN_FAIL("cfsetspeed() failed");
2140 #elif defined(__linux__)
2141 #ifdef USE_TERMIOS_SPEED
2143 TRY(set_baudrate(port->fd, config->baudrate));
2146 if (data->termiox_supported)
2147 TRY(set_flow(port->fd, data));
2151 #endif /* !_WIN32 */
2156 enum sp_return sp_new_config(struct sp_port_config **config_ptr)
2158 struct sp_port_config *config;
2160 TRACE("%p", config_ptr);
2163 RETURN_ERROR(SP_ERR_ARG, "Null result pointer");
2167 if (!(config = malloc(sizeof(struct sp_port_config))))
2168 RETURN_ERROR(SP_ERR_MEM, "config malloc failed");
2170 config->baudrate = -1;
2172 config->parity = -1;
2173 config->stopbits = -1;
2179 *config_ptr = config;
2184 void sp_free_config(struct sp_port_config *config)
2186 TRACE("%p", config);
2189 DEBUG("Null config");
2196 enum sp_return sp_get_config(struct sp_port *port, struct sp_port_config *config)
2198 struct port_data data;
2200 TRACE("%p, %p", port, config);
2205 RETURN_ERROR(SP_ERR_ARG, "Null config");
2207 TRY(get_config(port, &data, config));
2212 enum sp_return sp_set_config(struct sp_port *port, const struct sp_port_config *config)
2214 struct port_data data;
2215 struct sp_port_config prev_config;
2217 TRACE("%p, %p", port, config);
2222 RETURN_ERROR(SP_ERR_ARG, "Null config");
2224 TRY(get_config(port, &data, &prev_config));
2225 TRY(set_config(port, &data, config));
2230 #define CREATE_ACCESSORS(x, type) \
2231 enum sp_return sp_set_##x(struct sp_port *port, type x) { \
2232 struct port_data data; \
2233 struct sp_port_config config; \
2234 TRACE("%p, %d", port, x); \
2235 CHECK_OPEN_PORT(); \
2236 TRY(get_config(port, &data, &config)); \
2238 TRY(set_config(port, &data, &config)); \
2241 enum sp_return sp_get_config_##x(const struct sp_port_config *config, type *x) { \
2242 TRACE("%p, %p", config, x); \
2244 RETURN_ERROR(SP_ERR_ARG, "Null config"); \
2248 enum sp_return sp_set_config_##x(struct sp_port_config *config, type x) { \
2249 TRACE("%p, %d", config, x); \
2251 RETURN_ERROR(SP_ERR_ARG, "Null config"); \
2256 CREATE_ACCESSORS(baudrate, int)
2257 CREATE_ACCESSORS(bits, int)
2258 CREATE_ACCESSORS(parity, enum sp_parity)
2259 CREATE_ACCESSORS(stopbits, int)
2260 CREATE_ACCESSORS(rts, enum sp_rts)
2261 CREATE_ACCESSORS(cts, enum sp_cts)
2262 CREATE_ACCESSORS(dtr, enum sp_dtr)
2263 CREATE_ACCESSORS(dsr, enum sp_dsr)
2264 CREATE_ACCESSORS(xon_xoff, enum sp_xonxoff)
2266 enum sp_return sp_set_config_flowcontrol(struct sp_port_config *config, enum sp_flowcontrol flowcontrol)
2269 RETURN_ERROR(SP_ERR_ARG, "Null configuration");
2271 if (flowcontrol > SP_FLOWCONTROL_DTRDSR)
2272 RETURN_ERROR(SP_ERR_ARG, "Invalid flow control setting");
2274 if (flowcontrol == SP_FLOWCONTROL_XONXOFF)
2275 config->xon_xoff = SP_XONXOFF_INOUT;
2277 config->xon_xoff = SP_XONXOFF_DISABLED;
2279 if (flowcontrol == SP_FLOWCONTROL_RTSCTS) {
2280 config->rts = SP_RTS_FLOW_CONTROL;
2281 config->cts = SP_CTS_FLOW_CONTROL;
2283 if (config->rts == SP_RTS_FLOW_CONTROL)
2284 config->rts = SP_RTS_ON;
2285 config->cts = SP_CTS_IGNORE;
2288 if (flowcontrol == SP_FLOWCONTROL_DTRDSR) {
2289 config->dtr = SP_DTR_FLOW_CONTROL;
2290 config->dsr = SP_DSR_FLOW_CONTROL;
2292 if (config->dtr == SP_DTR_FLOW_CONTROL)
2293 config->dtr = SP_DTR_ON;
2294 config->dsr = SP_DSR_IGNORE;
2300 enum sp_return sp_set_flowcontrol(struct sp_port *port, enum sp_flowcontrol flowcontrol)
2302 struct port_data data;
2303 struct sp_port_config config;
2305 TRACE("%p, %d", port, flowcontrol);
2309 TRY(get_config(port, &data, &config));
2311 TRY(sp_set_config_flowcontrol(&config, flowcontrol));
2313 TRY(set_config(port, &data, &config));
2318 enum sp_return sp_get_signals(struct sp_port *port, enum sp_signal *signals)
2320 TRACE("%p, %p", port, signals);
2325 RETURN_ERROR(SP_ERR_ARG, "Null result pointer");
2327 DEBUG("Getting control signals for port %s", port->name);
2332 if (GetCommModemStatus(port->hdl, &bits) == 0)
2333 RETURN_FAIL("GetCommModemStatus() failed");
2334 if (bits & MS_CTS_ON)
2335 *signals |= SP_SIG_CTS;
2336 if (bits & MS_DSR_ON)
2337 *signals |= SP_SIG_DSR;
2338 if (bits & MS_RLSD_ON)
2339 *signals |= SP_SIG_DCD;
2340 if (bits & MS_RING_ON)
2341 *signals |= SP_SIG_RI;
2344 if (ioctl(port->fd, TIOCMGET, &bits) < 0)
2345 RETURN_FAIL("TIOCMGET ioctl failed");
2346 if (bits & TIOCM_CTS)
2347 *signals |= SP_SIG_CTS;
2348 if (bits & TIOCM_DSR)
2349 *signals |= SP_SIG_DSR;
2350 if (bits & TIOCM_CAR)
2351 *signals |= SP_SIG_DCD;
2352 if (bits & TIOCM_RNG)
2353 *signals |= SP_SIG_RI;
2358 enum sp_return sp_start_break(struct sp_port *port)
2364 if (SetCommBreak(port->hdl) == 0)
2365 RETURN_FAIL("SetCommBreak() failed");
2367 if (ioctl(port->fd, TIOCSBRK, 1) < 0)
2368 RETURN_FAIL("TIOCSBRK ioctl failed");
2374 enum sp_return sp_end_break(struct sp_port *port)
2380 if (ClearCommBreak(port->hdl) == 0)
2381 RETURN_FAIL("ClearCommBreak() failed");
2383 if (ioctl(port->fd, TIOCCBRK, 1) < 0)
2384 RETURN_FAIL("TIOCCBRK ioctl failed");
2390 int sp_last_error_code(void)
2394 RETURN_VALUE("%d", GetLastError());
2396 RETURN_VALUE("%d", errno);
2400 char *sp_last_error_message(void)
2406 DWORD error = GetLastError();
2409 FORMAT_MESSAGE_ALLOCATE_BUFFER |
2410 FORMAT_MESSAGE_FROM_SYSTEM |
2411 FORMAT_MESSAGE_IGNORE_INSERTS,
2414 MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
2418 RETURN_VALUE("%s", message);
2420 RETURN_VALUE("%s", strerror(errno));
2424 void sp_free_error_message(char *message)
2426 TRACE("%s", message);
2437 void sp_set_debug_handler(void (*handler)(const char *format, ...))
2439 TRACE("%p", handler);
2441 sp_debug_handler = handler;
2446 void sp_default_debug_handler(const char *format, ...)
2449 va_start(args, format);
2450 if (getenv("LIBSERIALPORT_DEBUG")) {
2451 fputs("sp: ", stderr);
2452 vfprintf(stderr, format, args);
2457 int sp_get_major_package_version(void)
2459 return SP_PACKAGE_VERSION_MAJOR;
2462 int sp_get_minor_package_version(void)
2464 return SP_PACKAGE_VERSION_MINOR;
2467 int sp_get_micro_package_version(void)
2469 return SP_PACKAGE_VERSION_MICRO;
2472 const char *sp_get_package_version_string(void)
2474 return SP_PACKAGE_VERSION_STRING;
2477 int sp_get_current_lib_version(void)
2479 return SP_LIB_VERSION_CURRENT;
2482 int sp_get_revision_lib_version(void)
2484 return SP_LIB_VERSION_REVISION;
2487 int sp_get_age_lib_version(void)
2489 return SP_LIB_VERSION_AGE;
2492 const char *sp_get_lib_version_string(void)
2494 return SP_LIB_VERSION_STRING;