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"
71 struct sp_port_config {
74 enum sp_parity parity;
80 enum sp_xonxoff xon_xoff;
89 int termiox_supported;
94 /* Standard baud rates. */
96 #define BAUD_TYPE DWORD
97 #define BAUD(n) {CBR_##n, n}
99 #define BAUD_TYPE speed_t
100 #define BAUD(n) {B##n, n}
103 struct std_baudrate {
108 const struct std_baudrate std_baudrates[] = {
111 * The baudrates 50/75/134/150/200/1800/230400/460800 do not seem to
112 * have documented CBR_* macros.
114 BAUD(110), BAUD(300), BAUD(600), BAUD(1200), BAUD(2400), BAUD(4800),
115 BAUD(9600), BAUD(14400), BAUD(19200), BAUD(38400), BAUD(57600),
116 BAUD(115200), BAUD(128000), BAUD(256000),
118 BAUD(50), BAUD(75), BAUD(110), BAUD(134), BAUD(150), BAUD(200),
119 BAUD(300), BAUD(600), BAUD(1200), BAUD(1800), BAUD(2400), BAUD(4800),
120 BAUD(9600), BAUD(19200), BAUD(38400), BAUD(57600), BAUD(115200),
122 #if !defined(__APPLE__) && !defined(__OpenBSD__)
128 void (*sp_debug_handler)(const char *format, ...) = sp_default_debug_handler;
130 #define ARRAY_SIZE(x) (sizeof(x) / sizeof(x[0]))
131 #define NUM_STD_BAUDRATES ARRAY_SIZE(std_baudrates)
133 /* Debug output macros. */
134 #define DEBUG(fmt, ...) do { if (sp_debug_handler) sp_debug_handler(fmt ".\n", ##__VA_ARGS__); } while (0)
135 #define DEBUG_ERROR(err, msg) DEBUG("%s returning " #err ": " msg, __func__)
136 #define DEBUG_FAIL(msg) do { \
137 char *errmsg = sp_last_error_message(); \
138 DEBUG("%s returning SP_ERR_FAIL: " msg ": %s", __func__, errmsg); \
139 sp_free_error_message(errmsg); \
141 #define RETURN() do { DEBUG("%s returning", __func__); return; } while(0)
142 #define RETURN_CODE(x) do { DEBUG("%s returning " #x, __func__); return x; } while (0)
143 #define RETURN_CODEVAL(x) do { \
145 case SP_OK: RETURN_CODE(SP_OK); \
146 case SP_ERR_ARG: RETURN_CODE(SP_ERR_ARG); \
147 case SP_ERR_FAIL: RETURN_CODE(SP_ERR_FAIL); \
148 case SP_ERR_MEM: RETURN_CODE(SP_ERR_MEM); \
149 case SP_ERR_SUPP: RETURN_CODE(SP_ERR_SUPP); \
152 #define RETURN_OK() RETURN_CODE(SP_OK);
153 #define RETURN_ERROR(err, msg) do { DEBUG_ERROR(err, msg); return err; } while (0)
154 #define RETURN_FAIL(msg) do { DEBUG_FAIL(msg); return SP_ERR_FAIL; } while (0)
155 #define RETURN_VALUE(fmt, x) do { DEBUG("%s returning " fmt, __func__, x); return x; } while (0)
156 #define SET_ERROR(val, err, msg) do { DEBUG_ERROR(err, msg); val = err; } while (0)
157 #define SET_FAIL(val, msg) do { DEBUG_FAIL(msg); val = err; } while (0)
158 #define TRACE(fmt, ...) DEBUG("%s(" fmt ") called", __func__, ##__VA_ARGS__)
160 #define TRY(x) do { int ret = x; if (ret != SP_OK) RETURN_CODEVAL(ret); } while (0)
162 /* Helper functions. */
163 static struct sp_port **list_append(struct sp_port **list, const char *portname);
164 static enum sp_return get_config(struct sp_port *port, struct port_data *data,
165 struct sp_port_config *config);
166 static enum sp_return set_config(struct sp_port *port, struct port_data *data,
167 const struct sp_port_config *config);
169 enum sp_return sp_get_port_by_name(const char *portname, struct sp_port **port_ptr)
171 struct sp_port *port;
174 TRACE("%s, %p", portname, port_ptr);
177 RETURN_ERROR(SP_ERR_ARG, "Null result pointer");
182 RETURN_ERROR(SP_ERR_ARG, "Null port name");
184 DEBUG("Building structure for port %s", portname);
186 if (!(port = malloc(sizeof(struct sp_port))))
187 RETURN_ERROR(SP_ERR_MEM, "Port structure malloc failed");
189 len = strlen(portname) + 1;
191 if (!(port->name = malloc(len))) {
193 RETURN_ERROR(SP_ERR_MEM, "Port name malloc failed");
196 memcpy(port->name, portname, len);
199 port->hdl = INVALID_HANDLE_VALUE;
209 char *sp_get_port_name(const struct sp_port *port)
216 RETURN_VALUE("%s", port->name);
219 enum sp_return sp_get_port_handle(const struct sp_port *port, void *result_ptr)
224 RETURN_ERROR(SP_ERR_ARG, "Null port");
227 HANDLE *handle_ptr = result_ptr;
228 *handle_ptr = port->hdl;
230 int *fd_ptr = result_ptr;
237 enum sp_return sp_copy_port(const struct sp_port *port, struct sp_port **copy_ptr)
239 TRACE("%p, %p", port, copy_ptr);
242 RETURN_ERROR(SP_ERR_ARG, "Null result pointer");
247 RETURN_ERROR(SP_ERR_ARG, "Null port");
250 RETURN_ERROR(SP_ERR_ARG, "Null port name");
252 DEBUG("Copying port structure");
254 RETURN_VALUE("%p", sp_get_port_by_name(port->name, copy_ptr));
257 void sp_free_port(struct sp_port *port)
267 DEBUG("Freeing port structure");
277 static struct sp_port **list_append(struct sp_port **list, const char *portname)
282 for (count = 0; list[count]; count++);
283 if (!(tmp = realloc(list, sizeof(struct sp_port *) * (count + 2))))
286 if (sp_get_port_by_name(portname, &list[count]) != SP_OK)
288 list[count + 1] = NULL;
292 sp_free_port_list(list);
296 enum sp_return sp_list_ports(struct sp_port ***list_ptr)
298 struct sp_port **list;
299 int ret = SP_ERR_SUPP;
301 TRACE("%p", list_ptr);
304 RETURN_ERROR(SP_ERR_ARG, "Null result pointer");
306 DEBUG("Enumerating ports");
308 if (!(list = malloc(sizeof(struct sp_port **))))
309 RETURN_ERROR(SP_ERR_MEM, "Port list malloc failed");
316 DWORD max_value_len, max_data_size, max_data_len;
317 DWORD value_len, data_size, data_len;
318 DWORD type, index = 0;
324 DEBUG("Opening registry key");
325 if (RegOpenKeyEx(HKEY_LOCAL_MACHINE, _T("HARDWARE\\DEVICEMAP\\SERIALCOMM"),
326 0, KEY_QUERY_VALUE, &key) != ERROR_SUCCESS) {
327 SET_FAIL(ret, "RegOpenKeyEx() failed");
330 DEBUG("Querying registry key value and data sizes");
331 if (RegQueryInfoKey(key, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
332 &max_value_len, &max_data_size, NULL, NULL) != ERROR_SUCCESS) {
333 SET_FAIL(ret, "RegQueryInfoKey() failed");
336 max_data_len = max_data_size / sizeof(TCHAR);
337 if (!(value = malloc((max_value_len + 1) * sizeof(TCHAR)))) {
338 SET_ERROR(ret, SP_ERR_MEM, "registry value malloc failed");
341 if (!(data = malloc((max_data_len + 1) * sizeof(TCHAR)))) {
342 SET_ERROR(ret, SP_ERR_MEM, "registry data malloc failed");
345 DEBUG("Iterating over values");
347 value_len = max_value_len + 1,
348 data_size = max_data_size,
349 RegEnumValue(key, index, value, &value_len,
350 NULL, &type, (LPBYTE)data, &data_size) == ERROR_SUCCESS)
352 data_len = data_size / sizeof(TCHAR);
353 data[data_len] = '\0';
355 name_len = WideCharToMultiByte(CP_ACP, 0, data, -1, NULL, 0, NULL, NULL)
357 name_len = data_len + 1;
359 if (!(name = malloc(name_len))) {
360 SET_ERROR(ret, SP_ERR_MEM, "registry port name malloc failed");
364 WideCharToMultiByte(CP_ACP, 0, data, -1, name, name_len, NULL, NULL);
368 if (type == REG_SZ) {
369 DEBUG("Found port %s", name);
370 if (!(list = list_append(list, name))) {
371 SET_ERROR(ret, SP_ERR_MEM, "list append failed");
387 CFMutableDictionaryRef classes;
396 DEBUG("Getting IOKit master port");
397 if (IOMasterPort(MACH_PORT_NULL, &master) != KERN_SUCCESS) {
398 SET_FAIL(ret, "IOMasterPort() failed");
402 DEBUG("Creating matching dictionary");
403 if (!(classes = IOServiceMatching(kIOSerialBSDServiceValue))) {
404 SET_FAIL(ret, "IOServiceMatching() failed");
408 CFDictionarySetValue(classes,
409 CFSTR(kIOSerialBSDTypeKey), CFSTR(kIOSerialBSDAllTypes));
411 DEBUG("Getting matching services");
412 if (IOServiceGetMatchingServices(master, classes, &iter) != KERN_SUCCESS) {
413 SET_FAIL(ret, "IOServiceGetMatchingServices() failed");
417 if (!(path = malloc(PATH_MAX))) {
418 SET_ERROR(ret, SP_ERR_MEM, "device path malloc failed");
422 DEBUG("Iterating over results");
423 while ((port = IOIteratorNext(iter))) {
424 cf_path = IORegistryEntryCreateCFProperty(port,
425 CFSTR(kIOCalloutDeviceKey), kCFAllocatorDefault, 0);
427 result = CFStringGetCString(cf_path,
428 path, PATH_MAX, kCFStringEncodingASCII);
431 DEBUG("Found port %s", path);
432 if (!(list = list_append(list, path))) {
433 SET_ERROR(ret, SP_ERR_MEM, "list append failed");
434 IOObjectRelease(port);
439 IOObjectRelease(port);
444 IOObjectRelease(iter);
449 struct udev_enumerate *ud_enumerate;
450 struct udev_list_entry *ud_list;
451 struct udev_list_entry *ud_entry;
453 struct udev_device *ud_dev, *ud_parent;
456 int fd, ioctl_result;
457 struct serial_struct serial_info;
461 DEBUG("Enumerating tty devices");
463 ud_enumerate = udev_enumerate_new(ud);
464 udev_enumerate_add_match_subsystem(ud_enumerate, "tty");
465 udev_enumerate_scan_devices(ud_enumerate);
466 ud_list = udev_enumerate_get_list_entry(ud_enumerate);
467 DEBUG("Iterating over results");
468 udev_list_entry_foreach(ud_entry, ud_list) {
469 path = udev_list_entry_get_name(ud_entry);
470 DEBUG("Found device %s", path);
471 ud_dev = udev_device_new_from_syspath(ud, path);
472 /* If there is no parent device, this is a virtual tty. */
473 ud_parent = udev_device_get_parent(ud_dev);
474 if (ud_parent == NULL) {
475 DEBUG("No parent device, assuming virtual tty");
476 udev_device_unref(ud_dev);
479 name = udev_device_get_devnode(ud_dev);
480 /* The serial8250 driver has a hardcoded number of ports.
481 * The only way to tell which actually exist on a given system
482 * is to try to open them and make an ioctl call. */
483 driver = udev_device_get_driver(ud_parent);
484 if (driver && !strcmp(driver, "serial8250")) {
485 DEBUG("serial8250 device, attempting to open");
486 if ((fd = open(name, O_RDWR | O_NONBLOCK | O_NOCTTY)) < 0) {
487 DEBUG("open failed, skipping");
490 ioctl_result = ioctl(fd, TIOCGSERIAL, &serial_info);
492 if (ioctl_result != 0) {
493 DEBUG("ioctl failed, skipping");
496 if (serial_info.type == PORT_UNKNOWN) {
497 DEBUG("port type is unknown, skipping");
501 DEBUG("Found port %s", name);
502 list = list_append(list, name);
504 udev_device_unref(ud_dev);
506 SET_ERROR(ret, SP_ERR_MEM, "list append failed");
511 udev_enumerate_unref(ud_enumerate);
520 DEBUG_ERROR(SP_ERR_SUPP, "Enumeration not supported on this platform.");
523 sp_free_port_list(list);
529 void sp_free_port_list(struct sp_port **list)
540 DEBUG("Freeing port list");
542 for (i = 0; list[i]; i++)
543 sp_free_port(list[i]);
549 #define CHECK_PORT() do { \
551 RETURN_ERROR(SP_ERR_ARG, "Null port"); \
552 if (port->name == NULL) \
553 RETURN_ERROR(SP_ERR_ARG, "Null port name"); \
556 #define CHECK_PORT_HANDLE() do { \
557 if (port->hdl == INVALID_HANDLE_VALUE) \
558 RETURN_ERROR(SP_ERR_ARG, "Invalid port handle"); \
561 #define CHECK_PORT_HANDLE() do { \
563 RETURN_ERROR(SP_ERR_ARG, "Invalid port fd"); \
566 #define CHECK_OPEN_PORT() do { \
568 CHECK_PORT_HANDLE(); \
571 enum sp_return sp_open(struct sp_port *port, enum sp_mode flags)
573 TRACE("%p, %x", port, flags);
577 if (flags > (SP_MODE_READ | SP_MODE_WRITE | SP_MODE_NONBLOCK))
578 RETURN_ERROR(SP_ERR_ARG, "Invalid flags");
580 DEBUG("Opening port %s", port->name);
582 port->nonblocking = (flags & SP_MODE_NONBLOCK) ? 1 : 0;
585 DWORD desired_access = 0, flags_and_attributes = 0;
586 char *escaped_port_name;
588 /* Prefix port name with '\\.\' to work with ports above COM9. */
589 if (!(escaped_port_name = malloc(strlen(port->name + 5))))
590 RETURN_ERROR(SP_ERR_MEM, "Escaped port name malloc failed");
591 sprintf(escaped_port_name, "\\\\.\\%s", port->name);
593 /* Map 'flags' to the OS-specific settings. */
594 flags_and_attributes = FILE_ATTRIBUTE_NORMAL;
595 if (flags & SP_MODE_READ)
596 desired_access |= GENERIC_READ;
597 if (flags & SP_MODE_WRITE)
598 desired_access |= GENERIC_WRITE;
599 if (flags & SP_MODE_NONBLOCK)
600 flags_and_attributes |= FILE_FLAG_OVERLAPPED;
602 port->hdl = CreateFile(escaped_port_name, desired_access, 0, 0,
603 OPEN_EXISTING, flags_and_attributes, 0);
605 free(escaped_port_name);
607 if (port->hdl == INVALID_HANDLE_VALUE)
608 RETURN_FAIL("CreateFile() failed");
611 struct port_data data;
612 struct sp_port_config config;
615 /* Map 'flags' to the OS-specific settings. */
616 if (flags & (SP_MODE_READ | SP_MODE_WRITE))
617 flags_local |= O_RDWR;
618 else if (flags & SP_MODE_READ)
619 flags_local |= O_RDONLY;
620 else if (flags & SP_MODE_WRITE)
621 flags_local |= O_WRONLY;
622 if (flags & SP_MODE_NONBLOCK)
623 flags_local |= O_NONBLOCK;
625 if ((port->fd = open(port->name, flags_local)) < 0)
626 RETURN_FAIL("open() failed");
628 ret = get_config(port, &data, &config);
635 /* Turn off all serial port cooking. */
636 data.term.c_iflag &= ~(ISTRIP | INLCR | ICRNL);
637 data.term.c_oflag &= ~(ONLCR | OCRNL | ONOCR);
638 #if !defined(__FreeBSD__) && !defined(__OpenBSD__) && !defined(__NetBSD__)
639 data.term.c_oflag &= ~OFILL;
641 /* Disable canonical mode, and don't echo input characters. */
642 data.term.c_lflag &= ~(ICANON | ECHO);
644 /* Ignore modem status lines; enable receiver */
645 data.term.c_cflag |= (CLOCAL | CREAD);
647 ret = set_config(port, &data, &config);
658 enum sp_return sp_close(struct sp_port *port)
664 DEBUG("Closing port %s", port->name);
667 /* Returns non-zero upon success, 0 upon failure. */
668 if (CloseHandle(port->hdl) == 0)
669 RETURN_FAIL("CloseHandle() failed");
670 port->hdl = INVALID_HANDLE_VALUE;
672 /* Returns 0 upon success, -1 upon failure. */
673 if (close(port->fd) == -1)
674 RETURN_FAIL("close() failed");
681 enum sp_return sp_flush(struct sp_port *port, enum sp_buffer buffers)
683 TRACE("%p, %x", port, buffers);
687 if (buffers > SP_BUF_BOTH)
688 RETURN_ERROR(SP_ERR_ARG, "Invalid buffer selection");
690 const char *buffer_names[] = {"no", "input", "output", "both"};
692 DEBUG("Flushing %s buffers on port %s", buffer_names[buffers], port->name);
696 if (buffers & SP_BUF_INPUT)
697 flags |= PURGE_RXCLEAR;
698 if (buffers & SP_BUF_OUTPUT)
699 flags |= PURGE_TXCLEAR;
701 /* Returns non-zero upon success, 0 upon failure. */
702 if (PurgeComm(port->hdl, flags) == 0)
703 RETURN_FAIL("PurgeComm() failed");
706 if (buffers & SP_BUF_BOTH)
708 else if (buffers & SP_BUF_INPUT)
710 else if (buffers & SP_BUF_OUTPUT)
713 /* Returns 0 upon success, -1 upon failure. */
714 if (tcflush(port->fd, flags) < 0)
715 RETURN_FAIL("tcflush() failed");
720 enum sp_return sp_drain(struct sp_port *port)
726 DEBUG("Draining port %s", port->name);
729 /* Returns non-zero upon success, 0 upon failure. */
730 if (FlushFileBuffers(port->hdl) == 0)
731 RETURN_FAIL("FlushFileBuffers() failed");
733 /* Returns 0 upon success, -1 upon failure. */
734 if (tcdrain(port->fd) < 0)
735 RETURN_FAIL("tcdrain() failed");
741 enum sp_return sp_write(struct sp_port *port, const void *buf, size_t count)
743 TRACE("%p, %p, %d", port, buf, count);
748 RETURN_ERROR(SP_ERR_ARG, "Null buffer");
750 DEBUG("Writing up to %d bytes to port %s", count, port->name);
755 /* Returns non-zero upon success, 0 upon failure. */
756 if (WriteFile(port->hdl, buf, count, &written, NULL) == 0)
757 RETURN_FAIL("WriteFile() failed");
758 RETURN_VALUE("%d", written);
760 /* Returns the number of bytes written, or -1 upon failure. */
761 ssize_t written = write(port->fd, buf, count);
764 RETURN_FAIL("write() failed");
766 RETURN_VALUE("%d", written);
770 enum sp_return sp_read(struct sp_port *port, void *buf, size_t count)
772 TRACE("%p, %p, %d", port, buf, count);
777 RETURN_ERROR(SP_ERR_ARG, "Null buffer");
779 DEBUG("Reading up to %d bytes from port %s", count, port->name);
782 DWORD bytes_read = 0;
784 /* Returns non-zero upon success, 0 upon failure. */
785 if (ReadFile(port->hdl, buf, count, &bytes_read, NULL) == 0)
786 RETURN_FAIL("ReadFile() failed");
787 RETURN_VALUE("%d", bytes_read);
791 /* Returns the number of bytes read, or -1 upon failure. */
792 if ((bytes_read = read(port->fd, buf, count)) < 0) {
793 if (port->nonblocking && errno == EAGAIN)
794 /* Port is opened in nonblocking mode and there are no bytes available. */
797 /* This is an actual failure. */
798 RETURN_FAIL("read() failed");
800 RETURN_VALUE("%d", bytes_read);
805 static enum sp_return get_baudrate(int fd, int *baudrate)
809 TRACE("%d, %p", fd, baudrate);
811 DEBUG("Getting baud rate");
813 if (!(data = malloc(get_termios_size())))
814 RETURN_ERROR(SP_ERR_MEM, "termios malloc failed");
816 if (ioctl(fd, get_termios_get_ioctl(), data) < 0) {
818 RETURN_FAIL("getting termios failed");
821 *baudrate = get_termios_speed(data);
828 static enum sp_return set_baudrate(int fd, int baudrate)
832 TRACE("%d, %d", fd, baudrate);
834 DEBUG("Getting baud rate");
836 if (!(data = malloc(get_termios_size())))
837 RETURN_ERROR(SP_ERR_MEM, "termios malloc failed");
839 if (ioctl(fd, get_termios_get_ioctl(), data) < 0) {
841 RETURN_FAIL("getting termios failed");
844 DEBUG("Setting baud rate");
846 set_termios_speed(data, baudrate);
848 if (ioctl(fd, get_termios_set_ioctl(), data) < 0) {
850 RETURN_FAIL("setting termios failed");
859 static enum sp_return get_flow(int fd, int *flow)
863 TRACE("%d, %p", fd, flow);
865 DEBUG("Getting advanced flow control");
867 if (!(data = malloc(get_termiox_size())))
868 RETURN_ERROR(SP_ERR_MEM, "termiox malloc failed");
870 if (ioctl(fd, TCGETX, data) < 0) {
872 RETURN_FAIL("getting termiox failed");
875 *flow = get_termiox_flow(data);
882 static enum sp_return set_flow(int fd, int flow)
886 TRACE("%d, %d", fd, flow);
888 DEBUG("Getting advanced flow control");
890 if (!(data = malloc(get_termiox_size())))
891 RETURN_ERROR(SP_ERR_MEM, "termiox malloc failed");
893 if (ioctl(fd, TCGETX, data) < 0) {
895 RETURN_FAIL("getting termiox failed");
898 DEBUG("Setting advanced flow control");
900 set_termiox_flow(data, flow);
902 if (ioctl(fd, TCSETX, data) < 0) {
904 RETURN_FAIL("setting termiox failed");
911 #endif /* USE_TERMIOX */
912 #endif /* __linux__ */
914 static enum sp_return get_config(struct sp_port *port, struct port_data *data,
915 struct sp_port_config *config)
919 TRACE("%p, %p, %p", port, data, config);
921 DEBUG("Getting configuration for port %s", port->name);
924 if (!GetCommState(port->hdl, &data->dcb))
925 RETURN_FAIL("GetCommState() failed");
927 for (i = 0; i < NUM_STD_BAUDRATES; i++) {
928 if (data->dcb.BaudRate == std_baudrates[i].index) {
929 config->baudrate = std_baudrates[i].value;
934 if (i == NUM_STD_BAUDRATES)
935 /* BaudRate field can be either an index or a custom baud rate. */
936 config->baudrate = data->dcb.BaudRate;
938 config->bits = data->dcb.ByteSize;
940 if (data->dcb.fParity)
941 switch (data->dcb.Parity) {
943 config->parity = SP_PARITY_NONE;
946 config->parity = SP_PARITY_EVEN;
949 config->parity = SP_PARITY_ODD;
955 config->parity = SP_PARITY_NONE;
957 switch (data->dcb.StopBits) {
959 config->stopbits = 1;
962 config->stopbits = 2;
965 config->stopbits = -1;
968 switch (data->dcb.fRtsControl) {
969 case RTS_CONTROL_DISABLE:
970 config->rts = SP_RTS_OFF;
972 case RTS_CONTROL_ENABLE:
973 config->rts = SP_RTS_ON;
975 case RTS_CONTROL_HANDSHAKE:
976 config->rts = SP_RTS_FLOW_CONTROL;
982 config->cts = data->dcb.fOutxCtsFlow ? SP_CTS_FLOW_CONTROL : SP_CTS_IGNORE;
984 switch (data->dcb.fDtrControl) {
985 case DTR_CONTROL_DISABLE:
986 config->dtr = SP_DTR_OFF;
988 case DTR_CONTROL_ENABLE:
989 config->dtr = SP_DTR_ON;
991 case DTR_CONTROL_HANDSHAKE:
992 config->dtr = SP_DTR_FLOW_CONTROL;
998 config->dsr = data->dcb.fOutxDsrFlow ? SP_DSR_FLOW_CONTROL : SP_DSR_IGNORE;
1000 if (data->dcb.fInX) {
1001 if (data->dcb.fOutX)
1002 config->xon_xoff = SP_XONXOFF_INOUT;
1004 config->xon_xoff = SP_XONXOFF_IN;
1006 if (data->dcb.fOutX)
1007 config->xon_xoff = SP_XONXOFF_OUT;
1009 config->xon_xoff = SP_XONXOFF_DISABLED;
1014 if (tcgetattr(port->fd, &data->term) < 0)
1015 RETURN_FAIL("tcgetattr() failed");
1017 if (ioctl(port->fd, TIOCMGET, &data->controlbits) < 0)
1018 RETURN_FAIL("TIOCMGET ioctl failed");
1021 int ret = get_flow(port->fd, &data->flow);
1023 if (ret == SP_ERR_FAIL && errno == EINVAL)
1024 data->termiox_supported = 0;
1026 RETURN_CODEVAL(ret);
1028 data->termiox_supported = 1;
1030 data->termiox_supported = 0;
1033 for (i = 0; i < NUM_STD_BAUDRATES; i++) {
1034 if (cfgetispeed(&data->term) == std_baudrates[i].index) {
1035 config->baudrate = std_baudrates[i].value;
1040 if (i == NUM_STD_BAUDRATES) {
1042 config->baudrate = (int)data->term.c_ispeed;
1043 #elif defined(__linux__)
1044 TRY(get_baudrate(port->fd, &config->baudrate));
1046 config->baudrate = -1;
1050 switch (data->term.c_cflag & CSIZE) {
1067 if (!(data->term.c_cflag & PARENB) && (data->term.c_iflag & IGNPAR))
1068 config->parity = SP_PARITY_NONE;
1069 else if (!(data->term.c_cflag & PARENB) || (data->term.c_iflag & IGNPAR))
1070 config->parity = -1;
1072 config->parity = (data->term.c_cflag & PARODD) ? SP_PARITY_ODD : SP_PARITY_EVEN;
1074 config->stopbits = (data->term.c_cflag & CSTOPB) ? 2 : 1;
1076 if (data->term.c_cflag & CRTSCTS) {
1077 config->rts = SP_RTS_FLOW_CONTROL;
1078 config->cts = SP_CTS_FLOW_CONTROL;
1080 if (data->termiox_supported && data->flow & RTS_FLOW)
1081 config->rts = SP_RTS_FLOW_CONTROL;
1083 config->rts = (data->controlbits & TIOCM_RTS) ? SP_RTS_ON : SP_RTS_OFF;
1085 config->cts = (data->termiox_supported && data->flow & CTS_FLOW) ?
1086 SP_CTS_FLOW_CONTROL : SP_CTS_IGNORE;
1089 if (data->termiox_supported && data->flow & DTR_FLOW)
1090 config->dtr = SP_DTR_FLOW_CONTROL;
1092 config->dtr = (data->controlbits & TIOCM_DTR) ? SP_DTR_ON : SP_DTR_OFF;
1094 config->dsr = (data->termiox_supported && data->flow & DSR_FLOW) ?
1095 SP_DSR_FLOW_CONTROL : SP_DSR_IGNORE;
1097 if (data->term.c_iflag & IXOFF) {
1098 if (data->term.c_iflag & IXON)
1099 config->xon_xoff = SP_XONXOFF_INOUT;
1101 config->xon_xoff = SP_XONXOFF_IN;
1103 if (data->term.c_iflag & IXON)
1104 config->xon_xoff = SP_XONXOFF_OUT;
1106 config->xon_xoff = SP_XONXOFF_DISABLED;
1113 static enum sp_return set_config(struct sp_port *port, struct port_data *data,
1114 const struct sp_port_config *config)
1118 BAUD_TYPE baud_nonstd;
1123 int baud_nonstd = 0;
1126 TRACE("%p, %p, %p", port, data, config);
1128 DEBUG("Setting configuration for port %s", port->name);
1131 if (config->baudrate >= 0) {
1132 for (i = 0; i < NUM_STD_BAUDRATES; i++) {
1133 if (config->baudrate == std_baudrates[i].value) {
1134 data->dcb.BaudRate = std_baudrates[i].index;
1139 if (i == NUM_STD_BAUDRATES)
1140 data->dcb.BaudRate = config->baudrate;
1143 if (config->bits >= 0)
1144 data->dcb.ByteSize = config->bits;
1146 if (config->parity >= 0) {
1147 switch (config->parity) {
1148 /* Note: There's also SPACEPARITY, MARKPARITY (unneeded so far). */
1149 case SP_PARITY_NONE:
1150 data->dcb.Parity = NOPARITY;
1152 case SP_PARITY_EVEN:
1153 data->dcb.Parity = EVENPARITY;
1156 data->dcb.Parity = ODDPARITY;
1159 RETURN_ERROR(SP_ERR_ARG, "Invalid parity setting");
1163 if (config->stopbits >= 0) {
1164 switch (config->stopbits) {
1165 /* Note: There's also ONE5STOPBITS == 1.5 (unneeded so far). */
1167 data->dcb.StopBits = ONESTOPBIT;
1170 data->dcb.StopBits = TWOSTOPBITS;
1173 RETURN_ERROR(SP_ERR_ARG, "Invalid stop bit setting");
1177 if (config->rts >= 0) {
1178 switch (config->rts) {
1180 data->dcb.fRtsControl = RTS_CONTROL_DISABLE;
1183 data->dcb.fRtsControl = RTS_CONTROL_ENABLE;
1185 case SP_RTS_FLOW_CONTROL:
1186 data->dcb.fRtsControl = RTS_CONTROL_HANDSHAKE;
1189 RETURN_ERROR(SP_ERR_ARG, "Invalid RTS setting");
1193 if (config->cts >= 0) {
1194 switch (config->cts) {
1196 data->dcb.fOutxCtsFlow = FALSE;
1198 case SP_CTS_FLOW_CONTROL:
1199 data->dcb.fOutxCtsFlow = TRUE;
1202 RETURN_ERROR(SP_ERR_ARG, "Invalid CTS setting");
1206 if (config->dtr >= 0) {
1207 switch (config->dtr) {
1209 data->dcb.fDtrControl = DTR_CONTROL_DISABLE;
1212 data->dcb.fDtrControl = DTR_CONTROL_ENABLE;
1214 case SP_DTR_FLOW_CONTROL:
1215 data->dcb.fDtrControl = DTR_CONTROL_HANDSHAKE;
1218 RETURN_ERROR(SP_ERR_ARG, "Invalid DTR setting");
1222 if (config->dsr >= 0) {
1223 switch (config->dsr) {
1225 data->dcb.fOutxDsrFlow = FALSE;
1227 case SP_DSR_FLOW_CONTROL:
1228 data->dcb.fOutxDsrFlow = TRUE;
1231 RETURN_ERROR(SP_ERR_ARG, "Invalid DSR setting");
1235 if (config->xon_xoff >= 0) {
1236 switch (config->xon_xoff) {
1237 case SP_XONXOFF_DISABLED:
1238 data->dcb.fInX = FALSE;
1239 data->dcb.fOutX = FALSE;
1242 data->dcb.fInX = TRUE;
1243 data->dcb.fOutX = FALSE;
1245 case SP_XONXOFF_OUT:
1246 data->dcb.fInX = FALSE;
1247 data->dcb.fOutX = TRUE;
1249 case SP_XONXOFF_INOUT:
1250 data->dcb.fInX = TRUE;
1251 data->dcb.fOutX = TRUE;
1254 RETURN_ERROR(SP_ERR_ARG, "Invalid XON/XOFF setting");
1258 if (!SetCommState(port->hdl, &data->dcb))
1259 RETURN_FAIL("SetCommState() failed");
1265 if (config->baudrate >= 0) {
1266 for (i = 0; i < NUM_STD_BAUDRATES; i++) {
1267 if (config->baudrate == std_baudrates[i].value) {
1268 if (cfsetospeed(&data->term, std_baudrates[i].index) < 0)
1269 RETURN_FAIL("cfsetospeed() failed");
1271 if (cfsetispeed(&data->term, std_baudrates[i].index) < 0)
1272 RETURN_FAIL("cfsetispeed() failed");
1277 /* Non-standard baud rate */
1278 if (i == NUM_STD_BAUDRATES) {
1280 /* Set "dummy" baud rate. */
1281 if (cfsetspeed(&data->term, B9600) < 0)
1282 RETURN_FAIL("cfsetspeed() failed");
1283 baud_nonstd = config->baudrate;
1284 #elif defined(__linux__)
1287 RETURN_ERROR(SP_ERR_SUPP, "Non-standard baudrate not supported");
1292 if (config->bits >= 0) {
1293 data->term.c_cflag &= ~CSIZE;
1294 switch (config->bits) {
1296 data->term.c_cflag |= CS8;
1299 data->term.c_cflag |= CS7;
1302 data->term.c_cflag |= CS6;
1305 data->term.c_cflag |= CS5;
1308 RETURN_ERROR(SP_ERR_ARG, "Invalid data bits setting");
1312 if (config->parity >= 0) {
1313 data->term.c_iflag &= ~IGNPAR;
1314 data->term.c_cflag &= ~(PARENB | PARODD);
1315 switch (config->parity) {
1316 case SP_PARITY_NONE:
1317 data->term.c_iflag |= IGNPAR;
1319 case SP_PARITY_EVEN:
1320 data->term.c_cflag |= PARENB;
1323 data->term.c_cflag |= PARENB | PARODD;
1326 RETURN_ERROR(SP_ERR_ARG, "Invalid parity setting");
1330 if (config->stopbits >= 0) {
1331 data->term.c_cflag &= ~CSTOPB;
1332 switch (config->stopbits) {
1334 data->term.c_cflag &= ~CSTOPB;
1337 data->term.c_cflag |= CSTOPB;
1340 RETURN_ERROR(SP_ERR_ARG, "Invalid stop bits setting");
1344 if (config->rts >= 0 || config->cts >= 0) {
1345 if (data->termiox_supported) {
1346 data->flow &= ~(RTS_FLOW | CTS_FLOW);
1347 switch (config->rts) {
1350 controlbits = TIOCM_RTS;
1351 if (ioctl(port->fd, config->rts == SP_RTS_ON ? TIOCMBIS : TIOCMBIC, &controlbits) < 0)
1352 RETURN_FAIL("Setting RTS signal level failed");
1354 case SP_RTS_FLOW_CONTROL:
1355 data->flow |= RTS_FLOW;
1360 if (config->cts == SP_CTS_FLOW_CONTROL)
1361 data->flow |= CTS_FLOW;
1363 if (data->flow & (RTS_FLOW | CTS_FLOW))
1364 data->term.c_iflag |= CRTSCTS;
1366 data->term.c_iflag &= ~CRTSCTS;
1368 /* Asymmetric use of RTS/CTS not supported. */
1369 if (data->term.c_iflag & CRTSCTS) {
1370 /* Flow control can only be disabled for both RTS & CTS together. */
1371 if (config->rts >= 0 && config->rts != SP_RTS_FLOW_CONTROL) {
1372 if (config->cts != SP_CTS_IGNORE)
1373 RETURN_ERROR(SP_ERR_SUPP, "RTS & CTS flow control must be disabled together");
1375 if (config->cts >= 0 && config->cts != SP_CTS_FLOW_CONTROL) {
1376 if (config->rts <= 0 || config->rts == SP_RTS_FLOW_CONTROL)
1377 RETURN_ERROR(SP_ERR_SUPP, "RTS & CTS flow control must be disabled together");
1380 /* Flow control can only be enabled for both RTS & CTS together. */
1381 if (((config->rts == SP_RTS_FLOW_CONTROL) && (config->cts != SP_CTS_FLOW_CONTROL)) ||
1382 ((config->cts == SP_CTS_FLOW_CONTROL) && (config->rts != SP_RTS_FLOW_CONTROL)))
1383 RETURN_ERROR(SP_ERR_SUPP, "RTS & CTS flow control must be enabled together");
1386 if (config->rts >= 0) {
1387 if (config->rts == SP_RTS_FLOW_CONTROL) {
1388 data->term.c_iflag |= CRTSCTS;
1390 controlbits = TIOCM_RTS;
1391 if (ioctl(port->fd, config->rts == SP_RTS_ON ? TIOCMBIS : TIOCMBIC,
1393 RETURN_FAIL("Setting RTS signal level failed");
1399 if (config->dtr >= 0 || config->dsr >= 0) {
1400 if (data->termiox_supported) {
1401 data->flow &= ~(DTR_FLOW | DSR_FLOW);
1402 switch (config->dtr) {
1405 controlbits = TIOCM_DTR;
1406 if (ioctl(port->fd, config->dtr == SP_DTR_ON ? TIOCMBIS : TIOCMBIC, &controlbits) < 0)
1407 RETURN_FAIL("Setting DTR signal level failed");
1409 case SP_DTR_FLOW_CONTROL:
1410 data->flow |= DTR_FLOW;
1415 if (config->dsr == SP_DSR_FLOW_CONTROL)
1416 data->flow |= DSR_FLOW;
1418 /* DTR/DSR flow control not supported. */
1419 if (config->dtr == SP_DTR_FLOW_CONTROL || config->dsr == SP_DSR_FLOW_CONTROL)
1420 RETURN_ERROR(SP_ERR_SUPP, "DTR/DSR flow control not supported");
1422 if (config->dtr >= 0) {
1423 controlbits = TIOCM_DTR;
1424 if (ioctl(port->fd, config->dtr == SP_DTR_ON ? TIOCMBIS : TIOCMBIC,
1426 RETURN_FAIL("Setting DTR signal level failed");
1431 if (config->xon_xoff >= 0) {
1432 data->term.c_iflag &= ~(IXON | IXOFF | IXANY);
1433 switch (config->xon_xoff) {
1434 case SP_XONXOFF_DISABLED:
1437 data->term.c_iflag |= IXOFF;
1439 case SP_XONXOFF_OUT:
1440 data->term.c_iflag |= IXON | IXANY;
1442 case SP_XONXOFF_INOUT:
1443 data->term.c_iflag |= IXON | IXOFF | IXANY;
1446 RETURN_ERROR(SP_ERR_ARG, "Invalid XON/XOFF setting");
1450 if (tcsetattr(port->fd, TCSADRAIN, &data->term) < 0)
1451 RETURN_FAIL("tcsetattr() failed");
1454 if (baud_nonstd != B0) {
1455 if (ioctl(port->fd, IOSSIOSPEED, &baud_nonstd) == -1)
1456 RETURN_FAIL("IOSSIOSPEED ioctl failed");
1457 /* Set baud rates in data->term to correct, but incompatible
1458 * with tcsetattr() value, same as delivered by tcgetattr(). */
1459 if (cfsetspeed(&data->term, baud_nonstd) < 0)
1460 RETURN_FAIL("cfsetspeed() failed");
1462 #elif defined(__linux__)
1464 TRY(set_baudrate(port->fd, config->baudrate));
1466 if (data->termiox_supported)
1467 TRY(set_flow(port->fd, data->flow));
1471 #endif /* !_WIN32 */
1476 enum sp_return sp_new_config(struct sp_port_config **config_ptr)
1478 TRACE("%p", config_ptr);
1479 struct sp_port_config *config;
1482 RETURN_ERROR(SP_ERR_ARG, "Null result pointer");
1486 if (!(config = malloc(sizeof(struct sp_port_config))))
1487 RETURN_ERROR(SP_ERR_MEM, "config malloc failed");
1489 config->baudrate = -1;
1491 config->parity = -1;
1492 config->stopbits = -1;
1498 *config_ptr = config;
1503 void sp_free_config(struct sp_port_config *config)
1505 TRACE("%p", config);
1508 DEBUG("Null config");
1515 enum sp_return sp_get_config(struct sp_port *port, struct sp_port_config *config)
1517 struct port_data data;
1519 TRACE("%p, %p", port, config);
1524 RETURN_ERROR(SP_ERR_ARG, "Null config");
1526 TRY(get_config(port, &data, config));
1531 enum sp_return sp_set_config(struct sp_port *port, const struct sp_port_config *config)
1533 struct port_data data;
1534 struct sp_port_config prev_config;
1536 TRACE("%p, %p", port, config);
1541 RETURN_ERROR(SP_ERR_ARG, "Null config");
1543 TRY(get_config(port, &data, &prev_config));
1544 TRY(set_config(port, &data, config));
1549 #define CREATE_ACCESSORS(x, type) \
1550 enum sp_return sp_set_##x(struct sp_port *port, type x) { \
1551 struct port_data data; \
1552 struct sp_port_config config; \
1553 TRACE("%p, %d", port, x); \
1554 CHECK_OPEN_PORT(); \
1555 TRY(get_config(port, &data, &config)); \
1557 TRY(set_config(port, &data, &config)); \
1560 enum sp_return sp_get_config_##x(const struct sp_port_config *config, type *x) { \
1561 TRACE("%p", config); \
1563 RETURN_ERROR(SP_ERR_ARG, "Null config"); \
1567 enum sp_return sp_set_config_##x(struct sp_port_config *config, type x) { \
1568 TRACE("%p, %d", config, x); \
1570 RETURN_ERROR(SP_ERR_ARG, "Null config"); \
1575 CREATE_ACCESSORS(baudrate, int)
1576 CREATE_ACCESSORS(bits, int)
1577 CREATE_ACCESSORS(parity, enum sp_parity)
1578 CREATE_ACCESSORS(stopbits, int)
1579 CREATE_ACCESSORS(rts, enum sp_rts)
1580 CREATE_ACCESSORS(cts, enum sp_cts)
1581 CREATE_ACCESSORS(dtr, enum sp_dtr)
1582 CREATE_ACCESSORS(dsr, enum sp_dsr)
1583 CREATE_ACCESSORS(xon_xoff, enum sp_xonxoff)
1585 enum sp_return sp_set_config_flowcontrol(struct sp_port_config *config, enum sp_flowcontrol flowcontrol)
1588 RETURN_ERROR(SP_ERR_ARG, "Null configuration");
1590 if (flowcontrol > SP_FLOWCONTROL_DTRDSR)
1591 RETURN_ERROR(SP_ERR_ARG, "Invalid flow control setting");
1593 if (flowcontrol == SP_FLOWCONTROL_XONXOFF)
1594 config->xon_xoff = SP_XONXOFF_INOUT;
1596 config->xon_xoff = SP_XONXOFF_DISABLED;
1598 if (flowcontrol == SP_FLOWCONTROL_RTSCTS) {
1599 config->rts = SP_RTS_FLOW_CONTROL;
1600 config->cts = SP_CTS_FLOW_CONTROL;
1602 if (config->rts == SP_RTS_FLOW_CONTROL)
1603 config->rts = SP_RTS_ON;
1604 config->cts = SP_CTS_IGNORE;
1607 if (flowcontrol == SP_FLOWCONTROL_DTRDSR) {
1608 config->dtr = SP_DTR_FLOW_CONTROL;
1609 config->dsr = SP_DSR_FLOW_CONTROL;
1611 if (config->dtr == SP_DTR_FLOW_CONTROL)
1612 config->dtr = SP_DTR_ON;
1613 config->dsr = SP_DSR_IGNORE;
1619 enum sp_return sp_set_flowcontrol(struct sp_port *port, enum sp_flowcontrol flowcontrol)
1621 struct port_data data;
1622 struct sp_port_config config;
1624 TRACE("%p, %d", port, flowcontrol);
1628 TRY(get_config(port, &data, &config));
1630 TRY(sp_set_config_flowcontrol(&config, flowcontrol));
1632 TRY(set_config(port, &data, &config));
1637 enum sp_return sp_get_signals(struct sp_port *port, enum sp_signal *signals)
1639 TRACE("%p, %p", port, signals);
1644 RETURN_ERROR(SP_ERR_ARG, "Null result pointer");
1646 DEBUG("Getting control signals for port %s", port->name);
1651 if (GetCommModemStatus(port->hdl, &bits) == 0)
1652 RETURN_FAIL("GetCommModemStatus() failed");
1653 if (bits & MS_CTS_ON)
1654 *signals |= SP_SIG_CTS;
1655 if (bits & MS_DSR_ON)
1656 *signals |= SP_SIG_DSR;
1657 if (bits & MS_RLSD_ON)
1658 *signals |= SP_SIG_DCD;
1659 if (bits & MS_RING_ON)
1660 *signals |= SP_SIG_RI;
1663 if (ioctl(port->fd, TIOCMGET, &bits) < 0)
1664 RETURN_FAIL("TIOCMGET ioctl failed");
1665 if (bits & TIOCM_CTS)
1666 *signals |= SP_SIG_CTS;
1667 if (bits & TIOCM_DSR)
1668 *signals |= SP_SIG_DSR;
1669 if (bits & TIOCM_CAR)
1670 *signals |= SP_SIG_DCD;
1671 if (bits & TIOCM_RNG)
1672 *signals |= SP_SIG_RI;
1677 enum sp_return sp_start_break(struct sp_port *port)
1683 if (SetCommBreak(port->hdl) == 0)
1684 RETURN_FAIL("SetCommBreak() failed");
1686 if (ioctl(port->fd, TIOCSBRK, 1) < 0)
1687 RETURN_FAIL("TIOCSBRK ioctl failed");
1693 enum sp_return sp_end_break(struct sp_port *port)
1699 if (ClearCommBreak(port->hdl) == 0)
1700 RETURN_FAIL("ClearCommBreak() failed");
1702 if (ioctl(port->fd, TIOCCBRK, 1) < 0)
1703 RETURN_FAIL("TIOCCBRK ioctl failed");
1709 int sp_last_error_code(void)
1713 RETURN_VALUE("%d", GetLastError());
1715 RETURN_VALUE("%d", errno);
1719 char *sp_last_error_message(void)
1725 DWORD error = GetLastError();
1728 FORMAT_MESSAGE_ALLOCATE_BUFFER |
1729 FORMAT_MESSAGE_FROM_SYSTEM |
1730 FORMAT_MESSAGE_IGNORE_INSERTS,
1733 MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
1737 RETURN_VALUE("%s", message);
1739 RETURN_VALUE("%s", strerror(errno));
1743 void sp_free_error_message(char *message)
1745 TRACE("%s", message);
1756 void sp_set_debug_handler(void (*handler)(const char *format, ...))
1758 TRACE("%p", handler);
1760 sp_debug_handler = handler;
1765 void sp_default_debug_handler(const char *format, ...)
1768 va_start(args, format);
1769 if (getenv("LIBSERIALPORT_DEBUG")) {
1770 fputs("libserialport: ", stderr);
1771 vfprintf(stderr, format, args);