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"
74 struct sp_port_config {
77 enum sp_parity parity;
83 enum sp_xonxoff xon_xoff;
92 int termiox_supported;
97 /* Standard baud rates. */
99 #define BAUD_TYPE DWORD
100 #define BAUD(n) {CBR_##n, n}
102 #define BAUD_TYPE speed_t
103 #define BAUD(n) {B##n, n}
106 struct std_baudrate {
111 const struct std_baudrate std_baudrates[] = {
114 * The baudrates 50/75/134/150/200/1800/230400/460800 do not seem to
115 * have documented CBR_* macros.
117 BAUD(110), BAUD(300), BAUD(600), BAUD(1200), BAUD(2400), BAUD(4800),
118 BAUD(9600), BAUD(14400), BAUD(19200), BAUD(38400), BAUD(57600),
119 BAUD(115200), BAUD(128000), BAUD(256000),
121 BAUD(50), BAUD(75), BAUD(110), BAUD(134), BAUD(150), BAUD(200),
122 BAUD(300), BAUD(600), BAUD(1200), BAUD(1800), BAUD(2400), BAUD(4800),
123 BAUD(9600), BAUD(19200), BAUD(38400), BAUD(57600), BAUD(115200),
125 #if !defined(__APPLE__) && !defined(__OpenBSD__)
131 void (*sp_debug_handler)(const char *format, ...) = sp_default_debug_handler;
133 #define ARRAY_SIZE(x) (sizeof(x) / sizeof(x[0]))
134 #define NUM_STD_BAUDRATES ARRAY_SIZE(std_baudrates)
136 /* Debug output macros. */
137 #define DEBUG(fmt, ...) do { if (sp_debug_handler) sp_debug_handler(fmt ".\n", ##__VA_ARGS__); } while (0)
138 #define DEBUG_ERROR(err, msg) DEBUG("%s returning " #err ": " msg, __func__)
139 #define DEBUG_FAIL(msg) do { \
140 char *errmsg = sp_last_error_message(); \
141 DEBUG("%s returning SP_ERR_FAIL: " msg ": %s", __func__, errmsg); \
142 sp_free_error_message(errmsg); \
144 #define RETURN() do { DEBUG("%s returning", __func__); return; } while(0)
145 #define RETURN_CODE(x) do { DEBUG("%s returning " #x, __func__); return x; } while (0)
146 #define RETURN_CODEVAL(x) do { \
148 case SP_OK: RETURN_CODE(SP_OK); \
149 case SP_ERR_ARG: RETURN_CODE(SP_ERR_ARG); \
150 case SP_ERR_FAIL: RETURN_CODE(SP_ERR_FAIL); \
151 case SP_ERR_MEM: RETURN_CODE(SP_ERR_MEM); \
152 case SP_ERR_SUPP: RETURN_CODE(SP_ERR_SUPP); \
155 #define RETURN_OK() RETURN_CODE(SP_OK);
156 #define RETURN_ERROR(err, msg) do { DEBUG_ERROR(err, msg); return err; } while (0)
157 #define RETURN_FAIL(msg) do { DEBUG_FAIL(msg); return SP_ERR_FAIL; } while (0)
158 #define RETURN_VALUE(fmt, x) do { DEBUG("%s returning " fmt, __func__, x); return x; } while (0)
159 #define SET_ERROR(val, err, msg) do { DEBUG_ERROR(err, msg); val = err; } while (0)
160 #define SET_FAIL(val, msg) do { DEBUG_FAIL(msg); val = SP_ERR_FAIL; } while (0)
161 #define TRACE(fmt, ...) DEBUG("%s(" fmt ") called", __func__, ##__VA_ARGS__)
163 #define TRY(x) do { int ret = x; if (ret != SP_OK) RETURN_CODEVAL(ret); } while (0)
165 /* Helper functions. */
166 static struct sp_port **list_append(struct sp_port **list, const char *portname);
167 static enum sp_return get_config(struct sp_port *port, struct port_data *data,
168 struct sp_port_config *config);
169 static enum sp_return set_config(struct sp_port *port, struct port_data *data,
170 const struct sp_port_config *config);
172 enum sp_return sp_get_port_by_name(const char *portname, struct sp_port **port_ptr)
174 struct sp_port *port;
177 TRACE("%s, %p", portname, port_ptr);
180 RETURN_ERROR(SP_ERR_ARG, "Null result pointer");
185 RETURN_ERROR(SP_ERR_ARG, "Null port name");
187 DEBUG("Building structure for port %s", portname);
189 if (!(port = malloc(sizeof(struct sp_port))))
190 RETURN_ERROR(SP_ERR_MEM, "Port structure malloc failed");
192 len = strlen(portname) + 1;
194 if (!(port->name = malloc(len))) {
196 RETURN_ERROR(SP_ERR_MEM, "Port name malloc failed");
199 memcpy(port->name, portname, len);
202 port->hdl = INVALID_HANDLE_VALUE;
212 char *sp_get_port_name(const struct sp_port *port)
219 RETURN_VALUE("%s", port->name);
222 enum sp_return sp_get_port_handle(const struct sp_port *port, void *result_ptr)
227 RETURN_ERROR(SP_ERR_ARG, "Null port");
230 HANDLE *handle_ptr = result_ptr;
231 *handle_ptr = port->hdl;
233 int *fd_ptr = result_ptr;
240 enum sp_return sp_copy_port(const struct sp_port *port, struct sp_port **copy_ptr)
242 TRACE("%p, %p", port, copy_ptr);
245 RETURN_ERROR(SP_ERR_ARG, "Null result pointer");
250 RETURN_ERROR(SP_ERR_ARG, "Null port");
253 RETURN_ERROR(SP_ERR_ARG, "Null port name");
255 DEBUG("Copying port structure");
257 RETURN_VALUE("%p", sp_get_port_by_name(port->name, copy_ptr));
260 void sp_free_port(struct sp_port *port)
270 DEBUG("Freeing port structure");
280 static struct sp_port **list_append(struct sp_port **list, const char *portname)
285 for (count = 0; list[count]; count++);
286 if (!(tmp = realloc(list, sizeof(struct sp_port *) * (count + 2))))
289 if (sp_get_port_by_name(portname, &list[count]) != SP_OK)
291 list[count + 1] = NULL;
295 sp_free_port_list(list);
299 enum sp_return sp_list_ports(struct sp_port ***list_ptr)
301 struct sp_port **list;
302 int ret = SP_ERR_SUPP;
304 TRACE("%p", list_ptr);
307 RETURN_ERROR(SP_ERR_ARG, "Null result pointer");
309 DEBUG("Enumerating ports");
311 if (!(list = malloc(sizeof(struct sp_port **))))
312 RETURN_ERROR(SP_ERR_MEM, "Port list malloc failed");
319 DWORD max_value_len, max_data_size, max_data_len;
320 DWORD value_len, data_size, data_len;
321 DWORD type, index = 0;
327 DEBUG("Opening registry key");
328 if (RegOpenKeyEx(HKEY_LOCAL_MACHINE, _T("HARDWARE\\DEVICEMAP\\SERIALCOMM"),
329 0, KEY_QUERY_VALUE, &key) != ERROR_SUCCESS) {
330 SET_FAIL(ret, "RegOpenKeyEx() failed");
333 DEBUG("Querying registry key value and data sizes");
334 if (RegQueryInfoKey(key, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
335 &max_value_len, &max_data_size, NULL, NULL) != ERROR_SUCCESS) {
336 SET_FAIL(ret, "RegQueryInfoKey() failed");
339 max_data_len = max_data_size / sizeof(TCHAR);
340 if (!(value = malloc((max_value_len + 1) * sizeof(TCHAR)))) {
341 SET_ERROR(ret, SP_ERR_MEM, "registry value malloc failed");
344 if (!(data = malloc((max_data_len + 1) * sizeof(TCHAR)))) {
345 SET_ERROR(ret, SP_ERR_MEM, "registry data malloc failed");
348 DEBUG("Iterating over values");
350 value_len = max_value_len + 1,
351 data_size = max_data_size,
352 RegEnumValue(key, index, value, &value_len,
353 NULL, &type, (LPBYTE)data, &data_size) == ERROR_SUCCESS)
355 data_len = data_size / sizeof(TCHAR);
356 data[data_len] = '\0';
358 name_len = WideCharToMultiByte(CP_ACP, 0, data, -1, NULL, 0, NULL, NULL)
360 name_len = data_len + 1;
362 if (!(name = malloc(name_len))) {
363 SET_ERROR(ret, SP_ERR_MEM, "registry port name malloc failed");
367 WideCharToMultiByte(CP_ACP, 0, data, -1, name, name_len, NULL, NULL);
371 if (type == REG_SZ) {
372 DEBUG("Found port %s", name);
373 if (!(list = list_append(list, name))) {
374 SET_ERROR(ret, SP_ERR_MEM, "list append failed");
390 CFMutableDictionaryRef classes;
399 DEBUG("Getting IOKit master port");
400 if (IOMasterPort(MACH_PORT_NULL, &master) != KERN_SUCCESS) {
401 SET_FAIL(ret, "IOMasterPort() failed");
405 DEBUG("Creating matching dictionary");
406 if (!(classes = IOServiceMatching(kIOSerialBSDServiceValue))) {
407 SET_FAIL(ret, "IOServiceMatching() failed");
411 CFDictionarySetValue(classes,
412 CFSTR(kIOSerialBSDTypeKey), CFSTR(kIOSerialBSDAllTypes));
414 DEBUG("Getting matching services");
415 if (IOServiceGetMatchingServices(master, classes, &iter) != KERN_SUCCESS) {
416 SET_FAIL(ret, "IOServiceGetMatchingServices() failed");
420 if (!(path = malloc(PATH_MAX))) {
421 SET_ERROR(ret, SP_ERR_MEM, "device path malloc failed");
425 DEBUG("Iterating over results");
426 while ((port = IOIteratorNext(iter))) {
427 cf_path = IORegistryEntryCreateCFProperty(port,
428 CFSTR(kIOCalloutDeviceKey), kCFAllocatorDefault, 0);
430 result = CFStringGetCString(cf_path,
431 path, PATH_MAX, kCFStringEncodingASCII);
434 DEBUG("Found port %s", path);
435 if (!(list = list_append(list, path))) {
436 SET_ERROR(ret, SP_ERR_MEM, "list append failed");
437 IOObjectRelease(port);
442 IOObjectRelease(port);
447 IOObjectRelease(iter);
452 struct udev_enumerate *ud_enumerate;
453 struct udev_list_entry *ud_list;
454 struct udev_list_entry *ud_entry;
456 struct udev_device *ud_dev, *ud_parent;
459 int fd, ioctl_result;
460 struct serial_struct serial_info;
464 DEBUG("Enumerating tty devices");
466 ud_enumerate = udev_enumerate_new(ud);
467 udev_enumerate_add_match_subsystem(ud_enumerate, "tty");
468 udev_enumerate_scan_devices(ud_enumerate);
469 ud_list = udev_enumerate_get_list_entry(ud_enumerate);
470 DEBUG("Iterating over results");
471 udev_list_entry_foreach(ud_entry, ud_list) {
472 path = udev_list_entry_get_name(ud_entry);
473 DEBUG("Found device %s", path);
474 ud_dev = udev_device_new_from_syspath(ud, path);
475 /* If there is no parent device, this is a virtual tty. */
476 ud_parent = udev_device_get_parent(ud_dev);
477 if (ud_parent == NULL) {
478 DEBUG("No parent device, assuming virtual tty");
479 udev_device_unref(ud_dev);
482 name = udev_device_get_devnode(ud_dev);
483 /* The serial8250 driver has a hardcoded number of ports.
484 * The only way to tell which actually exist on a given system
485 * is to try to open them and make an ioctl call. */
486 driver = udev_device_get_driver(ud_parent);
487 if (driver && !strcmp(driver, "serial8250")) {
488 DEBUG("serial8250 device, attempting to open");
489 if ((fd = open(name, O_RDWR | O_NONBLOCK | O_NOCTTY)) < 0) {
490 DEBUG("open failed, skipping");
493 ioctl_result = ioctl(fd, TIOCGSERIAL, &serial_info);
495 if (ioctl_result != 0) {
496 DEBUG("ioctl failed, skipping");
499 if (serial_info.type == PORT_UNKNOWN) {
500 DEBUG("port type is unknown, skipping");
504 DEBUG("Found port %s", name);
505 list = list_append(list, name);
507 udev_device_unref(ud_dev);
509 SET_ERROR(ret, SP_ERR_MEM, "list append failed");
514 udev_enumerate_unref(ud_enumerate);
523 DEBUG_ERROR(SP_ERR_SUPP, "Enumeration not supported on this platform.");
526 sp_free_port_list(list);
532 void sp_free_port_list(struct sp_port **list)
543 DEBUG("Freeing port list");
545 for (i = 0; list[i]; i++)
546 sp_free_port(list[i]);
552 #define CHECK_PORT() do { \
554 RETURN_ERROR(SP_ERR_ARG, "Null port"); \
555 if (port->name == NULL) \
556 RETURN_ERROR(SP_ERR_ARG, "Null port name"); \
559 #define CHECK_PORT_HANDLE() do { \
560 if (port->hdl == INVALID_HANDLE_VALUE) \
561 RETURN_ERROR(SP_ERR_ARG, "Invalid port handle"); \
564 #define CHECK_PORT_HANDLE() do { \
566 RETURN_ERROR(SP_ERR_ARG, "Invalid port fd"); \
569 #define CHECK_OPEN_PORT() do { \
571 CHECK_PORT_HANDLE(); \
574 enum sp_return sp_open(struct sp_port *port, enum sp_mode flags)
576 struct port_data data;
577 struct sp_port_config config;
580 TRACE("%p, %x", port, flags);
584 if (flags > (SP_MODE_READ | SP_MODE_WRITE | SP_MODE_NONBLOCK))
585 RETURN_ERROR(SP_ERR_ARG, "Invalid flags");
587 DEBUG("Opening port %s", port->name);
589 port->nonblocking = (flags & SP_MODE_NONBLOCK) ? 1 : 0;
592 DWORD desired_access = 0, flags_and_attributes = 0;
593 COMMTIMEOUTS timeouts;
594 char *escaped_port_name;
596 /* Prefix port name with '\\.\' to work with ports above COM9. */
597 if (!(escaped_port_name = malloc(strlen(port->name + 5))))
598 RETURN_ERROR(SP_ERR_MEM, "Escaped port name malloc failed");
599 sprintf(escaped_port_name, "\\\\.\\%s", port->name);
601 /* Map 'flags' to the OS-specific settings. */
602 flags_and_attributes = FILE_ATTRIBUTE_NORMAL;
603 if (flags & SP_MODE_READ)
604 desired_access |= GENERIC_READ;
605 if (flags & SP_MODE_WRITE)
606 desired_access |= GENERIC_WRITE;
607 if (flags & SP_MODE_NONBLOCK)
608 flags_and_attributes |= FILE_FLAG_OVERLAPPED;
610 port->hdl = CreateFile(escaped_port_name, desired_access, 0, 0,
611 OPEN_EXISTING, flags_and_attributes, 0);
613 free(escaped_port_name);
615 if (port->hdl == INVALID_HANDLE_VALUE)
616 RETURN_FAIL("CreateFile() failed");
618 /* All timeouts disabled. */
619 timeouts.ReadIntervalTimeout = 0;
620 timeouts.ReadTotalTimeoutMultiplier = 0;
621 timeouts.ReadTotalTimeoutConstant = 0;
622 timeouts.WriteTotalTimeoutMultiplier = 0;
623 timeouts.WriteTotalTimeoutConstant = 0;
625 if (port->nonblocking) {
626 /* Set read timeout such that all reads return immediately. */
627 timeouts.ReadIntervalTimeout = MAXDWORD;
628 /* Prepare OVERLAPPED structure for non-blocking writes. */
629 memset(&port->write_ovl, 0, sizeof(port->write_ovl));
630 if (!(port->write_ovl.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL))) {
632 RETURN_FAIL("CreateEvent() failed");
634 port->writing = FALSE;
637 if (SetCommTimeouts(port->hdl, &timeouts) == 0) {
639 RETURN_FAIL("SetCommTimeouts() failed");
644 /* Map 'flags' to the OS-specific settings. */
645 if (flags & (SP_MODE_READ | SP_MODE_WRITE))
646 flags_local |= O_RDWR;
647 else if (flags & SP_MODE_READ)
648 flags_local |= O_RDONLY;
649 else if (flags & SP_MODE_WRITE)
650 flags_local |= O_WRONLY;
651 if (flags & SP_MODE_NONBLOCK)
652 flags_local |= O_NONBLOCK;
654 if ((port->fd = open(port->name, flags_local)) < 0)
655 RETURN_FAIL("open() failed");
658 ret = get_config(port, &data, &config);
665 /* Set sane port settings. */
667 data.dcb.fBinary = TRUE;
668 data.dcb.fDsrSensitivity = FALSE;
669 data.dcb.fErrorChar = FALSE;
670 data.dcb.fNull = FALSE;
671 data.dcb.fAbortOnError = TRUE;
673 /* Turn off all fancy termios tricks, give us a raw channel. */
674 data.term.c_iflag &= ~(IGNBRK|BRKINT|PARMRK|ISTRIP|INLCR|IGNCR|ICRNL|IUCLC|IMAXBEL);
675 data.term.c_oflag &= ~(OPOST|OLCUC|ONLCR|OCRNL|ONOCR|ONLRET|NLDLY|CRDLY|TABDLY|BSDLY|VTDLY|FFDLY);
677 data.term.c_oflag &= ~OFILL;
679 data.term.c_lflag &= ~(ISIG|ICANON|ECHO|IEXTEN);
680 data.term.c_cc[VMIN] = 0;
681 data.term.c_cc[VTIME] = 0;
683 /* Ignore modem status lines; enable receiver; leave control lines alone on close. */
684 data.term.c_cflag |= (CLOCAL | CREAD | HUPCL);
687 ret = set_config(port, &data, &config);
697 enum sp_return sp_close(struct sp_port *port)
703 DEBUG("Closing port %s", port->name);
706 /* Returns non-zero upon success, 0 upon failure. */
707 if (CloseHandle(port->hdl) == 0)
708 RETURN_FAIL("CloseHandle() failed");
709 port->hdl = INVALID_HANDLE_VALUE;
710 if (port->nonblocking) {
711 /* Close event handle created for overlapped writes. */
712 if (CloseHandle(port->write_ovl.hEvent) == 0)
713 RETURN_FAIL("CloseHandle() failed");
716 /* Returns 0 upon success, -1 upon failure. */
717 if (close(port->fd) == -1)
718 RETURN_FAIL("close() failed");
725 enum sp_return sp_flush(struct sp_port *port, enum sp_buffer buffers)
727 TRACE("%p, %x", port, buffers);
731 if (buffers > SP_BUF_BOTH)
732 RETURN_ERROR(SP_ERR_ARG, "Invalid buffer selection");
734 const char *buffer_names[] = {"no", "input", "output", "both"};
736 DEBUG("Flushing %s buffers on port %s", buffer_names[buffers], port->name);
740 if (buffers & SP_BUF_INPUT)
741 flags |= PURGE_RXCLEAR;
742 if (buffers & SP_BUF_OUTPUT)
743 flags |= PURGE_TXCLEAR;
745 /* Returns non-zero upon success, 0 upon failure. */
746 if (PurgeComm(port->hdl, flags) == 0)
747 RETURN_FAIL("PurgeComm() failed");
750 if (buffers & SP_BUF_BOTH)
752 else if (buffers & SP_BUF_INPUT)
754 else if (buffers & SP_BUF_OUTPUT)
757 /* Returns 0 upon success, -1 upon failure. */
758 if (tcflush(port->fd, flags) < 0)
759 RETURN_FAIL("tcflush() failed");
764 enum sp_return sp_drain(struct sp_port *port)
770 DEBUG("Draining port %s", port->name);
773 /* Returns non-zero upon success, 0 upon failure. */
774 if (FlushFileBuffers(port->hdl) == 0)
775 RETURN_FAIL("FlushFileBuffers() failed");
777 /* Returns 0 upon success, -1 upon failure. */
778 if (tcdrain(port->fd) < 0)
779 RETURN_FAIL("tcdrain() failed");
785 enum sp_return sp_write(struct sp_port *port, const void *buf, size_t count)
787 TRACE("%p, %p, %d", port, buf, count);
792 RETURN_ERROR(SP_ERR_ARG, "Null buffer");
794 DEBUG("Writing up to %d bytes to port %s", count, port->name);
797 RETURN_VALUE("0", 0);
801 BYTE *ptr = (BYTE *) buf;
803 if (port->nonblocking) {
804 /* Non-blocking write. */
806 /* Check whether previous write is complete. */
808 if (HasOverlappedIoCompleted(&port->write_ovl)) {
809 DEBUG("Previous write completed");
812 DEBUG("Previous write not complete");
813 /* Can't take a new write until the previous one finishes. */
814 RETURN_VALUE("0", 0);
818 /* Keep writing data until the OS has to actually start an async IO for it.
819 * At that point we know the buffer is full. */
820 while (written < count)
822 /* Copy first byte of user buffer. */
823 port->pending_byte = *ptr++;
825 /* Start asynchronous write. */
826 if (WriteFile(port->hdl, &port->pending_byte, 1, NULL, &port->write_ovl) == 0) {
827 if (GetLastError() == ERROR_IO_PENDING) {
828 DEBUG("Asynchronous write started");
830 RETURN_VALUE("%d", ++written);
832 /* Actual failure of some kind. */
833 RETURN_FAIL("WriteFile() failed");
836 DEBUG("Single byte written immediately.");
841 DEBUG("All bytes written immediately.");
844 /* Blocking write. */
845 if (WriteFile(port->hdl, buf, count, &written, NULL) == 0) {
846 RETURN_FAIL("WriteFile() failed");
850 RETURN_VALUE("%d", written);
852 /* Returns the number of bytes written, or -1 upon failure. */
853 ssize_t written = write(port->fd, buf, count);
856 RETURN_FAIL("write() failed");
858 RETURN_VALUE("%d", written);
862 enum sp_return sp_read(struct sp_port *port, void *buf, size_t count)
864 TRACE("%p, %p, %d", port, buf, count);
869 RETURN_ERROR(SP_ERR_ARG, "Null buffer");
871 DEBUG("Reading up to %d bytes from port %s", count, port->name);
874 DWORD bytes_read = 0;
876 /* Returns non-zero upon success, 0 upon failure. */
877 if (ReadFile(port->hdl, buf, count, &bytes_read, NULL) == 0)
878 RETURN_FAIL("ReadFile() failed");
879 RETURN_VALUE("%d", bytes_read);
883 /* Returns the number of bytes read, or -1 upon failure. */
884 if ((bytes_read = read(port->fd, buf, count)) < 0) {
885 if (port->nonblocking && errno == EAGAIN)
886 /* Port is opened in nonblocking mode and there are no bytes available. */
889 /* This is an actual failure. */
890 RETURN_FAIL("read() failed");
892 RETURN_VALUE("%d", bytes_read);
897 static enum sp_return get_baudrate(int fd, int *baudrate)
901 TRACE("%d, %p", fd, baudrate);
903 DEBUG("Getting baud rate");
905 if (!(data = malloc(get_termios_size())))
906 RETURN_ERROR(SP_ERR_MEM, "termios malloc failed");
908 if (ioctl(fd, get_termios_get_ioctl(), data) < 0) {
910 RETURN_FAIL("getting termios failed");
913 *baudrate = get_termios_speed(data);
920 static enum sp_return set_baudrate(int fd, int baudrate)
924 TRACE("%d, %d", fd, baudrate);
926 DEBUG("Getting baud rate");
928 if (!(data = malloc(get_termios_size())))
929 RETURN_ERROR(SP_ERR_MEM, "termios malloc failed");
931 if (ioctl(fd, get_termios_get_ioctl(), data) < 0) {
933 RETURN_FAIL("getting termios failed");
936 DEBUG("Setting baud rate");
938 set_termios_speed(data, baudrate);
940 if (ioctl(fd, get_termios_set_ioctl(), data) < 0) {
942 RETURN_FAIL("setting termios failed");
951 static enum sp_return get_flow(int fd, int *flow)
955 TRACE("%d, %p", fd, flow);
957 DEBUG("Getting advanced flow control");
959 if (!(data = malloc(get_termiox_size())))
960 RETURN_ERROR(SP_ERR_MEM, "termiox malloc failed");
962 if (ioctl(fd, TCGETX, data) < 0) {
964 RETURN_FAIL("getting termiox failed");
967 *flow = get_termiox_flow(data);
974 static enum sp_return set_flow(int fd, int flow)
978 TRACE("%d, %d", fd, flow);
980 DEBUG("Getting advanced flow control");
982 if (!(data = malloc(get_termiox_size())))
983 RETURN_ERROR(SP_ERR_MEM, "termiox malloc failed");
985 if (ioctl(fd, TCGETX, data) < 0) {
987 RETURN_FAIL("getting termiox failed");
990 DEBUG("Setting advanced flow control");
992 set_termiox_flow(data, flow);
994 if (ioctl(fd, TCSETX, data) < 0) {
996 RETURN_FAIL("setting termiox failed");
1003 #endif /* USE_TERMIOX */
1004 #endif /* __linux__ */
1006 static enum sp_return get_config(struct sp_port *port, struct port_data *data,
1007 struct sp_port_config *config)
1011 TRACE("%p, %p, %p", port, data, config);
1013 DEBUG("Getting configuration for port %s", port->name);
1016 if (!GetCommState(port->hdl, &data->dcb))
1017 RETURN_FAIL("GetCommState() failed");
1019 for (i = 0; i < NUM_STD_BAUDRATES; i++) {
1020 if (data->dcb.BaudRate == std_baudrates[i].index) {
1021 config->baudrate = std_baudrates[i].value;
1026 if (i == NUM_STD_BAUDRATES)
1027 /* BaudRate field can be either an index or a custom baud rate. */
1028 config->baudrate = data->dcb.BaudRate;
1030 config->bits = data->dcb.ByteSize;
1032 if (data->dcb.fParity)
1033 switch (data->dcb.Parity) {
1035 config->parity = SP_PARITY_NONE;
1038 config->parity = SP_PARITY_ODD;
1041 config->parity = SP_PARITY_EVEN;
1044 config->parity = SP_PARITY_MARK;
1047 config->parity = SP_PARITY_SPACE;
1050 config->parity = -1;
1053 config->parity = SP_PARITY_NONE;
1055 switch (data->dcb.StopBits) {
1057 config->stopbits = 1;
1060 config->stopbits = 2;
1063 config->stopbits = -1;
1066 switch (data->dcb.fRtsControl) {
1067 case RTS_CONTROL_DISABLE:
1068 config->rts = SP_RTS_OFF;
1070 case RTS_CONTROL_ENABLE:
1071 config->rts = SP_RTS_ON;
1073 case RTS_CONTROL_HANDSHAKE:
1074 config->rts = SP_RTS_FLOW_CONTROL;
1080 config->cts = data->dcb.fOutxCtsFlow ? SP_CTS_FLOW_CONTROL : SP_CTS_IGNORE;
1082 switch (data->dcb.fDtrControl) {
1083 case DTR_CONTROL_DISABLE:
1084 config->dtr = SP_DTR_OFF;
1086 case DTR_CONTROL_ENABLE:
1087 config->dtr = SP_DTR_ON;
1089 case DTR_CONTROL_HANDSHAKE:
1090 config->dtr = SP_DTR_FLOW_CONTROL;
1096 config->dsr = data->dcb.fOutxDsrFlow ? SP_DSR_FLOW_CONTROL : SP_DSR_IGNORE;
1098 if (data->dcb.fInX) {
1099 if (data->dcb.fOutX)
1100 config->xon_xoff = SP_XONXOFF_INOUT;
1102 config->xon_xoff = SP_XONXOFF_IN;
1104 if (data->dcb.fOutX)
1105 config->xon_xoff = SP_XONXOFF_OUT;
1107 config->xon_xoff = SP_XONXOFF_DISABLED;
1112 if (tcgetattr(port->fd, &data->term) < 0)
1113 RETURN_FAIL("tcgetattr() failed");
1115 if (ioctl(port->fd, TIOCMGET, &data->controlbits) < 0)
1116 RETURN_FAIL("TIOCMGET ioctl failed");
1119 int ret = get_flow(port->fd, &data->flow);
1121 if (ret == SP_ERR_FAIL && errno == EINVAL)
1122 data->termiox_supported = 0;
1124 RETURN_CODEVAL(ret);
1126 data->termiox_supported = 1;
1128 data->termiox_supported = 0;
1131 for (i = 0; i < NUM_STD_BAUDRATES; i++) {
1132 if (cfgetispeed(&data->term) == std_baudrates[i].index) {
1133 config->baudrate = std_baudrates[i].value;
1138 if (i == NUM_STD_BAUDRATES) {
1140 config->baudrate = (int)data->term.c_ispeed;
1141 #elif defined(__linux__)
1142 TRY(get_baudrate(port->fd, &config->baudrate));
1144 config->baudrate = -1;
1148 switch (data->term.c_cflag & CSIZE) {
1165 if (!(data->term.c_cflag & PARENB) && (data->term.c_iflag & IGNPAR))
1166 config->parity = SP_PARITY_NONE;
1167 else if (!(data->term.c_cflag & PARENB) || (data->term.c_iflag & IGNPAR))
1168 config->parity = -1;
1169 else if (data->term.c_cflag & CMSPAR)
1170 config->parity = (data->term.c_cflag & PARODD) ? SP_PARITY_MARK : SP_PARITY_SPACE;
1172 config->parity = (data->term.c_cflag & PARODD) ? SP_PARITY_ODD : SP_PARITY_EVEN;
1174 config->stopbits = (data->term.c_cflag & CSTOPB) ? 2 : 1;
1176 if (data->term.c_cflag & CRTSCTS) {
1177 config->rts = SP_RTS_FLOW_CONTROL;
1178 config->cts = SP_CTS_FLOW_CONTROL;
1180 if (data->termiox_supported && data->flow & RTS_FLOW)
1181 config->rts = SP_RTS_FLOW_CONTROL;
1183 config->rts = (data->controlbits & TIOCM_RTS) ? SP_RTS_ON : SP_RTS_OFF;
1185 config->cts = (data->termiox_supported && data->flow & CTS_FLOW) ?
1186 SP_CTS_FLOW_CONTROL : SP_CTS_IGNORE;
1189 if (data->termiox_supported && data->flow & DTR_FLOW)
1190 config->dtr = SP_DTR_FLOW_CONTROL;
1192 config->dtr = (data->controlbits & TIOCM_DTR) ? SP_DTR_ON : SP_DTR_OFF;
1194 config->dsr = (data->termiox_supported && data->flow & DSR_FLOW) ?
1195 SP_DSR_FLOW_CONTROL : SP_DSR_IGNORE;
1197 if (data->term.c_iflag & IXOFF) {
1198 if (data->term.c_iflag & IXON)
1199 config->xon_xoff = SP_XONXOFF_INOUT;
1201 config->xon_xoff = SP_XONXOFF_IN;
1203 if (data->term.c_iflag & IXON)
1204 config->xon_xoff = SP_XONXOFF_OUT;
1206 config->xon_xoff = SP_XONXOFF_DISABLED;
1213 static enum sp_return set_config(struct sp_port *port, struct port_data *data,
1214 const struct sp_port_config *config)
1218 BAUD_TYPE baud_nonstd;
1223 int baud_nonstd = 0;
1226 TRACE("%p, %p, %p", port, data, config);
1228 DEBUG("Setting configuration for port %s", port->name);
1231 if (config->baudrate >= 0) {
1232 for (i = 0; i < NUM_STD_BAUDRATES; i++) {
1233 if (config->baudrate == std_baudrates[i].value) {
1234 data->dcb.BaudRate = std_baudrates[i].index;
1239 if (i == NUM_STD_BAUDRATES)
1240 data->dcb.BaudRate = config->baudrate;
1243 if (config->bits >= 0)
1244 data->dcb.ByteSize = config->bits;
1246 if (config->parity >= 0) {
1247 switch (config->parity) {
1248 /* Note: There's also SPACEPARITY, MARKPARITY (unneeded so far). */
1249 case SP_PARITY_NONE:
1250 data->dcb.Parity = NOPARITY;
1253 data->dcb.Parity = ODDPARITY;
1255 case SP_PARITY_EVEN:
1256 data->dcb.Parity = EVENPARITY;
1258 case SP_PARITY_MARK:
1259 data->dcb.Parity = MARKPARITY;
1261 case SP_PARITY_SPACE:
1262 data->dcb.Parity = SPACEPARITY;
1265 RETURN_ERROR(SP_ERR_ARG, "Invalid parity setting");
1269 if (config->stopbits >= 0) {
1270 switch (config->stopbits) {
1271 /* Note: There's also ONE5STOPBITS == 1.5 (unneeded so far). */
1273 data->dcb.StopBits = ONESTOPBIT;
1276 data->dcb.StopBits = TWOSTOPBITS;
1279 RETURN_ERROR(SP_ERR_ARG, "Invalid stop bit setting");
1283 if (config->rts >= 0) {
1284 switch (config->rts) {
1286 data->dcb.fRtsControl = RTS_CONTROL_DISABLE;
1289 data->dcb.fRtsControl = RTS_CONTROL_ENABLE;
1291 case SP_RTS_FLOW_CONTROL:
1292 data->dcb.fRtsControl = RTS_CONTROL_HANDSHAKE;
1295 RETURN_ERROR(SP_ERR_ARG, "Invalid RTS setting");
1299 if (config->cts >= 0) {
1300 switch (config->cts) {
1302 data->dcb.fOutxCtsFlow = FALSE;
1304 case SP_CTS_FLOW_CONTROL:
1305 data->dcb.fOutxCtsFlow = TRUE;
1308 RETURN_ERROR(SP_ERR_ARG, "Invalid CTS setting");
1312 if (config->dtr >= 0) {
1313 switch (config->dtr) {
1315 data->dcb.fDtrControl = DTR_CONTROL_DISABLE;
1318 data->dcb.fDtrControl = DTR_CONTROL_ENABLE;
1320 case SP_DTR_FLOW_CONTROL:
1321 data->dcb.fDtrControl = DTR_CONTROL_HANDSHAKE;
1324 RETURN_ERROR(SP_ERR_ARG, "Invalid DTR setting");
1328 if (config->dsr >= 0) {
1329 switch (config->dsr) {
1331 data->dcb.fOutxDsrFlow = FALSE;
1333 case SP_DSR_FLOW_CONTROL:
1334 data->dcb.fOutxDsrFlow = TRUE;
1337 RETURN_ERROR(SP_ERR_ARG, "Invalid DSR setting");
1341 if (config->xon_xoff >= 0) {
1342 switch (config->xon_xoff) {
1343 case SP_XONXOFF_DISABLED:
1344 data->dcb.fInX = FALSE;
1345 data->dcb.fOutX = FALSE;
1348 data->dcb.fInX = TRUE;
1349 data->dcb.fOutX = FALSE;
1351 case SP_XONXOFF_OUT:
1352 data->dcb.fInX = FALSE;
1353 data->dcb.fOutX = TRUE;
1355 case SP_XONXOFF_INOUT:
1356 data->dcb.fInX = TRUE;
1357 data->dcb.fOutX = TRUE;
1360 RETURN_ERROR(SP_ERR_ARG, "Invalid XON/XOFF setting");
1364 if (!SetCommState(port->hdl, &data->dcb))
1365 RETURN_FAIL("SetCommState() failed");
1371 if (config->baudrate >= 0) {
1372 for (i = 0; i < NUM_STD_BAUDRATES; i++) {
1373 if (config->baudrate == std_baudrates[i].value) {
1374 if (cfsetospeed(&data->term, std_baudrates[i].index) < 0)
1375 RETURN_FAIL("cfsetospeed() failed");
1377 if (cfsetispeed(&data->term, std_baudrates[i].index) < 0)
1378 RETURN_FAIL("cfsetispeed() failed");
1383 /* Non-standard baud rate */
1384 if (i == NUM_STD_BAUDRATES) {
1386 /* Set "dummy" baud rate. */
1387 if (cfsetspeed(&data->term, B9600) < 0)
1388 RETURN_FAIL("cfsetspeed() failed");
1389 baud_nonstd = config->baudrate;
1390 #elif defined(__linux__)
1393 RETURN_ERROR(SP_ERR_SUPP, "Non-standard baudrate not supported");
1398 if (config->bits >= 0) {
1399 data->term.c_cflag &= ~CSIZE;
1400 switch (config->bits) {
1402 data->term.c_cflag |= CS8;
1405 data->term.c_cflag |= CS7;
1408 data->term.c_cflag |= CS6;
1411 data->term.c_cflag |= CS5;
1414 RETURN_ERROR(SP_ERR_ARG, "Invalid data bits setting");
1418 if (config->parity >= 0) {
1419 data->term.c_iflag &= ~IGNPAR;
1420 data->term.c_cflag &= ~(PARENB | PARODD | CMSPAR);
1421 switch (config->parity) {
1422 case SP_PARITY_NONE:
1423 data->term.c_iflag |= IGNPAR;
1425 case SP_PARITY_EVEN:
1426 data->term.c_cflag |= PARENB;
1429 data->term.c_cflag |= PARENB | PARODD;
1431 case SP_PARITY_MARK:
1432 data->term.c_cflag |= PARENB | PARODD | CMSPAR;
1434 case SP_PARITY_SPACE:
1435 data->term.c_cflag |= PARENB | CMSPAR;
1438 RETURN_ERROR(SP_ERR_ARG, "Invalid parity setting");
1442 if (config->stopbits >= 0) {
1443 data->term.c_cflag &= ~CSTOPB;
1444 switch (config->stopbits) {
1446 data->term.c_cflag &= ~CSTOPB;
1449 data->term.c_cflag |= CSTOPB;
1452 RETURN_ERROR(SP_ERR_ARG, "Invalid stop bits setting");
1456 if (config->rts >= 0 || config->cts >= 0) {
1457 if (data->termiox_supported) {
1458 data->flow &= ~(RTS_FLOW | CTS_FLOW);
1459 switch (config->rts) {
1462 controlbits = TIOCM_RTS;
1463 if (ioctl(port->fd, config->rts == SP_RTS_ON ? TIOCMBIS : TIOCMBIC, &controlbits) < 0)
1464 RETURN_FAIL("Setting RTS signal level failed");
1466 case SP_RTS_FLOW_CONTROL:
1467 data->flow |= RTS_FLOW;
1472 if (config->cts == SP_CTS_FLOW_CONTROL)
1473 data->flow |= CTS_FLOW;
1475 if (data->flow & (RTS_FLOW | CTS_FLOW))
1476 data->term.c_iflag |= CRTSCTS;
1478 data->term.c_iflag &= ~CRTSCTS;
1480 /* Asymmetric use of RTS/CTS not supported. */
1481 if (data->term.c_iflag & CRTSCTS) {
1482 /* Flow control can only be disabled for both RTS & CTS together. */
1483 if (config->rts >= 0 && config->rts != SP_RTS_FLOW_CONTROL) {
1484 if (config->cts != SP_CTS_IGNORE)
1485 RETURN_ERROR(SP_ERR_SUPP, "RTS & CTS flow control must be disabled together");
1487 if (config->cts >= 0 && config->cts != SP_CTS_FLOW_CONTROL) {
1488 if (config->rts <= 0 || config->rts == SP_RTS_FLOW_CONTROL)
1489 RETURN_ERROR(SP_ERR_SUPP, "RTS & CTS flow control must be disabled together");
1492 /* Flow control can only be enabled for both RTS & CTS together. */
1493 if (((config->rts == SP_RTS_FLOW_CONTROL) && (config->cts != SP_CTS_FLOW_CONTROL)) ||
1494 ((config->cts == SP_CTS_FLOW_CONTROL) && (config->rts != SP_RTS_FLOW_CONTROL)))
1495 RETURN_ERROR(SP_ERR_SUPP, "RTS & CTS flow control must be enabled together");
1498 if (config->rts >= 0) {
1499 if (config->rts == SP_RTS_FLOW_CONTROL) {
1500 data->term.c_iflag |= CRTSCTS;
1502 controlbits = TIOCM_RTS;
1503 if (ioctl(port->fd, config->rts == SP_RTS_ON ? TIOCMBIS : TIOCMBIC,
1505 RETURN_FAIL("Setting RTS signal level failed");
1511 if (config->dtr >= 0 || config->dsr >= 0) {
1512 if (data->termiox_supported) {
1513 data->flow &= ~(DTR_FLOW | DSR_FLOW);
1514 switch (config->dtr) {
1517 controlbits = TIOCM_DTR;
1518 if (ioctl(port->fd, config->dtr == SP_DTR_ON ? TIOCMBIS : TIOCMBIC, &controlbits) < 0)
1519 RETURN_FAIL("Setting DTR signal level failed");
1521 case SP_DTR_FLOW_CONTROL:
1522 data->flow |= DTR_FLOW;
1527 if (config->dsr == SP_DSR_FLOW_CONTROL)
1528 data->flow |= DSR_FLOW;
1530 /* DTR/DSR flow control not supported. */
1531 if (config->dtr == SP_DTR_FLOW_CONTROL || config->dsr == SP_DSR_FLOW_CONTROL)
1532 RETURN_ERROR(SP_ERR_SUPP, "DTR/DSR flow control not supported");
1534 if (config->dtr >= 0) {
1535 controlbits = TIOCM_DTR;
1536 if (ioctl(port->fd, config->dtr == SP_DTR_ON ? TIOCMBIS : TIOCMBIC,
1538 RETURN_FAIL("Setting DTR signal level failed");
1543 if (config->xon_xoff >= 0) {
1544 data->term.c_iflag &= ~(IXON | IXOFF | IXANY);
1545 switch (config->xon_xoff) {
1546 case SP_XONXOFF_DISABLED:
1549 data->term.c_iflag |= IXOFF;
1551 case SP_XONXOFF_OUT:
1552 data->term.c_iflag |= IXON | IXANY;
1554 case SP_XONXOFF_INOUT:
1555 data->term.c_iflag |= IXON | IXOFF | IXANY;
1558 RETURN_ERROR(SP_ERR_ARG, "Invalid XON/XOFF setting");
1562 if (tcsetattr(port->fd, TCSANOW, &data->term) < 0)
1563 RETURN_FAIL("tcsetattr() failed");
1566 if (baud_nonstd != B0) {
1567 if (ioctl(port->fd, IOSSIOSPEED, &baud_nonstd) == -1)
1568 RETURN_FAIL("IOSSIOSPEED ioctl failed");
1569 /* Set baud rates in data->term to correct, but incompatible
1570 * with tcsetattr() value, same as delivered by tcgetattr(). */
1571 if (cfsetspeed(&data->term, baud_nonstd) < 0)
1572 RETURN_FAIL("cfsetspeed() failed");
1574 #elif defined(__linux__)
1576 TRY(set_baudrate(port->fd, config->baudrate));
1578 if (data->termiox_supported)
1579 TRY(set_flow(port->fd, data->flow));
1583 #endif /* !_WIN32 */
1588 enum sp_return sp_new_config(struct sp_port_config **config_ptr)
1590 TRACE("%p", config_ptr);
1591 struct sp_port_config *config;
1594 RETURN_ERROR(SP_ERR_ARG, "Null result pointer");
1598 if (!(config = malloc(sizeof(struct sp_port_config))))
1599 RETURN_ERROR(SP_ERR_MEM, "config malloc failed");
1601 config->baudrate = -1;
1603 config->parity = -1;
1604 config->stopbits = -1;
1610 *config_ptr = config;
1615 void sp_free_config(struct sp_port_config *config)
1617 TRACE("%p", config);
1620 DEBUG("Null config");
1627 enum sp_return sp_get_config(struct sp_port *port, struct sp_port_config *config)
1629 struct port_data data;
1631 TRACE("%p, %p", port, config);
1636 RETURN_ERROR(SP_ERR_ARG, "Null config");
1638 TRY(get_config(port, &data, config));
1643 enum sp_return sp_set_config(struct sp_port *port, const struct sp_port_config *config)
1645 struct port_data data;
1646 struct sp_port_config prev_config;
1648 TRACE("%p, %p", port, config);
1653 RETURN_ERROR(SP_ERR_ARG, "Null config");
1655 TRY(get_config(port, &data, &prev_config));
1656 TRY(set_config(port, &data, config));
1661 #define CREATE_ACCESSORS(x, type) \
1662 enum sp_return sp_set_##x(struct sp_port *port, type x) { \
1663 struct port_data data; \
1664 struct sp_port_config config; \
1665 TRACE("%p, %d", port, x); \
1666 CHECK_OPEN_PORT(); \
1667 TRY(get_config(port, &data, &config)); \
1669 TRY(set_config(port, &data, &config)); \
1672 enum sp_return sp_get_config_##x(const struct sp_port_config *config, type *x) { \
1673 TRACE("%p", config); \
1675 RETURN_ERROR(SP_ERR_ARG, "Null config"); \
1679 enum sp_return sp_set_config_##x(struct sp_port_config *config, type x) { \
1680 TRACE("%p, %d", config, x); \
1682 RETURN_ERROR(SP_ERR_ARG, "Null config"); \
1687 CREATE_ACCESSORS(baudrate, int)
1688 CREATE_ACCESSORS(bits, int)
1689 CREATE_ACCESSORS(parity, enum sp_parity)
1690 CREATE_ACCESSORS(stopbits, int)
1691 CREATE_ACCESSORS(rts, enum sp_rts)
1692 CREATE_ACCESSORS(cts, enum sp_cts)
1693 CREATE_ACCESSORS(dtr, enum sp_dtr)
1694 CREATE_ACCESSORS(dsr, enum sp_dsr)
1695 CREATE_ACCESSORS(xon_xoff, enum sp_xonxoff)
1697 enum sp_return sp_set_config_flowcontrol(struct sp_port_config *config, enum sp_flowcontrol flowcontrol)
1700 RETURN_ERROR(SP_ERR_ARG, "Null configuration");
1702 if (flowcontrol > SP_FLOWCONTROL_DTRDSR)
1703 RETURN_ERROR(SP_ERR_ARG, "Invalid flow control setting");
1705 if (flowcontrol == SP_FLOWCONTROL_XONXOFF)
1706 config->xon_xoff = SP_XONXOFF_INOUT;
1708 config->xon_xoff = SP_XONXOFF_DISABLED;
1710 if (flowcontrol == SP_FLOWCONTROL_RTSCTS) {
1711 config->rts = SP_RTS_FLOW_CONTROL;
1712 config->cts = SP_CTS_FLOW_CONTROL;
1714 if (config->rts == SP_RTS_FLOW_CONTROL)
1715 config->rts = SP_RTS_ON;
1716 config->cts = SP_CTS_IGNORE;
1719 if (flowcontrol == SP_FLOWCONTROL_DTRDSR) {
1720 config->dtr = SP_DTR_FLOW_CONTROL;
1721 config->dsr = SP_DSR_FLOW_CONTROL;
1723 if (config->dtr == SP_DTR_FLOW_CONTROL)
1724 config->dtr = SP_DTR_ON;
1725 config->dsr = SP_DSR_IGNORE;
1731 enum sp_return sp_set_flowcontrol(struct sp_port *port, enum sp_flowcontrol flowcontrol)
1733 struct port_data data;
1734 struct sp_port_config config;
1736 TRACE("%p, %d", port, flowcontrol);
1740 TRY(get_config(port, &data, &config));
1742 TRY(sp_set_config_flowcontrol(&config, flowcontrol));
1744 TRY(set_config(port, &data, &config));
1749 enum sp_return sp_get_signals(struct sp_port *port, enum sp_signal *signals)
1751 TRACE("%p, %p", port, signals);
1756 RETURN_ERROR(SP_ERR_ARG, "Null result pointer");
1758 DEBUG("Getting control signals for port %s", port->name);
1763 if (GetCommModemStatus(port->hdl, &bits) == 0)
1764 RETURN_FAIL("GetCommModemStatus() failed");
1765 if (bits & MS_CTS_ON)
1766 *signals |= SP_SIG_CTS;
1767 if (bits & MS_DSR_ON)
1768 *signals |= SP_SIG_DSR;
1769 if (bits & MS_RLSD_ON)
1770 *signals |= SP_SIG_DCD;
1771 if (bits & MS_RING_ON)
1772 *signals |= SP_SIG_RI;
1775 if (ioctl(port->fd, TIOCMGET, &bits) < 0)
1776 RETURN_FAIL("TIOCMGET ioctl failed");
1777 if (bits & TIOCM_CTS)
1778 *signals |= SP_SIG_CTS;
1779 if (bits & TIOCM_DSR)
1780 *signals |= SP_SIG_DSR;
1781 if (bits & TIOCM_CAR)
1782 *signals |= SP_SIG_DCD;
1783 if (bits & TIOCM_RNG)
1784 *signals |= SP_SIG_RI;
1789 enum sp_return sp_start_break(struct sp_port *port)
1795 if (SetCommBreak(port->hdl) == 0)
1796 RETURN_FAIL("SetCommBreak() failed");
1798 if (ioctl(port->fd, TIOCSBRK, 1) < 0)
1799 RETURN_FAIL("TIOCSBRK ioctl failed");
1805 enum sp_return sp_end_break(struct sp_port *port)
1811 if (ClearCommBreak(port->hdl) == 0)
1812 RETURN_FAIL("ClearCommBreak() failed");
1814 if (ioctl(port->fd, TIOCCBRK, 1) < 0)
1815 RETURN_FAIL("TIOCCBRK ioctl failed");
1821 int sp_last_error_code(void)
1825 RETURN_VALUE("%d", GetLastError());
1827 RETURN_VALUE("%d", errno);
1831 char *sp_last_error_message(void)
1837 DWORD error = GetLastError();
1840 FORMAT_MESSAGE_ALLOCATE_BUFFER |
1841 FORMAT_MESSAGE_FROM_SYSTEM |
1842 FORMAT_MESSAGE_IGNORE_INSERTS,
1845 MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
1849 RETURN_VALUE("%s", message);
1851 RETURN_VALUE("%s", strerror(errno));
1855 void sp_free_error_message(char *message)
1857 TRACE("%s", message);
1868 void sp_set_debug_handler(void (*handler)(const char *format, ...))
1870 TRACE("%p", handler);
1872 sp_debug_handler = handler;
1877 void sp_default_debug_handler(const char *format, ...)
1880 va_start(args, format);
1881 if (getenv("LIBSERIALPORT_DEBUG")) {
1882 fputs("libserialport: ", stderr);
1883 vfprintf(stderr, format, args);