2 * This file is part of the libserialport project.
4 * Copyright (C) 2010-2012 Bert Vermeulen <bert@biot.com>
5 * Copyright (C) 2010-2012 Uwe Hermann <uwe@hermann-uwe.de>
6 * Copyright (C) 2013 Martin Ling <martin-libserialport@earth.li>
7 * Copyright (C) 2013 Matthias Heidbrink <m-sigrok@heidbrink.biz>
9 * This program is free software: you can redistribute it and/or modify
10 * it under the terms of the GNU Lesser General Public License as
11 * published by the Free Software Foundation, either version 3 of the
12 * License, or (at your option) any later version.
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU General Public License for more details.
19 * You should have received a copy of the GNU Lesser General Public License
20 * along with this program. If not, see <http://www.gnu.org/licenses/>.
24 #include <sys/types.h>
38 #include <sys/ioctl.h>
41 #include <IOKit/IOKitLib.h>
42 #include <IOKit/serial/IOSerialKeys.h>
43 #include <IOKit/serial/ioss.h>
44 #include <sys/syslimits.h>
48 #include "linux/serial.h"
49 #include "linux_termios.h"
50 #if defined(TCGETX) && defined(TCSETX) && defined(HAVE_TERMIOX)
56 #include "linux_termios.h"
59 #include "libserialport.h"
76 int termiox_supported;
81 /* Standard baud rates. */
83 #define BAUD_TYPE DWORD
84 #define BAUD(n) {CBR_##n, n}
86 #define BAUD_TYPE speed_t
87 #define BAUD(n) {B##n, n}
95 const struct std_baudrate std_baudrates[] = {
98 * The baudrates 50/75/134/150/200/1800/230400/460800 do not seem to
99 * have documented CBR_* macros.
101 BAUD(110), BAUD(300), BAUD(600), BAUD(1200), BAUD(2400), BAUD(4800),
102 BAUD(9600), BAUD(14400), BAUD(19200), BAUD(38400), BAUD(57600),
103 BAUD(115200), BAUD(128000), BAUD(256000),
105 BAUD(50), BAUD(75), BAUD(110), BAUD(134), BAUD(150), BAUD(200),
106 BAUD(300), BAUD(600), BAUD(1200), BAUD(1800), BAUD(2400), BAUD(4800),
107 BAUD(9600), BAUD(19200), BAUD(38400), BAUD(57600), BAUD(115200),
109 #if !defined(__APPLE__) && !defined(__OpenBSD__)
115 void (*sp_debug_handler)(const char *format, ...) = sp_default_debug_handler;
117 #define ARRAY_SIZE(x) (sizeof(x) / sizeof(x[0]))
118 #define NUM_STD_BAUDRATES ARRAY_SIZE(std_baudrates)
120 /* Debug output macros. */
121 #define DEBUG(fmt, ...) do { if (sp_debug_handler) sp_debug_handler(fmt ".\n", ##__VA_ARGS__); } while (0)
122 #define DEBUG_ERROR(err, msg) DEBUG("%s returning " #err ": " msg, __func__)
123 #define DEBUG_FAIL(msg) do { \
124 char *errmsg = sp_last_error_message(); \
125 DEBUG("%s returning SP_ERR_FAIL: " msg ": %s", __func__, errmsg); \
126 sp_free_error_message(errmsg); \
128 #define RETURN() do { DEBUG("%s returning", __func__); return; } while(0)
129 #define RETURN_CODE(x) do { DEBUG("%s returning " #x, __func__); return x; } while (0)
130 #define RETURN_CODEVAL(x) do { \
132 case SP_OK: RETURN_CODE(SP_OK); \
133 case SP_ERR_ARG: RETURN_CODE(SP_ERR_ARG); \
134 case SP_ERR_FAIL: RETURN_CODE(SP_ERR_FAIL); \
135 case SP_ERR_MEM: RETURN_CODE(SP_ERR_MEM); \
136 case SP_ERR_SUPP: RETURN_CODE(SP_ERR_SUPP); \
139 #define RETURN_OK() RETURN_CODE(SP_OK);
140 #define RETURN_ERROR(err, msg) do { DEBUG_ERROR(err, msg); return err; } while (0)
141 #define RETURN_FAIL(msg) do { DEBUG_FAIL(msg); return SP_ERR_FAIL; } while (0)
142 #define RETURN_VALUE(fmt, x) do { DEBUG("%s returning " fmt, __func__, x); return x; } while (0)
143 #define SET_ERROR(val, err, msg) do { DEBUG_ERROR(err, msg); val = err; } while (0)
144 #define SET_FAIL(val, msg) do { DEBUG_FAIL(msg); val = err; } while (0)
145 #define TRACE(fmt, ...) DEBUG("%s(" fmt ") called", __func__, ##__VA_ARGS__)
147 #define TRY(x) do { int ret = x; if (ret != SP_OK) RETURN_CODEVAL(ret); } while (0)
149 /* Helper functions. */
150 static struct sp_port **list_append(struct sp_port **list, const char *portname);
151 static enum sp_return get_config(struct sp_port *port, struct port_data *data,
152 struct sp_port_config *config);
153 static enum sp_return set_config(struct sp_port *port, struct port_data *data,
154 const struct sp_port_config *config);
156 enum sp_return sp_get_port_by_name(const char *portname, struct sp_port **port_ptr)
158 struct sp_port *port;
161 TRACE("%s, %p", portname, port_ptr);
164 RETURN_ERROR(SP_ERR_ARG, "Null result pointer");
169 RETURN_ERROR(SP_ERR_ARG, "Null port name");
171 DEBUG("Building structure for port %s", portname);
173 if (!(port = malloc(sizeof(struct sp_port))))
174 RETURN_ERROR(SP_ERR_MEM, "Port structure malloc failed");
176 len = strlen(portname) + 1;
178 if (!(port->name = malloc(len))) {
180 RETURN_ERROR(SP_ERR_MEM, "Port name malloc failed");
183 memcpy(port->name, portname, len);
186 port->hdl = INVALID_HANDLE_VALUE;
196 char *sp_get_port_name(const struct sp_port *port)
203 RETURN_VALUE("%s", port->name);
206 enum sp_return sp_get_port_handle(const struct sp_port *port, void *result_ptr)
211 RETURN_ERROR(SP_ERR_ARG, "Null port");
214 HANDLE *handle_ptr = result_ptr;
215 *handle_ptr = port->hdl;
217 int *fd_ptr = result_ptr;
224 enum sp_return sp_copy_port(const struct sp_port *port, struct sp_port **copy_ptr)
226 TRACE("%p, %p", port, copy_ptr);
229 RETURN_ERROR(SP_ERR_ARG, "Null result pointer");
234 RETURN_ERROR(SP_ERR_ARG, "Null port");
237 RETURN_ERROR(SP_ERR_ARG, "Null port name");
239 DEBUG("Copying port structure");
241 RETURN_VALUE("%p", sp_get_port_by_name(port->name, copy_ptr));
244 void sp_free_port(struct sp_port *port)
254 DEBUG("Freeing port structure");
264 static struct sp_port **list_append(struct sp_port **list, const char *portname)
269 for (count = 0; list[count]; count++);
270 if (!(tmp = realloc(list, sizeof(struct sp_port *) * (count + 2))))
273 if (sp_get_port_by_name(portname, &list[count]) != SP_OK)
275 list[count + 1] = NULL;
279 sp_free_port_list(list);
283 enum sp_return sp_list_ports(struct sp_port ***list_ptr)
285 struct sp_port **list;
286 int ret = SP_ERR_SUPP;
288 TRACE("%p", list_ptr);
291 RETURN_ERROR(SP_ERR_ARG, "Null result pointer");
293 DEBUG("Enumerating ports");
295 if (!(list = malloc(sizeof(struct sp_port **))))
296 RETURN_ERROR(SP_ERR_MEM, "Port list malloc failed");
303 DWORD max_value_len, max_data_size, max_data_len;
304 DWORD value_len, data_size, data_len;
305 DWORD type, index = 0;
311 DEBUG("Opening registry key");
312 if (RegOpenKeyEx(HKEY_LOCAL_MACHINE, _T("HARDWARE\\DEVICEMAP\\SERIALCOMM"),
313 0, KEY_QUERY_VALUE, &key) != ERROR_SUCCESS) {
314 SET_FAIL(ret, "RegOpenKeyEx() failed");
317 DEBUG("Querying registry key value and data sizes");
318 if (RegQueryInfoKey(key, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
319 &max_value_len, &max_data_size, NULL, NULL) != ERROR_SUCCESS) {
320 SET_FAIL(ret, "RegQueryInfoKey() failed");
323 max_data_len = max_data_size / sizeof(TCHAR);
324 if (!(value = malloc((max_value_len + 1) * sizeof(TCHAR)))) {
325 SET_ERROR(ret, SP_ERR_MEM, "registry value malloc failed");
328 if (!(data = malloc((max_data_len + 1) * sizeof(TCHAR)))) {
329 SET_ERROR(ret, SP_ERR_MEM, "registry data malloc failed");
332 DEBUG("Iterating over values");
334 value_len = max_value_len + 1,
335 data_size = max_data_size,
336 RegEnumValue(key, index, value, &value_len,
337 NULL, &type, (LPBYTE)data, &data_size) == ERROR_SUCCESS)
339 data_len = data_size / sizeof(TCHAR);
340 data[data_len] = '\0';
342 name_len = WideCharToMultiByte(CP_ACP, 0, data, -1, NULL, 0, NULL, NULL)
344 name_len = data_len + 1;
346 if (!(name = malloc(name_len))) {
347 SET_ERROR(ret, SP_ERR_MEM, "registry port name malloc failed");
351 WideCharToMultiByte(CP_ACP, 0, data, -1, name, name_len, NULL, NULL);
355 if (type == REG_SZ) {
356 DEBUG("Found port %s", name);
357 if (!(list = list_append(list, name))) {
358 SET_ERROR(ret, SP_ERR_MEM, "list append failed");
374 CFMutableDictionaryRef classes;
383 DEBUG("Getting IOKit master port");
384 if (IOMasterPort(MACH_PORT_NULL, &master) != KERN_SUCCESS) {
385 SET_FAIL(ret, "IOMasterPort() failed");
389 DEBUG("Creating matching dictionary");
390 if (!(classes = IOServiceMatching(kIOSerialBSDServiceValue))) {
391 SET_FAIL(ret, "IOServiceMatching() failed");
395 CFDictionarySetValue(classes,
396 CFSTR(kIOSerialBSDTypeKey), CFSTR(kIOSerialBSDAllTypes));
398 DEBUG("Getting matching services");
399 if (IOServiceGetMatchingServices(master, classes, &iter) != KERN_SUCCESS) {
400 SET_FAIL(ret, "IOServiceGetMatchingServices() failed");
404 if (!(path = malloc(PATH_MAX))) {
405 SET_ERROR(ret, SP_ERR_MEM, "device path malloc failed");
409 DEBUG("Iterating over results");
410 while ((port = IOIteratorNext(iter))) {
411 cf_path = IORegistryEntryCreateCFProperty(port,
412 CFSTR(kIOCalloutDeviceKey), kCFAllocatorDefault, 0);
414 result = CFStringGetCString(cf_path,
415 path, PATH_MAX, kCFStringEncodingASCII);
418 DEBUG("Found port %s", path);
419 if (!(list = list_append(list, path))) {
420 SET_ERROR(ret, SP_ERR_MEM, "list append failed");
421 IOObjectRelease(port);
426 IOObjectRelease(port);
431 IOObjectRelease(iter);
436 struct udev_enumerate *ud_enumerate;
437 struct udev_list_entry *ud_list;
438 struct udev_list_entry *ud_entry;
440 struct udev_device *ud_dev, *ud_parent;
443 int fd, ioctl_result;
444 struct serial_struct serial_info;
448 DEBUG("Enumerating tty devices");
450 ud_enumerate = udev_enumerate_new(ud);
451 udev_enumerate_add_match_subsystem(ud_enumerate, "tty");
452 udev_enumerate_scan_devices(ud_enumerate);
453 ud_list = udev_enumerate_get_list_entry(ud_enumerate);
454 DEBUG("Iterating over results");
455 udev_list_entry_foreach(ud_entry, ud_list) {
456 path = udev_list_entry_get_name(ud_entry);
457 DEBUG("Found device %s", path);
458 ud_dev = udev_device_new_from_syspath(ud, path);
459 /* If there is no parent device, this is a virtual tty. */
460 ud_parent = udev_device_get_parent(ud_dev);
461 if (ud_parent == NULL) {
462 DEBUG("No parent device, assuming virtual tty");
463 udev_device_unref(ud_dev);
466 name = udev_device_get_devnode(ud_dev);
467 /* The serial8250 driver has a hardcoded number of ports.
468 * The only way to tell which actually exist on a given system
469 * is to try to open them and make an ioctl call. */
470 driver = udev_device_get_driver(ud_parent);
471 if (driver && !strcmp(driver, "serial8250")) {
472 DEBUG("serial8250 device, attempting to open");
473 if ((fd = open(name, O_RDWR | O_NONBLOCK | O_NOCTTY)) < 0) {
474 DEBUG("open failed, skipping");
477 ioctl_result = ioctl(fd, TIOCGSERIAL, &serial_info);
479 if (ioctl_result != 0) {
480 DEBUG("ioctl failed, skipping");
483 if (serial_info.type == PORT_UNKNOWN) {
484 DEBUG("port type is unknown, skipping");
488 DEBUG("Found port %s", name);
489 list = list_append(list, name);
491 udev_device_unref(ud_dev);
493 SET_ERROR(ret, SP_ERR_MEM, "list append failed");
498 udev_enumerate_unref(ud_enumerate);
507 DEBUG_ERROR(SP_ERR_SUPP, "Enumeration not supported on this platform.");
510 sp_free_port_list(list);
516 void sp_free_port_list(struct sp_port **list)
527 DEBUG("Freeing port list");
529 for (i = 0; list[i]; i++)
530 sp_free_port(list[i]);
536 #define CHECK_PORT() do { \
538 RETURN_ERROR(SP_ERR_ARG, "Null port"); \
539 if (port->name == NULL) \
540 RETURN_ERROR(SP_ERR_ARG, "Null port name"); \
543 #define CHECK_PORT_HANDLE() do { \
544 if (port->hdl == INVALID_HANDLE_VALUE) \
545 RETURN_ERROR(SP_ERR_ARG, "Invalid port handle"); \
548 #define CHECK_PORT_HANDLE() do { \
550 RETURN_ERROR(SP_ERR_ARG, "Invalid port fd"); \
553 #define CHECK_OPEN_PORT() do { \
555 CHECK_PORT_HANDLE(); \
558 enum sp_return sp_open(struct sp_port *port, enum sp_mode flags)
560 TRACE("%p, %x", port, flags);
564 if (flags > (SP_MODE_READ | SP_MODE_WRITE | SP_MODE_NONBLOCK))
565 RETURN_ERROR(SP_ERR_ARG, "Invalid flags");
567 DEBUG("Opening port %s", port->name);
570 DWORD desired_access = 0, flags_and_attributes = 0;
571 char *escaped_port_name;
573 /* Prefix port name with '\\.\' to work with ports above COM9. */
574 if (!(escaped_port_name = malloc(strlen(port->name + 5))))
575 RETURN_ERROR(SP_ERR_MEM, "Escaped port name malloc failed");
576 sprintf(escaped_port_name, "\\\\.\\%s", port->name);
578 /* Map 'flags' to the OS-specific settings. */
579 flags_and_attributes = FILE_ATTRIBUTE_NORMAL;
580 if (flags & SP_MODE_READ)
581 desired_access |= GENERIC_READ;
582 if (flags & SP_MODE_WRITE)
583 desired_access |= GENERIC_WRITE;
584 if (flags & SP_MODE_NONBLOCK)
585 flags_and_attributes |= FILE_FLAG_OVERLAPPED;
587 port->hdl = CreateFile(escaped_port_name, desired_access, 0, 0,
588 OPEN_EXISTING, flags_and_attributes, 0);
590 free(escaped_port_name);
592 if (port->hdl == INVALID_HANDLE_VALUE)
593 RETURN_FAIL("CreateFile() failed");
596 struct port_data data;
597 struct sp_port_config config;
600 /* Map 'flags' to the OS-specific settings. */
601 if (flags & (SP_MODE_READ | SP_MODE_WRITE))
602 flags_local |= O_RDWR;
603 else if (flags & SP_MODE_READ)
604 flags_local |= O_RDONLY;
605 else if (flags & SP_MODE_WRITE)
606 flags_local |= O_WRONLY;
607 if (flags & SP_MODE_NONBLOCK)
608 flags_local |= O_NONBLOCK;
610 if ((port->fd = open(port->name, flags_local)) < 0)
611 RETURN_FAIL("open() failed");
613 ret = get_config(port, &data, &config);
620 /* Turn off all serial port cooking. */
621 data.term.c_iflag &= ~(ISTRIP | INLCR | ICRNL);
622 data.term.c_oflag &= ~(ONLCR | OCRNL | ONOCR);
623 #if !defined(__FreeBSD__) && !defined(__OpenBSD__) && !defined(__NetBSD__)
624 data.term.c_oflag &= ~OFILL;
626 /* Disable canonical mode, and don't echo input characters. */
627 data.term.c_lflag &= ~(ICANON | ECHO);
629 /* Ignore modem status lines; enable receiver */
630 data.term.c_cflag |= (CLOCAL | CREAD);
632 ret = set_config(port, &data, &config);
643 enum sp_return sp_close(struct sp_port *port)
649 DEBUG("Closing port %s", port->name);
652 /* Returns non-zero upon success, 0 upon failure. */
653 if (CloseHandle(port->hdl) == 0)
654 RETURN_FAIL("CloseHandle() failed");
655 port->hdl = INVALID_HANDLE_VALUE;
657 /* Returns 0 upon success, -1 upon failure. */
658 if (close(port->fd) == -1)
659 RETURN_FAIL("close() failed");
666 enum sp_return sp_flush(struct sp_port *port, enum sp_buffer buffers)
668 TRACE("%p, %x", port, buffers);
672 if (buffers > SP_BUF_BOTH)
673 RETURN_ERROR(SP_ERR_ARG, "Invalid buffer selection");
675 const char *buffer_names[] = {"input", "output", "both"};
677 DEBUG("Flushing %s buffers on port %s", buffer_names[buffers], port->name);
681 if (buffers & SP_BUF_INPUT)
682 flags |= PURGE_RXCLEAR;
683 if (buffers & SP_BUF_OUTPUT)
684 flags |= PURGE_TXCLEAR;
686 /* Returns non-zero upon success, 0 upon failure. */
687 if (PurgeComm(port->hdl, flags) == 0)
688 RETURN_FAIL("PurgeComm() failed");
691 if (buffers & SP_BUF_BOTH)
693 else if (buffers & SP_BUF_INPUT)
695 else if (buffers & SP_BUF_OUTPUT)
698 /* Returns 0 upon success, -1 upon failure. */
699 if (tcflush(port->fd, flags) < 0)
700 RETURN_FAIL("tcflush() failed");
705 enum sp_return sp_drain(struct sp_port *port)
711 DEBUG("Draining port %s", port->name);
714 /* Returns non-zero upon success, 0 upon failure. */
715 if (FlushFileBuffers(port->hdl) == 0)
716 RETURN_FAIL("FlushFileBuffers() failed");
718 /* Returns 0 upon success, -1 upon failure. */
719 if (tcdrain(port->fd) < 0)
720 RETURN_FAIL("tcdrain() failed");
726 enum sp_return sp_write(struct sp_port *port, const void *buf, size_t count)
728 TRACE("%p, %p, %d", port, buf, count);
733 RETURN_ERROR(SP_ERR_ARG, "Null buffer");
735 DEBUG("Writing up to %d bytes to port %s", count, port->name);
740 /* Returns non-zero upon success, 0 upon failure. */
741 if (WriteFile(port->hdl, buf, count, &written, NULL) == 0)
742 RETURN_FAIL("WriteFile() failed");
743 RETURN_VALUE("%d", written);
745 /* Returns the number of bytes written, or -1 upon failure. */
746 ssize_t written = write(port->fd, buf, count);
749 RETURN_FAIL("write() failed");
751 RETURN_VALUE("%d", written);
755 enum sp_return sp_read(struct sp_port *port, void *buf, size_t count)
757 TRACE("%p, %p, %d", port, buf, count);
762 RETURN_ERROR(SP_ERR_ARG, "Null buffer");
764 DEBUG("Reading up to %d bytes from port %s", count, port->name);
767 DWORD bytes_read = 0;
769 /* Returns non-zero upon success, 0 upon failure. */
770 if (ReadFile(port->hdl, buf, count, &bytes_read, NULL) == 0)
771 RETURN_FAIL("ReadFile() failed");
772 RETURN_VALUE("%d", bytes_read);
776 /* Returns the number of bytes read, or -1 upon failure. */
777 if ((bytes_read = read(port->fd, buf, count)) < 0)
778 RETURN_FAIL("read() failed");
779 RETURN_VALUE("%d", bytes_read);
784 static enum sp_return get_baudrate(int fd, int *baudrate)
788 TRACE("%d, %p", fd, baudrate);
790 DEBUG("Getting baud rate");
792 if (!(data = malloc(get_termios_size())))
793 RETURN_ERROR(SP_ERR_MEM, "termios malloc failed");
795 if (ioctl(fd, get_termios_get_ioctl(), data) < 0) {
797 RETURN_FAIL("getting termios failed");
800 *baudrate = get_termios_speed(data);
807 static enum sp_return set_baudrate(int fd, int baudrate)
811 TRACE("%d, %d", fd, baudrate);
813 DEBUG("Getting baud rate");
815 if (!(data = malloc(get_termios_size())))
816 RETURN_ERROR(SP_ERR_MEM, "termios malloc failed");
818 if (ioctl(fd, get_termios_get_ioctl(), data) < 0) {
820 RETURN_FAIL("getting termios failed");
823 DEBUG("Setting baud rate");
825 set_termios_speed(data, baudrate);
827 if (ioctl(fd, get_termios_set_ioctl(), data) < 0) {
829 RETURN_FAIL("setting termios failed");
838 static enum sp_return get_flow(int fd, int *flow)
842 TRACE("%d, %p", fd, flow);
844 DEBUG("Getting advanced flow control");
846 if (!(data = malloc(get_termiox_size())))
847 RETURN_ERROR(SP_ERR_MEM, "termiox malloc failed");
849 if (ioctl(fd, TCGETX, data) < 0) {
851 RETURN_FAIL("getting termiox failed");
854 *flow = get_termiox_flow(data);
861 static enum sp_return set_flow(int fd, int flow)
865 TRACE("%d, %d", fd, flow);
867 DEBUG("Getting advanced flow control");
869 if (!(data = malloc(get_termiox_size())))
870 RETURN_ERROR(SP_ERR_MEM, "termiox malloc failed");
872 if (ioctl(fd, TCGETX, data) < 0) {
874 RETURN_FAIL("getting termiox failed");
877 DEBUG("Setting advanced flow control");
879 set_termiox_flow(data, flow);
881 if (ioctl(fd, TCSETX, data) < 0) {
883 RETURN_FAIL("setting termiox failed");
890 #endif /* USE_TERMIOX */
891 #endif /* __linux__ */
893 static enum sp_return get_config(struct sp_port *port, struct port_data *data,
894 struct sp_port_config *config)
898 TRACE("%p, %p, %p", port, data, config);
900 DEBUG("Getting configuration for port %s", port->name);
903 if (!GetCommState(port->hdl, &data->dcb))
904 RETURN_FAIL("GetCommState() failed");
906 for (i = 0; i < NUM_STD_BAUDRATES; i++) {
907 if (data->dcb.BaudRate == std_baudrates[i].index) {
908 config->baudrate = std_baudrates[i].value;
913 if (i == NUM_STD_BAUDRATES)
914 /* BaudRate field can be either an index or a custom baud rate. */
915 config->baudrate = data->dcb.BaudRate;
917 config->bits = data->dcb.ByteSize;
919 if (data->dcb.fParity)
920 switch (data->dcb.Parity) {
922 config->parity = SP_PARITY_NONE;
925 config->parity = SP_PARITY_EVEN;
928 config->parity = SP_PARITY_ODD;
934 config->parity = SP_PARITY_NONE;
936 switch (data->dcb.StopBits) {
938 config->stopbits = 1;
941 config->stopbits = 2;
944 config->stopbits = -1;
947 switch (data->dcb.fRtsControl) {
948 case RTS_CONTROL_DISABLE:
949 config->rts = SP_RTS_OFF;
951 case RTS_CONTROL_ENABLE:
952 config->rts = SP_RTS_ON;
954 case RTS_CONTROL_HANDSHAKE:
955 config->rts = SP_RTS_FLOW_CONTROL;
961 config->cts = data->dcb.fOutxCtsFlow ? SP_CTS_FLOW_CONTROL : SP_CTS_IGNORE;
963 switch (data->dcb.fDtrControl) {
964 case DTR_CONTROL_DISABLE:
965 config->dtr = SP_DTR_OFF;
967 case DTR_CONTROL_ENABLE:
968 config->dtr = SP_DTR_ON;
970 case DTR_CONTROL_HANDSHAKE:
971 config->dtr = SP_DTR_FLOW_CONTROL;
977 config->dsr = data->dcb.fOutxDsrFlow ? SP_DSR_FLOW_CONTROL : SP_DSR_IGNORE;
979 if (data->dcb.fInX) {
981 config->xon_xoff = SP_XONXOFF_INOUT;
983 config->xon_xoff = SP_XONXOFF_IN;
986 config->xon_xoff = SP_XONXOFF_OUT;
988 config->xon_xoff = SP_XONXOFF_DISABLED;
993 if (tcgetattr(port->fd, &data->term) < 0)
994 RETURN_FAIL("tcgetattr() failed");
996 if (ioctl(port->fd, TIOCMGET, &data->controlbits) < 0)
997 RETURN_FAIL("TIOCMGET ioctl failed");
1000 int ret = get_flow(port->fd, &data->flow);
1002 if (ret == SP_ERR_FAIL && errno == EINVAL)
1003 data->termiox_supported = 0;
1005 RETURN_CODEVAL(ret);
1007 data->termiox_supported = 1;
1009 data->termiox_supported = 0;
1012 for (i = 0; i < NUM_STD_BAUDRATES; i++) {
1013 if (cfgetispeed(&data->term) == std_baudrates[i].index) {
1014 config->baudrate = std_baudrates[i].value;
1019 if (i == NUM_STD_BAUDRATES) {
1021 config->baudrate = (int)data->term.c_ispeed;
1022 #elif defined(__linux__)
1023 TRY(get_baudrate(port->fd, &config->baudrate));
1025 config->baudrate = -1;
1029 switch (data->term.c_cflag & CSIZE) {
1046 if (!(data->term.c_cflag & PARENB) && (data->term.c_iflag & IGNPAR))
1047 config->parity = SP_PARITY_NONE;
1048 else if (!(data->term.c_cflag & PARENB) || (data->term.c_iflag & IGNPAR))
1049 config->parity = -1;
1051 config->parity = (data->term.c_cflag & PARODD) ? SP_PARITY_ODD : SP_PARITY_EVEN;
1053 config->stopbits = (data->term.c_cflag & CSTOPB) ? 2 : 1;
1055 if (data->term.c_cflag & CRTSCTS) {
1056 config->rts = SP_RTS_FLOW_CONTROL;
1057 config->cts = SP_CTS_FLOW_CONTROL;
1059 if (data->termiox_supported && data->flow & RTS_FLOW)
1060 config->rts = SP_RTS_FLOW_CONTROL;
1062 config->rts = (data->controlbits & TIOCM_RTS) ? SP_RTS_ON : SP_RTS_OFF;
1064 config->cts = (data->termiox_supported && data->flow & CTS_FLOW) ?
1065 SP_CTS_FLOW_CONTROL : SP_CTS_IGNORE;
1068 if (data->termiox_supported && data->flow & DTR_FLOW)
1069 config->dtr = SP_DTR_FLOW_CONTROL;
1071 config->dtr = (data->controlbits & TIOCM_DTR) ? SP_DTR_ON : SP_DTR_OFF;
1073 config->dsr = (data->termiox_supported && data->flow & DSR_FLOW) ?
1074 SP_DSR_FLOW_CONTROL : SP_DSR_IGNORE;
1076 if (data->term.c_iflag & IXOFF) {
1077 if (data->term.c_iflag & IXON)
1078 config->xon_xoff = SP_XONXOFF_INOUT;
1080 config->xon_xoff = SP_XONXOFF_IN;
1082 if (data->term.c_iflag & IXON)
1083 config->xon_xoff = SP_XONXOFF_OUT;
1085 config->xon_xoff = SP_XONXOFF_DISABLED;
1092 static enum sp_return set_config(struct sp_port *port, struct port_data *data,
1093 const struct sp_port_config *config)
1097 BAUD_TYPE baud_nonstd;
1102 int baud_nonstd = 0;
1105 TRACE("%p, %p, %p", port, data, config);
1107 DEBUG("Setting configuration for port %s", port->name);
1110 if (config->baudrate >= 0) {
1111 for (i = 0; i < NUM_STD_BAUDRATES; i++) {
1112 if (config->baudrate == std_baudrates[i].value) {
1113 data->dcb.BaudRate = std_baudrates[i].index;
1118 if (i == NUM_STD_BAUDRATES)
1119 data->dcb.BaudRate = config->baudrate;
1122 if (config->bits >= 0)
1123 data->dcb.ByteSize = config->bits;
1125 if (config->parity >= 0) {
1126 switch (config->parity) {
1127 /* Note: There's also SPACEPARITY, MARKPARITY (unneeded so far). */
1128 case SP_PARITY_NONE:
1129 data->dcb.Parity = NOPARITY;
1131 case SP_PARITY_EVEN:
1132 data->dcb.Parity = EVENPARITY;
1135 data->dcb.Parity = ODDPARITY;
1138 RETURN_ERROR(SP_ERR_ARG, "Invalid parity setting");
1142 if (config->stopbits >= 0) {
1143 switch (config->stopbits) {
1144 /* Note: There's also ONE5STOPBITS == 1.5 (unneeded so far). */
1146 data->dcb.StopBits = ONESTOPBIT;
1149 data->dcb.StopBits = TWOSTOPBITS;
1152 RETURN_ERROR(SP_ERR_ARG, "Invalid stop bit setting");
1156 if (config->rts >= 0) {
1157 switch (config->rts) {
1159 data->dcb.fRtsControl = RTS_CONTROL_DISABLE;
1162 data->dcb.fRtsControl = RTS_CONTROL_ENABLE;
1164 case SP_RTS_FLOW_CONTROL:
1165 data->dcb.fRtsControl = RTS_CONTROL_HANDSHAKE;
1168 RETURN_ERROR(SP_ERR_ARG, "Invalid RTS setting");
1172 if (config->cts >= 0) {
1173 switch (config->cts) {
1175 data->dcb.fOutxCtsFlow = FALSE;
1177 case SP_CTS_FLOW_CONTROL:
1178 data->dcb.fOutxCtsFlow = TRUE;
1181 RETURN_ERROR(SP_ERR_ARG, "Invalid CTS setting");
1185 if (config->dtr >= 0) {
1186 switch (config->dtr) {
1188 data->dcb.fDtrControl = DTR_CONTROL_DISABLE;
1191 data->dcb.fDtrControl = DTR_CONTROL_ENABLE;
1193 case SP_DTR_FLOW_CONTROL:
1194 data->dcb.fDtrControl = DTR_CONTROL_HANDSHAKE;
1197 RETURN_ERROR(SP_ERR_ARG, "Invalid DTR setting");
1201 if (config->dsr >= 0) {
1202 switch (config->dsr) {
1204 data->dcb.fOutxDsrFlow = FALSE;
1206 case SP_DSR_FLOW_CONTROL:
1207 data->dcb.fOutxDsrFlow = TRUE;
1210 RETURN_ERROR(SP_ERR_ARG, "Invalid DSR setting");
1214 if (config->xon_xoff >= 0) {
1215 switch (config->xon_xoff) {
1216 case SP_XONXOFF_DISABLED:
1217 data->dcb.fInX = FALSE;
1218 data->dcb.fOutX = FALSE;
1221 data->dcb.fInX = TRUE;
1222 data->dcb.fOutX = FALSE;
1224 case SP_XONXOFF_OUT:
1225 data->dcb.fInX = FALSE;
1226 data->dcb.fOutX = TRUE;
1228 case SP_XONXOFF_INOUT:
1229 data->dcb.fInX = TRUE;
1230 data->dcb.fOutX = TRUE;
1233 RETURN_ERROR(SP_ERR_ARG, "Invalid XON/XOFF setting");
1237 if (!SetCommState(port->hdl, &data->dcb))
1238 RETURN_FAIL("SetCommState() failed");
1244 if (config->baudrate >= 0) {
1245 for (i = 0; i < NUM_STD_BAUDRATES; i++) {
1246 if (config->baudrate == std_baudrates[i].value) {
1247 if (cfsetospeed(&data->term, std_baudrates[i].index) < 0)
1248 RETURN_FAIL("cfsetospeed() failed");
1250 if (cfsetispeed(&data->term, std_baudrates[i].index) < 0)
1251 RETURN_FAIL("cfsetispeed() failed");
1256 /* Non-standard baud rate */
1257 if (i == NUM_STD_BAUDRATES) {
1259 /* Set "dummy" baud rate. */
1260 if (cfsetspeed(&data->term, B9600) < 0)
1261 RETURN_FAIL("cfsetspeed() failed");
1262 baud_nonstd = config->baudrate;
1263 #elif defined(__linux__)
1266 RETURN_ERROR(SP_ERR_SUPP, "Non-standard baudrate not supported");
1271 if (config->bits >= 0) {
1272 data->term.c_cflag &= ~CSIZE;
1273 switch (config->bits) {
1275 data->term.c_cflag |= CS8;
1278 data->term.c_cflag |= CS7;
1281 data->term.c_cflag |= CS6;
1284 data->term.c_cflag |= CS5;
1287 RETURN_ERROR(SP_ERR_ARG, "Invalid data bits setting");
1291 if (config->parity >= 0) {
1292 data->term.c_iflag &= ~IGNPAR;
1293 data->term.c_cflag &= ~(PARENB | PARODD);
1294 switch (config->parity) {
1295 case SP_PARITY_NONE:
1296 data->term.c_iflag |= IGNPAR;
1298 case SP_PARITY_EVEN:
1299 data->term.c_cflag |= PARENB;
1302 data->term.c_cflag |= PARENB | PARODD;
1305 RETURN_ERROR(SP_ERR_ARG, "Invalid parity setting");
1309 if (config->stopbits >= 0) {
1310 data->term.c_cflag &= ~CSTOPB;
1311 switch (config->stopbits) {
1313 data->term.c_cflag &= ~CSTOPB;
1316 data->term.c_cflag |= CSTOPB;
1319 RETURN_ERROR(SP_ERR_ARG, "Invalid stop bits setting");
1323 if (config->rts >= 0 || config->cts >= 0) {
1324 if (data->termiox_supported) {
1325 data->flow &= ~(RTS_FLOW | CTS_FLOW);
1326 switch (config->rts) {
1329 controlbits = TIOCM_RTS;
1330 if (ioctl(port->fd, config->rts == SP_RTS_ON ? TIOCMBIS : TIOCMBIC, &controlbits) < 0)
1331 RETURN_FAIL("Setting RTS signal level failed");
1333 case SP_RTS_FLOW_CONTROL:
1334 data->flow |= RTS_FLOW;
1339 if (config->cts == SP_CTS_FLOW_CONTROL)
1340 data->flow |= CTS_FLOW;
1342 if (data->flow & (RTS_FLOW | CTS_FLOW))
1343 data->term.c_iflag |= CRTSCTS;
1345 data->term.c_iflag &= ~CRTSCTS;
1347 /* Asymmetric use of RTS/CTS not supported. */
1348 if (data->term.c_iflag & CRTSCTS) {
1349 /* Flow control can only be disabled for both RTS & CTS together. */
1350 if (config->rts >= 0 && config->rts != SP_RTS_FLOW_CONTROL) {
1351 if (config->cts != SP_CTS_IGNORE)
1352 RETURN_ERROR(SP_ERR_SUPP, "RTS & CTS flow control must be disabled together");
1354 if (config->cts >= 0 && config->cts != SP_CTS_FLOW_CONTROL) {
1355 if (config->rts <= 0 || config->rts == SP_RTS_FLOW_CONTROL)
1356 RETURN_ERROR(SP_ERR_SUPP, "RTS & CTS flow control must be disabled together");
1359 /* Flow control can only be enabled for both RTS & CTS together. */
1360 if (((config->rts == SP_RTS_FLOW_CONTROL) && (config->cts != SP_CTS_FLOW_CONTROL)) ||
1361 ((config->cts == SP_CTS_FLOW_CONTROL) && (config->rts != SP_RTS_FLOW_CONTROL)))
1362 RETURN_ERROR(SP_ERR_SUPP, "RTS & CTS flow control must be enabled together");
1365 if (config->rts >= 0) {
1366 if (config->rts == SP_RTS_FLOW_CONTROL) {
1367 data->term.c_iflag |= CRTSCTS;
1369 controlbits = TIOCM_RTS;
1370 if (ioctl(port->fd, config->rts == SP_RTS_ON ? TIOCMBIS : TIOCMBIC,
1372 RETURN_FAIL("Setting RTS signal level failed");
1378 if (config->dtr >= 0 || config->dsr >= 0) {
1379 if (data->termiox_supported) {
1380 data->flow &= ~(DTR_FLOW | DSR_FLOW);
1381 switch (config->dtr) {
1384 controlbits = TIOCM_DTR;
1385 if (ioctl(port->fd, config->dtr == SP_DTR_ON ? TIOCMBIS : TIOCMBIC, &controlbits) < 0)
1386 RETURN_FAIL("Setting DTR signal level failed");
1388 case SP_DTR_FLOW_CONTROL:
1389 data->flow |= DTR_FLOW;
1394 if (config->dsr == SP_DSR_FLOW_CONTROL)
1395 data->flow |= DSR_FLOW;
1397 /* DTR/DSR flow control not supported. */
1398 if (config->dtr == SP_DTR_FLOW_CONTROL || config->dsr == SP_DSR_FLOW_CONTROL)
1399 RETURN_ERROR(SP_ERR_SUPP, "DTR/DSR flow control not supported");
1401 if (config->dtr >= 0) {
1402 controlbits = TIOCM_DTR;
1403 if (ioctl(port->fd, config->dtr == SP_DTR_ON ? TIOCMBIS : TIOCMBIC,
1405 RETURN_FAIL("Setting DTR signal level failed");
1410 if (config->xon_xoff >= 0) {
1411 data->term.c_iflag &= ~(IXON | IXOFF | IXANY);
1412 switch (config->xon_xoff) {
1413 case SP_XONXOFF_DISABLED:
1416 data->term.c_iflag |= IXOFF;
1418 case SP_XONXOFF_OUT:
1419 data->term.c_iflag |= IXON | IXANY;
1421 case SP_XONXOFF_INOUT:
1422 data->term.c_iflag |= IXON | IXOFF | IXANY;
1425 RETURN_ERROR(SP_ERR_ARG, "Invalid XON/XOFF setting");
1429 if (tcsetattr(port->fd, TCSADRAIN, &data->term) < 0)
1430 RETURN_FAIL("tcsetattr() failed");
1433 if (baud_nonstd != B0) {
1434 if (ioctl(port->fd, IOSSIOSPEED, &baud_nonstd) == -1)
1435 RETURN_FAIL("IOSSIOSPEED ioctl failed");
1436 /* Set baud rates in data->term to correct, but incompatible
1437 * with tcsetattr() value, same as delivered by tcgetattr(). */
1438 if (cfsetspeed(&data->term, baud_nonstd) < 0)
1439 RETURN_FAIL("cfsetspeed() failed");
1441 #elif defined(__linux__)
1443 TRY(set_baudrate(port->fd, config->baudrate));
1445 if (data->termiox_supported)
1446 TRY(set_flow(port->fd, data->flow));
1450 #endif /* !_WIN32 */
1455 enum sp_return sp_get_config(struct sp_port *port, struct sp_port_config *config)
1457 struct port_data data;
1459 TRACE("%p, %p", port, config);
1464 RETURN_ERROR(SP_ERR_ARG, "Null result pointer");
1466 TRY(get_config(port, &data, config));
1471 enum sp_return sp_set_config(struct sp_port *port, const struct sp_port_config *config)
1473 struct port_data data;
1474 struct sp_port_config prev_config;
1476 TRACE("%p, %p", port, config);
1481 RETURN_ERROR(SP_ERR_ARG, "Null config");
1483 TRY(get_config(port, &data, &prev_config));
1484 TRY(set_config(port, &data, config));
1489 #define CREATE_SETTER(x, type) int sp_set_##x(struct sp_port *port, type x) { \
1490 struct port_data data; \
1491 struct sp_port_config config; \
1492 TRACE("%p, %d", port, x); \
1493 CHECK_OPEN_PORT(); \
1494 TRY(get_config(port, &data, &config)); \
1496 TRY(set_config(port, &data, &config)); \
1500 CREATE_SETTER(baudrate, int)
1501 CREATE_SETTER(bits, int)
1502 CREATE_SETTER(parity, enum sp_parity)
1503 CREATE_SETTER(stopbits, int)
1504 CREATE_SETTER(rts, enum sp_rts)
1505 CREATE_SETTER(cts, enum sp_cts)
1506 CREATE_SETTER(dtr, enum sp_dtr)
1507 CREATE_SETTER(dsr, enum sp_dsr)
1508 CREATE_SETTER(xon_xoff, enum sp_xonxoff)
1510 enum sp_return sp_set_flowcontrol(struct sp_port *port, enum sp_flowcontrol flowcontrol)
1512 struct port_data data;
1513 struct sp_port_config config;
1515 TRACE("%p, %d", port, flowcontrol);
1519 if (flowcontrol > SP_FLOWCONTROL_DTRDSR)
1520 RETURN_ERROR(SP_ERR_ARG, "Invalid flow control setting");
1522 TRY(get_config(port, &data, &config));
1524 if (flowcontrol == SP_FLOWCONTROL_XONXOFF)
1525 config.xon_xoff = SP_XONXOFF_INOUT;
1527 config.xon_xoff = SP_XONXOFF_DISABLED;
1529 if (flowcontrol == SP_FLOWCONTROL_RTSCTS) {
1530 config.rts = SP_RTS_FLOW_CONTROL;
1531 config.cts = SP_CTS_FLOW_CONTROL;
1533 if (config.rts == SP_RTS_FLOW_CONTROL)
1534 config.rts = SP_RTS_ON;
1535 config.cts = SP_CTS_IGNORE;
1538 if (flowcontrol == SP_FLOWCONTROL_DTRDSR) {
1539 config.dtr = SP_DTR_FLOW_CONTROL;
1540 config.dsr = SP_DSR_FLOW_CONTROL;
1542 if (config.dtr == SP_DTR_FLOW_CONTROL)
1543 config.dtr = SP_DTR_ON;
1544 config.dsr = SP_DSR_IGNORE;
1547 TRY(set_config(port, &data, &config));
1552 enum sp_return sp_get_signals(struct sp_port *port, enum sp_signal *signals)
1554 TRACE("%p, %p", port, signals);
1559 RETURN_ERROR(SP_ERR_ARG, "Null result pointer");
1561 DEBUG("Getting control signals for port %s", port->name);
1566 if (GetCommModemStatus(port->hdl, &bits) == 0)
1567 RETURN_FAIL("GetCommModemStatus() failed");
1568 if (bits & MS_CTS_ON)
1569 *signals |= SP_SIG_CTS;
1570 if (bits & MS_DSR_ON)
1571 *signals |= SP_SIG_DSR;
1572 if (bits & MS_RLSD_ON)
1573 *signals |= SP_SIG_DCD;
1574 if (bits & MS_RING_ON)
1575 *signals |= SP_SIG_RI;
1578 if (ioctl(port->fd, TIOCMGET, &bits) < 0)
1579 RETURN_FAIL("TIOCMGET ioctl failed");
1580 if (bits & TIOCM_CTS)
1581 *signals |= SP_SIG_CTS;
1582 if (bits & TIOCM_DSR)
1583 *signals |= SP_SIG_DSR;
1584 if (bits & TIOCM_CAR)
1585 *signals |= SP_SIG_DCD;
1586 if (bits & TIOCM_RNG)
1587 *signals |= SP_SIG_RI;
1592 enum sp_return sp_start_break(struct sp_port *port)
1598 if (SetCommBreak(port->hdl) == 0)
1599 RETURN_FAIL("SetCommBreak() failed");
1601 if (ioctl(port->fd, TIOCSBRK, 1) < 0)
1602 RETURN_FAIL("TIOCSBRK ioctl failed");
1608 enum sp_return sp_end_break(struct sp_port *port)
1614 if (ClearCommBreak(port->hdl) == 0)
1615 RETURN_FAIL("ClearCommBreak() failed");
1617 if (ioctl(port->fd, TIOCCBRK, 1) < 0)
1618 RETURN_FAIL("TIOCCBRK ioctl failed");
1624 int sp_last_error_code(void)
1628 RETURN_VALUE("%d", GetLastError());
1630 RETURN_VALUE("%d", errno);
1634 char *sp_last_error_message(void)
1640 DWORD error = GetLastError();
1643 FORMAT_MESSAGE_ALLOCATE_BUFFER |
1644 FORMAT_MESSAGE_FROM_SYSTEM |
1645 FORMAT_MESSAGE_IGNORE_INSERTS,
1648 MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
1652 RETURN_VALUE("%s", message);
1654 RETURN_VALUE("%s", strerror(errno));
1658 void sp_free_error_message(char *message)
1660 TRACE("%s", message);
1671 void sp_set_debug_handler(void (*handler)(const char *format, ...))
1673 TRACE("%p", handler);
1675 sp_debug_handler = handler;
1680 void sp_default_debug_handler(const char *format, ...)
1683 va_start(args, format);
1684 if (getenv("LIBSERIALPORT_DEBUG")) {
1685 fputs("libserialport: ", stderr);
1686 vfprintf(stderr, format, args);