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"
67 int termiox_supported;
72 /* Standard baud rates. */
74 #define BAUD_TYPE DWORD
75 #define BAUD(n) {CBR_##n, n}
77 #define BAUD_TYPE speed_t
78 #define BAUD(n) {B##n, n}
86 const struct std_baudrate std_baudrates[] = {
89 * The baudrates 50/75/134/150/200/1800/230400/460800 do not seem to
90 * have documented CBR_* macros.
92 BAUD(110), BAUD(300), BAUD(600), BAUD(1200), BAUD(2400), BAUD(4800),
93 BAUD(9600), BAUD(14400), BAUD(19200), BAUD(38400), BAUD(57600),
94 BAUD(115200), BAUD(128000), BAUD(256000),
96 BAUD(50), BAUD(75), BAUD(110), BAUD(134), BAUD(150), BAUD(200),
97 BAUD(300), BAUD(600), BAUD(1200), BAUD(1800), BAUD(2400), BAUD(4800),
98 BAUD(9600), BAUD(19200), BAUD(38400), BAUD(57600), BAUD(115200),
100 #if !defined(__APPLE__) && !defined(__OpenBSD__)
106 void (*sp_debug_handler)(const char *format, ...) = sp_default_debug_handler;
108 #define ARRAY_SIZE(x) (sizeof(x) / sizeof(x[0]))
109 #define NUM_STD_BAUDRATES ARRAY_SIZE(std_baudrates)
111 #define TRY(x) do { int ret = x; if (ret != SP_OK) return ret; } while (0)
113 /* Debug output macros. */
114 #define DEBUG(fmt, ...) do { if (sp_debug_handler) sp_debug_handler(fmt ".\n", ##__VA_ARGS__); } while (0)
115 #define DEBUG_ERROR(err, msg) DEBUG("%s returning " #err ": " msg, __func__)
116 #define DEBUG_FAIL(msg) do { \
117 char *errmsg = sp_last_error_message(); \
118 DEBUG("%s returning SP_ERR_FAIL: " msg ": %s", __func__, errmsg); \
119 sp_free_error_message(errmsg); \
121 #define RETURN() do { DEBUG("%s returning", __func__); return; } while(0)
122 #define RETURN_CODE(x) do { DEBUG("%s returning " #x, __func__); return x; } while (0)
123 #define RETURN_CODEVAL(x) do { \
125 case SP_OK: RETURN_CODE(SP_OK); \
126 case SP_ERR_ARG: RETURN_CODE(SP_ERR_ARG); \
127 case SP_ERR_FAIL: RETURN_CODE(SP_ERR_FAIL); \
128 case SP_ERR_MEM: RETURN_CODE(SP_ERR_MEM); \
129 case SP_ERR_SUPP: RETURN_CODE(SP_ERR_SUPP); \
132 #define RETURN_OK() RETURN_CODE(SP_OK);
133 #define RETURN_ERROR(err, msg) do { DEBUG_ERROR(err, msg); return err; } while (0)
134 #define RETURN_FAIL(msg) do { DEBUG_FAIL(msg); return SP_ERR_FAIL; } while (0)
135 #define RETURN_VALUE(fmt, x) do { DEBUG("%s returning " fmt, __func__, x); return x; } while (0)
136 #define SET_ERROR(val, err, msg) do { DEBUG_ERROR(err, msg); val = err; } while (0)
137 #define SET_FAIL(val, msg) do { DEBUG_FAIL(msg); val = err; } while (0)
138 #define TRACE(fmt, ...) DEBUG("%s(" fmt ") called", __func__, ##__VA_ARGS__)
140 /* Helper functions. */
141 static struct sp_port **list_append(struct sp_port **list, const char *portname);
142 static enum sp_return get_config(struct sp_port *port, struct port_data *data,
143 struct sp_port_config *config);
144 static enum sp_return set_config(struct sp_port *port, struct port_data *data,
145 const struct sp_port_config *config);
147 enum sp_return sp_get_port_by_name(const char *portname, struct sp_port **port_ptr)
149 struct sp_port *port;
152 TRACE("%s, %p", portname, port_ptr);
155 RETURN_ERROR(SP_ERR_ARG, "Null result pointer");
160 RETURN_ERROR(SP_ERR_ARG, "Null port name");
162 if (!(port = malloc(sizeof(struct sp_port))))
163 RETURN_ERROR(SP_ERR_MEM, "Port structure malloc failed");
165 len = strlen(portname) + 1;
167 if (!(port->name = malloc(len))) {
169 RETURN_ERROR(SP_ERR_MEM, "Port name malloc failed");
172 memcpy(port->name, portname, len);
175 port->hdl = INVALID_HANDLE_VALUE;
185 enum sp_return sp_copy_port(const struct sp_port *port, struct sp_port **copy_ptr)
187 TRACE("%p, %p", port, copy_ptr);
190 RETURN_ERROR(SP_ERR_ARG, "Null result pointer");
195 RETURN_ERROR(SP_ERR_ARG, "Null port");
198 RETURN_ERROR(SP_ERR_ARG, "Null port name");
200 RETURN_VALUE("%p", sp_get_port_by_name(port->name, copy_ptr));
203 void sp_free_port(struct sp_port *port)
221 static struct sp_port **list_append(struct sp_port **list, const char *portname)
226 for (count = 0; list[count]; count++);
227 if (!(tmp = realloc(list, sizeof(struct sp_port *) * (count + 2))))
230 if (sp_get_port_by_name(portname, &list[count]) != SP_OK)
232 list[count + 1] = NULL;
236 sp_free_port_list(list);
240 enum sp_return sp_list_ports(struct sp_port ***list_ptr)
242 struct sp_port **list;
245 TRACE("%p", list_ptr);
247 if (!(list = malloc(sizeof(struct sp_port **))))
248 RETURN_ERROR(SP_ERR_MEM, "Port list malloc failed");
255 DWORD max_value_len, max_data_size, max_data_len;
256 DWORD value_len, data_size, data_len;
257 DWORD type, index = 0;
261 if (RegOpenKeyEx(HKEY_LOCAL_MACHINE, _T("HARDWARE\\DEVICEMAP\\SERIALCOMM"),
262 0, KEY_QUERY_VALUE, &key) != ERROR_SUCCESS) {
263 SET_FAIL(ret, "RegOpenKeyEx() failed");
266 if (RegQueryInfoKey(key, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
267 &max_value_len, &max_data_size, NULL, NULL) != ERROR_SUCCESS) {
268 SET_FAIL(ret, "RegQueryInfoKey() failed");
271 max_data_len = max_data_size / sizeof(TCHAR);
272 if (!(value = malloc((max_value_len + 1) * sizeof(TCHAR)))) {
273 SET_ERROR(ret, SP_ERR_MEM, "registry value malloc failed");
276 if (!(data = malloc((max_data_len + 1) * sizeof(TCHAR)))) {
277 SET_ERROR(ret, SP_ERR_MEM, "registry data malloc failed");
281 value_len = max_value_len + 1,
282 data_size = max_data_size,
283 RegEnumValue(key, index, value, &value_len,
284 NULL, &type, (LPBYTE)data, &data_size) == ERROR_SUCCESS)
286 data_len = data_size / sizeof(TCHAR);
287 data[data_len] = '\0';
289 name_len = WideCharToMultiByte(CP_ACP, 0, data, -1, NULL, 0, NULL, NULL)
291 name_len = data_len + 1;
293 if (!(name = malloc(name_len))) {
294 SET_ERROR(ret, SP_ERR_MEM, "registry port name malloc failed");
298 WideCharToMultiByte(CP_ACP, 0, data, -1, name, name_len, NULL, NULL);
302 if (type == REG_SZ) {
303 DEBUG("Found port %s", name);
304 if (!(list = list_append(list, name))) {
305 SET_ERROR(ret, SP_ERR_MEM, "list append failed");
321 CFMutableDictionaryRef classes;
328 if (IOMasterPort(MACH_PORT_NULL, &master) != KERN_SUCCESS) {
329 SET_FAIL(ret, "IOMasterPort() failed");
333 if (!(classes = IOServiceMatching(kIOSerialBSDServiceValue))) {
334 SET_FAIL(ret, "IOServiceMatching() failed");
338 CFDictionarySetValue(classes,
339 CFSTR(kIOSerialBSDTypeKey), CFSTR(kIOSerialBSDAllTypes));
341 if (IOServiceGetMatchingServices(master, classes, &iter) != KERN_SUCCESS) {
342 SET_FAIL(ret, "IOServiceGetMatchingServices() failed");
346 if (!(path = malloc(PATH_MAX))) {
347 SET_ERROR(ret, SP_ERR_MEM, "device path malloc failed");
351 while ((port = IOIteratorNext(iter))) {
352 cf_path = IORegistryEntryCreateCFProperty(port,
353 CFSTR(kIOCalloutDeviceKey), kCFAllocatorDefault, 0);
355 result = CFStringGetCString(cf_path,
356 path, PATH_MAX, kCFStringEncodingASCII);
359 DEBUG("Found port %s", path);
360 if (!(list = list_append(list, path))) {
361 SET_ERROR(ret, SP_ERR_MEM, "list append failed");
362 IOObjectRelease(port);
367 IOObjectRelease(port);
372 IOObjectRelease(iter);
377 struct udev_enumerate *ud_enumerate;
378 struct udev_list_entry *ud_list;
379 struct udev_list_entry *ud_entry;
381 struct udev_device *ud_dev, *ud_parent;
384 int fd, ioctl_result;
385 struct serial_struct serial_info;
388 ud_enumerate = udev_enumerate_new(ud);
389 udev_enumerate_add_match_subsystem(ud_enumerate, "tty");
390 udev_enumerate_scan_devices(ud_enumerate);
391 ud_list = udev_enumerate_get_list_entry(ud_enumerate);
392 udev_list_entry_foreach(ud_entry, ud_list) {
393 path = udev_list_entry_get_name(ud_entry);
394 ud_dev = udev_device_new_from_syspath(ud, path);
395 /* If there is no parent device, this is a virtual tty. */
396 ud_parent = udev_device_get_parent(ud_dev);
397 if (ud_parent == NULL) {
398 udev_device_unref(ud_dev);
401 name = udev_device_get_devnode(ud_dev);
402 /* The serial8250 driver has a hardcoded number of ports.
403 * The only way to tell which actually exist on a given system
404 * is to try to open them and make an ioctl call. */
405 driver = udev_device_get_driver(ud_parent);
406 if (driver && !strcmp(driver, "serial8250")) {
407 if ((fd = open(name, O_RDWR | O_NONBLOCK | O_NOCTTY)) < 0)
409 ioctl_result = ioctl(fd, TIOCGSERIAL, &serial_info);
411 if (ioctl_result != 0)
413 if (serial_info.type == PORT_UNKNOWN)
416 DEBUG("Found port %s", name);
417 list = list_append(list, name);
419 udev_device_unref(ud_dev);
421 SET_ERROR(ret, SP_ERR_MEM, "list append failed");
426 udev_enumerate_unref(ud_enumerate);
435 sp_free_port_list(list);
441 void sp_free_port_list(struct sp_port **list)
447 for (i = 0; list[i]; i++)
448 sp_free_port(list[i]);
455 #define CHECK_PORT() do { \
457 RETURN_ERROR(SP_ERR_ARG, "Null port"); \
458 if (port->hdl == INVALID_HANDLE_VALUE) \
459 RETURN_ERROR(SP_ERR_ARG, "Invalid port handle"); \
462 #define CHECK_PORT() do { \
464 RETURN_ERROR(SP_ERR_ARG, "Null port"); \
466 RETURN_ERROR(SP_ERR_ARG, "Invalid port fd"); \
470 enum sp_return sp_open(struct sp_port *port, enum sp_mode flags)
472 TRACE("%p, %x", port, flags);
475 RETURN_ERROR(SP_ERR_ARG, "Null port");
478 DWORD desired_access = 0, flags_and_attributes = 0;
479 char *escaped_port_name;
481 /* Prefix port name with '\\.\' to work with ports above COM9. */
482 if (!(escaped_port_name = malloc(strlen(port->name + 5))))
483 RETURN_ERROR(SP_ERR_MEM, "Escaped port name malloc failed");
484 sprintf(escaped_port_name, "\\\\.\\%s", port->name);
486 /* Map 'flags' to the OS-specific settings. */
487 flags_and_attributes = FILE_ATTRIBUTE_NORMAL;
488 if (flags & SP_MODE_READ)
489 desired_access |= GENERIC_READ;
490 if (flags & SP_MODE_WRITE)
491 desired_access |= GENERIC_WRITE;
492 if (flags & SP_MODE_NONBLOCK)
493 flags_and_attributes |= FILE_FLAG_OVERLAPPED;
495 port->hdl = CreateFile(escaped_port_name, desired_access, 0, 0,
496 OPEN_EXISTING, flags_and_attributes, 0);
498 free(escaped_port_name);
500 if (port->hdl == INVALID_HANDLE_VALUE)
501 RETURN_FAIL("CreateFile() failed");
504 struct port_data data;
505 struct sp_port_config config;
508 /* Map 'flags' to the OS-specific settings. */
509 if (flags & (SP_MODE_READ | SP_MODE_WRITE))
510 flags_local |= O_RDWR;
511 else if (flags & SP_MODE_READ)
512 flags_local |= O_RDONLY;
513 else if (flags & SP_MODE_WRITE)
514 flags_local |= O_WRONLY;
515 if (flags & SP_MODE_NONBLOCK)
516 flags_local |= O_NONBLOCK;
518 if ((port->fd = open(port->name, flags_local)) < 0)
519 RETURN_FAIL("open() failed");
521 ret = get_config(port, &data, &config);
528 /* Turn off all serial port cooking. */
529 data.term.c_iflag &= ~(ISTRIP | INLCR | ICRNL);
530 data.term.c_oflag &= ~(ONLCR | OCRNL | ONOCR);
531 #if !defined(__FreeBSD__) && !defined(__OpenBSD__) && !defined(__NetBSD__)
532 data.term.c_oflag &= ~OFILL;
534 /* Disable canonical mode, and don't echo input characters. */
535 data.term.c_lflag &= ~(ICANON | ECHO);
537 /* Ignore modem status lines; enable receiver */
538 data.term.c_cflag |= (CLOCAL | CREAD);
540 ret = set_config(port, &data, &config);
551 enum sp_return sp_close(struct sp_port *port)
558 /* Returns non-zero upon success, 0 upon failure. */
559 if (CloseHandle(port->hdl) == 0)
560 RETURN_FAIL("CloseHandle() failed");
561 port->hdl = INVALID_HANDLE_VALUE;
563 /* Returns 0 upon success, -1 upon failure. */
564 if (close(port->fd) == -1)
565 RETURN_FAIL("close() failed");
572 enum sp_return sp_flush(struct sp_port *port, enum sp_buffer buffers)
574 TRACE("%p, %x", port, buffers);
580 if (buffers & SP_BUF_INPUT)
581 flags |= PURGE_RXCLEAR;
582 if (buffers & SP_BUF_OUTPUT)
583 flags |= PURGE_TXCLEAR;
585 /* Returns non-zero upon success, 0 upon failure. */
586 if (PurgeComm(port->hdl, flags) == 0)
587 RETURN_FAIL("PurgeComm() failed");
590 if (buffers & SP_BUF_BOTH)
592 else if (buffers & SP_BUF_INPUT)
594 else if (buffers & SP_BUF_OUTPUT)
597 /* Returns 0 upon success, -1 upon failure. */
598 if (tcflush(port->fd, flags) < 0)
599 RETURN_FAIL("tcflush() failed");
604 enum sp_return sp_drain(struct sp_port *port)
611 /* Returns non-zero upon success, 0 upon failure. */
612 if (FlushFileBuffers(port->hdl) == 0)
613 RETURN_FAIL("FlushFileBuffers() failed");
615 /* Returns 0 upon success, -1 upon failure. */
616 if (tcdrain(port->fd) < 0)
617 RETURN_FAIL("tcdrain() failed");
623 enum sp_return sp_write(struct sp_port *port, const void *buf, size_t count)
625 TRACE("%p, %p, %d", port, buf, count);
630 RETURN_ERROR(SP_ERR_ARG, "Null buffer");
635 /* Returns non-zero upon success, 0 upon failure. */
636 if (WriteFile(port->hdl, buf, count, &written, NULL) == 0)
637 RETURN_FAIL("WriteFile() failed");
638 RETURN_VALUE("%d", written);
640 /* Returns the number of bytes written, or -1 upon failure. */
641 ssize_t written = write(port->fd, buf, count);
644 RETURN_FAIL("write() failed");
646 RETURN_VALUE("%d", written);
650 enum sp_return sp_read(struct sp_port *port, void *buf, size_t count)
652 TRACE("%p, %p, %d", port, buf, count);
657 RETURN_ERROR(SP_ERR_ARG, "Null buffer");
660 DWORD bytes_read = 0;
662 /* Returns non-zero upon success, 0 upon failure. */
663 if (ReadFile(port->hdl, buf, count, &bytes_read, NULL) == 0)
664 RETURN_FAIL("ReadFile() failed");
665 RETURN_VALUE("%d", bytes_read);
669 /* Returns the number of bytes read, or -1 upon failure. */
670 if ((bytes_read = read(port->fd, buf, count)) < 0)
671 RETURN_FAIL("read() failed");
672 RETURN_VALUE("%d", bytes_read);
677 static enum sp_return get_baudrate(int fd, int *baudrate)
681 TRACE("%d, %p", fd, baudrate);
683 if (!(data = malloc(get_termios_size())))
684 RETURN_ERROR(SP_ERR_MEM, "termios malloc failed");
686 if (ioctl(fd, get_termios_get_ioctl(), data) < 0) {
688 RETURN_FAIL("getting termios failed");
691 *baudrate = get_termios_speed(data);
698 static enum sp_return set_baudrate(int fd, int baudrate)
702 TRACE("%d, %d", fd, baudrate);
704 if (!(data = malloc(get_termios_size())))
705 RETURN_ERROR(SP_ERR_MEM, "termios malloc failed");
707 if (ioctl(fd, get_termios_get_ioctl(), data) < 0) {
709 RETURN_FAIL("getting termios failed");
712 set_termios_speed(data, baudrate);
714 if (ioctl(fd, get_termios_set_ioctl(), data) < 0) {
716 RETURN_FAIL("setting termios failed");
725 static enum sp_return get_flow(int fd, int *flow)
729 TRACE("%d, %p", fd, flow);
731 if (!(data = malloc(get_termiox_size())))
732 RETURN_ERROR(SP_ERR_MEM, "termiox malloc failed");
734 if (ioctl(fd, TCGETX, data) < 0) {
736 RETURN_FAIL("getting termiox failed");
739 *flow = get_termiox_flow(data);
746 static enum sp_return set_flow(int fd, int flow)
750 TRACE("%d, %d", fd, flow);
752 if (!(data = malloc(get_termiox_size())))
753 RETURN_ERROR(SP_ERR_MEM, "termiox malloc failed");
755 if (ioctl(fd, TCGETX, data) < 0) {
757 RETURN_FAIL("getting termiox failed");
760 set_termiox_flow(data, flow);
762 if (ioctl(fd, TCSETX, data) < 0) {
764 RETURN_FAIL("setting termiox failed");
771 #endif /* USE_TERMIOX */
772 #endif /* __linux__ */
774 static enum sp_return get_config(struct sp_port *port, struct port_data *data,
775 struct sp_port_config *config)
779 TRACE("%p, %p, %p", port, data, config);
782 if (!GetCommState(port->hdl, &data->dcb))
783 RETURN_FAIL("GetCommState() failed");
785 for (i = 0; i < NUM_STD_BAUDRATES; i++) {
786 if (data->dcb.BaudRate == std_baudrates[i].index) {
787 config->baudrate = std_baudrates[i].value;
792 if (i == NUM_STD_BAUDRATES)
793 /* BaudRate field can be either an index or a custom baud rate. */
794 config->baudrate = data->dcb.BaudRate;
796 config->bits = data->dcb.ByteSize;
798 if (data->dcb.fParity)
799 switch (data->dcb.Parity) {
801 config->parity = SP_PARITY_NONE;
804 config->parity = SP_PARITY_EVEN;
807 config->parity = SP_PARITY_ODD;
813 config->parity = SP_PARITY_NONE;
815 switch (data->dcb.StopBits) {
817 config->stopbits = 1;
820 config->stopbits = 2;
823 config->stopbits = -1;
826 switch (data->dcb.fRtsControl) {
827 case RTS_CONTROL_DISABLE:
828 config->rts = SP_RTS_OFF;
830 case RTS_CONTROL_ENABLE:
831 config->rts = SP_RTS_ON;
833 case RTS_CONTROL_HANDSHAKE:
834 config->rts = SP_RTS_FLOW_CONTROL;
840 config->cts = data->dcb.fOutxCtsFlow ? SP_CTS_FLOW_CONTROL : SP_CTS_IGNORE;
842 switch (data->dcb.fDtrControl) {
843 case DTR_CONTROL_DISABLE:
844 config->dtr = SP_DTR_OFF;
846 case DTR_CONTROL_ENABLE:
847 config->dtr = SP_DTR_ON;
849 case DTR_CONTROL_HANDSHAKE:
850 config->dtr = SP_DTR_FLOW_CONTROL;
856 config->dsr = data->dcb.fOutxDsrFlow ? SP_DSR_FLOW_CONTROL : SP_DSR_IGNORE;
858 if (data->dcb.fInX) {
860 config->xon_xoff = SP_XONXOFF_INOUT;
862 config->xon_xoff = SP_XONXOFF_IN;
865 config->xon_xoff = SP_XONXOFF_OUT;
867 config->xon_xoff = SP_XONXOFF_DISABLED;
872 if (tcgetattr(port->fd, &data->term) < 0)
873 RETURN_FAIL("tcgetattr() failed");
875 if (ioctl(port->fd, TIOCMGET, &data->controlbits) < 0)
876 RETURN_FAIL("TIOCMGET ioctl failed");
879 int ret = get_flow(port->fd, &data->flow);
881 if (ret == SP_ERR_FAIL && errno == EINVAL)
882 data->termiox_supported = 0;
886 data->termiox_supported = 1;
888 data->termiox_supported = 0;
891 for (i = 0; i < NUM_STD_BAUDRATES; i++) {
892 if (cfgetispeed(&data->term) == std_baudrates[i].index) {
893 config->baudrate = std_baudrates[i].value;
898 if (i == NUM_STD_BAUDRATES) {
900 config->baudrate = (int)data->term.c_ispeed;
901 #elif defined(__linux__)
902 TRY(get_baudrate(port->fd, &config->baudrate));
904 config->baudrate = -1;
908 switch (data->term.c_cflag & CSIZE) {
925 if (!(data->term.c_cflag & PARENB) && (data->term.c_iflag & IGNPAR))
926 config->parity = SP_PARITY_NONE;
927 else if (!(data->term.c_cflag & PARENB) || (data->term.c_iflag & IGNPAR))
930 config->parity = (data->term.c_cflag & PARODD) ? SP_PARITY_ODD : SP_PARITY_EVEN;
932 config->stopbits = (data->term.c_cflag & CSTOPB) ? 2 : 1;
934 if (data->term.c_cflag & CRTSCTS) {
935 config->rts = SP_RTS_FLOW_CONTROL;
936 config->cts = SP_CTS_FLOW_CONTROL;
938 if (data->termiox_supported && data->flow & RTS_FLOW)
939 config->rts = SP_RTS_FLOW_CONTROL;
941 config->rts = (data->controlbits & TIOCM_RTS) ? SP_RTS_ON : SP_RTS_OFF;
943 config->cts = (data->termiox_supported && data->flow & CTS_FLOW) ?
944 SP_CTS_FLOW_CONTROL : SP_CTS_IGNORE;
947 if (data->termiox_supported && data->flow & DTR_FLOW)
948 config->dtr = SP_DTR_FLOW_CONTROL;
950 config->dtr = (data->controlbits & TIOCM_DTR) ? SP_DTR_ON : SP_DTR_OFF;
952 config->dsr = (data->termiox_supported && data->flow & DSR_FLOW) ?
953 SP_DSR_FLOW_CONTROL : SP_DSR_IGNORE;
955 if (data->term.c_iflag & IXOFF) {
956 if (data->term.c_iflag & IXON)
957 config->xon_xoff = SP_XONXOFF_INOUT;
959 config->xon_xoff = SP_XONXOFF_IN;
961 if (data->term.c_iflag & IXON)
962 config->xon_xoff = SP_XONXOFF_OUT;
964 config->xon_xoff = SP_XONXOFF_DISABLED;
971 static enum sp_return set_config(struct sp_port *port, struct port_data *data,
972 const struct sp_port_config *config)
976 BAUD_TYPE baud_nonstd;
984 TRACE("%p, %p, %p", port, data, config);
987 if (config->baudrate >= 0) {
988 for (i = 0; i < NUM_STD_BAUDRATES; i++) {
989 if (config->baudrate == std_baudrates[i].value) {
990 data->dcb.BaudRate = std_baudrates[i].index;
995 if (i == NUM_STD_BAUDRATES)
996 data->dcb.BaudRate = config->baudrate;
999 if (config->bits >= 0)
1000 data->dcb.ByteSize = config->bits;
1002 if (config->parity >= 0) {
1003 switch (config->parity) {
1004 /* Note: There's also SPACEPARITY, MARKPARITY (unneeded so far). */
1005 case SP_PARITY_NONE:
1006 data->dcb.Parity = NOPARITY;
1008 case SP_PARITY_EVEN:
1009 data->dcb.Parity = EVENPARITY;
1012 data->dcb.Parity = ODDPARITY;
1015 RETURN_ERROR(SP_ERR_ARG, "Invalid parity setting");
1019 if (config->stopbits >= 0) {
1020 switch (config->stopbits) {
1021 /* Note: There's also ONE5STOPBITS == 1.5 (unneeded so far). */
1023 data->dcb.StopBits = ONESTOPBIT;
1026 data->dcb.StopBits = TWOSTOPBITS;
1029 RETURN_ERROR(SP_ERR_ARG, "Invalid stop bit setting");
1033 if (config->rts >= 0) {
1034 switch (config->rts) {
1036 data->dcb.fRtsControl = RTS_CONTROL_DISABLE;
1039 data->dcb.fRtsControl = RTS_CONTROL_ENABLE;
1041 case SP_RTS_FLOW_CONTROL:
1042 data->dcb.fRtsControl = RTS_CONTROL_HANDSHAKE;
1045 RETURN_ERROR(SP_ERR_ARG, "Invalid RTS setting");
1049 if (config->cts >= 0) {
1050 switch (config->cts) {
1052 data->dcb.fOutxCtsFlow = FALSE;
1054 case SP_CTS_FLOW_CONTROL:
1055 data->dcb.fOutxCtsFlow = TRUE;
1058 RETURN_ERROR(SP_ERR_ARG, "Invalid CTS setting");
1062 if (config->dtr >= 0) {
1063 switch (config->dtr) {
1065 data->dcb.fDtrControl = DTR_CONTROL_DISABLE;
1068 data->dcb.fDtrControl = DTR_CONTROL_ENABLE;
1070 case SP_DTR_FLOW_CONTROL:
1071 data->dcb.fDtrControl = DTR_CONTROL_HANDSHAKE;
1074 RETURN_ERROR(SP_ERR_ARG, "Invalid DTR setting");
1078 if (config->dsr >= 0) {
1079 switch (config->dsr) {
1081 data->dcb.fOutxDsrFlow = FALSE;
1083 case SP_DSR_FLOW_CONTROL:
1084 data->dcb.fOutxDsrFlow = TRUE;
1087 RETURN_ERROR(SP_ERR_ARG, "Invalid DSR setting");
1091 if (config->xon_xoff >= 0) {
1092 switch (config->xon_xoff) {
1093 case SP_XONXOFF_DISABLED:
1094 data->dcb.fInX = FALSE;
1095 data->dcb.fOutX = FALSE;
1098 data->dcb.fInX = TRUE;
1099 data->dcb.fOutX = FALSE;
1101 case SP_XONXOFF_OUT:
1102 data->dcb.fInX = FALSE;
1103 data->dcb.fOutX = TRUE;
1105 case SP_XONXOFF_INOUT:
1106 data->dcb.fInX = TRUE;
1107 data->dcb.fOutX = TRUE;
1110 RETURN_ERROR(SP_ERR_ARG, "Invalid XON/XOFF setting");
1114 if (!SetCommState(port->hdl, &data->dcb))
1115 RETURN_FAIL("SetCommState() failed");
1121 if (config->baudrate >= 0) {
1122 for (i = 0; i < NUM_STD_BAUDRATES; i++) {
1123 if (config->baudrate == std_baudrates[i].value) {
1124 if (cfsetospeed(&data->term, std_baudrates[i].index) < 0)
1125 RETURN_FAIL("cfsetospeed() failed");
1127 if (cfsetispeed(&data->term, std_baudrates[i].index) < 0)
1128 RETURN_FAIL("cfsetispeed() failed");
1133 /* Non-standard baud rate */
1134 if (i == NUM_STD_BAUDRATES) {
1136 /* Set "dummy" baud rate. */
1137 if (cfsetspeed(&data->term, B9600) < 0)
1138 RETURN_FAIL("cfsetspeed() failed");
1139 baud_nonstd = config->baudrate;
1140 #elif defined(__linux__)
1143 RETURN_ERROR(SP_ERR_SUPP, "Non-standard baudrate not supported");
1148 if (config->bits >= 0) {
1149 data->term.c_cflag &= ~CSIZE;
1150 switch (config->bits) {
1152 data->term.c_cflag |= CS8;
1155 data->term.c_cflag |= CS7;
1158 data->term.c_cflag |= CS6;
1161 data->term.c_cflag |= CS5;
1164 RETURN_ERROR(SP_ERR_ARG, "Invalid data bits setting");
1168 if (config->parity >= 0) {
1169 data->term.c_iflag &= ~IGNPAR;
1170 data->term.c_cflag &= ~(PARENB | PARODD);
1171 switch (config->parity) {
1172 case SP_PARITY_NONE:
1173 data->term.c_iflag |= IGNPAR;
1175 case SP_PARITY_EVEN:
1176 data->term.c_cflag |= PARENB;
1179 data->term.c_cflag |= PARENB | PARODD;
1182 RETURN_ERROR(SP_ERR_ARG, "Invalid parity setting");
1186 if (config->stopbits >= 0) {
1187 data->term.c_cflag &= ~CSTOPB;
1188 switch (config->stopbits) {
1190 data->term.c_cflag &= ~CSTOPB;
1193 data->term.c_cflag |= CSTOPB;
1196 RETURN_ERROR(SP_ERR_ARG, "Invalid stop bits setting");
1200 if (config->rts >= 0 || config->cts >= 0) {
1201 if (data->termiox_supported) {
1202 data->flow &= ~(RTS_FLOW | CTS_FLOW);
1203 switch (config->rts) {
1206 controlbits = TIOCM_RTS;
1207 if (ioctl(port->fd, config->rts == SP_RTS_ON ? TIOCMBIS : TIOCMBIC, &controlbits) < 0)
1208 RETURN_FAIL("Setting RTS signal level failed");
1210 case SP_RTS_FLOW_CONTROL:
1211 data->flow |= RTS_FLOW;
1216 if (config->cts == SP_CTS_FLOW_CONTROL)
1217 data->flow |= CTS_FLOW;
1219 if (data->flow & (RTS_FLOW | CTS_FLOW))
1220 data->term.c_iflag |= CRTSCTS;
1222 data->term.c_iflag &= ~CRTSCTS;
1224 /* Asymmetric use of RTS/CTS not supported. */
1225 if (data->term.c_iflag & CRTSCTS) {
1226 /* Flow control can only be disabled for both RTS & CTS together. */
1227 if (config->rts >= 0 && config->rts != SP_RTS_FLOW_CONTROL) {
1228 if (config->cts != SP_CTS_IGNORE)
1229 RETURN_ERROR(SP_ERR_SUPP, "RTS & CTS flow control must be disabled together");
1231 if (config->cts >= 0 && config->cts != SP_CTS_FLOW_CONTROL) {
1232 if (config->rts <= 0 || config->rts == SP_RTS_FLOW_CONTROL)
1233 RETURN_ERROR(SP_ERR_SUPP, "RTS & CTS flow control must be disabled together");
1236 /* Flow control can only be enabled for both RTS & CTS together. */
1237 if (((config->rts == SP_RTS_FLOW_CONTROL) && (config->cts != SP_CTS_FLOW_CONTROL)) ||
1238 ((config->cts == SP_CTS_FLOW_CONTROL) && (config->rts != SP_RTS_FLOW_CONTROL)))
1239 RETURN_ERROR(SP_ERR_SUPP, "RTS & CTS flow control must be enabled together");
1242 if (config->rts >= 0) {
1243 if (config->rts == SP_RTS_FLOW_CONTROL) {
1244 data->term.c_iflag |= CRTSCTS;
1246 controlbits = TIOCM_RTS;
1247 if (ioctl(port->fd, config->rts == SP_RTS_ON ? TIOCMBIS : TIOCMBIC,
1249 RETURN_FAIL("Setting RTS signal level failed");
1255 if (config->dtr >= 0 || config->dsr >= 0) {
1256 if (data->termiox_supported) {
1257 data->flow &= ~(DTR_FLOW | DSR_FLOW);
1258 switch (config->dtr) {
1261 controlbits = TIOCM_DTR;
1262 if (ioctl(port->fd, config->dtr == SP_DTR_ON ? TIOCMBIS : TIOCMBIC, &controlbits) < 0)
1263 RETURN_FAIL("Setting DTR signal level failed");
1265 case SP_DTR_FLOW_CONTROL:
1266 data->flow |= DTR_FLOW;
1271 if (config->dsr == SP_DSR_FLOW_CONTROL)
1272 data->flow |= DSR_FLOW;
1274 /* DTR/DSR flow control not supported. */
1275 if (config->dtr == SP_DTR_FLOW_CONTROL || config->dsr == SP_DSR_FLOW_CONTROL)
1276 RETURN_ERROR(SP_ERR_SUPP, "DTR/DSR flow control not supported");
1278 if (config->dtr >= 0) {
1279 controlbits = TIOCM_DTR;
1280 if (ioctl(port->fd, config->dtr == SP_DTR_ON ? TIOCMBIS : TIOCMBIC,
1282 RETURN_FAIL("Setting DTR signal level failed");
1287 if (config->xon_xoff >= 0) {
1288 data->term.c_iflag &= ~(IXON | IXOFF | IXANY);
1289 switch (config->xon_xoff) {
1290 case SP_XONXOFF_DISABLED:
1293 data->term.c_iflag |= IXOFF;
1295 case SP_XONXOFF_OUT:
1296 data->term.c_iflag |= IXON | IXANY;
1298 case SP_XONXOFF_INOUT:
1299 data->term.c_iflag |= IXON | IXOFF | IXANY;
1302 RETURN_ERROR(SP_ERR_ARG, "Invalid XON/XOFF setting");
1306 if (tcsetattr(port->fd, TCSADRAIN, &data->term) < 0)
1307 RETURN_FAIL("tcsetattr() failed");
1310 if (baud_nonstd != B0) {
1311 if (ioctl(port->fd, IOSSIOSPEED, &baud_nonstd) == -1)
1312 RETURN_FAIL("IOSSIOSPEED ioctl failed");
1313 /* Set baud rates in data->term to correct, but incompatible
1314 * with tcsetattr() value, same as delivered by tcgetattr(). */
1315 if (cfsetspeed(&data->term, baud_nonstd) < 0)
1316 RETURN_FAIL("cfsetspeed() failed");
1318 #elif defined(__linux__)
1320 TRY(set_baudrate(port->fd, config->baudrate));
1322 if (data->termiox_supported)
1323 TRY(set_flow(port->fd, data->flow));
1327 #endif /* !_WIN32 */
1332 enum sp_return sp_set_config(struct sp_port *port, const struct sp_port_config *config)
1334 struct port_data data;
1335 struct sp_port_config prev_config;
1337 TRACE("%p, %p", port, config);
1342 RETURN_ERROR(SP_ERR_ARG, "Null config");
1344 TRY(get_config(port, &data, &prev_config));
1345 TRY(set_config(port, &data, config));
1350 #define CREATE_SETTER(x, type) int sp_set_##x(struct sp_port *port, type x) { \
1351 struct port_data data; \
1352 struct sp_port_config config; \
1353 TRACE("%p, %d", port, x); \
1355 TRY(get_config(port, &data, &config)); \
1357 TRY(set_config(port, &data, &config)); \
1361 CREATE_SETTER(baudrate, int)
1362 CREATE_SETTER(bits, int)
1363 CREATE_SETTER(parity, enum sp_parity)
1364 CREATE_SETTER(stopbits, int)
1365 CREATE_SETTER(rts, enum sp_rts)
1366 CREATE_SETTER(cts, enum sp_cts)
1367 CREATE_SETTER(dtr, enum sp_dtr)
1368 CREATE_SETTER(dsr, enum sp_dsr)
1369 CREATE_SETTER(xon_xoff, enum sp_xonxoff)
1371 enum sp_return sp_set_flowcontrol(struct sp_port *port, enum sp_flowcontrol flowcontrol)
1373 struct port_data data;
1374 struct sp_port_config config;
1376 TRACE("%p, %d", port, flowcontrol);
1380 TRY(get_config(port, &data, &config));
1382 if (flowcontrol == SP_FLOWCONTROL_XONXOFF)
1383 config.xon_xoff = SP_XONXOFF_INOUT;
1385 config.xon_xoff = SP_XONXOFF_DISABLED;
1387 if (flowcontrol == SP_FLOWCONTROL_RTSCTS) {
1388 config.rts = SP_RTS_FLOW_CONTROL;
1389 config.cts = SP_CTS_FLOW_CONTROL;
1391 if (config.rts == SP_RTS_FLOW_CONTROL)
1392 config.rts = SP_RTS_ON;
1393 config.cts = SP_CTS_IGNORE;
1396 if (flowcontrol == SP_FLOWCONTROL_DTRDSR) {
1397 config.dtr = SP_DTR_FLOW_CONTROL;
1398 config.dsr = SP_DSR_FLOW_CONTROL;
1400 if (config.dtr == SP_DTR_FLOW_CONTROL)
1401 config.dtr = SP_DTR_ON;
1402 config.dsr = SP_DSR_IGNORE;
1405 TRY(set_config(port, &data, &config));
1410 enum sp_return sp_get_signals(struct sp_port *port, enum sp_signal *signals)
1412 TRACE("%p, %p", port, signals);
1417 RETURN_ERROR(SP_ERR_ARG, "Null result pointer");
1422 if (GetCommModemStatus(port->hdl, &bits) == 0)
1423 RETURN_FAIL("GetCommModemStatus() failed");
1424 if (bits & MS_CTS_ON)
1425 *signals |= SP_SIG_CTS;
1426 if (bits & MS_DSR_ON)
1427 *signals |= SP_SIG_DSR;
1428 if (bits & MS_RING_ON)
1429 *signals |= SP_SIG_DCD;
1430 if (bits & MS_RLSD_ON)
1431 *signals |= SP_SIG_RI;
1434 if (ioctl(port->fd, TIOCMGET, &bits) < 0)
1435 RETURN_FAIL("TIOCMGET ioctl failed");
1436 if (bits & TIOCM_CTS)
1437 *signals |= SP_SIG_CTS;
1438 if (bits & TIOCM_DSR)
1439 *signals |= SP_SIG_DSR;
1440 if (bits & TIOCM_CAR)
1441 *signals |= SP_SIG_DCD;
1442 if (bits & TIOCM_RNG)
1443 *signals |= SP_SIG_RI;
1448 enum sp_return sp_start_break(struct sp_port *port)
1454 if (SetCommBreak(port->hdl) == 0)
1455 RETURN_FAIL("SetCommBreak() failed");
1457 if (ioctl(port->fd, TIOCSBRK, 1) < 0)
1458 RETURN_FAIL("TIOCSBRK ioctl failed");
1464 enum sp_return sp_end_break(struct sp_port *port)
1470 if (ClearCommBreak(port->hdl) == 0)
1471 RETURN_FAIL("ClearCommBreak() failed");
1473 if (ioctl(port->fd, TIOCCBRK, 1) < 0)
1474 RETURN_FAIL("TIOCCBRK ioctl failed");
1480 int sp_last_error_code(void)
1484 RETURN_VALUE("%d", GetLastError());
1486 RETURN_VALUE("%d", errno);
1490 char *sp_last_error_message(void)
1496 DWORD error = GetLastError();
1499 FORMAT_MESSAGE_ALLOCATE_BUFFER |
1500 FORMAT_MESSAGE_FROM_SYSTEM |
1501 FORMAT_MESSAGE_IGNORE_INSERTS,
1504 MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
1508 RETURN_VALUE("%s", message);
1510 RETURN_VALUE("%s", strerror(errno));
1514 void sp_free_error_message(char *message)
1516 TRACE("%s", message);
1527 void sp_set_debug_handler(void (*handler)(const char *format, ...))
1529 TRACE("%p", handler);
1531 sp_debug_handler = handler;
1536 void sp_default_debug_handler(const char *format, ...)
1539 va_start(args, format);
1540 if (getenv("LIBSERIALPORT_DEBUG")) {
1541 fputs("libserialport: ", stderr);
1542 vfprintf(stderr, format, args);