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 | IMAXBEL);
676 data.term.c_iflag &= ~IUCLC;
678 data.term.c_oflag &= ~(OPOST | ONLCR | OCRNL | ONOCR | ONLRET);
680 data.term.c_oflag &= ~OLCUC;
683 data.term.c_oflag &= ~NLDLY;
686 data.term.c_oflag &= ~CRDLY;
689 data.term.c_oflag &= ~TABDLY;
692 data.term.c_oflag &= ~BSDLY;
695 data.term.c_oflag &= ~VTDLY;
698 data.term.c_oflag &= ~FFDLY;
701 data.term.c_oflag &= ~OFILL;
703 data.term.c_lflag &= ~(ISIG | ICANON | ECHO | IEXTEN);
704 data.term.c_cc[VMIN] = 0;
705 data.term.c_cc[VTIME] = 0;
707 /* Ignore modem status lines; enable receiver; leave control lines alone on close. */
708 data.term.c_cflag |= (CLOCAL | CREAD | HUPCL);
711 ret = set_config(port, &data, &config);
721 enum sp_return sp_close(struct sp_port *port)
727 DEBUG("Closing port %s", port->name);
730 /* Returns non-zero upon success, 0 upon failure. */
731 if (CloseHandle(port->hdl) == 0)
732 RETURN_FAIL("CloseHandle() failed");
733 port->hdl = INVALID_HANDLE_VALUE;
734 if (port->nonblocking) {
735 /* Close event handle created for overlapped writes. */
736 if (CloseHandle(port->write_ovl.hEvent) == 0)
737 RETURN_FAIL("CloseHandle() failed");
740 /* Returns 0 upon success, -1 upon failure. */
741 if (close(port->fd) == -1)
742 RETURN_FAIL("close() failed");
749 enum sp_return sp_flush(struct sp_port *port, enum sp_buffer buffers)
751 TRACE("%p, %x", port, buffers);
755 if (buffers > SP_BUF_BOTH)
756 RETURN_ERROR(SP_ERR_ARG, "Invalid buffer selection");
758 const char *buffer_names[] = {"no", "input", "output", "both"};
760 DEBUG("Flushing %s buffers on port %s", buffer_names[buffers], port->name);
764 if (buffers & SP_BUF_INPUT)
765 flags |= PURGE_RXCLEAR;
766 if (buffers & SP_BUF_OUTPUT)
767 flags |= PURGE_TXCLEAR;
769 /* Returns non-zero upon success, 0 upon failure. */
770 if (PurgeComm(port->hdl, flags) == 0)
771 RETURN_FAIL("PurgeComm() failed");
774 if (buffers & SP_BUF_BOTH)
776 else if (buffers & SP_BUF_INPUT)
778 else if (buffers & SP_BUF_OUTPUT)
781 /* Returns 0 upon success, -1 upon failure. */
782 if (tcflush(port->fd, flags) < 0)
783 RETURN_FAIL("tcflush() failed");
788 enum sp_return sp_drain(struct sp_port *port)
794 DEBUG("Draining port %s", port->name);
797 /* Returns non-zero upon success, 0 upon failure. */
798 if (FlushFileBuffers(port->hdl) == 0)
799 RETURN_FAIL("FlushFileBuffers() failed");
801 /* Returns 0 upon success, -1 upon failure. */
802 if (tcdrain(port->fd) < 0)
803 RETURN_FAIL("tcdrain() failed");
809 enum sp_return sp_write(struct sp_port *port, const void *buf, size_t count)
811 TRACE("%p, %p, %d", port, buf, count);
816 RETURN_ERROR(SP_ERR_ARG, "Null buffer");
818 DEBUG("Writing up to %d bytes to port %s", count, port->name);
821 RETURN_VALUE("0", 0);
825 BYTE *ptr = (BYTE *) buf;
827 if (port->nonblocking) {
828 /* Non-blocking write. */
830 /* Check whether previous write is complete. */
832 if (HasOverlappedIoCompleted(&port->write_ovl)) {
833 DEBUG("Previous write completed");
836 DEBUG("Previous write not complete");
837 /* Can't take a new write until the previous one finishes. */
838 RETURN_VALUE("0", 0);
842 /* Keep writing data until the OS has to actually start an async IO for it.
843 * At that point we know the buffer is full. */
844 while (written < count)
846 /* Copy first byte of user buffer. */
847 port->pending_byte = *ptr++;
849 /* Start asynchronous write. */
850 if (WriteFile(port->hdl, &port->pending_byte, 1, NULL, &port->write_ovl) == 0) {
851 if (GetLastError() == ERROR_IO_PENDING) {
852 DEBUG("Asynchronous write started");
854 RETURN_VALUE("%d", ++written);
856 /* Actual failure of some kind. */
857 RETURN_FAIL("WriteFile() failed");
860 DEBUG("Single byte written immediately.");
865 DEBUG("All bytes written immediately.");
868 /* Blocking write. */
869 if (WriteFile(port->hdl, buf, count, &written, NULL) == 0) {
870 RETURN_FAIL("WriteFile() failed");
874 RETURN_VALUE("%d", written);
876 /* Returns the number of bytes written, or -1 upon failure. */
877 ssize_t written = write(port->fd, buf, count);
880 RETURN_FAIL("write() failed");
882 RETURN_VALUE("%d", written);
886 enum sp_return sp_read(struct sp_port *port, void *buf, size_t count)
888 TRACE("%p, %p, %d", port, buf, count);
893 RETURN_ERROR(SP_ERR_ARG, "Null buffer");
895 DEBUG("Reading up to %d bytes from port %s", count, port->name);
898 DWORD bytes_read = 0;
900 /* Returns non-zero upon success, 0 upon failure. */
901 if (ReadFile(port->hdl, buf, count, &bytes_read, NULL) == 0)
902 RETURN_FAIL("ReadFile() failed");
903 RETURN_VALUE("%d", bytes_read);
907 /* Returns the number of bytes read, or -1 upon failure. */
908 if ((bytes_read = read(port->fd, buf, count)) < 0) {
909 if (port->nonblocking && errno == EAGAIN)
910 /* Port is opened in nonblocking mode and there are no bytes available. */
913 /* This is an actual failure. */
914 RETURN_FAIL("read() failed");
916 RETURN_VALUE("%d", bytes_read);
921 static enum sp_return get_baudrate(int fd, int *baudrate)
925 TRACE("%d, %p", fd, baudrate);
927 DEBUG("Getting baud rate");
929 if (!(data = malloc(get_termios_size())))
930 RETURN_ERROR(SP_ERR_MEM, "termios malloc failed");
932 if (ioctl(fd, get_termios_get_ioctl(), data) < 0) {
934 RETURN_FAIL("getting termios failed");
937 *baudrate = get_termios_speed(data);
944 static enum sp_return set_baudrate(int fd, int baudrate)
948 TRACE("%d, %d", fd, baudrate);
950 DEBUG("Getting baud rate");
952 if (!(data = malloc(get_termios_size())))
953 RETURN_ERROR(SP_ERR_MEM, "termios malloc failed");
955 if (ioctl(fd, get_termios_get_ioctl(), data) < 0) {
957 RETURN_FAIL("getting termios failed");
960 DEBUG("Setting baud rate");
962 set_termios_speed(data, baudrate);
964 if (ioctl(fd, get_termios_set_ioctl(), data) < 0) {
966 RETURN_FAIL("setting termios failed");
975 static enum sp_return get_flow(int fd, int *flow)
979 TRACE("%d, %p", fd, flow);
981 DEBUG("Getting advanced flow control");
983 if (!(data = malloc(get_termiox_size())))
984 RETURN_ERROR(SP_ERR_MEM, "termiox malloc failed");
986 if (ioctl(fd, TCGETX, data) < 0) {
988 RETURN_FAIL("getting termiox failed");
991 *flow = get_termiox_flow(data);
998 static enum sp_return set_flow(int fd, int flow)
1002 TRACE("%d, %d", fd, flow);
1004 DEBUG("Getting advanced flow control");
1006 if (!(data = malloc(get_termiox_size())))
1007 RETURN_ERROR(SP_ERR_MEM, "termiox malloc failed");
1009 if (ioctl(fd, TCGETX, data) < 0) {
1011 RETURN_FAIL("getting termiox failed");
1014 DEBUG("Setting advanced flow control");
1016 set_termiox_flow(data, flow);
1018 if (ioctl(fd, TCSETX, data) < 0) {
1020 RETURN_FAIL("setting termiox failed");
1027 #endif /* USE_TERMIOX */
1028 #endif /* __linux__ */
1030 static enum sp_return get_config(struct sp_port *port, struct port_data *data,
1031 struct sp_port_config *config)
1035 TRACE("%p, %p, %p", port, data, config);
1037 DEBUG("Getting configuration for port %s", port->name);
1040 if (!GetCommState(port->hdl, &data->dcb))
1041 RETURN_FAIL("GetCommState() failed");
1043 for (i = 0; i < NUM_STD_BAUDRATES; i++) {
1044 if (data->dcb.BaudRate == std_baudrates[i].index) {
1045 config->baudrate = std_baudrates[i].value;
1050 if (i == NUM_STD_BAUDRATES)
1051 /* BaudRate field can be either an index or a custom baud rate. */
1052 config->baudrate = data->dcb.BaudRate;
1054 config->bits = data->dcb.ByteSize;
1056 if (data->dcb.fParity)
1057 switch (data->dcb.Parity) {
1059 config->parity = SP_PARITY_NONE;
1062 config->parity = SP_PARITY_ODD;
1065 config->parity = SP_PARITY_EVEN;
1068 config->parity = SP_PARITY_MARK;
1071 config->parity = SP_PARITY_SPACE;
1074 config->parity = -1;
1077 config->parity = SP_PARITY_NONE;
1079 switch (data->dcb.StopBits) {
1081 config->stopbits = 1;
1084 config->stopbits = 2;
1087 config->stopbits = -1;
1090 switch (data->dcb.fRtsControl) {
1091 case RTS_CONTROL_DISABLE:
1092 config->rts = SP_RTS_OFF;
1094 case RTS_CONTROL_ENABLE:
1095 config->rts = SP_RTS_ON;
1097 case RTS_CONTROL_HANDSHAKE:
1098 config->rts = SP_RTS_FLOW_CONTROL;
1104 config->cts = data->dcb.fOutxCtsFlow ? SP_CTS_FLOW_CONTROL : SP_CTS_IGNORE;
1106 switch (data->dcb.fDtrControl) {
1107 case DTR_CONTROL_DISABLE:
1108 config->dtr = SP_DTR_OFF;
1110 case DTR_CONTROL_ENABLE:
1111 config->dtr = SP_DTR_ON;
1113 case DTR_CONTROL_HANDSHAKE:
1114 config->dtr = SP_DTR_FLOW_CONTROL;
1120 config->dsr = data->dcb.fOutxDsrFlow ? SP_DSR_FLOW_CONTROL : SP_DSR_IGNORE;
1122 if (data->dcb.fInX) {
1123 if (data->dcb.fOutX)
1124 config->xon_xoff = SP_XONXOFF_INOUT;
1126 config->xon_xoff = SP_XONXOFF_IN;
1128 if (data->dcb.fOutX)
1129 config->xon_xoff = SP_XONXOFF_OUT;
1131 config->xon_xoff = SP_XONXOFF_DISABLED;
1136 if (tcgetattr(port->fd, &data->term) < 0)
1137 RETURN_FAIL("tcgetattr() failed");
1139 if (ioctl(port->fd, TIOCMGET, &data->controlbits) < 0)
1140 RETURN_FAIL("TIOCMGET ioctl failed");
1143 int ret = get_flow(port->fd, &data->flow);
1145 if (ret == SP_ERR_FAIL && errno == EINVAL)
1146 data->termiox_supported = 0;
1148 RETURN_CODEVAL(ret);
1150 data->termiox_supported = 1;
1152 data->termiox_supported = 0;
1155 for (i = 0; i < NUM_STD_BAUDRATES; i++) {
1156 if (cfgetispeed(&data->term) == std_baudrates[i].index) {
1157 config->baudrate = std_baudrates[i].value;
1162 if (i == NUM_STD_BAUDRATES) {
1164 config->baudrate = (int)data->term.c_ispeed;
1165 #elif defined(__linux__)
1166 TRY(get_baudrate(port->fd, &config->baudrate));
1168 config->baudrate = -1;
1172 switch (data->term.c_cflag & CSIZE) {
1189 if (!(data->term.c_cflag & PARENB) && (data->term.c_iflag & IGNPAR))
1190 config->parity = SP_PARITY_NONE;
1191 else if (!(data->term.c_cflag & PARENB) || (data->term.c_iflag & IGNPAR))
1192 config->parity = -1;
1194 else if (data->term.c_cflag & CMSPAR)
1195 config->parity = (data->term.c_cflag & PARODD) ? SP_PARITY_MARK : SP_PARITY_SPACE;
1198 config->parity = (data->term.c_cflag & PARODD) ? SP_PARITY_ODD : SP_PARITY_EVEN;
1200 config->stopbits = (data->term.c_cflag & CSTOPB) ? 2 : 1;
1202 if (data->term.c_cflag & CRTSCTS) {
1203 config->rts = SP_RTS_FLOW_CONTROL;
1204 config->cts = SP_CTS_FLOW_CONTROL;
1206 if (data->termiox_supported && data->flow & RTS_FLOW)
1207 config->rts = SP_RTS_FLOW_CONTROL;
1209 config->rts = (data->controlbits & TIOCM_RTS) ? SP_RTS_ON : SP_RTS_OFF;
1211 config->cts = (data->termiox_supported && data->flow & CTS_FLOW) ?
1212 SP_CTS_FLOW_CONTROL : SP_CTS_IGNORE;
1215 if (data->termiox_supported && data->flow & DTR_FLOW)
1216 config->dtr = SP_DTR_FLOW_CONTROL;
1218 config->dtr = (data->controlbits & TIOCM_DTR) ? SP_DTR_ON : SP_DTR_OFF;
1220 config->dsr = (data->termiox_supported && data->flow & DSR_FLOW) ?
1221 SP_DSR_FLOW_CONTROL : SP_DSR_IGNORE;
1223 if (data->term.c_iflag & IXOFF) {
1224 if (data->term.c_iflag & IXON)
1225 config->xon_xoff = SP_XONXOFF_INOUT;
1227 config->xon_xoff = SP_XONXOFF_IN;
1229 if (data->term.c_iflag & IXON)
1230 config->xon_xoff = SP_XONXOFF_OUT;
1232 config->xon_xoff = SP_XONXOFF_DISABLED;
1239 static enum sp_return set_config(struct sp_port *port, struct port_data *data,
1240 const struct sp_port_config *config)
1244 BAUD_TYPE baud_nonstd;
1249 int baud_nonstd = 0;
1252 TRACE("%p, %p, %p", port, data, config);
1254 DEBUG("Setting configuration for port %s", port->name);
1257 if (config->baudrate >= 0) {
1258 for (i = 0; i < NUM_STD_BAUDRATES; i++) {
1259 if (config->baudrate == std_baudrates[i].value) {
1260 data->dcb.BaudRate = std_baudrates[i].index;
1265 if (i == NUM_STD_BAUDRATES)
1266 data->dcb.BaudRate = config->baudrate;
1269 if (config->bits >= 0)
1270 data->dcb.ByteSize = config->bits;
1272 if (config->parity >= 0) {
1273 switch (config->parity) {
1274 /* Note: There's also SPACEPARITY, MARKPARITY (unneeded so far). */
1275 case SP_PARITY_NONE:
1276 data->dcb.Parity = NOPARITY;
1279 data->dcb.Parity = ODDPARITY;
1281 case SP_PARITY_EVEN:
1282 data->dcb.Parity = EVENPARITY;
1284 case SP_PARITY_MARK:
1285 data->dcb.Parity = MARKPARITY;
1287 case SP_PARITY_SPACE:
1288 data->dcb.Parity = SPACEPARITY;
1291 RETURN_ERROR(SP_ERR_ARG, "Invalid parity setting");
1295 if (config->stopbits >= 0) {
1296 switch (config->stopbits) {
1297 /* Note: There's also ONE5STOPBITS == 1.5 (unneeded so far). */
1299 data->dcb.StopBits = ONESTOPBIT;
1302 data->dcb.StopBits = TWOSTOPBITS;
1305 RETURN_ERROR(SP_ERR_ARG, "Invalid stop bit setting");
1309 if (config->rts >= 0) {
1310 switch (config->rts) {
1312 data->dcb.fRtsControl = RTS_CONTROL_DISABLE;
1315 data->dcb.fRtsControl = RTS_CONTROL_ENABLE;
1317 case SP_RTS_FLOW_CONTROL:
1318 data->dcb.fRtsControl = RTS_CONTROL_HANDSHAKE;
1321 RETURN_ERROR(SP_ERR_ARG, "Invalid RTS setting");
1325 if (config->cts >= 0) {
1326 switch (config->cts) {
1328 data->dcb.fOutxCtsFlow = FALSE;
1330 case SP_CTS_FLOW_CONTROL:
1331 data->dcb.fOutxCtsFlow = TRUE;
1334 RETURN_ERROR(SP_ERR_ARG, "Invalid CTS setting");
1338 if (config->dtr >= 0) {
1339 switch (config->dtr) {
1341 data->dcb.fDtrControl = DTR_CONTROL_DISABLE;
1344 data->dcb.fDtrControl = DTR_CONTROL_ENABLE;
1346 case SP_DTR_FLOW_CONTROL:
1347 data->dcb.fDtrControl = DTR_CONTROL_HANDSHAKE;
1350 RETURN_ERROR(SP_ERR_ARG, "Invalid DTR setting");
1354 if (config->dsr >= 0) {
1355 switch (config->dsr) {
1357 data->dcb.fOutxDsrFlow = FALSE;
1359 case SP_DSR_FLOW_CONTROL:
1360 data->dcb.fOutxDsrFlow = TRUE;
1363 RETURN_ERROR(SP_ERR_ARG, "Invalid DSR setting");
1367 if (config->xon_xoff >= 0) {
1368 switch (config->xon_xoff) {
1369 case SP_XONXOFF_DISABLED:
1370 data->dcb.fInX = FALSE;
1371 data->dcb.fOutX = FALSE;
1374 data->dcb.fInX = TRUE;
1375 data->dcb.fOutX = FALSE;
1377 case SP_XONXOFF_OUT:
1378 data->dcb.fInX = FALSE;
1379 data->dcb.fOutX = TRUE;
1381 case SP_XONXOFF_INOUT:
1382 data->dcb.fInX = TRUE;
1383 data->dcb.fOutX = TRUE;
1386 RETURN_ERROR(SP_ERR_ARG, "Invalid XON/XOFF setting");
1390 if (!SetCommState(port->hdl, &data->dcb))
1391 RETURN_FAIL("SetCommState() failed");
1397 if (config->baudrate >= 0) {
1398 for (i = 0; i < NUM_STD_BAUDRATES; i++) {
1399 if (config->baudrate == std_baudrates[i].value) {
1400 if (cfsetospeed(&data->term, std_baudrates[i].index) < 0)
1401 RETURN_FAIL("cfsetospeed() failed");
1403 if (cfsetispeed(&data->term, std_baudrates[i].index) < 0)
1404 RETURN_FAIL("cfsetispeed() failed");
1409 /* Non-standard baud rate */
1410 if (i == NUM_STD_BAUDRATES) {
1412 /* Set "dummy" baud rate. */
1413 if (cfsetspeed(&data->term, B9600) < 0)
1414 RETURN_FAIL("cfsetspeed() failed");
1415 baud_nonstd = config->baudrate;
1416 #elif defined(__linux__)
1419 RETURN_ERROR(SP_ERR_SUPP, "Non-standard baudrate not supported");
1424 if (config->bits >= 0) {
1425 data->term.c_cflag &= ~CSIZE;
1426 switch (config->bits) {
1428 data->term.c_cflag |= CS8;
1431 data->term.c_cflag |= CS7;
1434 data->term.c_cflag |= CS6;
1437 data->term.c_cflag |= CS5;
1440 RETURN_ERROR(SP_ERR_ARG, "Invalid data bits setting");
1444 if (config->parity >= 0) {
1445 data->term.c_iflag &= ~IGNPAR;
1446 data->term.c_cflag &= ~(PARENB | PARODD);
1448 data->term.c_cflag &= ~CMSPAR;
1450 switch (config->parity) {
1451 case SP_PARITY_NONE:
1452 data->term.c_iflag |= IGNPAR;
1454 case SP_PARITY_EVEN:
1455 data->term.c_cflag |= PARENB;
1458 data->term.c_cflag |= PARENB | PARODD;
1460 case SP_PARITY_MARK:
1461 data->term.c_cflag |= PARENB | PARODD;
1463 data->term.c_cflag |= CMSPAR;
1466 case SP_PARITY_SPACE:
1467 data->term.c_cflag |= PARENB;
1469 data->term.c_cflag |= CMSPAR;
1473 RETURN_ERROR(SP_ERR_ARG, "Invalid parity setting");
1477 if (config->stopbits >= 0) {
1478 data->term.c_cflag &= ~CSTOPB;
1479 switch (config->stopbits) {
1481 data->term.c_cflag &= ~CSTOPB;
1484 data->term.c_cflag |= CSTOPB;
1487 RETURN_ERROR(SP_ERR_ARG, "Invalid stop bits setting");
1491 if (config->rts >= 0 || config->cts >= 0) {
1492 if (data->termiox_supported) {
1493 data->flow &= ~(RTS_FLOW | CTS_FLOW);
1494 switch (config->rts) {
1497 controlbits = TIOCM_RTS;
1498 if (ioctl(port->fd, config->rts == SP_RTS_ON ? TIOCMBIS : TIOCMBIC, &controlbits) < 0)
1499 RETURN_FAIL("Setting RTS signal level failed");
1501 case SP_RTS_FLOW_CONTROL:
1502 data->flow |= RTS_FLOW;
1507 if (config->cts == SP_CTS_FLOW_CONTROL)
1508 data->flow |= CTS_FLOW;
1510 if (data->flow & (RTS_FLOW | CTS_FLOW))
1511 data->term.c_iflag |= CRTSCTS;
1513 data->term.c_iflag &= ~CRTSCTS;
1515 /* Asymmetric use of RTS/CTS not supported. */
1516 if (data->term.c_iflag & CRTSCTS) {
1517 /* Flow control can only be disabled for both RTS & CTS together. */
1518 if (config->rts >= 0 && config->rts != SP_RTS_FLOW_CONTROL) {
1519 if (config->cts != SP_CTS_IGNORE)
1520 RETURN_ERROR(SP_ERR_SUPP, "RTS & CTS flow control must be disabled together");
1522 if (config->cts >= 0 && config->cts != SP_CTS_FLOW_CONTROL) {
1523 if (config->rts <= 0 || config->rts == SP_RTS_FLOW_CONTROL)
1524 RETURN_ERROR(SP_ERR_SUPP, "RTS & CTS flow control must be disabled together");
1527 /* Flow control can only be enabled for both RTS & CTS together. */
1528 if (((config->rts == SP_RTS_FLOW_CONTROL) && (config->cts != SP_CTS_FLOW_CONTROL)) ||
1529 ((config->cts == SP_CTS_FLOW_CONTROL) && (config->rts != SP_RTS_FLOW_CONTROL)))
1530 RETURN_ERROR(SP_ERR_SUPP, "RTS & CTS flow control must be enabled together");
1533 if (config->rts >= 0) {
1534 if (config->rts == SP_RTS_FLOW_CONTROL) {
1535 data->term.c_iflag |= CRTSCTS;
1537 controlbits = TIOCM_RTS;
1538 if (ioctl(port->fd, config->rts == SP_RTS_ON ? TIOCMBIS : TIOCMBIC,
1540 RETURN_FAIL("Setting RTS signal level failed");
1546 if (config->dtr >= 0 || config->dsr >= 0) {
1547 if (data->termiox_supported) {
1548 data->flow &= ~(DTR_FLOW | DSR_FLOW);
1549 switch (config->dtr) {
1552 controlbits = TIOCM_DTR;
1553 if (ioctl(port->fd, config->dtr == SP_DTR_ON ? TIOCMBIS : TIOCMBIC, &controlbits) < 0)
1554 RETURN_FAIL("Setting DTR signal level failed");
1556 case SP_DTR_FLOW_CONTROL:
1557 data->flow |= DTR_FLOW;
1562 if (config->dsr == SP_DSR_FLOW_CONTROL)
1563 data->flow |= DSR_FLOW;
1565 /* DTR/DSR flow control not supported. */
1566 if (config->dtr == SP_DTR_FLOW_CONTROL || config->dsr == SP_DSR_FLOW_CONTROL)
1567 RETURN_ERROR(SP_ERR_SUPP, "DTR/DSR flow control not supported");
1569 if (config->dtr >= 0) {
1570 controlbits = TIOCM_DTR;
1571 if (ioctl(port->fd, config->dtr == SP_DTR_ON ? TIOCMBIS : TIOCMBIC,
1573 RETURN_FAIL("Setting DTR signal level failed");
1578 if (config->xon_xoff >= 0) {
1579 data->term.c_iflag &= ~(IXON | IXOFF | IXANY);
1580 switch (config->xon_xoff) {
1581 case SP_XONXOFF_DISABLED:
1584 data->term.c_iflag |= IXOFF;
1586 case SP_XONXOFF_OUT:
1587 data->term.c_iflag |= IXON | IXANY;
1589 case SP_XONXOFF_INOUT:
1590 data->term.c_iflag |= IXON | IXOFF | IXANY;
1593 RETURN_ERROR(SP_ERR_ARG, "Invalid XON/XOFF setting");
1597 if (tcsetattr(port->fd, TCSANOW, &data->term) < 0)
1598 RETURN_FAIL("tcsetattr() failed");
1601 if (baud_nonstd != B0) {
1602 if (ioctl(port->fd, IOSSIOSPEED, &baud_nonstd) == -1)
1603 RETURN_FAIL("IOSSIOSPEED ioctl failed");
1604 /* Set baud rates in data->term to correct, but incompatible
1605 * with tcsetattr() value, same as delivered by tcgetattr(). */
1606 if (cfsetspeed(&data->term, baud_nonstd) < 0)
1607 RETURN_FAIL("cfsetspeed() failed");
1609 #elif defined(__linux__)
1611 TRY(set_baudrate(port->fd, config->baudrate));
1613 if (data->termiox_supported)
1614 TRY(set_flow(port->fd, data->flow));
1618 #endif /* !_WIN32 */
1623 enum sp_return sp_new_config(struct sp_port_config **config_ptr)
1625 TRACE("%p", config_ptr);
1626 struct sp_port_config *config;
1629 RETURN_ERROR(SP_ERR_ARG, "Null result pointer");
1633 if (!(config = malloc(sizeof(struct sp_port_config))))
1634 RETURN_ERROR(SP_ERR_MEM, "config malloc failed");
1636 config->baudrate = -1;
1638 config->parity = -1;
1639 config->stopbits = -1;
1645 *config_ptr = config;
1650 void sp_free_config(struct sp_port_config *config)
1652 TRACE("%p", config);
1655 DEBUG("Null config");
1662 enum sp_return sp_get_config(struct sp_port *port, struct sp_port_config *config)
1664 struct port_data data;
1666 TRACE("%p, %p", port, config);
1671 RETURN_ERROR(SP_ERR_ARG, "Null config");
1673 TRY(get_config(port, &data, config));
1678 enum sp_return sp_set_config(struct sp_port *port, const struct sp_port_config *config)
1680 struct port_data data;
1681 struct sp_port_config prev_config;
1683 TRACE("%p, %p", port, config);
1688 RETURN_ERROR(SP_ERR_ARG, "Null config");
1690 TRY(get_config(port, &data, &prev_config));
1691 TRY(set_config(port, &data, config));
1696 #define CREATE_ACCESSORS(x, type) \
1697 enum sp_return sp_set_##x(struct sp_port *port, type x) { \
1698 struct port_data data; \
1699 struct sp_port_config config; \
1700 TRACE("%p, %d", port, x); \
1701 CHECK_OPEN_PORT(); \
1702 TRY(get_config(port, &data, &config)); \
1704 TRY(set_config(port, &data, &config)); \
1707 enum sp_return sp_get_config_##x(const struct sp_port_config *config, type *x) { \
1708 TRACE("%p", config); \
1710 RETURN_ERROR(SP_ERR_ARG, "Null config"); \
1714 enum sp_return sp_set_config_##x(struct sp_port_config *config, type x) { \
1715 TRACE("%p, %d", config, x); \
1717 RETURN_ERROR(SP_ERR_ARG, "Null config"); \
1722 CREATE_ACCESSORS(baudrate, int)
1723 CREATE_ACCESSORS(bits, int)
1724 CREATE_ACCESSORS(parity, enum sp_parity)
1725 CREATE_ACCESSORS(stopbits, int)
1726 CREATE_ACCESSORS(rts, enum sp_rts)
1727 CREATE_ACCESSORS(cts, enum sp_cts)
1728 CREATE_ACCESSORS(dtr, enum sp_dtr)
1729 CREATE_ACCESSORS(dsr, enum sp_dsr)
1730 CREATE_ACCESSORS(xon_xoff, enum sp_xonxoff)
1732 enum sp_return sp_set_config_flowcontrol(struct sp_port_config *config, enum sp_flowcontrol flowcontrol)
1735 RETURN_ERROR(SP_ERR_ARG, "Null configuration");
1737 if (flowcontrol > SP_FLOWCONTROL_DTRDSR)
1738 RETURN_ERROR(SP_ERR_ARG, "Invalid flow control setting");
1740 if (flowcontrol == SP_FLOWCONTROL_XONXOFF)
1741 config->xon_xoff = SP_XONXOFF_INOUT;
1743 config->xon_xoff = SP_XONXOFF_DISABLED;
1745 if (flowcontrol == SP_FLOWCONTROL_RTSCTS) {
1746 config->rts = SP_RTS_FLOW_CONTROL;
1747 config->cts = SP_CTS_FLOW_CONTROL;
1749 if (config->rts == SP_RTS_FLOW_CONTROL)
1750 config->rts = SP_RTS_ON;
1751 config->cts = SP_CTS_IGNORE;
1754 if (flowcontrol == SP_FLOWCONTROL_DTRDSR) {
1755 config->dtr = SP_DTR_FLOW_CONTROL;
1756 config->dsr = SP_DSR_FLOW_CONTROL;
1758 if (config->dtr == SP_DTR_FLOW_CONTROL)
1759 config->dtr = SP_DTR_ON;
1760 config->dsr = SP_DSR_IGNORE;
1766 enum sp_return sp_set_flowcontrol(struct sp_port *port, enum sp_flowcontrol flowcontrol)
1768 struct port_data data;
1769 struct sp_port_config config;
1771 TRACE("%p, %d", port, flowcontrol);
1775 TRY(get_config(port, &data, &config));
1777 TRY(sp_set_config_flowcontrol(&config, flowcontrol));
1779 TRY(set_config(port, &data, &config));
1784 enum sp_return sp_get_signals(struct sp_port *port, enum sp_signal *signals)
1786 TRACE("%p, %p", port, signals);
1791 RETURN_ERROR(SP_ERR_ARG, "Null result pointer");
1793 DEBUG("Getting control signals for port %s", port->name);
1798 if (GetCommModemStatus(port->hdl, &bits) == 0)
1799 RETURN_FAIL("GetCommModemStatus() failed");
1800 if (bits & MS_CTS_ON)
1801 *signals |= SP_SIG_CTS;
1802 if (bits & MS_DSR_ON)
1803 *signals |= SP_SIG_DSR;
1804 if (bits & MS_RLSD_ON)
1805 *signals |= SP_SIG_DCD;
1806 if (bits & MS_RING_ON)
1807 *signals |= SP_SIG_RI;
1810 if (ioctl(port->fd, TIOCMGET, &bits) < 0)
1811 RETURN_FAIL("TIOCMGET ioctl failed");
1812 if (bits & TIOCM_CTS)
1813 *signals |= SP_SIG_CTS;
1814 if (bits & TIOCM_DSR)
1815 *signals |= SP_SIG_DSR;
1816 if (bits & TIOCM_CAR)
1817 *signals |= SP_SIG_DCD;
1818 if (bits & TIOCM_RNG)
1819 *signals |= SP_SIG_RI;
1824 enum sp_return sp_start_break(struct sp_port *port)
1830 if (SetCommBreak(port->hdl) == 0)
1831 RETURN_FAIL("SetCommBreak() failed");
1833 if (ioctl(port->fd, TIOCSBRK, 1) < 0)
1834 RETURN_FAIL("TIOCSBRK ioctl failed");
1840 enum sp_return sp_end_break(struct sp_port *port)
1846 if (ClearCommBreak(port->hdl) == 0)
1847 RETURN_FAIL("ClearCommBreak() failed");
1849 if (ioctl(port->fd, TIOCCBRK, 1) < 0)
1850 RETURN_FAIL("TIOCCBRK ioctl failed");
1856 int sp_last_error_code(void)
1860 RETURN_VALUE("%d", GetLastError());
1862 RETURN_VALUE("%d", errno);
1866 char *sp_last_error_message(void)
1872 DWORD error = GetLastError();
1875 FORMAT_MESSAGE_ALLOCATE_BUFFER |
1876 FORMAT_MESSAGE_FROM_SYSTEM |
1877 FORMAT_MESSAGE_IGNORE_INSERTS,
1880 MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
1884 RETURN_VALUE("%s", message);
1886 RETURN_VALUE("%s", strerror(errno));
1890 void sp_free_error_message(char *message)
1892 TRACE("%s", message);
1903 void sp_set_debug_handler(void (*handler)(const char *format, ...))
1905 TRACE("%p", handler);
1907 sp_debug_handler = handler;
1912 void sp_default_debug_handler(const char *format, ...)
1915 va_start(args, format);
1916 if (getenv("LIBSERIALPORT_DEBUG")) {
1917 fputs("libserialport: ", stderr);
1918 vfprintf(stderr, format, args);