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>
41 #include <IOKit/IOKitLib.h>
42 #include <IOKit/serial/IOSerialKeys.h>
43 #include <IOKit/serial/ioss.h>
44 #include <sys/syslimits.h>
48 #include "linux/serial.h"
49 #include "linux_termios.h"
50 #if defined(TCGETX) && defined(TCSETX) && defined(HAVE_TERMIOX)
56 #include "linux_termios.h"
59 #include "libserialport.h"
76 int termiox_supported;
81 /* Standard baud rates. */
83 #define BAUD_TYPE DWORD
84 #define BAUD(n) {CBR_##n, n}
86 #define BAUD_TYPE speed_t
87 #define BAUD(n) {B##n, n}
95 const struct std_baudrate std_baudrates[] = {
98 * The baudrates 50/75/134/150/200/1800/230400/460800 do not seem to
99 * have documented CBR_* macros.
101 BAUD(110), BAUD(300), BAUD(600), BAUD(1200), BAUD(2400), BAUD(4800),
102 BAUD(9600), BAUD(14400), BAUD(19200), BAUD(38400), BAUD(57600),
103 BAUD(115200), BAUD(128000), BAUD(256000),
105 BAUD(50), BAUD(75), BAUD(110), BAUD(134), BAUD(150), BAUD(200),
106 BAUD(300), BAUD(600), BAUD(1200), BAUD(1800), BAUD(2400), BAUD(4800),
107 BAUD(9600), BAUD(19200), BAUD(38400), BAUD(57600), BAUD(115200),
109 #if !defined(__APPLE__) && !defined(__OpenBSD__)
115 void (*sp_debug_handler)(const char *format, ...) = sp_default_debug_handler;
117 #define ARRAY_SIZE(x) (sizeof(x) / sizeof(x[0]))
118 #define NUM_STD_BAUDRATES ARRAY_SIZE(std_baudrates)
120 /* Debug output macros. */
121 #define DEBUG(fmt, ...) do { if (sp_debug_handler) sp_debug_handler(fmt ".\n", ##__VA_ARGS__); } while (0)
122 #define DEBUG_ERROR(err, msg) DEBUG("%s returning " #err ": " msg, __func__)
123 #define DEBUG_FAIL(msg) do { \
124 char *errmsg = sp_last_error_message(); \
125 DEBUG("%s returning SP_ERR_FAIL: " msg ": %s", __func__, errmsg); \
126 sp_free_error_message(errmsg); \
128 #define RETURN() do { DEBUG("%s returning", __func__); return; } while(0)
129 #define RETURN_CODE(x) do { DEBUG("%s returning " #x, __func__); return x; } while (0)
130 #define RETURN_CODEVAL(x) do { \
132 case SP_OK: RETURN_CODE(SP_OK); \
133 case SP_ERR_ARG: RETURN_CODE(SP_ERR_ARG); \
134 case SP_ERR_FAIL: RETURN_CODE(SP_ERR_FAIL); \
135 case SP_ERR_MEM: RETURN_CODE(SP_ERR_MEM); \
136 case SP_ERR_SUPP: RETURN_CODE(SP_ERR_SUPP); \
139 #define RETURN_OK() RETURN_CODE(SP_OK);
140 #define RETURN_ERROR(err, msg) do { DEBUG_ERROR(err, msg); return err; } while (0)
141 #define RETURN_FAIL(msg) do { DEBUG_FAIL(msg); return SP_ERR_FAIL; } while (0)
142 #define RETURN_VALUE(fmt, x) do { DEBUG("%s returning " fmt, __func__, x); return x; } while (0)
143 #define SET_ERROR(val, err, msg) do { DEBUG_ERROR(err, msg); val = err; } while (0)
144 #define SET_FAIL(val, msg) do { DEBUG_FAIL(msg); val = err; } while (0)
145 #define TRACE(fmt, ...) DEBUG("%s(" fmt ") called", __func__, ##__VA_ARGS__)
147 #define TRY(x) do { int ret = x; if (ret != SP_OK) RETURN_CODEVAL(ret); } while (0)
149 /* Helper functions. */
150 static struct sp_port **list_append(struct sp_port **list, const char *portname);
151 static enum sp_return get_config(struct sp_port *port, struct port_data *data,
152 struct sp_port_config *config);
153 static enum sp_return set_config(struct sp_port *port, struct port_data *data,
154 const struct sp_port_config *config);
156 enum sp_return sp_get_port_by_name(const char *portname, struct sp_port **port_ptr)
158 struct sp_port *port;
161 TRACE("%s, %p", portname, port_ptr);
164 RETURN_ERROR(SP_ERR_ARG, "Null result pointer");
169 RETURN_ERROR(SP_ERR_ARG, "Null port name");
171 DEBUG("Building structure for port %s", portname);
173 if (!(port = malloc(sizeof(struct sp_port))))
174 RETURN_ERROR(SP_ERR_MEM, "Port structure malloc failed");
176 len = strlen(portname) + 1;
178 if (!(port->name = malloc(len))) {
180 RETURN_ERROR(SP_ERR_MEM, "Port name malloc failed");
183 memcpy(port->name, portname, len);
186 port->hdl = INVALID_HANDLE_VALUE;
196 char *sp_get_port_name(const struct sp_port *port)
203 RETURN_VALUE("%s", port->name);
206 enum sp_return sp_copy_port(const struct sp_port *port, struct sp_port **copy_ptr)
208 TRACE("%p, %p", port, copy_ptr);
211 RETURN_ERROR(SP_ERR_ARG, "Null result pointer");
216 RETURN_ERROR(SP_ERR_ARG, "Null port");
219 RETURN_ERROR(SP_ERR_ARG, "Null port name");
221 DEBUG("Copying port structure");
223 RETURN_VALUE("%p", sp_get_port_by_name(port->name, copy_ptr));
226 void sp_free_port(struct sp_port *port)
236 DEBUG("Freeing port structure");
246 static struct sp_port **list_append(struct sp_port **list, const char *portname)
251 for (count = 0; list[count]; count++);
252 if (!(tmp = realloc(list, sizeof(struct sp_port *) * (count + 2))))
255 if (sp_get_port_by_name(portname, &list[count]) != SP_OK)
257 list[count + 1] = NULL;
261 sp_free_port_list(list);
265 enum sp_return sp_list_ports(struct sp_port ***list_ptr)
267 struct sp_port **list;
268 int ret = SP_ERR_SUPP;
270 TRACE("%p", list_ptr);
273 RETURN_ERROR(SP_ERR_ARG, "Null result pointer");
275 DEBUG("Enumerating ports");
277 if (!(list = malloc(sizeof(struct sp_port **))))
278 RETURN_ERROR(SP_ERR_MEM, "Port list malloc failed");
285 DWORD max_value_len, max_data_size, max_data_len;
286 DWORD value_len, data_size, data_len;
287 DWORD type, index = 0;
293 DEBUG("Opening registry key");
294 if (RegOpenKeyEx(HKEY_LOCAL_MACHINE, _T("HARDWARE\\DEVICEMAP\\SERIALCOMM"),
295 0, KEY_QUERY_VALUE, &key) != ERROR_SUCCESS) {
296 SET_FAIL(ret, "RegOpenKeyEx() failed");
299 DEBUG("Querying registry key value and data sizes");
300 if (RegQueryInfoKey(key, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
301 &max_value_len, &max_data_size, NULL, NULL) != ERROR_SUCCESS) {
302 SET_FAIL(ret, "RegQueryInfoKey() failed");
305 max_data_len = max_data_size / sizeof(TCHAR);
306 if (!(value = malloc((max_value_len + 1) * sizeof(TCHAR)))) {
307 SET_ERROR(ret, SP_ERR_MEM, "registry value malloc failed");
310 if (!(data = malloc((max_data_len + 1) * sizeof(TCHAR)))) {
311 SET_ERROR(ret, SP_ERR_MEM, "registry data malloc failed");
314 DEBUG("Iterating over values");
316 value_len = max_value_len + 1,
317 data_size = max_data_size,
318 RegEnumValue(key, index, value, &value_len,
319 NULL, &type, (LPBYTE)data, &data_size) == ERROR_SUCCESS)
321 data_len = data_size / sizeof(TCHAR);
322 data[data_len] = '\0';
324 name_len = WideCharToMultiByte(CP_ACP, 0, data, -1, NULL, 0, NULL, NULL)
326 name_len = data_len + 1;
328 if (!(name = malloc(name_len))) {
329 SET_ERROR(ret, SP_ERR_MEM, "registry port name malloc failed");
333 WideCharToMultiByte(CP_ACP, 0, data, -1, name, name_len, NULL, NULL);
337 if (type == REG_SZ) {
338 DEBUG("Found port %s", name);
339 if (!(list = list_append(list, name))) {
340 SET_ERROR(ret, SP_ERR_MEM, "list append failed");
356 CFMutableDictionaryRef classes;
365 DEBUG("Getting IOKit master port");
366 if (IOMasterPort(MACH_PORT_NULL, &master) != KERN_SUCCESS) {
367 SET_FAIL(ret, "IOMasterPort() failed");
371 DEBUG("Creating matching dictionary");
372 if (!(classes = IOServiceMatching(kIOSerialBSDServiceValue))) {
373 SET_FAIL(ret, "IOServiceMatching() failed");
377 CFDictionarySetValue(classes,
378 CFSTR(kIOSerialBSDTypeKey), CFSTR(kIOSerialBSDAllTypes));
380 DEBUG("Getting matching services");
381 if (IOServiceGetMatchingServices(master, classes, &iter) != KERN_SUCCESS) {
382 SET_FAIL(ret, "IOServiceGetMatchingServices() failed");
386 if (!(path = malloc(PATH_MAX))) {
387 SET_ERROR(ret, SP_ERR_MEM, "device path malloc failed");
391 DEBUG("Iterating over results");
392 while ((port = IOIteratorNext(iter))) {
393 cf_path = IORegistryEntryCreateCFProperty(port,
394 CFSTR(kIOCalloutDeviceKey), kCFAllocatorDefault, 0);
396 result = CFStringGetCString(cf_path,
397 path, PATH_MAX, kCFStringEncodingASCII);
400 DEBUG("Found port %s", path);
401 if (!(list = list_append(list, path))) {
402 SET_ERROR(ret, SP_ERR_MEM, "list append failed");
403 IOObjectRelease(port);
408 IOObjectRelease(port);
413 IOObjectRelease(iter);
418 struct udev_enumerate *ud_enumerate;
419 struct udev_list_entry *ud_list;
420 struct udev_list_entry *ud_entry;
422 struct udev_device *ud_dev, *ud_parent;
425 int fd, ioctl_result;
426 struct serial_struct serial_info;
430 DEBUG("Enumerating tty devices");
432 ud_enumerate = udev_enumerate_new(ud);
433 udev_enumerate_add_match_subsystem(ud_enumerate, "tty");
434 udev_enumerate_scan_devices(ud_enumerate);
435 ud_list = udev_enumerate_get_list_entry(ud_enumerate);
436 DEBUG("Iterating over results");
437 udev_list_entry_foreach(ud_entry, ud_list) {
438 path = udev_list_entry_get_name(ud_entry);
439 DEBUG("Found device %s", path);
440 ud_dev = udev_device_new_from_syspath(ud, path);
441 /* If there is no parent device, this is a virtual tty. */
442 ud_parent = udev_device_get_parent(ud_dev);
443 if (ud_parent == NULL) {
444 DEBUG("No parent device, assuming virtual tty");
445 udev_device_unref(ud_dev);
448 name = udev_device_get_devnode(ud_dev);
449 /* The serial8250 driver has a hardcoded number of ports.
450 * The only way to tell which actually exist on a given system
451 * is to try to open them and make an ioctl call. */
452 driver = udev_device_get_driver(ud_parent);
453 if (driver && !strcmp(driver, "serial8250")) {
454 DEBUG("serial8250 device, attempting to open");
455 if ((fd = open(name, O_RDWR | O_NONBLOCK | O_NOCTTY)) < 0) {
456 DEBUG("open failed, skipping");
459 ioctl_result = ioctl(fd, TIOCGSERIAL, &serial_info);
461 if (ioctl_result != 0) {
462 DEBUG("ioctl failed, skipping");
465 if (serial_info.type == PORT_UNKNOWN) {
466 DEBUG("port type is unknown, skipping");
470 DEBUG("Found port %s", name);
471 list = list_append(list, name);
473 udev_device_unref(ud_dev);
475 SET_ERROR(ret, SP_ERR_MEM, "list append failed");
480 udev_enumerate_unref(ud_enumerate);
489 DEBUG_ERROR(SP_ERR_SUPP, "Enumeration not supported on this platform.");
492 sp_free_port_list(list);
498 void sp_free_port_list(struct sp_port **list)
509 DEBUG("Freeing port list");
511 for (i = 0; list[i]; i++)
512 sp_free_port(list[i]);
518 #define CHECK_PORT() do { \
520 RETURN_ERROR(SP_ERR_ARG, "Null port"); \
521 if (port->name == NULL) \
522 RETURN_ERROR(SP_ERR_ARG, "Null port name"); \
525 #define CHECK_PORT_HANDLE() do { \
526 if (port->hdl == INVALID_HANDLE_VALUE) \
527 RETURN_ERROR(SP_ERR_ARG, "Invalid port handle"); \
530 #define CHECK_PORT_HANDLE() do { \
532 RETURN_ERROR(SP_ERR_ARG, "Invalid port fd"); \
535 #define CHECK_OPEN_PORT() do { \
537 CHECK_PORT_HANDLE(); \
540 enum sp_return sp_open(struct sp_port *port, enum sp_mode flags)
542 TRACE("%p, %x", port, flags);
546 if (flags > (SP_MODE_READ | SP_MODE_WRITE | SP_MODE_NONBLOCK))
547 RETURN_ERROR(SP_ERR_ARG, "Invalid flags");
549 DEBUG("Opening port %s", port->name);
552 DWORD desired_access = 0, flags_and_attributes = 0;
553 char *escaped_port_name;
555 /* Prefix port name with '\\.\' to work with ports above COM9. */
556 if (!(escaped_port_name = malloc(strlen(port->name + 5))))
557 RETURN_ERROR(SP_ERR_MEM, "Escaped port name malloc failed");
558 sprintf(escaped_port_name, "\\\\.\\%s", port->name);
560 /* Map 'flags' to the OS-specific settings. */
561 flags_and_attributes = FILE_ATTRIBUTE_NORMAL;
562 if (flags & SP_MODE_READ)
563 desired_access |= GENERIC_READ;
564 if (flags & SP_MODE_WRITE)
565 desired_access |= GENERIC_WRITE;
566 if (flags & SP_MODE_NONBLOCK)
567 flags_and_attributes |= FILE_FLAG_OVERLAPPED;
569 port->hdl = CreateFile(escaped_port_name, desired_access, 0, 0,
570 OPEN_EXISTING, flags_and_attributes, 0);
572 free(escaped_port_name);
574 if (port->hdl == INVALID_HANDLE_VALUE)
575 RETURN_FAIL("CreateFile() failed");
578 struct port_data data;
579 struct sp_port_config config;
582 /* Map 'flags' to the OS-specific settings. */
583 if (flags & (SP_MODE_READ | SP_MODE_WRITE))
584 flags_local |= O_RDWR;
585 else if (flags & SP_MODE_READ)
586 flags_local |= O_RDONLY;
587 else if (flags & SP_MODE_WRITE)
588 flags_local |= O_WRONLY;
589 if (flags & SP_MODE_NONBLOCK)
590 flags_local |= O_NONBLOCK;
592 if ((port->fd = open(port->name, flags_local)) < 0)
593 RETURN_FAIL("open() failed");
595 ret = get_config(port, &data, &config);
602 /* Turn off all serial port cooking. */
603 data.term.c_iflag &= ~(ISTRIP | INLCR | ICRNL);
604 data.term.c_oflag &= ~(ONLCR | OCRNL | ONOCR);
605 #if !defined(__FreeBSD__) && !defined(__OpenBSD__) && !defined(__NetBSD__)
606 data.term.c_oflag &= ~OFILL;
608 /* Disable canonical mode, and don't echo input characters. */
609 data.term.c_lflag &= ~(ICANON | ECHO);
611 /* Ignore modem status lines; enable receiver */
612 data.term.c_cflag |= (CLOCAL | CREAD);
614 ret = set_config(port, &data, &config);
625 enum sp_return sp_close(struct sp_port *port)
631 DEBUG("Closing port %s", port->name);
634 /* Returns non-zero upon success, 0 upon failure. */
635 if (CloseHandle(port->hdl) == 0)
636 RETURN_FAIL("CloseHandle() failed");
637 port->hdl = INVALID_HANDLE_VALUE;
639 /* Returns 0 upon success, -1 upon failure. */
640 if (close(port->fd) == -1)
641 RETURN_FAIL("close() failed");
648 enum sp_return sp_flush(struct sp_port *port, enum sp_buffer buffers)
650 TRACE("%p, %x", port, buffers);
654 if (buffers > SP_BUF_BOTH)
655 RETURN_ERROR(SP_ERR_ARG, "Invalid buffer selection");
657 const char *buffer_names[] = {"input", "output", "both"};
659 DEBUG("Flushing %s buffers on port %s", buffer_names[buffers], port->name);
663 if (buffers & SP_BUF_INPUT)
664 flags |= PURGE_RXCLEAR;
665 if (buffers & SP_BUF_OUTPUT)
666 flags |= PURGE_TXCLEAR;
668 /* Returns non-zero upon success, 0 upon failure. */
669 if (PurgeComm(port->hdl, flags) == 0)
670 RETURN_FAIL("PurgeComm() failed");
673 if (buffers & SP_BUF_BOTH)
675 else if (buffers & SP_BUF_INPUT)
677 else if (buffers & SP_BUF_OUTPUT)
680 /* Returns 0 upon success, -1 upon failure. */
681 if (tcflush(port->fd, flags) < 0)
682 RETURN_FAIL("tcflush() failed");
687 enum sp_return sp_drain(struct sp_port *port)
693 DEBUG("Draining port %s", port->name);
696 /* Returns non-zero upon success, 0 upon failure. */
697 if (FlushFileBuffers(port->hdl) == 0)
698 RETURN_FAIL("FlushFileBuffers() failed");
700 /* Returns 0 upon success, -1 upon failure. */
701 if (tcdrain(port->fd) < 0)
702 RETURN_FAIL("tcdrain() failed");
708 enum sp_return sp_write(struct sp_port *port, const void *buf, size_t count)
710 TRACE("%p, %p, %d", port, buf, count);
715 RETURN_ERROR(SP_ERR_ARG, "Null buffer");
717 DEBUG("Writing up to %d bytes to port %s", count, port->name);
722 /* Returns non-zero upon success, 0 upon failure. */
723 if (WriteFile(port->hdl, buf, count, &written, NULL) == 0)
724 RETURN_FAIL("WriteFile() failed");
725 RETURN_VALUE("%d", written);
727 /* Returns the number of bytes written, or -1 upon failure. */
728 ssize_t written = write(port->fd, buf, count);
731 RETURN_FAIL("write() failed");
733 RETURN_VALUE("%d", written);
737 enum sp_return sp_read(struct sp_port *port, void *buf, size_t count)
739 TRACE("%p, %p, %d", port, buf, count);
744 RETURN_ERROR(SP_ERR_ARG, "Null buffer");
746 DEBUG("Reading up to %d bytes from port %s", count, port->name);
749 DWORD bytes_read = 0;
751 /* Returns non-zero upon success, 0 upon failure. */
752 if (ReadFile(port->hdl, buf, count, &bytes_read, NULL) == 0)
753 RETURN_FAIL("ReadFile() failed");
754 RETURN_VALUE("%d", bytes_read);
758 /* Returns the number of bytes read, or -1 upon failure. */
759 if ((bytes_read = read(port->fd, buf, count)) < 0)
760 RETURN_FAIL("read() failed");
761 RETURN_VALUE("%d", bytes_read);
766 static enum sp_return get_baudrate(int fd, int *baudrate)
770 TRACE("%d, %p", fd, baudrate);
772 DEBUG("Getting baud rate");
774 if (!(data = malloc(get_termios_size())))
775 RETURN_ERROR(SP_ERR_MEM, "termios malloc failed");
777 if (ioctl(fd, get_termios_get_ioctl(), data) < 0) {
779 RETURN_FAIL("getting termios failed");
782 *baudrate = get_termios_speed(data);
789 static enum sp_return set_baudrate(int fd, int baudrate)
793 TRACE("%d, %d", fd, baudrate);
795 DEBUG("Getting baud rate");
797 if (!(data = malloc(get_termios_size())))
798 RETURN_ERROR(SP_ERR_MEM, "termios malloc failed");
800 if (ioctl(fd, get_termios_get_ioctl(), data) < 0) {
802 RETURN_FAIL("getting termios failed");
805 DEBUG("Setting baud rate");
807 set_termios_speed(data, baudrate);
809 if (ioctl(fd, get_termios_set_ioctl(), data) < 0) {
811 RETURN_FAIL("setting termios failed");
820 static enum sp_return get_flow(int fd, int *flow)
824 TRACE("%d, %p", fd, flow);
826 DEBUG("Getting advanced flow control");
828 if (!(data = malloc(get_termiox_size())))
829 RETURN_ERROR(SP_ERR_MEM, "termiox malloc failed");
831 if (ioctl(fd, TCGETX, data) < 0) {
833 RETURN_FAIL("getting termiox failed");
836 *flow = get_termiox_flow(data);
843 static enum sp_return set_flow(int fd, int flow)
847 TRACE("%d, %d", fd, flow);
849 DEBUG("Getting advanced flow control");
851 if (!(data = malloc(get_termiox_size())))
852 RETURN_ERROR(SP_ERR_MEM, "termiox malloc failed");
854 if (ioctl(fd, TCGETX, data) < 0) {
856 RETURN_FAIL("getting termiox failed");
859 DEBUG("Setting advanced flow control");
861 set_termiox_flow(data, flow);
863 if (ioctl(fd, TCSETX, data) < 0) {
865 RETURN_FAIL("setting termiox failed");
872 #endif /* USE_TERMIOX */
873 #endif /* __linux__ */
875 static enum sp_return get_config(struct sp_port *port, struct port_data *data,
876 struct sp_port_config *config)
880 TRACE("%p, %p, %p", port, data, config);
882 DEBUG("Getting configuration for port %s", port->name);
885 if (!GetCommState(port->hdl, &data->dcb))
886 RETURN_FAIL("GetCommState() failed");
888 for (i = 0; i < NUM_STD_BAUDRATES; i++) {
889 if (data->dcb.BaudRate == std_baudrates[i].index) {
890 config->baudrate = std_baudrates[i].value;
895 if (i == NUM_STD_BAUDRATES)
896 /* BaudRate field can be either an index or a custom baud rate. */
897 config->baudrate = data->dcb.BaudRate;
899 config->bits = data->dcb.ByteSize;
901 if (data->dcb.fParity)
902 switch (data->dcb.Parity) {
904 config->parity = SP_PARITY_NONE;
907 config->parity = SP_PARITY_EVEN;
910 config->parity = SP_PARITY_ODD;
916 config->parity = SP_PARITY_NONE;
918 switch (data->dcb.StopBits) {
920 config->stopbits = 1;
923 config->stopbits = 2;
926 config->stopbits = -1;
929 switch (data->dcb.fRtsControl) {
930 case RTS_CONTROL_DISABLE:
931 config->rts = SP_RTS_OFF;
933 case RTS_CONTROL_ENABLE:
934 config->rts = SP_RTS_ON;
936 case RTS_CONTROL_HANDSHAKE:
937 config->rts = SP_RTS_FLOW_CONTROL;
943 config->cts = data->dcb.fOutxCtsFlow ? SP_CTS_FLOW_CONTROL : SP_CTS_IGNORE;
945 switch (data->dcb.fDtrControl) {
946 case DTR_CONTROL_DISABLE:
947 config->dtr = SP_DTR_OFF;
949 case DTR_CONTROL_ENABLE:
950 config->dtr = SP_DTR_ON;
952 case DTR_CONTROL_HANDSHAKE:
953 config->dtr = SP_DTR_FLOW_CONTROL;
959 config->dsr = data->dcb.fOutxDsrFlow ? SP_DSR_FLOW_CONTROL : SP_DSR_IGNORE;
961 if (data->dcb.fInX) {
963 config->xon_xoff = SP_XONXOFF_INOUT;
965 config->xon_xoff = SP_XONXOFF_IN;
968 config->xon_xoff = SP_XONXOFF_OUT;
970 config->xon_xoff = SP_XONXOFF_DISABLED;
975 if (tcgetattr(port->fd, &data->term) < 0)
976 RETURN_FAIL("tcgetattr() failed");
978 if (ioctl(port->fd, TIOCMGET, &data->controlbits) < 0)
979 RETURN_FAIL("TIOCMGET ioctl failed");
982 int ret = get_flow(port->fd, &data->flow);
984 if (ret == SP_ERR_FAIL && errno == EINVAL)
985 data->termiox_supported = 0;
989 data->termiox_supported = 1;
991 data->termiox_supported = 0;
994 for (i = 0; i < NUM_STD_BAUDRATES; i++) {
995 if (cfgetispeed(&data->term) == std_baudrates[i].index) {
996 config->baudrate = std_baudrates[i].value;
1001 if (i == NUM_STD_BAUDRATES) {
1003 config->baudrate = (int)data->term.c_ispeed;
1004 #elif defined(__linux__)
1005 TRY(get_baudrate(port->fd, &config->baudrate));
1007 config->baudrate = -1;
1011 switch (data->term.c_cflag & CSIZE) {
1028 if (!(data->term.c_cflag & PARENB) && (data->term.c_iflag & IGNPAR))
1029 config->parity = SP_PARITY_NONE;
1030 else if (!(data->term.c_cflag & PARENB) || (data->term.c_iflag & IGNPAR))
1031 config->parity = -1;
1033 config->parity = (data->term.c_cflag & PARODD) ? SP_PARITY_ODD : SP_PARITY_EVEN;
1035 config->stopbits = (data->term.c_cflag & CSTOPB) ? 2 : 1;
1037 if (data->term.c_cflag & CRTSCTS) {
1038 config->rts = SP_RTS_FLOW_CONTROL;
1039 config->cts = SP_CTS_FLOW_CONTROL;
1041 if (data->termiox_supported && data->flow & RTS_FLOW)
1042 config->rts = SP_RTS_FLOW_CONTROL;
1044 config->rts = (data->controlbits & TIOCM_RTS) ? SP_RTS_ON : SP_RTS_OFF;
1046 config->cts = (data->termiox_supported && data->flow & CTS_FLOW) ?
1047 SP_CTS_FLOW_CONTROL : SP_CTS_IGNORE;
1050 if (data->termiox_supported && data->flow & DTR_FLOW)
1051 config->dtr = SP_DTR_FLOW_CONTROL;
1053 config->dtr = (data->controlbits & TIOCM_DTR) ? SP_DTR_ON : SP_DTR_OFF;
1055 config->dsr = (data->termiox_supported && data->flow & DSR_FLOW) ?
1056 SP_DSR_FLOW_CONTROL : SP_DSR_IGNORE;
1058 if (data->term.c_iflag & IXOFF) {
1059 if (data->term.c_iflag & IXON)
1060 config->xon_xoff = SP_XONXOFF_INOUT;
1062 config->xon_xoff = SP_XONXOFF_IN;
1064 if (data->term.c_iflag & IXON)
1065 config->xon_xoff = SP_XONXOFF_OUT;
1067 config->xon_xoff = SP_XONXOFF_DISABLED;
1074 static enum sp_return set_config(struct sp_port *port, struct port_data *data,
1075 const struct sp_port_config *config)
1079 BAUD_TYPE baud_nonstd;
1084 int baud_nonstd = 0;
1087 TRACE("%p, %p, %p", port, data, config);
1089 DEBUG("Setting configuration for port %s", port->name);
1092 if (config->baudrate >= 0) {
1093 for (i = 0; i < NUM_STD_BAUDRATES; i++) {
1094 if (config->baudrate == std_baudrates[i].value) {
1095 data->dcb.BaudRate = std_baudrates[i].index;
1100 if (i == NUM_STD_BAUDRATES)
1101 data->dcb.BaudRate = config->baudrate;
1104 if (config->bits >= 0)
1105 data->dcb.ByteSize = config->bits;
1107 if (config->parity >= 0) {
1108 switch (config->parity) {
1109 /* Note: There's also SPACEPARITY, MARKPARITY (unneeded so far). */
1110 case SP_PARITY_NONE:
1111 data->dcb.Parity = NOPARITY;
1113 case SP_PARITY_EVEN:
1114 data->dcb.Parity = EVENPARITY;
1117 data->dcb.Parity = ODDPARITY;
1120 RETURN_ERROR(SP_ERR_ARG, "Invalid parity setting");
1124 if (config->stopbits >= 0) {
1125 switch (config->stopbits) {
1126 /* Note: There's also ONE5STOPBITS == 1.5 (unneeded so far). */
1128 data->dcb.StopBits = ONESTOPBIT;
1131 data->dcb.StopBits = TWOSTOPBITS;
1134 RETURN_ERROR(SP_ERR_ARG, "Invalid stop bit setting");
1138 if (config->rts >= 0) {
1139 switch (config->rts) {
1141 data->dcb.fRtsControl = RTS_CONTROL_DISABLE;
1144 data->dcb.fRtsControl = RTS_CONTROL_ENABLE;
1146 case SP_RTS_FLOW_CONTROL:
1147 data->dcb.fRtsControl = RTS_CONTROL_HANDSHAKE;
1150 RETURN_ERROR(SP_ERR_ARG, "Invalid RTS setting");
1154 if (config->cts >= 0) {
1155 switch (config->cts) {
1157 data->dcb.fOutxCtsFlow = FALSE;
1159 case SP_CTS_FLOW_CONTROL:
1160 data->dcb.fOutxCtsFlow = TRUE;
1163 RETURN_ERROR(SP_ERR_ARG, "Invalid CTS setting");
1167 if (config->dtr >= 0) {
1168 switch (config->dtr) {
1170 data->dcb.fDtrControl = DTR_CONTROL_DISABLE;
1173 data->dcb.fDtrControl = DTR_CONTROL_ENABLE;
1175 case SP_DTR_FLOW_CONTROL:
1176 data->dcb.fDtrControl = DTR_CONTROL_HANDSHAKE;
1179 RETURN_ERROR(SP_ERR_ARG, "Invalid DTR setting");
1183 if (config->dsr >= 0) {
1184 switch (config->dsr) {
1186 data->dcb.fOutxDsrFlow = FALSE;
1188 case SP_DSR_FLOW_CONTROL:
1189 data->dcb.fOutxDsrFlow = TRUE;
1192 RETURN_ERROR(SP_ERR_ARG, "Invalid DSR setting");
1196 if (config->xon_xoff >= 0) {
1197 switch (config->xon_xoff) {
1198 case SP_XONXOFF_DISABLED:
1199 data->dcb.fInX = FALSE;
1200 data->dcb.fOutX = FALSE;
1203 data->dcb.fInX = TRUE;
1204 data->dcb.fOutX = FALSE;
1206 case SP_XONXOFF_OUT:
1207 data->dcb.fInX = FALSE;
1208 data->dcb.fOutX = TRUE;
1210 case SP_XONXOFF_INOUT:
1211 data->dcb.fInX = TRUE;
1212 data->dcb.fOutX = TRUE;
1215 RETURN_ERROR(SP_ERR_ARG, "Invalid XON/XOFF setting");
1219 if (!SetCommState(port->hdl, &data->dcb))
1220 RETURN_FAIL("SetCommState() failed");
1226 if (config->baudrate >= 0) {
1227 for (i = 0; i < NUM_STD_BAUDRATES; i++) {
1228 if (config->baudrate == std_baudrates[i].value) {
1229 if (cfsetospeed(&data->term, std_baudrates[i].index) < 0)
1230 RETURN_FAIL("cfsetospeed() failed");
1232 if (cfsetispeed(&data->term, std_baudrates[i].index) < 0)
1233 RETURN_FAIL("cfsetispeed() failed");
1238 /* Non-standard baud rate */
1239 if (i == NUM_STD_BAUDRATES) {
1241 /* Set "dummy" baud rate. */
1242 if (cfsetspeed(&data->term, B9600) < 0)
1243 RETURN_FAIL("cfsetspeed() failed");
1244 baud_nonstd = config->baudrate;
1245 #elif defined(__linux__)
1248 RETURN_ERROR(SP_ERR_SUPP, "Non-standard baudrate not supported");
1253 if (config->bits >= 0) {
1254 data->term.c_cflag &= ~CSIZE;
1255 switch (config->bits) {
1257 data->term.c_cflag |= CS8;
1260 data->term.c_cflag |= CS7;
1263 data->term.c_cflag |= CS6;
1266 data->term.c_cflag |= CS5;
1269 RETURN_ERROR(SP_ERR_ARG, "Invalid data bits setting");
1273 if (config->parity >= 0) {
1274 data->term.c_iflag &= ~IGNPAR;
1275 data->term.c_cflag &= ~(PARENB | PARODD);
1276 switch (config->parity) {
1277 case SP_PARITY_NONE:
1278 data->term.c_iflag |= IGNPAR;
1280 case SP_PARITY_EVEN:
1281 data->term.c_cflag |= PARENB;
1284 data->term.c_cflag |= PARENB | PARODD;
1287 RETURN_ERROR(SP_ERR_ARG, "Invalid parity setting");
1291 if (config->stopbits >= 0) {
1292 data->term.c_cflag &= ~CSTOPB;
1293 switch (config->stopbits) {
1295 data->term.c_cflag &= ~CSTOPB;
1298 data->term.c_cflag |= CSTOPB;
1301 RETURN_ERROR(SP_ERR_ARG, "Invalid stop bits setting");
1305 if (config->rts >= 0 || config->cts >= 0) {
1306 if (data->termiox_supported) {
1307 data->flow &= ~(RTS_FLOW | CTS_FLOW);
1308 switch (config->rts) {
1311 controlbits = TIOCM_RTS;
1312 if (ioctl(port->fd, config->rts == SP_RTS_ON ? TIOCMBIS : TIOCMBIC, &controlbits) < 0)
1313 RETURN_FAIL("Setting RTS signal level failed");
1315 case SP_RTS_FLOW_CONTROL:
1316 data->flow |= RTS_FLOW;
1321 if (config->cts == SP_CTS_FLOW_CONTROL)
1322 data->flow |= CTS_FLOW;
1324 if (data->flow & (RTS_FLOW | CTS_FLOW))
1325 data->term.c_iflag |= CRTSCTS;
1327 data->term.c_iflag &= ~CRTSCTS;
1329 /* Asymmetric use of RTS/CTS not supported. */
1330 if (data->term.c_iflag & CRTSCTS) {
1331 /* Flow control can only be disabled for both RTS & CTS together. */
1332 if (config->rts >= 0 && config->rts != SP_RTS_FLOW_CONTROL) {
1333 if (config->cts != SP_CTS_IGNORE)
1334 RETURN_ERROR(SP_ERR_SUPP, "RTS & CTS flow control must be disabled together");
1336 if (config->cts >= 0 && config->cts != SP_CTS_FLOW_CONTROL) {
1337 if (config->rts <= 0 || config->rts == SP_RTS_FLOW_CONTROL)
1338 RETURN_ERROR(SP_ERR_SUPP, "RTS & CTS flow control must be disabled together");
1341 /* Flow control can only be enabled for both RTS & CTS together. */
1342 if (((config->rts == SP_RTS_FLOW_CONTROL) && (config->cts != SP_CTS_FLOW_CONTROL)) ||
1343 ((config->cts == SP_CTS_FLOW_CONTROL) && (config->rts != SP_RTS_FLOW_CONTROL)))
1344 RETURN_ERROR(SP_ERR_SUPP, "RTS & CTS flow control must be enabled together");
1347 if (config->rts >= 0) {
1348 if (config->rts == SP_RTS_FLOW_CONTROL) {
1349 data->term.c_iflag |= CRTSCTS;
1351 controlbits = TIOCM_RTS;
1352 if (ioctl(port->fd, config->rts == SP_RTS_ON ? TIOCMBIS : TIOCMBIC,
1354 RETURN_FAIL("Setting RTS signal level failed");
1360 if (config->dtr >= 0 || config->dsr >= 0) {
1361 if (data->termiox_supported) {
1362 data->flow &= ~(DTR_FLOW | DSR_FLOW);
1363 switch (config->dtr) {
1366 controlbits = TIOCM_DTR;
1367 if (ioctl(port->fd, config->dtr == SP_DTR_ON ? TIOCMBIS : TIOCMBIC, &controlbits) < 0)
1368 RETURN_FAIL("Setting DTR signal level failed");
1370 case SP_DTR_FLOW_CONTROL:
1371 data->flow |= DTR_FLOW;
1376 if (config->dsr == SP_DSR_FLOW_CONTROL)
1377 data->flow |= DSR_FLOW;
1379 /* DTR/DSR flow control not supported. */
1380 if (config->dtr == SP_DTR_FLOW_CONTROL || config->dsr == SP_DSR_FLOW_CONTROL)
1381 RETURN_ERROR(SP_ERR_SUPP, "DTR/DSR flow control not supported");
1383 if (config->dtr >= 0) {
1384 controlbits = TIOCM_DTR;
1385 if (ioctl(port->fd, config->dtr == SP_DTR_ON ? TIOCMBIS : TIOCMBIC,
1387 RETURN_FAIL("Setting DTR signal level failed");
1392 if (config->xon_xoff >= 0) {
1393 data->term.c_iflag &= ~(IXON | IXOFF | IXANY);
1394 switch (config->xon_xoff) {
1395 case SP_XONXOFF_DISABLED:
1398 data->term.c_iflag |= IXOFF;
1400 case SP_XONXOFF_OUT:
1401 data->term.c_iflag |= IXON | IXANY;
1403 case SP_XONXOFF_INOUT:
1404 data->term.c_iflag |= IXON | IXOFF | IXANY;
1407 RETURN_ERROR(SP_ERR_ARG, "Invalid XON/XOFF setting");
1411 if (tcsetattr(port->fd, TCSADRAIN, &data->term) < 0)
1412 RETURN_FAIL("tcsetattr() failed");
1415 if (baud_nonstd != B0) {
1416 if (ioctl(port->fd, IOSSIOSPEED, &baud_nonstd) == -1)
1417 RETURN_FAIL("IOSSIOSPEED ioctl failed");
1418 /* Set baud rates in data->term to correct, but incompatible
1419 * with tcsetattr() value, same as delivered by tcgetattr(). */
1420 if (cfsetspeed(&data->term, baud_nonstd) < 0)
1421 RETURN_FAIL("cfsetspeed() failed");
1423 #elif defined(__linux__)
1425 TRY(set_baudrate(port->fd, config->baudrate));
1427 if (data->termiox_supported)
1428 TRY(set_flow(port->fd, data->flow));
1432 #endif /* !_WIN32 */
1437 enum sp_return sp_get_config(struct sp_port *port, struct sp_port_config *config)
1439 struct port_data data;
1441 TRACE("%p, %p", port, config);
1446 RETURN_ERROR(SP_ERR_ARG, "Null result pointer");
1448 TRY(get_config(port, &data, config));
1453 enum sp_return sp_set_config(struct sp_port *port, const struct sp_port_config *config)
1455 struct port_data data;
1456 struct sp_port_config prev_config;
1458 TRACE("%p, %p", port, config);
1463 RETURN_ERROR(SP_ERR_ARG, "Null config");
1465 TRY(get_config(port, &data, &prev_config));
1466 TRY(set_config(port, &data, config));
1471 #define CREATE_SETTER(x, type) int sp_set_##x(struct sp_port *port, type x) { \
1472 struct port_data data; \
1473 struct sp_port_config config; \
1474 TRACE("%p, %d", port, x); \
1475 CHECK_OPEN_PORT(); \
1476 TRY(get_config(port, &data, &config)); \
1478 TRY(set_config(port, &data, &config)); \
1482 CREATE_SETTER(baudrate, int)
1483 CREATE_SETTER(bits, int)
1484 CREATE_SETTER(parity, enum sp_parity)
1485 CREATE_SETTER(stopbits, int)
1486 CREATE_SETTER(rts, enum sp_rts)
1487 CREATE_SETTER(cts, enum sp_cts)
1488 CREATE_SETTER(dtr, enum sp_dtr)
1489 CREATE_SETTER(dsr, enum sp_dsr)
1490 CREATE_SETTER(xon_xoff, enum sp_xonxoff)
1492 enum sp_return sp_set_flowcontrol(struct sp_port *port, enum sp_flowcontrol flowcontrol)
1494 struct port_data data;
1495 struct sp_port_config config;
1497 TRACE("%p, %d", port, flowcontrol);
1501 if (flowcontrol > SP_FLOWCONTROL_DTRDSR)
1502 RETURN_ERROR(SP_ERR_ARG, "Invalid flow control setting");
1504 TRY(get_config(port, &data, &config));
1506 if (flowcontrol == SP_FLOWCONTROL_XONXOFF)
1507 config.xon_xoff = SP_XONXOFF_INOUT;
1509 config.xon_xoff = SP_XONXOFF_DISABLED;
1511 if (flowcontrol == SP_FLOWCONTROL_RTSCTS) {
1512 config.rts = SP_RTS_FLOW_CONTROL;
1513 config.cts = SP_CTS_FLOW_CONTROL;
1515 if (config.rts == SP_RTS_FLOW_CONTROL)
1516 config.rts = SP_RTS_ON;
1517 config.cts = SP_CTS_IGNORE;
1520 if (flowcontrol == SP_FLOWCONTROL_DTRDSR) {
1521 config.dtr = SP_DTR_FLOW_CONTROL;
1522 config.dsr = SP_DSR_FLOW_CONTROL;
1524 if (config.dtr == SP_DTR_FLOW_CONTROL)
1525 config.dtr = SP_DTR_ON;
1526 config.dsr = SP_DSR_IGNORE;
1529 TRY(set_config(port, &data, &config));
1534 enum sp_return sp_get_signals(struct sp_port *port, enum sp_signal *signals)
1536 TRACE("%p, %p", port, signals);
1541 RETURN_ERROR(SP_ERR_ARG, "Null result pointer");
1543 DEBUG("Getting control signals for port %s", port->name);
1548 if (GetCommModemStatus(port->hdl, &bits) == 0)
1549 RETURN_FAIL("GetCommModemStatus() failed");
1550 if (bits & MS_CTS_ON)
1551 *signals |= SP_SIG_CTS;
1552 if (bits & MS_DSR_ON)
1553 *signals |= SP_SIG_DSR;
1554 if (bits & MS_RLSD_ON)
1555 *signals |= SP_SIG_DCD;
1556 if (bits & MS_RING_ON)
1557 *signals |= SP_SIG_RI;
1560 if (ioctl(port->fd, TIOCMGET, &bits) < 0)
1561 RETURN_FAIL("TIOCMGET ioctl failed");
1562 if (bits & TIOCM_CTS)
1563 *signals |= SP_SIG_CTS;
1564 if (bits & TIOCM_DSR)
1565 *signals |= SP_SIG_DSR;
1566 if (bits & TIOCM_CAR)
1567 *signals |= SP_SIG_DCD;
1568 if (bits & TIOCM_RNG)
1569 *signals |= SP_SIG_RI;
1574 enum sp_return sp_start_break(struct sp_port *port)
1580 if (SetCommBreak(port->hdl) == 0)
1581 RETURN_FAIL("SetCommBreak() failed");
1583 if (ioctl(port->fd, TIOCSBRK, 1) < 0)
1584 RETURN_FAIL("TIOCSBRK ioctl failed");
1590 enum sp_return sp_end_break(struct sp_port *port)
1596 if (ClearCommBreak(port->hdl) == 0)
1597 RETURN_FAIL("ClearCommBreak() failed");
1599 if (ioctl(port->fd, TIOCCBRK, 1) < 0)
1600 RETURN_FAIL("TIOCCBRK ioctl failed");
1606 int sp_last_error_code(void)
1610 RETURN_VALUE("%d", GetLastError());
1612 RETURN_VALUE("%d", errno);
1616 char *sp_last_error_message(void)
1622 DWORD error = GetLastError();
1625 FORMAT_MESSAGE_ALLOCATE_BUFFER |
1626 FORMAT_MESSAGE_FROM_SYSTEM |
1627 FORMAT_MESSAGE_IGNORE_INSERTS,
1630 MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
1634 RETURN_VALUE("%s", message);
1636 RETURN_VALUE("%s", strerror(errno));
1640 void sp_free_error_message(char *message)
1642 TRACE("%s", message);
1653 void sp_set_debug_handler(void (*handler)(const char *format, ...))
1655 TRACE("%p", handler);
1657 sp_debug_handler = handler;
1662 void sp_default_debug_handler(const char *format, ...)
1665 va_start(args, format);
1666 if (getenv("LIBSERIALPORT_DEBUG")) {
1667 fputs("libserialport: ", stderr);
1668 vfprintf(stderr, format, args);