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");
422 CFMutableDictionaryRef classes;
431 DEBUG("Getting IOKit master port");
432 if (IOMasterPort(MACH_PORT_NULL, &master) != KERN_SUCCESS) {
433 SET_FAIL(ret, "IOMasterPort() failed");
437 DEBUG("Creating matching dictionary");
438 if (!(classes = IOServiceMatching(kIOSerialBSDServiceValue))) {
439 SET_FAIL(ret, "IOServiceMatching() failed");
443 CFDictionarySetValue(classes,
444 CFSTR(kIOSerialBSDTypeKey), CFSTR(kIOSerialBSDAllTypes));
446 DEBUG("Getting matching services");
447 if (IOServiceGetMatchingServices(master, classes, &iter) != KERN_SUCCESS) {
448 SET_FAIL(ret, "IOServiceGetMatchingServices() failed");
452 if (!(path = malloc(PATH_MAX))) {
453 SET_ERROR(ret, SP_ERR_MEM, "device path malloc failed");
457 DEBUG("Iterating over results");
458 while ((port = IOIteratorNext(iter))) {
459 cf_path = IORegistryEntryCreateCFProperty(port,
460 CFSTR(kIOCalloutDeviceKey), kCFAllocatorDefault, 0);
462 result = CFStringGetCString(cf_path,
463 path, PATH_MAX, kCFStringEncodingASCII);
466 DEBUG("Found port %s", path);
467 if (!(list = list_append(list, path))) {
468 SET_ERROR(ret, SP_ERR_MEM, "list append failed");
469 IOObjectRelease(port);
474 IOObjectRelease(port);
479 IOObjectRelease(iter);
482 #if defined(__linux__) && defined(HAVE_LIBUDEV)
484 struct udev_enumerate *ud_enumerate;
485 struct udev_list_entry *ud_list;
486 struct udev_list_entry *ud_entry;
488 struct udev_device *ud_dev, *ud_parent;
491 int fd, ioctl_result;
492 struct serial_struct serial_info;
496 DEBUG("Enumerating tty devices");
498 ud_enumerate = udev_enumerate_new(ud);
499 udev_enumerate_add_match_subsystem(ud_enumerate, "tty");
500 udev_enumerate_scan_devices(ud_enumerate);
501 ud_list = udev_enumerate_get_list_entry(ud_enumerate);
502 DEBUG("Iterating over results");
503 udev_list_entry_foreach(ud_entry, ud_list) {
504 path = udev_list_entry_get_name(ud_entry);
505 DEBUG("Found device %s", path);
506 ud_dev = udev_device_new_from_syspath(ud, path);
507 /* If there is no parent device, this is a virtual tty. */
508 ud_parent = udev_device_get_parent(ud_dev);
509 if (ud_parent == NULL) {
510 DEBUG("No parent device, assuming virtual tty");
511 udev_device_unref(ud_dev);
514 name = udev_device_get_devnode(ud_dev);
515 /* The serial8250 driver has a hardcoded number of ports.
516 * The only way to tell which actually exist on a given system
517 * is to try to open them and make an ioctl call. */
518 driver = udev_device_get_driver(ud_parent);
519 if (driver && !strcmp(driver, "serial8250")) {
520 DEBUG("serial8250 device, attempting to open");
521 if ((fd = open(name, O_RDWR | O_NONBLOCK | O_NOCTTY)) < 0) {
522 DEBUG("open failed, skipping");
525 ioctl_result = ioctl(fd, TIOCGSERIAL, &serial_info);
527 if (ioctl_result != 0) {
528 DEBUG("ioctl failed, skipping");
531 if (serial_info.type == PORT_UNKNOWN) {
532 DEBUG("port type is unknown, skipping");
536 DEBUG("Found port %s", name);
537 list = list_append(list, name);
539 udev_device_unref(ud_dev);
541 SET_ERROR(ret, SP_ERR_MEM, "list append failed");
546 udev_enumerate_unref(ud_enumerate);
555 DEBUG_ERROR(SP_ERR_SUPP, "Enumeration not supported on this platform");
558 sp_free_port_list(list);
564 void sp_free_port_list(struct sp_port **list)
575 DEBUG("Freeing port list");
577 for (i = 0; list[i]; i++)
578 sp_free_port(list[i]);
584 #define CHECK_PORT() do { \
586 RETURN_ERROR(SP_ERR_ARG, "Null port"); \
587 if (port->name == NULL) \
588 RETURN_ERROR(SP_ERR_ARG, "Null port name"); \
591 #define CHECK_PORT_HANDLE() do { \
592 if (port->hdl == INVALID_HANDLE_VALUE) \
593 RETURN_ERROR(SP_ERR_ARG, "Invalid port handle"); \
596 #define CHECK_PORT_HANDLE() do { \
598 RETURN_ERROR(SP_ERR_ARG, "Invalid port fd"); \
601 #define CHECK_OPEN_PORT() do { \
603 CHECK_PORT_HANDLE(); \
606 enum sp_return sp_open(struct sp_port *port, enum sp_mode flags)
608 struct port_data data;
609 struct sp_port_config config;
612 TRACE("%p, 0x%x", port, flags);
616 if (flags > (SP_MODE_READ | SP_MODE_WRITE))
617 RETURN_ERROR(SP_ERR_ARG, "Invalid flags");
619 DEBUG("Opening port %s", port->name);
622 DWORD desired_access = 0, flags_and_attributes = 0, errors;
623 char *escaped_port_name;
626 /* Prefix port name with '\\.\' to work with ports above COM9. */
627 if (!(escaped_port_name = malloc(strlen(port->name) + 5)))
628 RETURN_ERROR(SP_ERR_MEM, "Escaped port name malloc failed");
629 sprintf(escaped_port_name, "\\\\.\\%s", port->name);
631 /* Map 'flags' to the OS-specific settings. */
632 flags_and_attributes = FILE_ATTRIBUTE_NORMAL | FILE_FLAG_OVERLAPPED;
633 if (flags & SP_MODE_READ)
634 desired_access |= GENERIC_READ;
635 if (flags & SP_MODE_WRITE)
636 desired_access |= GENERIC_WRITE;
638 port->hdl = CreateFile(escaped_port_name, desired_access, 0, 0,
639 OPEN_EXISTING, flags_and_attributes, 0);
641 free(escaped_port_name);
643 if (port->hdl == INVALID_HANDLE_VALUE)
644 RETURN_FAIL("port CreateFile() failed");
646 /* All timeouts initially disabled. */
647 port->timeouts.ReadIntervalTimeout = 0;
648 port->timeouts.ReadTotalTimeoutMultiplier = 0;
649 port->timeouts.ReadTotalTimeoutConstant = 0;
650 port->timeouts.WriteTotalTimeoutMultiplier = 0;
651 port->timeouts.WriteTotalTimeoutConstant = 0;
653 if (SetCommTimeouts(port->hdl, &port->timeouts) == 0) {
655 RETURN_FAIL("SetCommTimeouts() failed");
658 /* Prepare OVERLAPPED structures. */
659 #define INIT_OVERLAPPED(ovl) do { \
660 memset(&port->ovl, 0, sizeof(port->ovl)); \
661 port->ovl.hEvent = INVALID_HANDLE_VALUE; \
662 if ((port->ovl.hEvent = CreateEvent(NULL, TRUE, TRUE, NULL)) \
663 == INVALID_HANDLE_VALUE) { \
665 RETURN_FAIL(#ovl "CreateEvent() failed"); \
669 INIT_OVERLAPPED(read_ovl);
670 INIT_OVERLAPPED(write_ovl);
671 INIT_OVERLAPPED(wait_ovl);
673 /* Set event mask for RX and error events. */
674 if (SetCommMask(port->hdl, EV_RXCHAR | EV_ERR) == 0) {
676 RETURN_FAIL("SetCommMask() failed");
679 /* Start background operation for RX and error events. */
680 if (WaitCommEvent(port->hdl, &port->events, &port->wait_ovl) == 0) {
681 if (GetLastError() != ERROR_IO_PENDING) {
683 RETURN_FAIL("WaitCommEvent() failed");
687 port->writing = FALSE;
690 int flags_local = O_NONBLOCK | O_NOCTTY;
692 /* Map 'flags' to the OS-specific settings. */
693 if (flags & (SP_MODE_READ | SP_MODE_WRITE))
694 flags_local |= O_RDWR;
695 else if (flags & SP_MODE_READ)
696 flags_local |= O_RDONLY;
697 else if (flags & SP_MODE_WRITE)
698 flags_local |= O_WRONLY;
700 if ((port->fd = open(port->name, flags_local)) < 0)
701 RETURN_FAIL("open() failed");
704 ret = get_config(port, &data, &config);
711 /* Set sane port settings. */
713 data.dcb.fBinary = TRUE;
714 data.dcb.fDsrSensitivity = FALSE;
715 data.dcb.fErrorChar = FALSE;
716 data.dcb.fNull = FALSE;
717 data.dcb.fAbortOnError = TRUE;
719 /* Turn off all fancy termios tricks, give us a raw channel. */
720 data.term.c_iflag &= ~(IGNBRK | BRKINT | PARMRK | ISTRIP | INLCR | IGNCR | ICRNL | IMAXBEL);
722 data.term.c_iflag &= ~IUCLC;
724 data.term.c_oflag &= ~(OPOST | ONLCR | OCRNL | ONOCR | ONLRET);
726 data.term.c_oflag &= ~OLCUC;
729 data.term.c_oflag &= ~NLDLY;
732 data.term.c_oflag &= ~CRDLY;
735 data.term.c_oflag &= ~TABDLY;
738 data.term.c_oflag &= ~BSDLY;
741 data.term.c_oflag &= ~VTDLY;
744 data.term.c_oflag &= ~FFDLY;
747 data.term.c_oflag &= ~OFILL;
749 data.term.c_lflag &= ~(ISIG | ICANON | ECHO | IEXTEN);
750 data.term.c_cc[VMIN] = 0;
751 data.term.c_cc[VTIME] = 0;
753 /* Ignore modem status lines; enable receiver; leave control lines alone on close. */
754 data.term.c_cflag |= (CLOCAL | CREAD | HUPCL);
758 if (ClearCommError(port->hdl, &errors, &status) == 0)
759 RETURN_FAIL("ClearCommError() failed");
762 ret = set_config(port, &data, &config);
772 enum sp_return sp_close(struct sp_port *port)
778 DEBUG("Closing port %s", port->name);
781 /* Returns non-zero upon success, 0 upon failure. */
782 if (CloseHandle(port->hdl) == 0)
783 RETURN_FAIL("port CloseHandle() failed");
784 port->hdl = INVALID_HANDLE_VALUE;
786 /* Close event handles for overlapped structures. */
787 #define CLOSE_OVERLAPPED(ovl) do { \
788 if (port->ovl.hEvent != INVALID_HANDLE_VALUE && \
789 CloseHandle(port->ovl.hEvent) == 0) \
790 RETURN_FAIL(# ovl "event CloseHandle() failed"); \
792 CLOSE_OVERLAPPED(read_ovl);
793 CLOSE_OVERLAPPED(write_ovl);
794 CLOSE_OVERLAPPED(wait_ovl);
797 /* Returns 0 upon success, -1 upon failure. */
798 if (close(port->fd) == -1)
799 RETURN_FAIL("close() failed");
806 enum sp_return sp_flush(struct sp_port *port, enum sp_buffer buffers)
808 TRACE("%p, 0x%x", port, buffers);
812 if (buffers > SP_BUF_BOTH)
813 RETURN_ERROR(SP_ERR_ARG, "Invalid buffer selection");
815 const char *buffer_names[] = {"no", "input", "output", "both"};
817 DEBUG("Flushing %s buffers on port %s", buffer_names[buffers], port->name);
821 if (buffers & SP_BUF_INPUT)
822 flags |= PURGE_RXCLEAR;
823 if (buffers & SP_BUF_OUTPUT)
824 flags |= PURGE_TXCLEAR;
826 /* Returns non-zero upon success, 0 upon failure. */
827 if (PurgeComm(port->hdl, flags) == 0)
828 RETURN_FAIL("PurgeComm() failed");
831 if (buffers & SP_BUF_BOTH)
833 else if (buffers & SP_BUF_INPUT)
835 else if (buffers & SP_BUF_OUTPUT)
838 /* Returns 0 upon success, -1 upon failure. */
839 if (tcflush(port->fd, flags) < 0)
840 RETURN_FAIL("tcflush() failed");
845 enum sp_return sp_drain(struct sp_port *port)
851 DEBUG("Draining port %s", port->name);
854 /* Returns non-zero upon success, 0 upon failure. */
855 if (FlushFileBuffers(port->hdl) == 0)
856 RETURN_FAIL("FlushFileBuffers() failed");
863 result = ioctl(port->fd, TCSBRK, &arg);
865 result = tcdrain(port->fd);
868 if (errno == EINTR) {
869 DEBUG("tcdrain() was interrupted");
872 RETURN_FAIL("tcdrain() failed");
881 enum sp_return sp_blocking_write(struct sp_port *port, const void *buf, size_t count, unsigned int timeout)
883 TRACE("%p, %p, %d, %d", port, buf, count, timeout);
888 RETURN_ERROR(SP_ERR_ARG, "Null buffer");
891 DEBUG("Writing %d bytes to port %s, timeout %d ms", count, port->name, timeout);
893 DEBUG("Writing %d bytes to port %s, no timeout", count, port->name);
896 RETURN_VALUE("0", 0);
899 DWORD bytes_written = 0;
902 /* Wait for previous non-blocking write to complete, if any. */
904 DEBUG("Waiting for previous write to complete");
905 result = GetOverlappedResult(port->hdl, &port->write_ovl, &bytes_written, TRUE);
908 RETURN_FAIL("Previous write failed to complete");
909 DEBUG("Previous write completed");
913 port->timeouts.WriteTotalTimeoutConstant = timeout;
914 if (SetCommTimeouts(port->hdl, &port->timeouts) == 0)
915 RETURN_FAIL("SetCommTimeouts() failed");
918 if (WriteFile(port->hdl, buf, count, NULL, &port->write_ovl) == 0) {
919 if (GetLastError() == ERROR_IO_PENDING) {
920 DEBUG("Waiting for write to complete");
921 GetOverlappedResult(port->hdl, &port->write_ovl, &bytes_written, TRUE);
922 DEBUG("Write completed, %d/%d bytes written", bytes_written, count);
923 RETURN_VALUE("%d", bytes_written);
925 RETURN_FAIL("WriteFile() failed");
928 DEBUG("Write completed immediately");
929 RETURN_VALUE("%d", count);
932 size_t bytes_written = 0;
933 unsigned char *ptr = (unsigned char *) buf;
934 struct timeval start, delta, now, end = {0, 0};
939 /* Get time at start of operation. */
940 gettimeofday(&start, NULL);
941 /* Define duration of timeout. */
942 delta.tv_sec = timeout / 1000;
943 delta.tv_usec = (timeout % 1000) * 1000;
944 /* Calculate time at which we should give up. */
945 timeradd(&start, &delta, &end);
948 /* Loop until we have written the requested number of bytes. */
949 while (bytes_written < count)
951 /* Wait until space is available. */
953 FD_SET(port->fd, &fds);
955 gettimeofday(&now, NULL);
956 if (timercmp(&now, &end, >)) {
957 DEBUG("write timed out");
958 RETURN_VALUE("%d", bytes_written);
960 timersub(&end, &now, &delta);
962 result = select(port->fd + 1, NULL, &fds, NULL, timeout ? &delta : NULL);
964 if (errno == EINTR) {
965 DEBUG("select() call was interrupted, repeating");
968 RETURN_FAIL("select() failed");
970 } else if (result == 0) {
971 DEBUG("write timed out");
972 RETURN_VALUE("%d", bytes_written);
976 result = write(port->fd, ptr, count - bytes_written);
980 /* This shouldn't happen because we did a select() first, but handle anyway. */
983 /* This is an actual failure. */
984 RETURN_FAIL("write() failed");
987 bytes_written += result;
991 RETURN_VALUE("%d", bytes_written);
995 enum sp_return sp_nonblocking_write(struct sp_port *port, const void *buf, size_t count)
997 TRACE("%p, %p, %d", port, buf, count);
1002 RETURN_ERROR(SP_ERR_ARG, "Null buffer");
1004 DEBUG("Writing up to %d bytes to port %s", count, port->name);
1007 RETURN_VALUE("0", 0);
1011 BYTE *ptr = (BYTE *) buf;
1013 /* Check whether previous write is complete. */
1014 if (port->writing) {
1015 if (HasOverlappedIoCompleted(&port->write_ovl)) {
1016 DEBUG("Previous write completed");
1019 DEBUG("Previous write not complete");
1020 /* Can't take a new write until the previous one finishes. */
1021 RETURN_VALUE("0", 0);
1026 port->timeouts.WriteTotalTimeoutConstant = 0;
1027 if (SetCommTimeouts(port->hdl, &port->timeouts) == 0)
1028 RETURN_FAIL("SetCommTimeouts() failed");
1030 /* Keep writing data until the OS has to actually start an async IO for it.
1031 * At that point we know the buffer is full. */
1032 while (written < count)
1034 /* Copy first byte of user buffer. */
1035 port->pending_byte = *ptr++;
1037 /* Start asynchronous write. */
1038 if (WriteFile(port->hdl, &port->pending_byte, 1, NULL, &port->write_ovl) == 0) {
1039 if (GetLastError() == ERROR_IO_PENDING) {
1040 if (HasOverlappedIoCompleted(&port->write_ovl)) {
1041 DEBUG("Asynchronous write completed immediately");
1046 DEBUG("Asynchronous write running");
1048 RETURN_VALUE("%d", ++written);
1051 /* Actual failure of some kind. */
1052 RETURN_FAIL("WriteFile() failed");
1055 DEBUG("Single byte written immediately");
1060 DEBUG("All bytes written immediately");
1062 RETURN_VALUE("%d", written);
1064 /* Returns the number of bytes written, or -1 upon failure. */
1065 ssize_t written = write(port->fd, buf, count);
1068 RETURN_FAIL("write() failed");
1070 RETURN_VALUE("%d", written);
1074 enum sp_return sp_blocking_read(struct sp_port *port, void *buf, size_t count, unsigned int timeout)
1076 TRACE("%p, %p, %d, %d", port, buf, count, timeout);
1081 RETURN_ERROR(SP_ERR_ARG, "Null buffer");
1084 DEBUG("Reading %d bytes from port %s, timeout %d ms", count, port->name, timeout);
1086 DEBUG("Reading %d bytes from port %s, no timeout", count, port->name);
1089 RETURN_VALUE("0", 0);
1092 DWORD bytes_read = 0;
1095 port->timeouts.ReadIntervalTimeout = 0;
1096 port->timeouts.ReadTotalTimeoutConstant = timeout;
1097 if (SetCommTimeouts(port->hdl, &port->timeouts) == 0)
1098 RETURN_FAIL("SetCommTimeouts() failed");
1101 if (ReadFile(port->hdl, buf, count, NULL, &port->read_ovl) == 0) {
1102 if (GetLastError() == ERROR_IO_PENDING) {
1103 DEBUG("Waiting for read to complete");
1104 GetOverlappedResult(port->hdl, &port->read_ovl, &bytes_read, TRUE);
1105 DEBUG("Read completed, %d/%d bytes read", bytes_read, count);
1107 RETURN_FAIL("ReadFile() failed");
1110 DEBUG("Read completed immediately");
1114 /* Start background operation for subsequent events. */
1115 if (WaitCommEvent(port->hdl, &port->events, &port->wait_ovl) == 0) {
1116 if (GetLastError() != ERROR_IO_PENDING)
1117 RETURN_FAIL("WaitCommEvent() failed");
1120 RETURN_VALUE("%d", bytes_read);
1123 size_t bytes_read = 0;
1124 unsigned char *ptr = (unsigned char *) buf;
1125 struct timeval start, delta, now, end = {0, 0};
1130 /* Get time at start of operation. */
1131 gettimeofday(&start, NULL);
1132 /* Define duration of timeout. */
1133 delta.tv_sec = timeout / 1000;
1134 delta.tv_usec = (timeout % 1000) * 1000;
1135 /* Calculate time at which we should give up. */
1136 timeradd(&start, &delta, &end);
1139 /* Loop until we have the requested number of bytes. */
1140 while (bytes_read < count)
1142 /* Wait until data is available. */
1144 FD_SET(port->fd, &fds);
1146 gettimeofday(&now, NULL);
1147 if (timercmp(&now, &end, >))
1148 /* Timeout has expired. */
1149 RETURN_VALUE("%d", bytes_read);
1150 timersub(&end, &now, &delta);
1152 result = select(port->fd + 1, &fds, NULL, NULL, timeout ? &delta : NULL);
1154 if (errno == EINTR) {
1155 DEBUG("select() call was interrupted, repeating");
1158 RETURN_FAIL("select() failed");
1160 } else if (result == 0) {
1161 DEBUG("read timed out");
1162 RETURN_VALUE("%d", bytes_read);
1166 result = read(port->fd, ptr, count - bytes_read);
1169 if (errno == EAGAIN)
1170 /* This shouldn't happen because we did a select() first, but handle anyway. */
1173 /* This is an actual failure. */
1174 RETURN_FAIL("read() failed");
1177 bytes_read += result;
1181 RETURN_VALUE("%d", bytes_read);
1185 enum sp_return sp_nonblocking_read(struct sp_port *port, void *buf, size_t count)
1187 TRACE("%p, %p, %d", port, buf, count);
1192 RETURN_ERROR(SP_ERR_ARG, "Null buffer");
1194 DEBUG("Reading up to %d bytes from port %s", count, port->name);
1200 port->timeouts.ReadIntervalTimeout = MAXDWORD;
1201 port->timeouts.ReadTotalTimeoutConstant = 0;
1202 if (SetCommTimeouts(port->hdl, &port->timeouts) == 0)
1203 RETURN_FAIL("SetCommTimeouts() failed");
1206 if (ReadFile(port->hdl, buf, count, NULL, &port->read_ovl) == 0)
1207 RETURN_FAIL("ReadFile() failed");
1209 /* Get number of bytes read. */
1210 if (GetOverlappedResult(port->hdl, &port->read_ovl, &bytes_read, TRUE) == 0)
1211 RETURN_FAIL("GetOverlappedResult() failed");
1213 if (bytes_read > 0) {
1214 /* Start background operation for subsequent events. */
1215 if (WaitCommEvent(port->hdl, &port->events, &port->wait_ovl) == 0) {
1216 if (GetLastError() != ERROR_IO_PENDING)
1217 RETURN_FAIL("WaitCommEvent() failed");
1221 RETURN_VALUE("%d", bytes_read);
1225 /* Returns the number of bytes read, or -1 upon failure. */
1226 if ((bytes_read = read(port->fd, buf, count)) < 0) {
1227 if (errno == EAGAIN)
1228 /* No bytes available. */
1231 /* This is an actual failure. */
1232 RETURN_FAIL("read() failed");
1234 RETURN_VALUE("%d", bytes_read);
1238 enum sp_return sp_input_waiting(struct sp_port *port)
1244 DEBUG("Checking input bytes waiting on port %s", port->name);
1250 if (ClearCommError(port->hdl, &errors, &comstat) == 0)
1251 RETURN_FAIL("ClearCommError() failed");
1252 RETURN_VALUE("%d", comstat.cbInQue);
1255 if (ioctl(port->fd, TIOCINQ, &bytes_waiting) < 0)
1256 RETURN_FAIL("TIOCINQ ioctl failed");
1257 RETURN_VALUE("%d", bytes_waiting);
1261 enum sp_return sp_output_waiting(struct sp_port *port)
1267 DEBUG("Checking output bytes waiting on port %s", port->name);
1273 if (ClearCommError(port->hdl, &errors, &comstat) == 0)
1274 RETURN_FAIL("ClearCommError() failed");
1275 RETURN_VALUE("%d", comstat.cbOutQue);
1278 if (ioctl(port->fd, TIOCOUTQ, &bytes_waiting) < 0)
1279 RETURN_FAIL("TIOCOUTQ ioctl failed");
1280 RETURN_VALUE("%d", bytes_waiting);
1284 enum sp_return sp_new_event_set(struct sp_event_set **result_ptr)
1286 struct sp_event_set *result;
1288 TRACE("%p", result_ptr);
1291 RETURN_ERROR(SP_ERR_ARG, "Null result");
1295 if (!(result = malloc(sizeof(struct sp_event_set))))
1296 RETURN_ERROR(SP_ERR_MEM, "sp_event_set malloc() failed");
1298 memset(result, 0, sizeof(struct sp_event_set));
1300 *result_ptr = result;
1305 static enum sp_return add_handle(struct sp_event_set *event_set,
1306 event_handle handle, enum sp_event mask)
1309 enum sp_event *new_masks;
1311 TRACE("%p, %d, %d", event_set, handle, mask);
1313 if (!(new_handles = realloc(event_set->handles,
1314 sizeof(event_handle) * (event_set->count + 1))))
1315 RETURN_ERROR(SP_ERR_MEM, "handle array realloc() failed");
1317 if (!(new_masks = realloc(event_set->masks,
1318 sizeof(enum sp_event) * (event_set->count + 1))))
1319 RETURN_ERROR(SP_ERR_MEM, "mask array realloc() failed");
1321 event_set->handles = new_handles;
1322 event_set->masks = new_masks;
1324 ((event_handle *) event_set->handles)[event_set->count] = handle;
1325 event_set->masks[event_set->count] = mask;
1332 enum sp_return sp_add_port_events(struct sp_event_set *event_set,
1333 const struct sp_port *port, enum sp_event mask)
1335 TRACE("%p, %p, %d", event_set, port, mask);
1338 RETURN_ERROR(SP_ERR_ARG, "Null event set");
1341 RETURN_ERROR(SP_ERR_ARG, "Null port");
1343 if (mask > (SP_EVENT_RX_READY | SP_EVENT_TX_READY | SP_EVENT_ERROR))
1344 RETURN_ERROR(SP_ERR_ARG, "Invalid event mask");
1350 enum sp_event handle_mask;
1351 if ((handle_mask = mask & SP_EVENT_TX_READY))
1352 TRY(add_handle(event_set, port->write_ovl.hEvent, handle_mask));
1353 if ((handle_mask = mask & (SP_EVENT_RX_READY | SP_EVENT_ERROR)))
1354 TRY(add_handle(event_set, port->wait_ovl.hEvent, handle_mask));
1356 TRY(add_handle(event_set, port->fd, mask));
1362 void sp_free_event_set(struct sp_event_set *event_set)
1364 TRACE("%p", event_set);
1367 DEBUG("Null event set");
1371 DEBUG("Freeing event set");
1373 if (event_set->handles)
1374 free(event_set->handles);
1375 if (event_set->masks)
1376 free(event_set->masks);
1383 enum sp_return sp_wait(struct sp_event_set *event_set, unsigned int timeout)
1385 TRACE("%p, %d", event_set, timeout);
1388 RETURN_ERROR(SP_ERR_ARG, "Null event set");
1391 if (WaitForMultipleObjects(event_set->count, event_set->handles, FALSE,
1392 timeout ? timeout : INFINITE) == WAIT_FAILED)
1393 RETURN_FAIL("WaitForMultipleObjects() failed");
1397 struct timeval start, delta, now, end = {0, 0};
1398 int result, timeout_remaining;
1399 struct pollfd *pollfds;
1402 if (!(pollfds = malloc(sizeof(struct pollfd) * event_set->count)))
1403 RETURN_ERROR(SP_ERR_MEM, "pollfds malloc() failed");
1405 for (i = 0; i < event_set->count; i++) {
1406 pollfds[i].fd = ((int *) event_set->handles)[i];
1407 pollfds[i].events = 0;
1408 pollfds[i].revents = 0;
1409 if (event_set->masks[i] & SP_EVENT_RX_READY)
1410 pollfds[i].events |= POLLIN;
1411 if (event_set->masks[i] & SP_EVENT_TX_READY)
1412 pollfds[i].events |= POLLOUT;
1413 if (event_set->masks[i] & SP_EVENT_ERROR)
1414 pollfds[i].events |= POLLERR;
1418 /* Get time at start of operation. */
1419 gettimeofday(&start, NULL);
1420 /* Define duration of timeout. */
1421 delta.tv_sec = timeout / 1000;
1422 delta.tv_usec = (timeout % 1000) * 1000;
1423 /* Calculate time at which we should give up. */
1424 timeradd(&start, &delta, &end);
1427 /* Loop until an event occurs. */
1431 gettimeofday(&now, NULL);
1432 if (timercmp(&now, &end, >)) {
1433 DEBUG("wait timed out");
1436 timersub(&end, &now, &delta);
1437 timeout_remaining = delta.tv_sec * 1000 + delta.tv_usec / 1000;
1440 result = poll(pollfds, event_set->count, timeout ? timeout_remaining : -1);
1443 if (errno == EINTR) {
1444 DEBUG("poll() call was interrupted, repeating");
1448 RETURN_FAIL("poll() failed");
1450 } else if (result == 0) {
1451 DEBUG("poll() timed out");
1454 DEBUG("poll() completed");
1464 #ifdef USE_TERMIOS_SPEED
1465 static enum sp_return get_baudrate(int fd, int *baudrate)
1469 TRACE("%d, %p", fd, baudrate);
1471 DEBUG("Getting baud rate");
1473 if (!(data = malloc(get_termios_size())))
1474 RETURN_ERROR(SP_ERR_MEM, "termios malloc failed");
1476 if (ioctl(fd, get_termios_get_ioctl(), data) < 0) {
1478 RETURN_FAIL("getting termios failed");
1481 *baudrate = get_termios_speed(data);
1488 static enum sp_return set_baudrate(int fd, int baudrate)
1492 TRACE("%d, %d", fd, baudrate);
1494 DEBUG("Getting baud rate");
1496 if (!(data = malloc(get_termios_size())))
1497 RETURN_ERROR(SP_ERR_MEM, "termios malloc failed");
1499 if (ioctl(fd, get_termios_get_ioctl(), data) < 0) {
1501 RETURN_FAIL("getting termios failed");
1504 DEBUG("Setting baud rate");
1506 set_termios_speed(data, baudrate);
1508 if (ioctl(fd, get_termios_set_ioctl(), data) < 0) {
1510 RETURN_FAIL("setting termios failed");
1517 #endif /* USE_TERMIOS_SPEED */
1520 static enum sp_return get_flow(int fd, struct port_data *data)
1524 TRACE("%d, %p", fd, data);
1526 DEBUG("Getting advanced flow control");
1528 if (!(termx = malloc(get_termiox_size())))
1529 RETURN_ERROR(SP_ERR_MEM, "termiox malloc failed");
1531 if (ioctl(fd, TCGETX, termx) < 0) {
1533 RETURN_FAIL("getting termiox failed");
1536 get_termiox_flow(termx, &data->rts_flow, &data->cts_flow,
1537 &data->dtr_flow, &data->dsr_flow);
1544 static enum sp_return set_flow(int fd, struct port_data *data)
1548 TRACE("%d, %p", fd, data);
1550 DEBUG("Getting advanced flow control");
1552 if (!(termx = malloc(get_termiox_size())))
1553 RETURN_ERROR(SP_ERR_MEM, "termiox malloc failed");
1555 if (ioctl(fd, TCGETX, termx) < 0) {
1557 RETURN_FAIL("getting termiox failed");
1560 DEBUG("Setting advanced flow control");
1562 set_termiox_flow(termx, data->rts_flow, data->cts_flow,
1563 data->dtr_flow, data->dsr_flow);
1565 if (ioctl(fd, TCSETX, termx) < 0) {
1567 RETURN_FAIL("setting termiox failed");
1574 #endif /* USE_TERMIOX */
1576 static enum sp_return get_config(struct sp_port *port, struct port_data *data,
1577 struct sp_port_config *config)
1581 TRACE("%p, %p, %p", port, data, config);
1583 DEBUG("Getting configuration for port %s", port->name);
1586 if (!GetCommState(port->hdl, &data->dcb))
1587 RETURN_FAIL("GetCommState() failed");
1589 for (i = 0; i < NUM_STD_BAUDRATES; i++) {
1590 if (data->dcb.BaudRate == std_baudrates[i].index) {
1591 config->baudrate = std_baudrates[i].value;
1596 if (i == NUM_STD_BAUDRATES)
1597 /* BaudRate field can be either an index or a custom baud rate. */
1598 config->baudrate = data->dcb.BaudRate;
1600 config->bits = data->dcb.ByteSize;
1602 if (data->dcb.fParity)
1603 switch (data->dcb.Parity) {
1605 config->parity = SP_PARITY_NONE;
1608 config->parity = SP_PARITY_ODD;
1611 config->parity = SP_PARITY_EVEN;
1614 config->parity = SP_PARITY_MARK;
1617 config->parity = SP_PARITY_SPACE;
1620 config->parity = -1;
1623 config->parity = SP_PARITY_NONE;
1625 switch (data->dcb.StopBits) {
1627 config->stopbits = 1;
1630 config->stopbits = 2;
1633 config->stopbits = -1;
1636 switch (data->dcb.fRtsControl) {
1637 case RTS_CONTROL_DISABLE:
1638 config->rts = SP_RTS_OFF;
1640 case RTS_CONTROL_ENABLE:
1641 config->rts = SP_RTS_ON;
1643 case RTS_CONTROL_HANDSHAKE:
1644 config->rts = SP_RTS_FLOW_CONTROL;
1650 config->cts = data->dcb.fOutxCtsFlow ? SP_CTS_FLOW_CONTROL : SP_CTS_IGNORE;
1652 switch (data->dcb.fDtrControl) {
1653 case DTR_CONTROL_DISABLE:
1654 config->dtr = SP_DTR_OFF;
1656 case DTR_CONTROL_ENABLE:
1657 config->dtr = SP_DTR_ON;
1659 case DTR_CONTROL_HANDSHAKE:
1660 config->dtr = SP_DTR_FLOW_CONTROL;
1666 config->dsr = data->dcb.fOutxDsrFlow ? SP_DSR_FLOW_CONTROL : SP_DSR_IGNORE;
1668 if (data->dcb.fInX) {
1669 if (data->dcb.fOutX)
1670 config->xon_xoff = SP_XONXOFF_INOUT;
1672 config->xon_xoff = SP_XONXOFF_IN;
1674 if (data->dcb.fOutX)
1675 config->xon_xoff = SP_XONXOFF_OUT;
1677 config->xon_xoff = SP_XONXOFF_DISABLED;
1682 if (tcgetattr(port->fd, &data->term) < 0)
1683 RETURN_FAIL("tcgetattr() failed");
1685 if (ioctl(port->fd, TIOCMGET, &data->controlbits) < 0)
1686 RETURN_FAIL("TIOCMGET ioctl failed");
1689 int ret = get_flow(port->fd, data);
1691 if (ret == SP_ERR_FAIL && errno == EINVAL)
1692 data->termiox_supported = 0;
1694 RETURN_CODEVAL(ret);
1696 data->termiox_supported = 1;
1698 data->termiox_supported = 0;
1701 for (i = 0; i < NUM_STD_BAUDRATES; i++) {
1702 if (cfgetispeed(&data->term) == std_baudrates[i].index) {
1703 config->baudrate = std_baudrates[i].value;
1708 if (i == NUM_STD_BAUDRATES) {
1710 config->baudrate = (int)data->term.c_ispeed;
1711 #elif defined(USE_TERMIOS_SPEED)
1712 TRY(get_baudrate(port->fd, &config->baudrate));
1714 config->baudrate = -1;
1718 switch (data->term.c_cflag & CSIZE) {
1735 if (!(data->term.c_cflag & PARENB) && (data->term.c_iflag & IGNPAR))
1736 config->parity = SP_PARITY_NONE;
1737 else if (!(data->term.c_cflag & PARENB) || (data->term.c_iflag & IGNPAR))
1738 config->parity = -1;
1740 else if (data->term.c_cflag & CMSPAR)
1741 config->parity = (data->term.c_cflag & PARODD) ? SP_PARITY_MARK : SP_PARITY_SPACE;
1744 config->parity = (data->term.c_cflag & PARODD) ? SP_PARITY_ODD : SP_PARITY_EVEN;
1746 config->stopbits = (data->term.c_cflag & CSTOPB) ? 2 : 1;
1748 if (data->term.c_cflag & CRTSCTS) {
1749 config->rts = SP_RTS_FLOW_CONTROL;
1750 config->cts = SP_CTS_FLOW_CONTROL;
1752 if (data->termiox_supported && data->rts_flow)
1753 config->rts = SP_RTS_FLOW_CONTROL;
1755 config->rts = (data->controlbits & TIOCM_RTS) ? SP_RTS_ON : SP_RTS_OFF;
1757 config->cts = (data->termiox_supported && data->cts_flow) ?
1758 SP_CTS_FLOW_CONTROL : SP_CTS_IGNORE;
1761 if (data->termiox_supported && data->dtr_flow)
1762 config->dtr = SP_DTR_FLOW_CONTROL;
1764 config->dtr = (data->controlbits & TIOCM_DTR) ? SP_DTR_ON : SP_DTR_OFF;
1766 config->dsr = (data->termiox_supported && data->dsr_flow) ?
1767 SP_DSR_FLOW_CONTROL : SP_DSR_IGNORE;
1769 if (data->term.c_iflag & IXOFF) {
1770 if (data->term.c_iflag & IXON)
1771 config->xon_xoff = SP_XONXOFF_INOUT;
1773 config->xon_xoff = SP_XONXOFF_IN;
1775 if (data->term.c_iflag & IXON)
1776 config->xon_xoff = SP_XONXOFF_OUT;
1778 config->xon_xoff = SP_XONXOFF_DISABLED;
1785 static enum sp_return set_config(struct sp_port *port, struct port_data *data,
1786 const struct sp_port_config *config)
1790 BAUD_TYPE baud_nonstd;
1794 #ifdef USE_TERMIOS_SPEED
1795 int baud_nonstd = 0;
1798 TRACE("%p, %p, %p", port, data, config);
1800 DEBUG("Setting configuration for port %s", port->name);
1803 if (config->baudrate >= 0) {
1804 for (i = 0; i < NUM_STD_BAUDRATES; i++) {
1805 if (config->baudrate == std_baudrates[i].value) {
1806 data->dcb.BaudRate = std_baudrates[i].index;
1811 if (i == NUM_STD_BAUDRATES)
1812 data->dcb.BaudRate = config->baudrate;
1815 if (config->bits >= 0)
1816 data->dcb.ByteSize = config->bits;
1818 if (config->parity >= 0) {
1819 switch (config->parity) {
1820 case SP_PARITY_NONE:
1821 data->dcb.Parity = NOPARITY;
1824 data->dcb.Parity = ODDPARITY;
1826 case SP_PARITY_EVEN:
1827 data->dcb.Parity = EVENPARITY;
1829 case SP_PARITY_MARK:
1830 data->dcb.Parity = MARKPARITY;
1832 case SP_PARITY_SPACE:
1833 data->dcb.Parity = SPACEPARITY;
1836 RETURN_ERROR(SP_ERR_ARG, "Invalid parity setting");
1840 if (config->stopbits >= 0) {
1841 switch (config->stopbits) {
1842 /* Note: There's also ONE5STOPBITS == 1.5 (unneeded so far). */
1844 data->dcb.StopBits = ONESTOPBIT;
1847 data->dcb.StopBits = TWOSTOPBITS;
1850 RETURN_ERROR(SP_ERR_ARG, "Invalid stop bit setting");
1854 if (config->rts >= 0) {
1855 switch (config->rts) {
1857 data->dcb.fRtsControl = RTS_CONTROL_DISABLE;
1860 data->dcb.fRtsControl = RTS_CONTROL_ENABLE;
1862 case SP_RTS_FLOW_CONTROL:
1863 data->dcb.fRtsControl = RTS_CONTROL_HANDSHAKE;
1866 RETURN_ERROR(SP_ERR_ARG, "Invalid RTS setting");
1870 if (config->cts >= 0) {
1871 switch (config->cts) {
1873 data->dcb.fOutxCtsFlow = FALSE;
1875 case SP_CTS_FLOW_CONTROL:
1876 data->dcb.fOutxCtsFlow = TRUE;
1879 RETURN_ERROR(SP_ERR_ARG, "Invalid CTS setting");
1883 if (config->dtr >= 0) {
1884 switch (config->dtr) {
1886 data->dcb.fDtrControl = DTR_CONTROL_DISABLE;
1889 data->dcb.fDtrControl = DTR_CONTROL_ENABLE;
1891 case SP_DTR_FLOW_CONTROL:
1892 data->dcb.fDtrControl = DTR_CONTROL_HANDSHAKE;
1895 RETURN_ERROR(SP_ERR_ARG, "Invalid DTR setting");
1899 if (config->dsr >= 0) {
1900 switch (config->dsr) {
1902 data->dcb.fOutxDsrFlow = FALSE;
1904 case SP_DSR_FLOW_CONTROL:
1905 data->dcb.fOutxDsrFlow = TRUE;
1908 RETURN_ERROR(SP_ERR_ARG, "Invalid DSR setting");
1912 if (config->xon_xoff >= 0) {
1913 switch (config->xon_xoff) {
1914 case SP_XONXOFF_DISABLED:
1915 data->dcb.fInX = FALSE;
1916 data->dcb.fOutX = FALSE;
1919 data->dcb.fInX = TRUE;
1920 data->dcb.fOutX = FALSE;
1922 case SP_XONXOFF_OUT:
1923 data->dcb.fInX = FALSE;
1924 data->dcb.fOutX = TRUE;
1926 case SP_XONXOFF_INOUT:
1927 data->dcb.fInX = TRUE;
1928 data->dcb.fOutX = TRUE;
1931 RETURN_ERROR(SP_ERR_ARG, "Invalid XON/XOFF setting");
1935 if (!SetCommState(port->hdl, &data->dcb))
1936 RETURN_FAIL("SetCommState() failed");
1942 if (config->baudrate >= 0) {
1943 for (i = 0; i < NUM_STD_BAUDRATES; i++) {
1944 if (config->baudrate == std_baudrates[i].value) {
1945 if (cfsetospeed(&data->term, std_baudrates[i].index) < 0)
1946 RETURN_FAIL("cfsetospeed() failed");
1948 if (cfsetispeed(&data->term, std_baudrates[i].index) < 0)
1949 RETURN_FAIL("cfsetispeed() failed");
1954 /* Non-standard baud rate */
1955 if (i == NUM_STD_BAUDRATES) {
1957 /* Set "dummy" baud rate. */
1958 if (cfsetspeed(&data->term, B9600) < 0)
1959 RETURN_FAIL("cfsetspeed() failed");
1960 baud_nonstd = config->baudrate;
1961 #elif defined(USE_TERMIOS_SPEED)
1964 RETURN_ERROR(SP_ERR_SUPP, "Non-standard baudrate not supported");
1969 if (config->bits >= 0) {
1970 data->term.c_cflag &= ~CSIZE;
1971 switch (config->bits) {
1973 data->term.c_cflag |= CS8;
1976 data->term.c_cflag |= CS7;
1979 data->term.c_cflag |= CS6;
1982 data->term.c_cflag |= CS5;
1985 RETURN_ERROR(SP_ERR_ARG, "Invalid data bits setting");
1989 if (config->parity >= 0) {
1990 data->term.c_iflag &= ~IGNPAR;
1991 data->term.c_cflag &= ~(PARENB | PARODD);
1993 data->term.c_cflag &= ~CMSPAR;
1995 switch (config->parity) {
1996 case SP_PARITY_NONE:
1997 data->term.c_iflag |= IGNPAR;
1999 case SP_PARITY_EVEN:
2000 data->term.c_cflag |= PARENB;
2003 data->term.c_cflag |= PARENB | PARODD;
2006 case SP_PARITY_MARK:
2007 data->term.c_cflag |= PARENB | PARODD;
2008 data->term.c_cflag |= CMSPAR;
2010 case SP_PARITY_SPACE:
2011 data->term.c_cflag |= PARENB;
2012 data->term.c_cflag |= CMSPAR;
2015 case SP_PARITY_MARK:
2016 case SP_PARITY_SPACE:
2017 RETURN_ERROR(SP_ERR_SUPP, "Mark/space parity not supported");
2020 RETURN_ERROR(SP_ERR_ARG, "Invalid parity setting");
2024 if (config->stopbits >= 0) {
2025 data->term.c_cflag &= ~CSTOPB;
2026 switch (config->stopbits) {
2028 data->term.c_cflag &= ~CSTOPB;
2031 data->term.c_cflag |= CSTOPB;
2034 RETURN_ERROR(SP_ERR_ARG, "Invalid stop bits setting");
2038 if (config->rts >= 0 || config->cts >= 0) {
2039 if (data->termiox_supported) {
2040 data->rts_flow = data->cts_flow = 0;
2041 switch (config->rts) {
2044 controlbits = TIOCM_RTS;
2045 if (ioctl(port->fd, config->rts == SP_RTS_ON ? TIOCMBIS : TIOCMBIC, &controlbits) < 0)
2046 RETURN_FAIL("Setting RTS signal level failed");
2048 case SP_RTS_FLOW_CONTROL:
2054 if (config->cts == SP_CTS_FLOW_CONTROL)
2057 if (data->rts_flow && data->cts_flow)
2058 data->term.c_iflag |= CRTSCTS;
2060 data->term.c_iflag &= ~CRTSCTS;
2062 /* Asymmetric use of RTS/CTS not supported. */
2063 if (data->term.c_iflag & CRTSCTS) {
2064 /* Flow control can only be disabled for both RTS & CTS together. */
2065 if (config->rts >= 0 && config->rts != SP_RTS_FLOW_CONTROL) {
2066 if (config->cts != SP_CTS_IGNORE)
2067 RETURN_ERROR(SP_ERR_SUPP, "RTS & CTS flow control must be disabled together");
2069 if (config->cts >= 0 && config->cts != SP_CTS_FLOW_CONTROL) {
2070 if (config->rts <= 0 || config->rts == SP_RTS_FLOW_CONTROL)
2071 RETURN_ERROR(SP_ERR_SUPP, "RTS & CTS flow control must be disabled together");
2074 /* Flow control can only be enabled for both RTS & CTS together. */
2075 if (((config->rts == SP_RTS_FLOW_CONTROL) && (config->cts != SP_CTS_FLOW_CONTROL)) ||
2076 ((config->cts == SP_CTS_FLOW_CONTROL) && (config->rts != SP_RTS_FLOW_CONTROL)))
2077 RETURN_ERROR(SP_ERR_SUPP, "RTS & CTS flow control must be enabled together");
2080 if (config->rts >= 0) {
2081 if (config->rts == SP_RTS_FLOW_CONTROL) {
2082 data->term.c_iflag |= CRTSCTS;
2084 controlbits = TIOCM_RTS;
2085 if (ioctl(port->fd, config->rts == SP_RTS_ON ? TIOCMBIS : TIOCMBIC,
2087 RETURN_FAIL("Setting RTS signal level failed");
2093 if (config->dtr >= 0 || config->dsr >= 0) {
2094 if (data->termiox_supported) {
2095 data->dtr_flow = data->dsr_flow = 0;
2096 switch (config->dtr) {
2099 controlbits = TIOCM_DTR;
2100 if (ioctl(port->fd, config->dtr == SP_DTR_ON ? TIOCMBIS : TIOCMBIC, &controlbits) < 0)
2101 RETURN_FAIL("Setting DTR signal level failed");
2103 case SP_DTR_FLOW_CONTROL:
2109 if (config->dsr == SP_DSR_FLOW_CONTROL)
2112 /* DTR/DSR flow control not supported. */
2113 if (config->dtr == SP_DTR_FLOW_CONTROL || config->dsr == SP_DSR_FLOW_CONTROL)
2114 RETURN_ERROR(SP_ERR_SUPP, "DTR/DSR flow control not supported");
2116 if (config->dtr >= 0) {
2117 controlbits = TIOCM_DTR;
2118 if (ioctl(port->fd, config->dtr == SP_DTR_ON ? TIOCMBIS : TIOCMBIC,
2120 RETURN_FAIL("Setting DTR signal level failed");
2125 if (config->xon_xoff >= 0) {
2126 data->term.c_iflag &= ~(IXON | IXOFF | IXANY);
2127 switch (config->xon_xoff) {
2128 case SP_XONXOFF_DISABLED:
2131 data->term.c_iflag |= IXOFF;
2133 case SP_XONXOFF_OUT:
2134 data->term.c_iflag |= IXON | IXANY;
2136 case SP_XONXOFF_INOUT:
2137 data->term.c_iflag |= IXON | IXOFF | IXANY;
2140 RETURN_ERROR(SP_ERR_ARG, "Invalid XON/XOFF setting");
2144 if (tcsetattr(port->fd, TCSANOW, &data->term) < 0)
2145 RETURN_FAIL("tcsetattr() failed");
2148 if (baud_nonstd != B0) {
2149 if (ioctl(port->fd, IOSSIOSPEED, &baud_nonstd) == -1)
2150 RETURN_FAIL("IOSSIOSPEED ioctl failed");
2151 /* Set baud rates in data->term to correct, but incompatible
2152 * with tcsetattr() value, same as delivered by tcgetattr(). */
2153 if (cfsetspeed(&data->term, baud_nonstd) < 0)
2154 RETURN_FAIL("cfsetspeed() failed");
2156 #elif defined(__linux__)
2157 #ifdef USE_TERMIOS_SPEED
2159 TRY(set_baudrate(port->fd, config->baudrate));
2162 if (data->termiox_supported)
2163 TRY(set_flow(port->fd, data));
2167 #endif /* !_WIN32 */
2172 enum sp_return sp_new_config(struct sp_port_config **config_ptr)
2174 struct sp_port_config *config;
2176 TRACE("%p", config_ptr);
2179 RETURN_ERROR(SP_ERR_ARG, "Null result pointer");
2183 if (!(config = malloc(sizeof(struct sp_port_config))))
2184 RETURN_ERROR(SP_ERR_MEM, "config malloc failed");
2186 config->baudrate = -1;
2188 config->parity = -1;
2189 config->stopbits = -1;
2195 *config_ptr = config;
2200 void sp_free_config(struct sp_port_config *config)
2202 TRACE("%p", config);
2205 DEBUG("Null config");
2212 enum sp_return sp_get_config(struct sp_port *port, struct sp_port_config *config)
2214 struct port_data data;
2216 TRACE("%p, %p", port, config);
2221 RETURN_ERROR(SP_ERR_ARG, "Null config");
2223 TRY(get_config(port, &data, config));
2228 enum sp_return sp_set_config(struct sp_port *port, const struct sp_port_config *config)
2230 struct port_data data;
2231 struct sp_port_config prev_config;
2233 TRACE("%p, %p", port, config);
2238 RETURN_ERROR(SP_ERR_ARG, "Null config");
2240 TRY(get_config(port, &data, &prev_config));
2241 TRY(set_config(port, &data, config));
2246 #define CREATE_ACCESSORS(x, type) \
2247 enum sp_return sp_set_##x(struct sp_port *port, type x) { \
2248 struct port_data data; \
2249 struct sp_port_config config; \
2250 TRACE("%p, %d", port, x); \
2251 CHECK_OPEN_PORT(); \
2252 TRY(get_config(port, &data, &config)); \
2254 TRY(set_config(port, &data, &config)); \
2257 enum sp_return sp_get_config_##x(const struct sp_port_config *config, type *x) { \
2258 TRACE("%p, %p", config, x); \
2260 RETURN_ERROR(SP_ERR_ARG, "Null config"); \
2264 enum sp_return sp_set_config_##x(struct sp_port_config *config, type x) { \
2265 TRACE("%p, %d", config, x); \
2267 RETURN_ERROR(SP_ERR_ARG, "Null config"); \
2272 CREATE_ACCESSORS(baudrate, int)
2273 CREATE_ACCESSORS(bits, int)
2274 CREATE_ACCESSORS(parity, enum sp_parity)
2275 CREATE_ACCESSORS(stopbits, int)
2276 CREATE_ACCESSORS(rts, enum sp_rts)
2277 CREATE_ACCESSORS(cts, enum sp_cts)
2278 CREATE_ACCESSORS(dtr, enum sp_dtr)
2279 CREATE_ACCESSORS(dsr, enum sp_dsr)
2280 CREATE_ACCESSORS(xon_xoff, enum sp_xonxoff)
2282 enum sp_return sp_set_config_flowcontrol(struct sp_port_config *config, enum sp_flowcontrol flowcontrol)
2285 RETURN_ERROR(SP_ERR_ARG, "Null configuration");
2287 if (flowcontrol > SP_FLOWCONTROL_DTRDSR)
2288 RETURN_ERROR(SP_ERR_ARG, "Invalid flow control setting");
2290 if (flowcontrol == SP_FLOWCONTROL_XONXOFF)
2291 config->xon_xoff = SP_XONXOFF_INOUT;
2293 config->xon_xoff = SP_XONXOFF_DISABLED;
2295 if (flowcontrol == SP_FLOWCONTROL_RTSCTS) {
2296 config->rts = SP_RTS_FLOW_CONTROL;
2297 config->cts = SP_CTS_FLOW_CONTROL;
2299 if (config->rts == SP_RTS_FLOW_CONTROL)
2300 config->rts = SP_RTS_ON;
2301 config->cts = SP_CTS_IGNORE;
2304 if (flowcontrol == SP_FLOWCONTROL_DTRDSR) {
2305 config->dtr = SP_DTR_FLOW_CONTROL;
2306 config->dsr = SP_DSR_FLOW_CONTROL;
2308 if (config->dtr == SP_DTR_FLOW_CONTROL)
2309 config->dtr = SP_DTR_ON;
2310 config->dsr = SP_DSR_IGNORE;
2316 enum sp_return sp_set_flowcontrol(struct sp_port *port, enum sp_flowcontrol flowcontrol)
2318 struct port_data data;
2319 struct sp_port_config config;
2321 TRACE("%p, %d", port, flowcontrol);
2325 TRY(get_config(port, &data, &config));
2327 TRY(sp_set_config_flowcontrol(&config, flowcontrol));
2329 TRY(set_config(port, &data, &config));
2334 enum sp_return sp_get_signals(struct sp_port *port, enum sp_signal *signals)
2336 TRACE("%p, %p", port, signals);
2341 RETURN_ERROR(SP_ERR_ARG, "Null result pointer");
2343 DEBUG("Getting control signals for port %s", port->name);
2348 if (GetCommModemStatus(port->hdl, &bits) == 0)
2349 RETURN_FAIL("GetCommModemStatus() failed");
2350 if (bits & MS_CTS_ON)
2351 *signals |= SP_SIG_CTS;
2352 if (bits & MS_DSR_ON)
2353 *signals |= SP_SIG_DSR;
2354 if (bits & MS_RLSD_ON)
2355 *signals |= SP_SIG_DCD;
2356 if (bits & MS_RING_ON)
2357 *signals |= SP_SIG_RI;
2360 if (ioctl(port->fd, TIOCMGET, &bits) < 0)
2361 RETURN_FAIL("TIOCMGET ioctl failed");
2362 if (bits & TIOCM_CTS)
2363 *signals |= SP_SIG_CTS;
2364 if (bits & TIOCM_DSR)
2365 *signals |= SP_SIG_DSR;
2366 if (bits & TIOCM_CAR)
2367 *signals |= SP_SIG_DCD;
2368 if (bits & TIOCM_RNG)
2369 *signals |= SP_SIG_RI;
2374 enum sp_return sp_start_break(struct sp_port *port)
2380 if (SetCommBreak(port->hdl) == 0)
2381 RETURN_FAIL("SetCommBreak() failed");
2383 if (ioctl(port->fd, TIOCSBRK, 1) < 0)
2384 RETURN_FAIL("TIOCSBRK ioctl failed");
2390 enum sp_return sp_end_break(struct sp_port *port)
2396 if (ClearCommBreak(port->hdl) == 0)
2397 RETURN_FAIL("ClearCommBreak() failed");
2399 if (ioctl(port->fd, TIOCCBRK, 1) < 0)
2400 RETURN_FAIL("TIOCCBRK ioctl failed");
2406 int sp_last_error_code(void)
2410 RETURN_VALUE("%d", GetLastError());
2412 RETURN_VALUE("%d", errno);
2416 char *sp_last_error_message(void)
2422 DWORD error = GetLastError();
2425 FORMAT_MESSAGE_ALLOCATE_BUFFER |
2426 FORMAT_MESSAGE_FROM_SYSTEM |
2427 FORMAT_MESSAGE_IGNORE_INSERTS,
2430 MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
2434 RETURN_VALUE("%s", message);
2436 RETURN_VALUE("%s", strerror(errno));
2440 void sp_free_error_message(char *message)
2442 TRACE("%s", message);
2453 void sp_set_debug_handler(void (*handler)(const char *format, ...))
2455 TRACE("%p", handler);
2457 sp_debug_handler = handler;
2462 void sp_default_debug_handler(const char *format, ...)
2465 va_start(args, format);
2466 if (getenv("LIBSERIALPORT_DEBUG")) {
2467 fputs("sp: ", stderr);
2468 vfprintf(stderr, format, args);
2473 int sp_get_major_package_version(void)
2475 return SP_PACKAGE_VERSION_MAJOR;
2478 int sp_get_minor_package_version(void)
2480 return SP_PACKAGE_VERSION_MINOR;
2483 int sp_get_micro_package_version(void)
2485 return SP_PACKAGE_VERSION_MICRO;
2488 const char *sp_get_package_version_string(void)
2490 return SP_PACKAGE_VERSION_STRING;
2493 int sp_get_current_lib_version(void)
2495 return SP_LIB_VERSION_CURRENT;
2498 int sp_get_revision_lib_version(void)
2500 return SP_LIB_VERSION_REVISION;
2503 int sp_get_age_lib_version(void)
2505 return SP_LIB_VERSION_AGE;
2508 const char *sp_get_lib_version_string(void)
2510 return SP_LIB_VERSION_STRING;