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>
39 #include <sys/ioctl.h>
42 #include <IOKit/IOKitLib.h>
43 #include <IOKit/serial/IOSerialKeys.h>
44 #include <IOKit/serial/ioss.h>
45 #include <sys/syslimits.h>
49 #include "linux/serial.h"
50 #include "linux_termios.h"
51 #if defined(TCGETX) && defined(TCSETX) && defined(HAVE_TERMIOX)
57 #include "linux_termios.h"
60 #include "libserialport.h"
75 struct sp_port_config {
78 enum sp_parity parity;
84 enum sp_xonxoff xon_xoff;
93 int termiox_supported;
98 /* Standard baud rates. */
100 #define BAUD_TYPE DWORD
101 #define BAUD(n) {CBR_##n, n}
103 #define BAUD_TYPE speed_t
104 #define BAUD(n) {B##n, n}
107 struct std_baudrate {
112 const struct std_baudrate std_baudrates[] = {
115 * The baudrates 50/75/134/150/200/1800/230400/460800 do not seem to
116 * have documented CBR_* macros.
118 BAUD(110), BAUD(300), BAUD(600), BAUD(1200), BAUD(2400), BAUD(4800),
119 BAUD(9600), BAUD(14400), BAUD(19200), BAUD(38400), BAUD(57600),
120 BAUD(115200), BAUD(128000), BAUD(256000),
122 BAUD(50), BAUD(75), BAUD(110), BAUD(134), BAUD(150), BAUD(200),
123 BAUD(300), BAUD(600), BAUD(1200), BAUD(1800), BAUD(2400), BAUD(4800),
124 BAUD(9600), BAUD(19200), BAUD(38400), BAUD(57600), BAUD(115200),
126 #if !defined(__APPLE__) && !defined(__OpenBSD__)
132 void (*sp_debug_handler)(const char *format, ...) = sp_default_debug_handler;
134 #define ARRAY_SIZE(x) (sizeof(x) / sizeof(x[0]))
135 #define NUM_STD_BAUDRATES ARRAY_SIZE(std_baudrates)
137 /* Debug output macros. */
138 #define DEBUG(fmt, ...) do { if (sp_debug_handler) sp_debug_handler(fmt ".\n", ##__VA_ARGS__); } while (0)
139 #define DEBUG_ERROR(err, msg) DEBUG("%s returning " #err ": " msg, __func__)
140 #define DEBUG_FAIL(msg) do { \
141 char *errmsg = sp_last_error_message(); \
142 DEBUG("%s returning SP_ERR_FAIL: " msg ": %s", __func__, errmsg); \
143 sp_free_error_message(errmsg); \
145 #define RETURN() do { DEBUG("%s returning", __func__); return; } while(0)
146 #define RETURN_CODE(x) do { DEBUG("%s returning " #x, __func__); return x; } while (0)
147 #define RETURN_CODEVAL(x) do { \
149 case SP_OK: RETURN_CODE(SP_OK); \
150 case SP_ERR_ARG: RETURN_CODE(SP_ERR_ARG); \
151 case SP_ERR_FAIL: RETURN_CODE(SP_ERR_FAIL); \
152 case SP_ERR_MEM: RETURN_CODE(SP_ERR_MEM); \
153 case SP_ERR_SUPP: RETURN_CODE(SP_ERR_SUPP); \
156 #define RETURN_OK() RETURN_CODE(SP_OK);
157 #define RETURN_ERROR(err, msg) do { DEBUG_ERROR(err, msg); return err; } while (0)
158 #define RETURN_FAIL(msg) do { DEBUG_FAIL(msg); return SP_ERR_FAIL; } while (0)
159 #define RETURN_VALUE(fmt, x) do { DEBUG("%s returning " fmt, __func__, x); return x; } while (0)
160 #define SET_ERROR(val, err, msg) do { DEBUG_ERROR(err, msg); val = err; } while (0)
161 #define SET_FAIL(val, msg) do { DEBUG_FAIL(msg); val = SP_ERR_FAIL; } while (0)
162 #define TRACE(fmt, ...) DEBUG("%s(" fmt ") called", __func__, ##__VA_ARGS__)
164 #define TRY(x) do { int ret = x; if (ret != SP_OK) RETURN_CODEVAL(ret); } while (0)
166 /* Helper functions. */
167 static struct sp_port **list_append(struct sp_port **list, const char *portname);
168 static enum sp_return get_config(struct sp_port *port, struct port_data *data,
169 struct sp_port_config *config);
170 static enum sp_return set_config(struct sp_port *port, struct port_data *data,
171 const struct sp_port_config *config);
173 enum sp_return sp_get_port_by_name(const char *portname, struct sp_port **port_ptr)
175 struct sp_port *port;
178 TRACE("%s, %p", portname, port_ptr);
181 RETURN_ERROR(SP_ERR_ARG, "Null result pointer");
186 RETURN_ERROR(SP_ERR_ARG, "Null port name");
188 DEBUG("Building structure for port %s", portname);
190 if (!(port = malloc(sizeof(struct sp_port))))
191 RETURN_ERROR(SP_ERR_MEM, "Port structure malloc failed");
193 len = strlen(portname) + 1;
195 if (!(port->name = malloc(len))) {
197 RETURN_ERROR(SP_ERR_MEM, "Port name malloc failed");
200 memcpy(port->name, portname, len);
203 port->hdl = INVALID_HANDLE_VALUE;
213 char *sp_get_port_name(const struct sp_port *port)
220 RETURN_VALUE("%s", port->name);
223 enum sp_return sp_get_port_handle(const struct sp_port *port, void *result_ptr)
225 TRACE("%p, %p", port, result_ptr);
228 RETURN_ERROR(SP_ERR_ARG, "Null port");
231 HANDLE *handle_ptr = result_ptr;
232 *handle_ptr = port->hdl;
234 int *fd_ptr = result_ptr;
241 enum sp_return sp_copy_port(const struct sp_port *port, struct sp_port **copy_ptr)
243 TRACE("%p, %p", port, copy_ptr);
246 RETURN_ERROR(SP_ERR_ARG, "Null result pointer");
251 RETURN_ERROR(SP_ERR_ARG, "Null port");
254 RETURN_ERROR(SP_ERR_ARG, "Null port name");
256 DEBUG("Copying port structure");
258 RETURN_VALUE("%p", sp_get_port_by_name(port->name, copy_ptr));
261 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, 0x%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] = 1;
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, 0x%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;
1461 case SP_PARITY_MARK:
1462 data->term.c_cflag |= PARENB | PARODD;
1463 data->term.c_cflag |= CMSPAR;
1465 case SP_PARITY_SPACE:
1466 data->term.c_cflag |= PARENB;
1467 data->term.c_cflag |= CMSPAR;
1470 case SP_PARITY_MARK:
1471 case SP_PARITY_SPACE:
1472 RETURN_ERROR(SP_ERR_SUPP, "Mark/space parity not supported");
1475 RETURN_ERROR(SP_ERR_ARG, "Invalid parity setting");
1479 if (config->stopbits >= 0) {
1480 data->term.c_cflag &= ~CSTOPB;
1481 switch (config->stopbits) {
1483 data->term.c_cflag &= ~CSTOPB;
1486 data->term.c_cflag |= CSTOPB;
1489 RETURN_ERROR(SP_ERR_ARG, "Invalid stop bits setting");
1493 if (config->rts >= 0 || config->cts >= 0) {
1494 if (data->termiox_supported) {
1495 data->flow &= ~(RTS_FLOW | CTS_FLOW);
1496 switch (config->rts) {
1499 controlbits = TIOCM_RTS;
1500 if (ioctl(port->fd, config->rts == SP_RTS_ON ? TIOCMBIS : TIOCMBIC, &controlbits) < 0)
1501 RETURN_FAIL("Setting RTS signal level failed");
1503 case SP_RTS_FLOW_CONTROL:
1504 data->flow |= RTS_FLOW;
1509 if (config->cts == SP_CTS_FLOW_CONTROL)
1510 data->flow |= CTS_FLOW;
1512 if (data->flow & (RTS_FLOW | CTS_FLOW))
1513 data->term.c_iflag |= CRTSCTS;
1515 data->term.c_iflag &= ~CRTSCTS;
1517 /* Asymmetric use of RTS/CTS not supported. */
1518 if (data->term.c_iflag & CRTSCTS) {
1519 /* Flow control can only be disabled for both RTS & CTS together. */
1520 if (config->rts >= 0 && config->rts != SP_RTS_FLOW_CONTROL) {
1521 if (config->cts != SP_CTS_IGNORE)
1522 RETURN_ERROR(SP_ERR_SUPP, "RTS & CTS flow control must be disabled together");
1524 if (config->cts >= 0 && config->cts != SP_CTS_FLOW_CONTROL) {
1525 if (config->rts <= 0 || config->rts == SP_RTS_FLOW_CONTROL)
1526 RETURN_ERROR(SP_ERR_SUPP, "RTS & CTS flow control must be disabled together");
1529 /* Flow control can only be enabled for both RTS & CTS together. */
1530 if (((config->rts == SP_RTS_FLOW_CONTROL) && (config->cts != SP_CTS_FLOW_CONTROL)) ||
1531 ((config->cts == SP_CTS_FLOW_CONTROL) && (config->rts != SP_RTS_FLOW_CONTROL)))
1532 RETURN_ERROR(SP_ERR_SUPP, "RTS & CTS flow control must be enabled together");
1535 if (config->rts >= 0) {
1536 if (config->rts == SP_RTS_FLOW_CONTROL) {
1537 data->term.c_iflag |= CRTSCTS;
1539 controlbits = TIOCM_RTS;
1540 if (ioctl(port->fd, config->rts == SP_RTS_ON ? TIOCMBIS : TIOCMBIC,
1542 RETURN_FAIL("Setting RTS signal level failed");
1548 if (config->dtr >= 0 || config->dsr >= 0) {
1549 if (data->termiox_supported) {
1550 data->flow &= ~(DTR_FLOW | DSR_FLOW);
1551 switch (config->dtr) {
1554 controlbits = TIOCM_DTR;
1555 if (ioctl(port->fd, config->dtr == SP_DTR_ON ? TIOCMBIS : TIOCMBIC, &controlbits) < 0)
1556 RETURN_FAIL("Setting DTR signal level failed");
1558 case SP_DTR_FLOW_CONTROL:
1559 data->flow |= DTR_FLOW;
1564 if (config->dsr == SP_DSR_FLOW_CONTROL)
1565 data->flow |= DSR_FLOW;
1567 /* DTR/DSR flow control not supported. */
1568 if (config->dtr == SP_DTR_FLOW_CONTROL || config->dsr == SP_DSR_FLOW_CONTROL)
1569 RETURN_ERROR(SP_ERR_SUPP, "DTR/DSR flow control not supported");
1571 if (config->dtr >= 0) {
1572 controlbits = TIOCM_DTR;
1573 if (ioctl(port->fd, config->dtr == SP_DTR_ON ? TIOCMBIS : TIOCMBIC,
1575 RETURN_FAIL("Setting DTR signal level failed");
1580 if (config->xon_xoff >= 0) {
1581 data->term.c_iflag &= ~(IXON | IXOFF | IXANY);
1582 switch (config->xon_xoff) {
1583 case SP_XONXOFF_DISABLED:
1586 data->term.c_iflag |= IXOFF;
1588 case SP_XONXOFF_OUT:
1589 data->term.c_iflag |= IXON | IXANY;
1591 case SP_XONXOFF_INOUT:
1592 data->term.c_iflag |= IXON | IXOFF | IXANY;
1595 RETURN_ERROR(SP_ERR_ARG, "Invalid XON/XOFF setting");
1599 if (tcsetattr(port->fd, TCSANOW, &data->term) < 0)
1600 RETURN_FAIL("tcsetattr() failed");
1603 if (baud_nonstd != B0) {
1604 if (ioctl(port->fd, IOSSIOSPEED, &baud_nonstd) == -1)
1605 RETURN_FAIL("IOSSIOSPEED ioctl failed");
1606 /* Set baud rates in data->term to correct, but incompatible
1607 * with tcsetattr() value, same as delivered by tcgetattr(). */
1608 if (cfsetspeed(&data->term, baud_nonstd) < 0)
1609 RETURN_FAIL("cfsetspeed() failed");
1611 #elif defined(__linux__)
1613 TRY(set_baudrate(port->fd, config->baudrate));
1615 if (data->termiox_supported)
1616 TRY(set_flow(port->fd, data->flow));
1620 #endif /* !_WIN32 */
1625 enum sp_return sp_new_config(struct sp_port_config **config_ptr)
1627 struct sp_port_config *config;
1629 TRACE("%p", config_ptr);
1632 RETURN_ERROR(SP_ERR_ARG, "Null result pointer");
1636 if (!(config = malloc(sizeof(struct sp_port_config))))
1637 RETURN_ERROR(SP_ERR_MEM, "config malloc failed");
1639 config->baudrate = -1;
1641 config->parity = -1;
1642 config->stopbits = -1;
1648 *config_ptr = config;
1653 void sp_free_config(struct sp_port_config *config)
1655 TRACE("%p", config);
1658 DEBUG("Null config");
1665 enum sp_return sp_get_config(struct sp_port *port, struct sp_port_config *config)
1667 struct port_data data;
1669 TRACE("%p, %p", port, config);
1674 RETURN_ERROR(SP_ERR_ARG, "Null config");
1676 TRY(get_config(port, &data, config));
1681 enum sp_return sp_set_config(struct sp_port *port, const struct sp_port_config *config)
1683 struct port_data data;
1684 struct sp_port_config prev_config;
1686 TRACE("%p, %p", port, config);
1691 RETURN_ERROR(SP_ERR_ARG, "Null config");
1693 TRY(get_config(port, &data, &prev_config));
1694 TRY(set_config(port, &data, config));
1699 #define CREATE_ACCESSORS(x, type) \
1700 enum sp_return sp_set_##x(struct sp_port *port, type x) { \
1701 struct port_data data; \
1702 struct sp_port_config config; \
1703 TRACE("%p, %d", port, x); \
1704 CHECK_OPEN_PORT(); \
1705 TRY(get_config(port, &data, &config)); \
1707 TRY(set_config(port, &data, &config)); \
1710 enum sp_return sp_get_config_##x(const struct sp_port_config *config, type *x) { \
1711 TRACE("%p, %p", config, x); \
1713 RETURN_ERROR(SP_ERR_ARG, "Null config"); \
1717 enum sp_return sp_set_config_##x(struct sp_port_config *config, type x) { \
1718 TRACE("%p, %d", config, x); \
1720 RETURN_ERROR(SP_ERR_ARG, "Null config"); \
1725 CREATE_ACCESSORS(baudrate, int)
1726 CREATE_ACCESSORS(bits, int)
1727 CREATE_ACCESSORS(parity, enum sp_parity)
1728 CREATE_ACCESSORS(stopbits, int)
1729 CREATE_ACCESSORS(rts, enum sp_rts)
1730 CREATE_ACCESSORS(cts, enum sp_cts)
1731 CREATE_ACCESSORS(dtr, enum sp_dtr)
1732 CREATE_ACCESSORS(dsr, enum sp_dsr)
1733 CREATE_ACCESSORS(xon_xoff, enum sp_xonxoff)
1735 enum sp_return sp_set_config_flowcontrol(struct sp_port_config *config, enum sp_flowcontrol flowcontrol)
1738 RETURN_ERROR(SP_ERR_ARG, "Null configuration");
1740 if (flowcontrol > SP_FLOWCONTROL_DTRDSR)
1741 RETURN_ERROR(SP_ERR_ARG, "Invalid flow control setting");
1743 if (flowcontrol == SP_FLOWCONTROL_XONXOFF)
1744 config->xon_xoff = SP_XONXOFF_INOUT;
1746 config->xon_xoff = SP_XONXOFF_DISABLED;
1748 if (flowcontrol == SP_FLOWCONTROL_RTSCTS) {
1749 config->rts = SP_RTS_FLOW_CONTROL;
1750 config->cts = SP_CTS_FLOW_CONTROL;
1752 if (config->rts == SP_RTS_FLOW_CONTROL)
1753 config->rts = SP_RTS_ON;
1754 config->cts = SP_CTS_IGNORE;
1757 if (flowcontrol == SP_FLOWCONTROL_DTRDSR) {
1758 config->dtr = SP_DTR_FLOW_CONTROL;
1759 config->dsr = SP_DSR_FLOW_CONTROL;
1761 if (config->dtr == SP_DTR_FLOW_CONTROL)
1762 config->dtr = SP_DTR_ON;
1763 config->dsr = SP_DSR_IGNORE;
1769 enum sp_return sp_set_flowcontrol(struct sp_port *port, enum sp_flowcontrol flowcontrol)
1771 struct port_data data;
1772 struct sp_port_config config;
1774 TRACE("%p, %d", port, flowcontrol);
1778 TRY(get_config(port, &data, &config));
1780 TRY(sp_set_config_flowcontrol(&config, flowcontrol));
1782 TRY(set_config(port, &data, &config));
1787 enum sp_return sp_get_signals(struct sp_port *port, enum sp_signal *signals)
1789 TRACE("%p, %p", port, signals);
1794 RETURN_ERROR(SP_ERR_ARG, "Null result pointer");
1796 DEBUG("Getting control signals for port %s", port->name);
1801 if (GetCommModemStatus(port->hdl, &bits) == 0)
1802 RETURN_FAIL("GetCommModemStatus() failed");
1803 if (bits & MS_CTS_ON)
1804 *signals |= SP_SIG_CTS;
1805 if (bits & MS_DSR_ON)
1806 *signals |= SP_SIG_DSR;
1807 if (bits & MS_RLSD_ON)
1808 *signals |= SP_SIG_DCD;
1809 if (bits & MS_RING_ON)
1810 *signals |= SP_SIG_RI;
1813 if (ioctl(port->fd, TIOCMGET, &bits) < 0)
1814 RETURN_FAIL("TIOCMGET ioctl failed");
1815 if (bits & TIOCM_CTS)
1816 *signals |= SP_SIG_CTS;
1817 if (bits & TIOCM_DSR)
1818 *signals |= SP_SIG_DSR;
1819 if (bits & TIOCM_CAR)
1820 *signals |= SP_SIG_DCD;
1821 if (bits & TIOCM_RNG)
1822 *signals |= SP_SIG_RI;
1827 enum sp_return sp_start_break(struct sp_port *port)
1833 if (SetCommBreak(port->hdl) == 0)
1834 RETURN_FAIL("SetCommBreak() failed");
1836 if (ioctl(port->fd, TIOCSBRK, 1) < 0)
1837 RETURN_FAIL("TIOCSBRK ioctl failed");
1843 enum sp_return sp_end_break(struct sp_port *port)
1849 if (ClearCommBreak(port->hdl) == 0)
1850 RETURN_FAIL("ClearCommBreak() failed");
1852 if (ioctl(port->fd, TIOCCBRK, 1) < 0)
1853 RETURN_FAIL("TIOCCBRK ioctl failed");
1859 int sp_last_error_code(void)
1863 RETURN_VALUE("%d", GetLastError());
1865 RETURN_VALUE("%d", errno);
1869 char *sp_last_error_message(void)
1875 DWORD error = GetLastError();
1878 FORMAT_MESSAGE_ALLOCATE_BUFFER |
1879 FORMAT_MESSAGE_FROM_SYSTEM |
1880 FORMAT_MESSAGE_IGNORE_INSERTS,
1883 MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
1887 RETURN_VALUE("%s", message);
1889 RETURN_VALUE("%s", strerror(errno));
1893 void sp_free_error_message(char *message)
1895 TRACE("%s", message);
1906 void sp_set_debug_handler(void (*handler)(const char *format, ...))
1908 TRACE("%p", handler);
1910 sp_debug_handler = handler;
1915 void sp_default_debug_handler(const char *format, ...)
1918 va_start(args, format);
1919 if (getenv("LIBSERIALPORT_DEBUG")) {
1920 fputs("sp: ", stderr);
1921 vfprintf(stderr, format, args);