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"
70 struct sp_port_config {
73 enum sp_parity parity;
79 enum sp_xonxoff xon_xoff;
88 int termiox_supported;
93 /* Standard baud rates. */
95 #define BAUD_TYPE DWORD
96 #define BAUD(n) {CBR_##n, n}
98 #define BAUD_TYPE speed_t
99 #define BAUD(n) {B##n, n}
102 struct std_baudrate {
107 const struct std_baudrate std_baudrates[] = {
110 * The baudrates 50/75/134/150/200/1800/230400/460800 do not seem to
111 * have documented CBR_* macros.
113 BAUD(110), BAUD(300), BAUD(600), BAUD(1200), BAUD(2400), BAUD(4800),
114 BAUD(9600), BAUD(14400), BAUD(19200), BAUD(38400), BAUD(57600),
115 BAUD(115200), BAUD(128000), BAUD(256000),
117 BAUD(50), BAUD(75), BAUD(110), BAUD(134), BAUD(150), BAUD(200),
118 BAUD(300), BAUD(600), BAUD(1200), BAUD(1800), BAUD(2400), BAUD(4800),
119 BAUD(9600), BAUD(19200), BAUD(38400), BAUD(57600), BAUD(115200),
121 #if !defined(__APPLE__) && !defined(__OpenBSD__)
127 void (*sp_debug_handler)(const char *format, ...) = sp_default_debug_handler;
129 #define ARRAY_SIZE(x) (sizeof(x) / sizeof(x[0]))
130 #define NUM_STD_BAUDRATES ARRAY_SIZE(std_baudrates)
132 /* Debug output macros. */
133 #define DEBUG(fmt, ...) do { if (sp_debug_handler) sp_debug_handler(fmt ".\n", ##__VA_ARGS__); } while (0)
134 #define DEBUG_ERROR(err, msg) DEBUG("%s returning " #err ": " msg, __func__)
135 #define DEBUG_FAIL(msg) do { \
136 char *errmsg = sp_last_error_message(); \
137 DEBUG("%s returning SP_ERR_FAIL: " msg ": %s", __func__, errmsg); \
138 sp_free_error_message(errmsg); \
140 #define RETURN() do { DEBUG("%s returning", __func__); return; } while(0)
141 #define RETURN_CODE(x) do { DEBUG("%s returning " #x, __func__); return x; } while (0)
142 #define RETURN_CODEVAL(x) do { \
144 case SP_OK: RETURN_CODE(SP_OK); \
145 case SP_ERR_ARG: RETURN_CODE(SP_ERR_ARG); \
146 case SP_ERR_FAIL: RETURN_CODE(SP_ERR_FAIL); \
147 case SP_ERR_MEM: RETURN_CODE(SP_ERR_MEM); \
148 case SP_ERR_SUPP: RETURN_CODE(SP_ERR_SUPP); \
151 #define RETURN_OK() RETURN_CODE(SP_OK);
152 #define RETURN_ERROR(err, msg) do { DEBUG_ERROR(err, msg); return err; } while (0)
153 #define RETURN_FAIL(msg) do { DEBUG_FAIL(msg); return SP_ERR_FAIL; } while (0)
154 #define RETURN_VALUE(fmt, x) do { DEBUG("%s returning " fmt, __func__, x); return x; } while (0)
155 #define SET_ERROR(val, err, msg) do { DEBUG_ERROR(err, msg); val = err; } while (0)
156 #define SET_FAIL(val, msg) do { DEBUG_FAIL(msg); val = err; } while (0)
157 #define TRACE(fmt, ...) DEBUG("%s(" fmt ") called", __func__, ##__VA_ARGS__)
159 #define TRY(x) do { int ret = x; if (ret != SP_OK) RETURN_CODEVAL(ret); } while (0)
161 /* Helper functions. */
162 static struct sp_port **list_append(struct sp_port **list, const char *portname);
163 static enum sp_return get_config(struct sp_port *port, struct port_data *data,
164 struct sp_port_config *config);
165 static enum sp_return set_config(struct sp_port *port, struct port_data *data,
166 const struct sp_port_config *config);
168 enum sp_return sp_get_port_by_name(const char *portname, struct sp_port **port_ptr)
170 struct sp_port *port;
173 TRACE("%s, %p", portname, port_ptr);
176 RETURN_ERROR(SP_ERR_ARG, "Null result pointer");
181 RETURN_ERROR(SP_ERR_ARG, "Null port name");
183 DEBUG("Building structure for port %s", portname);
185 if (!(port = malloc(sizeof(struct sp_port))))
186 RETURN_ERROR(SP_ERR_MEM, "Port structure malloc failed");
188 len = strlen(portname) + 1;
190 if (!(port->name = malloc(len))) {
192 RETURN_ERROR(SP_ERR_MEM, "Port name malloc failed");
195 memcpy(port->name, portname, len);
198 port->hdl = INVALID_HANDLE_VALUE;
208 char *sp_get_port_name(const struct sp_port *port)
215 RETURN_VALUE("%s", port->name);
218 enum sp_return sp_get_port_handle(const struct sp_port *port, void *result_ptr)
223 RETURN_ERROR(SP_ERR_ARG, "Null port");
226 HANDLE *handle_ptr = result_ptr;
227 *handle_ptr = port->hdl;
229 int *fd_ptr = result_ptr;
236 enum sp_return sp_copy_port(const struct sp_port *port, struct sp_port **copy_ptr)
238 TRACE("%p, %p", port, copy_ptr);
241 RETURN_ERROR(SP_ERR_ARG, "Null result pointer");
246 RETURN_ERROR(SP_ERR_ARG, "Null port");
249 RETURN_ERROR(SP_ERR_ARG, "Null port name");
251 DEBUG("Copying port structure");
253 RETURN_VALUE("%p", sp_get_port_by_name(port->name, copy_ptr));
256 void sp_free_port(struct sp_port *port)
266 DEBUG("Freeing port structure");
276 static struct sp_port **list_append(struct sp_port **list, const char *portname)
281 for (count = 0; list[count]; count++);
282 if (!(tmp = realloc(list, sizeof(struct sp_port *) * (count + 2))))
285 if (sp_get_port_by_name(portname, &list[count]) != SP_OK)
287 list[count + 1] = NULL;
291 sp_free_port_list(list);
295 enum sp_return sp_list_ports(struct sp_port ***list_ptr)
297 struct sp_port **list;
298 int ret = SP_ERR_SUPP;
300 TRACE("%p", list_ptr);
303 RETURN_ERROR(SP_ERR_ARG, "Null result pointer");
305 DEBUG("Enumerating ports");
307 if (!(list = malloc(sizeof(struct sp_port **))))
308 RETURN_ERROR(SP_ERR_MEM, "Port list malloc failed");
315 DWORD max_value_len, max_data_size, max_data_len;
316 DWORD value_len, data_size, data_len;
317 DWORD type, index = 0;
323 DEBUG("Opening registry key");
324 if (RegOpenKeyEx(HKEY_LOCAL_MACHINE, _T("HARDWARE\\DEVICEMAP\\SERIALCOMM"),
325 0, KEY_QUERY_VALUE, &key) != ERROR_SUCCESS) {
326 SET_FAIL(ret, "RegOpenKeyEx() failed");
329 DEBUG("Querying registry key value and data sizes");
330 if (RegQueryInfoKey(key, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
331 &max_value_len, &max_data_size, NULL, NULL) != ERROR_SUCCESS) {
332 SET_FAIL(ret, "RegQueryInfoKey() failed");
335 max_data_len = max_data_size / sizeof(TCHAR);
336 if (!(value = malloc((max_value_len + 1) * sizeof(TCHAR)))) {
337 SET_ERROR(ret, SP_ERR_MEM, "registry value malloc failed");
340 if (!(data = malloc((max_data_len + 1) * sizeof(TCHAR)))) {
341 SET_ERROR(ret, SP_ERR_MEM, "registry data malloc failed");
344 DEBUG("Iterating over values");
346 value_len = max_value_len + 1,
347 data_size = max_data_size,
348 RegEnumValue(key, index, value, &value_len,
349 NULL, &type, (LPBYTE)data, &data_size) == ERROR_SUCCESS)
351 data_len = data_size / sizeof(TCHAR);
352 data[data_len] = '\0';
354 name_len = WideCharToMultiByte(CP_ACP, 0, data, -1, NULL, 0, NULL, NULL)
356 name_len = data_len + 1;
358 if (!(name = malloc(name_len))) {
359 SET_ERROR(ret, SP_ERR_MEM, "registry port name malloc failed");
363 WideCharToMultiByte(CP_ACP, 0, data, -1, name, name_len, NULL, NULL);
367 if (type == REG_SZ) {
368 DEBUG("Found port %s", name);
369 if (!(list = list_append(list, name))) {
370 SET_ERROR(ret, SP_ERR_MEM, "list append failed");
386 CFMutableDictionaryRef classes;
395 DEBUG("Getting IOKit master port");
396 if (IOMasterPort(MACH_PORT_NULL, &master) != KERN_SUCCESS) {
397 SET_FAIL(ret, "IOMasterPort() failed");
401 DEBUG("Creating matching dictionary");
402 if (!(classes = IOServiceMatching(kIOSerialBSDServiceValue))) {
403 SET_FAIL(ret, "IOServiceMatching() failed");
407 CFDictionarySetValue(classes,
408 CFSTR(kIOSerialBSDTypeKey), CFSTR(kIOSerialBSDAllTypes));
410 DEBUG("Getting matching services");
411 if (IOServiceGetMatchingServices(master, classes, &iter) != KERN_SUCCESS) {
412 SET_FAIL(ret, "IOServiceGetMatchingServices() failed");
416 if (!(path = malloc(PATH_MAX))) {
417 SET_ERROR(ret, SP_ERR_MEM, "device path malloc failed");
421 DEBUG("Iterating over results");
422 while ((port = IOIteratorNext(iter))) {
423 cf_path = IORegistryEntryCreateCFProperty(port,
424 CFSTR(kIOCalloutDeviceKey), kCFAllocatorDefault, 0);
426 result = CFStringGetCString(cf_path,
427 path, PATH_MAX, kCFStringEncodingASCII);
430 DEBUG("Found port %s", path);
431 if (!(list = list_append(list, path))) {
432 SET_ERROR(ret, SP_ERR_MEM, "list append failed");
433 IOObjectRelease(port);
438 IOObjectRelease(port);
443 IOObjectRelease(iter);
448 struct udev_enumerate *ud_enumerate;
449 struct udev_list_entry *ud_list;
450 struct udev_list_entry *ud_entry;
452 struct udev_device *ud_dev, *ud_parent;
455 int fd, ioctl_result;
456 struct serial_struct serial_info;
460 DEBUG("Enumerating tty devices");
462 ud_enumerate = udev_enumerate_new(ud);
463 udev_enumerate_add_match_subsystem(ud_enumerate, "tty");
464 udev_enumerate_scan_devices(ud_enumerate);
465 ud_list = udev_enumerate_get_list_entry(ud_enumerate);
466 DEBUG("Iterating over results");
467 udev_list_entry_foreach(ud_entry, ud_list) {
468 path = udev_list_entry_get_name(ud_entry);
469 DEBUG("Found device %s", path);
470 ud_dev = udev_device_new_from_syspath(ud, path);
471 /* If there is no parent device, this is a virtual tty. */
472 ud_parent = udev_device_get_parent(ud_dev);
473 if (ud_parent == NULL) {
474 DEBUG("No parent device, assuming virtual tty");
475 udev_device_unref(ud_dev);
478 name = udev_device_get_devnode(ud_dev);
479 /* The serial8250 driver has a hardcoded number of ports.
480 * The only way to tell which actually exist on a given system
481 * is to try to open them and make an ioctl call. */
482 driver = udev_device_get_driver(ud_parent);
483 if (driver && !strcmp(driver, "serial8250")) {
484 DEBUG("serial8250 device, attempting to open");
485 if ((fd = open(name, O_RDWR | O_NONBLOCK | O_NOCTTY)) < 0) {
486 DEBUG("open failed, skipping");
489 ioctl_result = ioctl(fd, TIOCGSERIAL, &serial_info);
491 if (ioctl_result != 0) {
492 DEBUG("ioctl failed, skipping");
495 if (serial_info.type == PORT_UNKNOWN) {
496 DEBUG("port type is unknown, skipping");
500 DEBUG("Found port %s", name);
501 list = list_append(list, name);
503 udev_device_unref(ud_dev);
505 SET_ERROR(ret, SP_ERR_MEM, "list append failed");
510 udev_enumerate_unref(ud_enumerate);
519 DEBUG_ERROR(SP_ERR_SUPP, "Enumeration not supported on this platform.");
522 sp_free_port_list(list);
528 void sp_free_port_list(struct sp_port **list)
539 DEBUG("Freeing port list");
541 for (i = 0; list[i]; i++)
542 sp_free_port(list[i]);
548 #define CHECK_PORT() do { \
550 RETURN_ERROR(SP_ERR_ARG, "Null port"); \
551 if (port->name == NULL) \
552 RETURN_ERROR(SP_ERR_ARG, "Null port name"); \
555 #define CHECK_PORT_HANDLE() do { \
556 if (port->hdl == INVALID_HANDLE_VALUE) \
557 RETURN_ERROR(SP_ERR_ARG, "Invalid port handle"); \
560 #define CHECK_PORT_HANDLE() do { \
562 RETURN_ERROR(SP_ERR_ARG, "Invalid port fd"); \
565 #define CHECK_OPEN_PORT() do { \
567 CHECK_PORT_HANDLE(); \
570 enum sp_return sp_open(struct sp_port *port, enum sp_mode flags)
572 TRACE("%p, %x", port, flags);
576 if (flags > (SP_MODE_READ | SP_MODE_WRITE | SP_MODE_NONBLOCK))
577 RETURN_ERROR(SP_ERR_ARG, "Invalid flags");
579 DEBUG("Opening port %s", port->name);
582 DWORD desired_access = 0, flags_and_attributes = 0;
583 char *escaped_port_name;
585 /* Prefix port name with '\\.\' to work with ports above COM9. */
586 if (!(escaped_port_name = malloc(strlen(port->name + 5))))
587 RETURN_ERROR(SP_ERR_MEM, "Escaped port name malloc failed");
588 sprintf(escaped_port_name, "\\\\.\\%s", port->name);
590 /* Map 'flags' to the OS-specific settings. */
591 flags_and_attributes = FILE_ATTRIBUTE_NORMAL;
592 if (flags & SP_MODE_READ)
593 desired_access |= GENERIC_READ;
594 if (flags & SP_MODE_WRITE)
595 desired_access |= GENERIC_WRITE;
596 if (flags & SP_MODE_NONBLOCK)
597 flags_and_attributes |= FILE_FLAG_OVERLAPPED;
599 port->hdl = CreateFile(escaped_port_name, desired_access, 0, 0,
600 OPEN_EXISTING, flags_and_attributes, 0);
602 free(escaped_port_name);
604 if (port->hdl == INVALID_HANDLE_VALUE)
605 RETURN_FAIL("CreateFile() failed");
608 struct port_data data;
609 struct sp_port_config config;
612 /* Map 'flags' to the OS-specific settings. */
613 if (flags & (SP_MODE_READ | SP_MODE_WRITE))
614 flags_local |= O_RDWR;
615 else if (flags & SP_MODE_READ)
616 flags_local |= O_RDONLY;
617 else if (flags & SP_MODE_WRITE)
618 flags_local |= O_WRONLY;
619 if (flags & SP_MODE_NONBLOCK)
620 flags_local |= O_NONBLOCK;
622 if ((port->fd = open(port->name, flags_local)) < 0)
623 RETURN_FAIL("open() failed");
625 ret = get_config(port, &data, &config);
632 /* Turn off all serial port cooking. */
633 data.term.c_iflag &= ~(ISTRIP | INLCR | ICRNL);
634 data.term.c_oflag &= ~(ONLCR | OCRNL | ONOCR);
635 #if !defined(__FreeBSD__) && !defined(__OpenBSD__) && !defined(__NetBSD__)
636 data.term.c_oflag &= ~OFILL;
638 /* Disable canonical mode, and don't echo input characters. */
639 data.term.c_lflag &= ~(ICANON | ECHO);
641 /* Ignore modem status lines; enable receiver */
642 data.term.c_cflag |= (CLOCAL | CREAD);
644 ret = set_config(port, &data, &config);
655 enum sp_return sp_close(struct sp_port *port)
661 DEBUG("Closing port %s", port->name);
664 /* Returns non-zero upon success, 0 upon failure. */
665 if (CloseHandle(port->hdl) == 0)
666 RETURN_FAIL("CloseHandle() failed");
667 port->hdl = INVALID_HANDLE_VALUE;
669 /* Returns 0 upon success, -1 upon failure. */
670 if (close(port->fd) == -1)
671 RETURN_FAIL("close() failed");
678 enum sp_return sp_flush(struct sp_port *port, enum sp_buffer buffers)
680 TRACE("%p, %x", port, buffers);
684 if (buffers > SP_BUF_BOTH)
685 RETURN_ERROR(SP_ERR_ARG, "Invalid buffer selection");
687 const char *buffer_names[] = {"input", "output", "both"};
689 DEBUG("Flushing %s buffers on port %s", buffer_names[buffers], port->name);
693 if (buffers & SP_BUF_INPUT)
694 flags |= PURGE_RXCLEAR;
695 if (buffers & SP_BUF_OUTPUT)
696 flags |= PURGE_TXCLEAR;
698 /* Returns non-zero upon success, 0 upon failure. */
699 if (PurgeComm(port->hdl, flags) == 0)
700 RETURN_FAIL("PurgeComm() failed");
703 if (buffers & SP_BUF_BOTH)
705 else if (buffers & SP_BUF_INPUT)
707 else if (buffers & SP_BUF_OUTPUT)
710 /* Returns 0 upon success, -1 upon failure. */
711 if (tcflush(port->fd, flags) < 0)
712 RETURN_FAIL("tcflush() failed");
717 enum sp_return sp_drain(struct sp_port *port)
723 DEBUG("Draining port %s", port->name);
726 /* Returns non-zero upon success, 0 upon failure. */
727 if (FlushFileBuffers(port->hdl) == 0)
728 RETURN_FAIL("FlushFileBuffers() failed");
730 /* Returns 0 upon success, -1 upon failure. */
731 if (tcdrain(port->fd) < 0)
732 RETURN_FAIL("tcdrain() failed");
738 enum sp_return sp_write(struct sp_port *port, const void *buf, size_t count)
740 TRACE("%p, %p, %d", port, buf, count);
745 RETURN_ERROR(SP_ERR_ARG, "Null buffer");
747 DEBUG("Writing up to %d bytes to port %s", count, port->name);
752 /* Returns non-zero upon success, 0 upon failure. */
753 if (WriteFile(port->hdl, buf, count, &written, NULL) == 0)
754 RETURN_FAIL("WriteFile() failed");
755 RETURN_VALUE("%d", written);
757 /* Returns the number of bytes written, or -1 upon failure. */
758 ssize_t written = write(port->fd, buf, count);
761 RETURN_FAIL("write() failed");
763 RETURN_VALUE("%d", written);
767 enum sp_return sp_read(struct sp_port *port, void *buf, size_t count)
769 TRACE("%p, %p, %d", port, buf, count);
774 RETURN_ERROR(SP_ERR_ARG, "Null buffer");
776 DEBUG("Reading up to %d bytes from port %s", count, port->name);
779 DWORD bytes_read = 0;
781 /* Returns non-zero upon success, 0 upon failure. */
782 if (ReadFile(port->hdl, buf, count, &bytes_read, NULL) == 0)
783 RETURN_FAIL("ReadFile() failed");
784 RETURN_VALUE("%d", bytes_read);
788 /* Returns the number of bytes read, or -1 upon failure. */
789 if ((bytes_read = read(port->fd, buf, count)) < 0)
790 RETURN_FAIL("read() failed");
791 RETURN_VALUE("%d", bytes_read);
796 static enum sp_return get_baudrate(int fd, int *baudrate)
800 TRACE("%d, %p", fd, baudrate);
802 DEBUG("Getting baud rate");
804 if (!(data = malloc(get_termios_size())))
805 RETURN_ERROR(SP_ERR_MEM, "termios malloc failed");
807 if (ioctl(fd, get_termios_get_ioctl(), data) < 0) {
809 RETURN_FAIL("getting termios failed");
812 *baudrate = get_termios_speed(data);
819 static enum sp_return set_baudrate(int fd, int baudrate)
823 TRACE("%d, %d", fd, baudrate);
825 DEBUG("Getting baud rate");
827 if (!(data = malloc(get_termios_size())))
828 RETURN_ERROR(SP_ERR_MEM, "termios malloc failed");
830 if (ioctl(fd, get_termios_get_ioctl(), data) < 0) {
832 RETURN_FAIL("getting termios failed");
835 DEBUG("Setting baud rate");
837 set_termios_speed(data, baudrate);
839 if (ioctl(fd, get_termios_set_ioctl(), data) < 0) {
841 RETURN_FAIL("setting termios failed");
850 static enum sp_return get_flow(int fd, int *flow)
854 TRACE("%d, %p", fd, flow);
856 DEBUG("Getting advanced flow control");
858 if (!(data = malloc(get_termiox_size())))
859 RETURN_ERROR(SP_ERR_MEM, "termiox malloc failed");
861 if (ioctl(fd, TCGETX, data) < 0) {
863 RETURN_FAIL("getting termiox failed");
866 *flow = get_termiox_flow(data);
873 static enum sp_return set_flow(int fd, int flow)
877 TRACE("%d, %d", fd, flow);
879 DEBUG("Getting advanced flow control");
881 if (!(data = malloc(get_termiox_size())))
882 RETURN_ERROR(SP_ERR_MEM, "termiox malloc failed");
884 if (ioctl(fd, TCGETX, data) < 0) {
886 RETURN_FAIL("getting termiox failed");
889 DEBUG("Setting advanced flow control");
891 set_termiox_flow(data, flow);
893 if (ioctl(fd, TCSETX, data) < 0) {
895 RETURN_FAIL("setting termiox failed");
902 #endif /* USE_TERMIOX */
903 #endif /* __linux__ */
905 static enum sp_return get_config(struct sp_port *port, struct port_data *data,
906 struct sp_port_config *config)
910 TRACE("%p, %p, %p", port, data, config);
912 DEBUG("Getting configuration for port %s", port->name);
915 if (!GetCommState(port->hdl, &data->dcb))
916 RETURN_FAIL("GetCommState() failed");
918 for (i = 0; i < NUM_STD_BAUDRATES; i++) {
919 if (data->dcb.BaudRate == std_baudrates[i].index) {
920 config->baudrate = std_baudrates[i].value;
925 if (i == NUM_STD_BAUDRATES)
926 /* BaudRate field can be either an index or a custom baud rate. */
927 config->baudrate = data->dcb.BaudRate;
929 config->bits = data->dcb.ByteSize;
931 if (data->dcb.fParity)
932 switch (data->dcb.Parity) {
934 config->parity = SP_PARITY_NONE;
937 config->parity = SP_PARITY_EVEN;
940 config->parity = SP_PARITY_ODD;
946 config->parity = SP_PARITY_NONE;
948 switch (data->dcb.StopBits) {
950 config->stopbits = 1;
953 config->stopbits = 2;
956 config->stopbits = -1;
959 switch (data->dcb.fRtsControl) {
960 case RTS_CONTROL_DISABLE:
961 config->rts = SP_RTS_OFF;
963 case RTS_CONTROL_ENABLE:
964 config->rts = SP_RTS_ON;
966 case RTS_CONTROL_HANDSHAKE:
967 config->rts = SP_RTS_FLOW_CONTROL;
973 config->cts = data->dcb.fOutxCtsFlow ? SP_CTS_FLOW_CONTROL : SP_CTS_IGNORE;
975 switch (data->dcb.fDtrControl) {
976 case DTR_CONTROL_DISABLE:
977 config->dtr = SP_DTR_OFF;
979 case DTR_CONTROL_ENABLE:
980 config->dtr = SP_DTR_ON;
982 case DTR_CONTROL_HANDSHAKE:
983 config->dtr = SP_DTR_FLOW_CONTROL;
989 config->dsr = data->dcb.fOutxDsrFlow ? SP_DSR_FLOW_CONTROL : SP_DSR_IGNORE;
991 if (data->dcb.fInX) {
993 config->xon_xoff = SP_XONXOFF_INOUT;
995 config->xon_xoff = SP_XONXOFF_IN;
998 config->xon_xoff = SP_XONXOFF_OUT;
1000 config->xon_xoff = SP_XONXOFF_DISABLED;
1005 if (tcgetattr(port->fd, &data->term) < 0)
1006 RETURN_FAIL("tcgetattr() failed");
1008 if (ioctl(port->fd, TIOCMGET, &data->controlbits) < 0)
1009 RETURN_FAIL("TIOCMGET ioctl failed");
1012 int ret = get_flow(port->fd, &data->flow);
1014 if (ret == SP_ERR_FAIL && errno == EINVAL)
1015 data->termiox_supported = 0;
1017 RETURN_CODEVAL(ret);
1019 data->termiox_supported = 1;
1021 data->termiox_supported = 0;
1024 for (i = 0; i < NUM_STD_BAUDRATES; i++) {
1025 if (cfgetispeed(&data->term) == std_baudrates[i].index) {
1026 config->baudrate = std_baudrates[i].value;
1031 if (i == NUM_STD_BAUDRATES) {
1033 config->baudrate = (int)data->term.c_ispeed;
1034 #elif defined(__linux__)
1035 TRY(get_baudrate(port->fd, &config->baudrate));
1037 config->baudrate = -1;
1041 switch (data->term.c_cflag & CSIZE) {
1058 if (!(data->term.c_cflag & PARENB) && (data->term.c_iflag & IGNPAR))
1059 config->parity = SP_PARITY_NONE;
1060 else if (!(data->term.c_cflag & PARENB) || (data->term.c_iflag & IGNPAR))
1061 config->parity = -1;
1063 config->parity = (data->term.c_cflag & PARODD) ? SP_PARITY_ODD : SP_PARITY_EVEN;
1065 config->stopbits = (data->term.c_cflag & CSTOPB) ? 2 : 1;
1067 if (data->term.c_cflag & CRTSCTS) {
1068 config->rts = SP_RTS_FLOW_CONTROL;
1069 config->cts = SP_CTS_FLOW_CONTROL;
1071 if (data->termiox_supported && data->flow & RTS_FLOW)
1072 config->rts = SP_RTS_FLOW_CONTROL;
1074 config->rts = (data->controlbits & TIOCM_RTS) ? SP_RTS_ON : SP_RTS_OFF;
1076 config->cts = (data->termiox_supported && data->flow & CTS_FLOW) ?
1077 SP_CTS_FLOW_CONTROL : SP_CTS_IGNORE;
1080 if (data->termiox_supported && data->flow & DTR_FLOW)
1081 config->dtr = SP_DTR_FLOW_CONTROL;
1083 config->dtr = (data->controlbits & TIOCM_DTR) ? SP_DTR_ON : SP_DTR_OFF;
1085 config->dsr = (data->termiox_supported && data->flow & DSR_FLOW) ?
1086 SP_DSR_FLOW_CONTROL : SP_DSR_IGNORE;
1088 if (data->term.c_iflag & IXOFF) {
1089 if (data->term.c_iflag & IXON)
1090 config->xon_xoff = SP_XONXOFF_INOUT;
1092 config->xon_xoff = SP_XONXOFF_IN;
1094 if (data->term.c_iflag & IXON)
1095 config->xon_xoff = SP_XONXOFF_OUT;
1097 config->xon_xoff = SP_XONXOFF_DISABLED;
1104 static enum sp_return set_config(struct sp_port *port, struct port_data *data,
1105 const struct sp_port_config *config)
1109 BAUD_TYPE baud_nonstd;
1114 int baud_nonstd = 0;
1117 TRACE("%p, %p, %p", port, data, config);
1119 DEBUG("Setting configuration for port %s", port->name);
1122 if (config->baudrate >= 0) {
1123 for (i = 0; i < NUM_STD_BAUDRATES; i++) {
1124 if (config->baudrate == std_baudrates[i].value) {
1125 data->dcb.BaudRate = std_baudrates[i].index;
1130 if (i == NUM_STD_BAUDRATES)
1131 data->dcb.BaudRate = config->baudrate;
1134 if (config->bits >= 0)
1135 data->dcb.ByteSize = config->bits;
1137 if (config->parity >= 0) {
1138 switch (config->parity) {
1139 /* Note: There's also SPACEPARITY, MARKPARITY (unneeded so far). */
1140 case SP_PARITY_NONE:
1141 data->dcb.Parity = NOPARITY;
1143 case SP_PARITY_EVEN:
1144 data->dcb.Parity = EVENPARITY;
1147 data->dcb.Parity = ODDPARITY;
1150 RETURN_ERROR(SP_ERR_ARG, "Invalid parity setting");
1154 if (config->stopbits >= 0) {
1155 switch (config->stopbits) {
1156 /* Note: There's also ONE5STOPBITS == 1.5 (unneeded so far). */
1158 data->dcb.StopBits = ONESTOPBIT;
1161 data->dcb.StopBits = TWOSTOPBITS;
1164 RETURN_ERROR(SP_ERR_ARG, "Invalid stop bit setting");
1168 if (config->rts >= 0) {
1169 switch (config->rts) {
1171 data->dcb.fRtsControl = RTS_CONTROL_DISABLE;
1174 data->dcb.fRtsControl = RTS_CONTROL_ENABLE;
1176 case SP_RTS_FLOW_CONTROL:
1177 data->dcb.fRtsControl = RTS_CONTROL_HANDSHAKE;
1180 RETURN_ERROR(SP_ERR_ARG, "Invalid RTS setting");
1184 if (config->cts >= 0) {
1185 switch (config->cts) {
1187 data->dcb.fOutxCtsFlow = FALSE;
1189 case SP_CTS_FLOW_CONTROL:
1190 data->dcb.fOutxCtsFlow = TRUE;
1193 RETURN_ERROR(SP_ERR_ARG, "Invalid CTS setting");
1197 if (config->dtr >= 0) {
1198 switch (config->dtr) {
1200 data->dcb.fDtrControl = DTR_CONTROL_DISABLE;
1203 data->dcb.fDtrControl = DTR_CONTROL_ENABLE;
1205 case SP_DTR_FLOW_CONTROL:
1206 data->dcb.fDtrControl = DTR_CONTROL_HANDSHAKE;
1209 RETURN_ERROR(SP_ERR_ARG, "Invalid DTR setting");
1213 if (config->dsr >= 0) {
1214 switch (config->dsr) {
1216 data->dcb.fOutxDsrFlow = FALSE;
1218 case SP_DSR_FLOW_CONTROL:
1219 data->dcb.fOutxDsrFlow = TRUE;
1222 RETURN_ERROR(SP_ERR_ARG, "Invalid DSR setting");
1226 if (config->xon_xoff >= 0) {
1227 switch (config->xon_xoff) {
1228 case SP_XONXOFF_DISABLED:
1229 data->dcb.fInX = FALSE;
1230 data->dcb.fOutX = FALSE;
1233 data->dcb.fInX = TRUE;
1234 data->dcb.fOutX = FALSE;
1236 case SP_XONXOFF_OUT:
1237 data->dcb.fInX = FALSE;
1238 data->dcb.fOutX = TRUE;
1240 case SP_XONXOFF_INOUT:
1241 data->dcb.fInX = TRUE;
1242 data->dcb.fOutX = TRUE;
1245 RETURN_ERROR(SP_ERR_ARG, "Invalid XON/XOFF setting");
1249 if (!SetCommState(port->hdl, &data->dcb))
1250 RETURN_FAIL("SetCommState() failed");
1256 if (config->baudrate >= 0) {
1257 for (i = 0; i < NUM_STD_BAUDRATES; i++) {
1258 if (config->baudrate == std_baudrates[i].value) {
1259 if (cfsetospeed(&data->term, std_baudrates[i].index) < 0)
1260 RETURN_FAIL("cfsetospeed() failed");
1262 if (cfsetispeed(&data->term, std_baudrates[i].index) < 0)
1263 RETURN_FAIL("cfsetispeed() failed");
1268 /* Non-standard baud rate */
1269 if (i == NUM_STD_BAUDRATES) {
1271 /* Set "dummy" baud rate. */
1272 if (cfsetspeed(&data->term, B9600) < 0)
1273 RETURN_FAIL("cfsetspeed() failed");
1274 baud_nonstd = config->baudrate;
1275 #elif defined(__linux__)
1278 RETURN_ERROR(SP_ERR_SUPP, "Non-standard baudrate not supported");
1283 if (config->bits >= 0) {
1284 data->term.c_cflag &= ~CSIZE;
1285 switch (config->bits) {
1287 data->term.c_cflag |= CS8;
1290 data->term.c_cflag |= CS7;
1293 data->term.c_cflag |= CS6;
1296 data->term.c_cflag |= CS5;
1299 RETURN_ERROR(SP_ERR_ARG, "Invalid data bits setting");
1303 if (config->parity >= 0) {
1304 data->term.c_iflag &= ~IGNPAR;
1305 data->term.c_cflag &= ~(PARENB | PARODD);
1306 switch (config->parity) {
1307 case SP_PARITY_NONE:
1308 data->term.c_iflag |= IGNPAR;
1310 case SP_PARITY_EVEN:
1311 data->term.c_cflag |= PARENB;
1314 data->term.c_cflag |= PARENB | PARODD;
1317 RETURN_ERROR(SP_ERR_ARG, "Invalid parity setting");
1321 if (config->stopbits >= 0) {
1322 data->term.c_cflag &= ~CSTOPB;
1323 switch (config->stopbits) {
1325 data->term.c_cflag &= ~CSTOPB;
1328 data->term.c_cflag |= CSTOPB;
1331 RETURN_ERROR(SP_ERR_ARG, "Invalid stop bits setting");
1335 if (config->rts >= 0 || config->cts >= 0) {
1336 if (data->termiox_supported) {
1337 data->flow &= ~(RTS_FLOW | CTS_FLOW);
1338 switch (config->rts) {
1341 controlbits = TIOCM_RTS;
1342 if (ioctl(port->fd, config->rts == SP_RTS_ON ? TIOCMBIS : TIOCMBIC, &controlbits) < 0)
1343 RETURN_FAIL("Setting RTS signal level failed");
1345 case SP_RTS_FLOW_CONTROL:
1346 data->flow |= RTS_FLOW;
1351 if (config->cts == SP_CTS_FLOW_CONTROL)
1352 data->flow |= CTS_FLOW;
1354 if (data->flow & (RTS_FLOW | CTS_FLOW))
1355 data->term.c_iflag |= CRTSCTS;
1357 data->term.c_iflag &= ~CRTSCTS;
1359 /* Asymmetric use of RTS/CTS not supported. */
1360 if (data->term.c_iflag & CRTSCTS) {
1361 /* Flow control can only be disabled for both RTS & CTS together. */
1362 if (config->rts >= 0 && config->rts != SP_RTS_FLOW_CONTROL) {
1363 if (config->cts != SP_CTS_IGNORE)
1364 RETURN_ERROR(SP_ERR_SUPP, "RTS & CTS flow control must be disabled together");
1366 if (config->cts >= 0 && config->cts != SP_CTS_FLOW_CONTROL) {
1367 if (config->rts <= 0 || config->rts == SP_RTS_FLOW_CONTROL)
1368 RETURN_ERROR(SP_ERR_SUPP, "RTS & CTS flow control must be disabled together");
1371 /* Flow control can only be enabled for both RTS & CTS together. */
1372 if (((config->rts == SP_RTS_FLOW_CONTROL) && (config->cts != SP_CTS_FLOW_CONTROL)) ||
1373 ((config->cts == SP_CTS_FLOW_CONTROL) && (config->rts != SP_RTS_FLOW_CONTROL)))
1374 RETURN_ERROR(SP_ERR_SUPP, "RTS & CTS flow control must be enabled together");
1377 if (config->rts >= 0) {
1378 if (config->rts == SP_RTS_FLOW_CONTROL) {
1379 data->term.c_iflag |= CRTSCTS;
1381 controlbits = TIOCM_RTS;
1382 if (ioctl(port->fd, config->rts == SP_RTS_ON ? TIOCMBIS : TIOCMBIC,
1384 RETURN_FAIL("Setting RTS signal level failed");
1390 if (config->dtr >= 0 || config->dsr >= 0) {
1391 if (data->termiox_supported) {
1392 data->flow &= ~(DTR_FLOW | DSR_FLOW);
1393 switch (config->dtr) {
1396 controlbits = TIOCM_DTR;
1397 if (ioctl(port->fd, config->dtr == SP_DTR_ON ? TIOCMBIS : TIOCMBIC, &controlbits) < 0)
1398 RETURN_FAIL("Setting DTR signal level failed");
1400 case SP_DTR_FLOW_CONTROL:
1401 data->flow |= DTR_FLOW;
1406 if (config->dsr == SP_DSR_FLOW_CONTROL)
1407 data->flow |= DSR_FLOW;
1409 /* DTR/DSR flow control not supported. */
1410 if (config->dtr == SP_DTR_FLOW_CONTROL || config->dsr == SP_DSR_FLOW_CONTROL)
1411 RETURN_ERROR(SP_ERR_SUPP, "DTR/DSR flow control not supported");
1413 if (config->dtr >= 0) {
1414 controlbits = TIOCM_DTR;
1415 if (ioctl(port->fd, config->dtr == SP_DTR_ON ? TIOCMBIS : TIOCMBIC,
1417 RETURN_FAIL("Setting DTR signal level failed");
1422 if (config->xon_xoff >= 0) {
1423 data->term.c_iflag &= ~(IXON | IXOFF | IXANY);
1424 switch (config->xon_xoff) {
1425 case SP_XONXOFF_DISABLED:
1428 data->term.c_iflag |= IXOFF;
1430 case SP_XONXOFF_OUT:
1431 data->term.c_iflag |= IXON | IXANY;
1433 case SP_XONXOFF_INOUT:
1434 data->term.c_iflag |= IXON | IXOFF | IXANY;
1437 RETURN_ERROR(SP_ERR_ARG, "Invalid XON/XOFF setting");
1441 if (tcsetattr(port->fd, TCSADRAIN, &data->term) < 0)
1442 RETURN_FAIL("tcsetattr() failed");
1445 if (baud_nonstd != B0) {
1446 if (ioctl(port->fd, IOSSIOSPEED, &baud_nonstd) == -1)
1447 RETURN_FAIL("IOSSIOSPEED ioctl failed");
1448 /* Set baud rates in data->term to correct, but incompatible
1449 * with tcsetattr() value, same as delivered by tcgetattr(). */
1450 if (cfsetspeed(&data->term, baud_nonstd) < 0)
1451 RETURN_FAIL("cfsetspeed() failed");
1453 #elif defined(__linux__)
1455 TRY(set_baudrate(port->fd, config->baudrate));
1457 if (data->termiox_supported)
1458 TRY(set_flow(port->fd, data->flow));
1462 #endif /* !_WIN32 */
1467 enum sp_return sp_new_config(struct sp_port_config **config_ptr)
1469 TRACE("%p", config_ptr);
1470 struct sp_port_config *config;
1473 RETURN_ERROR(SP_ERR_ARG, "Null result pointer");
1477 if (!(config = malloc(sizeof(struct sp_port_config))))
1478 RETURN_ERROR(SP_ERR_MEM, "config malloc failed");
1480 config->baudrate = -1;
1482 config->parity = -1;
1483 config->stopbits = -1;
1489 *config_ptr = config;
1494 void sp_free_config(struct sp_port_config *config)
1496 TRACE("%p", config);
1499 DEBUG("Null config");
1506 enum sp_return sp_get_config(struct sp_port *port, struct sp_port_config *config)
1508 struct port_data data;
1510 TRACE("%p, %p", port, config);
1515 RETURN_ERROR(SP_ERR_ARG, "Null config");
1517 TRY(get_config(port, &data, config));
1522 enum sp_return sp_set_config(struct sp_port *port, const struct sp_port_config *config)
1524 struct port_data data;
1525 struct sp_port_config prev_config;
1527 TRACE("%p, %p", port, config);
1532 RETURN_ERROR(SP_ERR_ARG, "Null config");
1534 TRY(get_config(port, &data, &prev_config));
1535 TRY(set_config(port, &data, config));
1540 #define CREATE_ACCESSORS(x, type) \
1541 enum sp_return sp_set_##x(struct sp_port *port, type x) { \
1542 struct port_data data; \
1543 struct sp_port_config config; \
1544 TRACE("%p, %d", port, x); \
1545 CHECK_OPEN_PORT(); \
1546 TRY(get_config(port, &data, &config)); \
1548 TRY(set_config(port, &data, &config)); \
1551 enum sp_return sp_get_config_##x(const struct sp_port_config *config, type *x) { \
1552 TRACE("%p", config); \
1554 RETURN_ERROR(SP_ERR_ARG, "Null config"); \
1558 enum sp_return sp_set_config_##x(struct sp_port_config *config, type x) { \
1559 TRACE("%p, %d", config, x); \
1561 RETURN_ERROR(SP_ERR_ARG, "Null config"); \
1566 CREATE_ACCESSORS(baudrate, int)
1567 CREATE_ACCESSORS(bits, int)
1568 CREATE_ACCESSORS(parity, enum sp_parity)
1569 CREATE_ACCESSORS(stopbits, int)
1570 CREATE_ACCESSORS(rts, enum sp_rts)
1571 CREATE_ACCESSORS(cts, enum sp_cts)
1572 CREATE_ACCESSORS(dtr, enum sp_dtr)
1573 CREATE_ACCESSORS(dsr, enum sp_dsr)
1574 CREATE_ACCESSORS(xon_xoff, enum sp_xonxoff)
1576 enum sp_return sp_set_config_flowcontrol(struct sp_port_config *config, enum sp_flowcontrol flowcontrol)
1579 RETURN_ERROR(SP_ERR_ARG, "Null configuration");
1581 if (flowcontrol > SP_FLOWCONTROL_DTRDSR)
1582 RETURN_ERROR(SP_ERR_ARG, "Invalid flow control setting");
1584 if (flowcontrol == SP_FLOWCONTROL_XONXOFF)
1585 config->xon_xoff = SP_XONXOFF_INOUT;
1587 config->xon_xoff = SP_XONXOFF_DISABLED;
1589 if (flowcontrol == SP_FLOWCONTROL_RTSCTS) {
1590 config->rts = SP_RTS_FLOW_CONTROL;
1591 config->cts = SP_CTS_FLOW_CONTROL;
1593 if (config->rts == SP_RTS_FLOW_CONTROL)
1594 config->rts = SP_RTS_ON;
1595 config->cts = SP_CTS_IGNORE;
1598 if (flowcontrol == SP_FLOWCONTROL_DTRDSR) {
1599 config->dtr = SP_DTR_FLOW_CONTROL;
1600 config->dsr = SP_DSR_FLOW_CONTROL;
1602 if (config->dtr == SP_DTR_FLOW_CONTROL)
1603 config->dtr = SP_DTR_ON;
1604 config->dsr = SP_DSR_IGNORE;
1610 enum sp_return sp_set_flowcontrol(struct sp_port *port, enum sp_flowcontrol flowcontrol)
1612 struct port_data data;
1613 struct sp_port_config config;
1615 TRACE("%p, %d", port, flowcontrol);
1619 TRY(get_config(port, &data, &config));
1621 TRY(sp_set_config_flowcontrol(&config, flowcontrol));
1623 TRY(set_config(port, &data, &config));
1628 enum sp_return sp_get_signals(struct sp_port *port, enum sp_signal *signals)
1630 TRACE("%p, %p", port, signals);
1635 RETURN_ERROR(SP_ERR_ARG, "Null result pointer");
1637 DEBUG("Getting control signals for port %s", port->name);
1642 if (GetCommModemStatus(port->hdl, &bits) == 0)
1643 RETURN_FAIL("GetCommModemStatus() failed");
1644 if (bits & MS_CTS_ON)
1645 *signals |= SP_SIG_CTS;
1646 if (bits & MS_DSR_ON)
1647 *signals |= SP_SIG_DSR;
1648 if (bits & MS_RLSD_ON)
1649 *signals |= SP_SIG_DCD;
1650 if (bits & MS_RING_ON)
1651 *signals |= SP_SIG_RI;
1654 if (ioctl(port->fd, TIOCMGET, &bits) < 0)
1655 RETURN_FAIL("TIOCMGET ioctl failed");
1656 if (bits & TIOCM_CTS)
1657 *signals |= SP_SIG_CTS;
1658 if (bits & TIOCM_DSR)
1659 *signals |= SP_SIG_DSR;
1660 if (bits & TIOCM_CAR)
1661 *signals |= SP_SIG_DCD;
1662 if (bits & TIOCM_RNG)
1663 *signals |= SP_SIG_RI;
1668 enum sp_return sp_start_break(struct sp_port *port)
1674 if (SetCommBreak(port->hdl) == 0)
1675 RETURN_FAIL("SetCommBreak() failed");
1677 if (ioctl(port->fd, TIOCSBRK, 1) < 0)
1678 RETURN_FAIL("TIOCSBRK ioctl failed");
1684 enum sp_return sp_end_break(struct sp_port *port)
1690 if (ClearCommBreak(port->hdl) == 0)
1691 RETURN_FAIL("ClearCommBreak() failed");
1693 if (ioctl(port->fd, TIOCCBRK, 1) < 0)
1694 RETURN_FAIL("TIOCCBRK ioctl failed");
1700 int sp_last_error_code(void)
1704 RETURN_VALUE("%d", GetLastError());
1706 RETURN_VALUE("%d", errno);
1710 char *sp_last_error_message(void)
1716 DWORD error = GetLastError();
1719 FORMAT_MESSAGE_ALLOCATE_BUFFER |
1720 FORMAT_MESSAGE_FROM_SYSTEM |
1721 FORMAT_MESSAGE_IGNORE_INSERTS,
1724 MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
1728 RETURN_VALUE("%s", message);
1730 RETURN_VALUE("%s", strerror(errno));
1734 void sp_free_error_message(char *message)
1736 TRACE("%s", message);
1747 void sp_set_debug_handler(void (*handler)(const char *format, ...))
1749 TRACE("%p", handler);
1751 sp_debug_handler = handler;
1756 void sp_default_debug_handler(const char *format, ...)
1759 va_start(args, format);
1760 if (getenv("LIBSERIALPORT_DEBUG")) {
1761 fputs("libserialport: ", stderr);
1762 vfprintf(stderr, format, args);