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 TRACE("%p, %x", port, flags);
580 if (flags > (SP_MODE_READ | SP_MODE_WRITE | SP_MODE_NONBLOCK))
581 RETURN_ERROR(SP_ERR_ARG, "Invalid flags");
583 DEBUG("Opening port %s", port->name);
585 port->nonblocking = (flags & SP_MODE_NONBLOCK) ? 1 : 0;
588 DWORD desired_access = 0, flags_and_attributes = 0;
589 COMMTIMEOUTS timeouts;
590 char *escaped_port_name;
592 /* Prefix port name with '\\.\' to work with ports above COM9. */
593 if (!(escaped_port_name = malloc(strlen(port->name + 5))))
594 RETURN_ERROR(SP_ERR_MEM, "Escaped port name malloc failed");
595 sprintf(escaped_port_name, "\\\\.\\%s", port->name);
597 /* Map 'flags' to the OS-specific settings. */
598 flags_and_attributes = FILE_ATTRIBUTE_NORMAL;
599 if (flags & SP_MODE_READ)
600 desired_access |= GENERIC_READ;
601 if (flags & SP_MODE_WRITE)
602 desired_access |= GENERIC_WRITE;
603 if (flags & SP_MODE_NONBLOCK)
604 flags_and_attributes |= FILE_FLAG_OVERLAPPED;
606 port->hdl = CreateFile(escaped_port_name, desired_access, 0, 0,
607 OPEN_EXISTING, flags_and_attributes, 0);
609 free(escaped_port_name);
611 if (port->hdl == INVALID_HANDLE_VALUE)
612 RETURN_FAIL("CreateFile() failed");
614 /* All timeouts disabled. */
615 timeouts.ReadIntervalTimeout = 0;
616 timeouts.ReadTotalTimeoutMultiplier = 0;
617 timeouts.ReadTotalTimeoutConstant = 0;
618 timeouts.WriteTotalTimeoutMultiplier = 0;
619 timeouts.WriteTotalTimeoutConstant = 0;
621 if (port->nonblocking) {
622 /* Set read timeout such that all reads return immediately. */
623 timeouts.ReadIntervalTimeout = MAXDWORD;
624 /* Prepare OVERLAPPED structure for non-blocking writes. */
625 memset(&port->write_ovl, 0, sizeof(port->write_ovl));
626 if (!(port->write_ovl.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL))) {
628 RETURN_FAIL("CreateEvent() failed");
630 port->writing = FALSE;
633 if (SetCommTimeouts(port->hdl, &timeouts) == 0) {
635 RETURN_FAIL("SetCommTimeouts() failed");
639 struct port_data data;
640 struct sp_port_config config;
643 /* Map 'flags' to the OS-specific settings. */
644 if (flags & (SP_MODE_READ | SP_MODE_WRITE))
645 flags_local |= O_RDWR;
646 else if (flags & SP_MODE_READ)
647 flags_local |= O_RDONLY;
648 else if (flags & SP_MODE_WRITE)
649 flags_local |= O_WRONLY;
650 if (flags & SP_MODE_NONBLOCK)
651 flags_local |= O_NONBLOCK;
653 if ((port->fd = open(port->name, flags_local)) < 0)
654 RETURN_FAIL("open() failed");
656 ret = get_config(port, &data, &config);
663 /* Turn off all fancy termios tricks, give us a raw channel. */
664 data.term.c_iflag &= ~(IGNBRK|BRKINT|PARMRK|ISTRIP|INLCR|IGNCR|ICRNL|IUCLC|IMAXBEL);
665 data.term.c_oflag &= ~(OPOST|OLCUC|ONLCR|OCRNL|ONOCR|ONLRET|NLDLY|CRDLY|TABDLY|BSDLY|VTDLY|FFDLY);
667 data.term.c_oflag &= ~OFILL;
669 data.term.c_lflag &= ~(ISIG|ICANON|ECHO|IEXTEN);
670 data.term.c_cc[VMIN] = 0;
671 data.term.c_cc[VTIME] = 0;
673 /* Ignore modem status lines; enable receiver; leave control lines alone on close. */
674 data.term.c_cflag |= (CLOCAL | CREAD | HUPCL);
676 ret = set_config(port, &data, &config);
687 enum sp_return sp_close(struct sp_port *port)
693 DEBUG("Closing port %s", port->name);
696 /* Returns non-zero upon success, 0 upon failure. */
697 if (CloseHandle(port->hdl) == 0)
698 RETURN_FAIL("CloseHandle() failed");
699 port->hdl = INVALID_HANDLE_VALUE;
700 if (port->nonblocking) {
701 /* Close event handle created for overlapped writes. */
702 if (CloseHandle(port->write_ovl.hEvent) == 0)
703 RETURN_FAIL("CloseHandle() failed");
706 /* Returns 0 upon success, -1 upon failure. */
707 if (close(port->fd) == -1)
708 RETURN_FAIL("close() failed");
715 enum sp_return sp_flush(struct sp_port *port, enum sp_buffer buffers)
717 TRACE("%p, %x", port, buffers);
721 if (buffers > SP_BUF_BOTH)
722 RETURN_ERROR(SP_ERR_ARG, "Invalid buffer selection");
724 const char *buffer_names[] = {"no", "input", "output", "both"};
726 DEBUG("Flushing %s buffers on port %s", buffer_names[buffers], port->name);
730 if (buffers & SP_BUF_INPUT)
731 flags |= PURGE_RXCLEAR;
732 if (buffers & SP_BUF_OUTPUT)
733 flags |= PURGE_TXCLEAR;
735 /* Returns non-zero upon success, 0 upon failure. */
736 if (PurgeComm(port->hdl, flags) == 0)
737 RETURN_FAIL("PurgeComm() failed");
740 if (buffers & SP_BUF_BOTH)
742 else if (buffers & SP_BUF_INPUT)
744 else if (buffers & SP_BUF_OUTPUT)
747 /* Returns 0 upon success, -1 upon failure. */
748 if (tcflush(port->fd, flags) < 0)
749 RETURN_FAIL("tcflush() failed");
754 enum sp_return sp_drain(struct sp_port *port)
760 DEBUG("Draining port %s", port->name);
763 /* Returns non-zero upon success, 0 upon failure. */
764 if (FlushFileBuffers(port->hdl) == 0)
765 RETURN_FAIL("FlushFileBuffers() failed");
767 /* Returns 0 upon success, -1 upon failure. */
768 if (tcdrain(port->fd) < 0)
769 RETURN_FAIL("tcdrain() failed");
775 enum sp_return sp_write(struct sp_port *port, const void *buf, size_t count)
777 TRACE("%p, %p, %d", port, buf, count);
782 RETURN_ERROR(SP_ERR_ARG, "Null buffer");
784 DEBUG("Writing up to %d bytes to port %s", count, port->name);
787 RETURN_VALUE("0", 0);
791 BYTE *ptr = (BYTE *) buf;
793 if (port->nonblocking) {
794 /* Non-blocking write. */
796 /* Check whether previous write is complete. */
798 if (HasOverlappedIoCompleted(&port->write_ovl)) {
799 DEBUG("Previous write completed");
802 DEBUG("Previous write not complete");
803 /* Can't take a new write until the previous one finishes. */
804 RETURN_VALUE("0", 0);
808 /* Keep writing data until the OS has to actually start an async IO for it.
809 * At that point we know the buffer is full. */
810 while (written < count)
812 /* Copy first byte of user buffer. */
813 port->pending_byte = *ptr++;
815 /* Start asynchronous write. */
816 if (WriteFile(port->hdl, &port->pending_byte, 1, NULL, &port->write_ovl) == 0) {
817 if (GetLastError() == ERROR_IO_PENDING) {
818 DEBUG("Asynchronous write started");
820 RETURN_VALUE("%d", ++written);
822 /* Actual failure of some kind. */
823 RETURN_FAIL("WriteFile() failed");
826 DEBUG("Single byte written immediately.");
831 DEBUG("All bytes written immediately.");
834 /* Blocking write. */
835 if (WriteFile(port->hdl, buf, count, &written, NULL) == 0) {
836 RETURN_FAIL("WriteFile() failed");
840 RETURN_VALUE("%d", written);
842 /* Returns the number of bytes written, or -1 upon failure. */
843 ssize_t written = write(port->fd, buf, count);
846 RETURN_FAIL("write() failed");
848 RETURN_VALUE("%d", written);
852 enum sp_return sp_read(struct sp_port *port, void *buf, size_t count)
854 TRACE("%p, %p, %d", port, buf, count);
859 RETURN_ERROR(SP_ERR_ARG, "Null buffer");
861 DEBUG("Reading up to %d bytes from port %s", count, port->name);
864 DWORD bytes_read = 0;
866 /* Returns non-zero upon success, 0 upon failure. */
867 if (ReadFile(port->hdl, buf, count, &bytes_read, NULL) == 0)
868 RETURN_FAIL("ReadFile() failed");
869 RETURN_VALUE("%d", bytes_read);
873 /* Returns the number of bytes read, or -1 upon failure. */
874 if ((bytes_read = read(port->fd, buf, count)) < 0) {
875 if (port->nonblocking && errno == EAGAIN)
876 /* Port is opened in nonblocking mode and there are no bytes available. */
879 /* This is an actual failure. */
880 RETURN_FAIL("read() failed");
882 RETURN_VALUE("%d", bytes_read);
887 static enum sp_return get_baudrate(int fd, int *baudrate)
891 TRACE("%d, %p", fd, baudrate);
893 DEBUG("Getting baud rate");
895 if (!(data = malloc(get_termios_size())))
896 RETURN_ERROR(SP_ERR_MEM, "termios malloc failed");
898 if (ioctl(fd, get_termios_get_ioctl(), data) < 0) {
900 RETURN_FAIL("getting termios failed");
903 *baudrate = get_termios_speed(data);
910 static enum sp_return set_baudrate(int fd, int baudrate)
914 TRACE("%d, %d", fd, baudrate);
916 DEBUG("Getting baud rate");
918 if (!(data = malloc(get_termios_size())))
919 RETURN_ERROR(SP_ERR_MEM, "termios malloc failed");
921 if (ioctl(fd, get_termios_get_ioctl(), data) < 0) {
923 RETURN_FAIL("getting termios failed");
926 DEBUG("Setting baud rate");
928 set_termios_speed(data, baudrate);
930 if (ioctl(fd, get_termios_set_ioctl(), data) < 0) {
932 RETURN_FAIL("setting termios failed");
941 static enum sp_return get_flow(int fd, int *flow)
945 TRACE("%d, %p", fd, flow);
947 DEBUG("Getting advanced flow control");
949 if (!(data = malloc(get_termiox_size())))
950 RETURN_ERROR(SP_ERR_MEM, "termiox malloc failed");
952 if (ioctl(fd, TCGETX, data) < 0) {
954 RETURN_FAIL("getting termiox failed");
957 *flow = get_termiox_flow(data);
964 static enum sp_return set_flow(int fd, int flow)
968 TRACE("%d, %d", fd, flow);
970 DEBUG("Getting advanced flow control");
972 if (!(data = malloc(get_termiox_size())))
973 RETURN_ERROR(SP_ERR_MEM, "termiox malloc failed");
975 if (ioctl(fd, TCGETX, data) < 0) {
977 RETURN_FAIL("getting termiox failed");
980 DEBUG("Setting advanced flow control");
982 set_termiox_flow(data, flow);
984 if (ioctl(fd, TCSETX, data) < 0) {
986 RETURN_FAIL("setting termiox failed");
993 #endif /* USE_TERMIOX */
994 #endif /* __linux__ */
996 static enum sp_return get_config(struct sp_port *port, struct port_data *data,
997 struct sp_port_config *config)
1001 TRACE("%p, %p, %p", port, data, config);
1003 DEBUG("Getting configuration for port %s", port->name);
1006 if (!GetCommState(port->hdl, &data->dcb))
1007 RETURN_FAIL("GetCommState() failed");
1009 for (i = 0; i < NUM_STD_BAUDRATES; i++) {
1010 if (data->dcb.BaudRate == std_baudrates[i].index) {
1011 config->baudrate = std_baudrates[i].value;
1016 if (i == NUM_STD_BAUDRATES)
1017 /* BaudRate field can be either an index or a custom baud rate. */
1018 config->baudrate = data->dcb.BaudRate;
1020 config->bits = data->dcb.ByteSize;
1022 if (data->dcb.fParity)
1023 switch (data->dcb.Parity) {
1025 config->parity = SP_PARITY_NONE;
1028 config->parity = SP_PARITY_ODD;
1031 config->parity = SP_PARITY_EVEN;
1034 config->parity = SP_PARITY_MARK;
1037 config->parity = SP_PARITY_SPACE;
1040 config->parity = -1;
1043 config->parity = SP_PARITY_NONE;
1045 switch (data->dcb.StopBits) {
1047 config->stopbits = 1;
1050 config->stopbits = 2;
1053 config->stopbits = -1;
1056 switch (data->dcb.fRtsControl) {
1057 case RTS_CONTROL_DISABLE:
1058 config->rts = SP_RTS_OFF;
1060 case RTS_CONTROL_ENABLE:
1061 config->rts = SP_RTS_ON;
1063 case RTS_CONTROL_HANDSHAKE:
1064 config->rts = SP_RTS_FLOW_CONTROL;
1070 config->cts = data->dcb.fOutxCtsFlow ? SP_CTS_FLOW_CONTROL : SP_CTS_IGNORE;
1072 switch (data->dcb.fDtrControl) {
1073 case DTR_CONTROL_DISABLE:
1074 config->dtr = SP_DTR_OFF;
1076 case DTR_CONTROL_ENABLE:
1077 config->dtr = SP_DTR_ON;
1079 case DTR_CONTROL_HANDSHAKE:
1080 config->dtr = SP_DTR_FLOW_CONTROL;
1086 config->dsr = data->dcb.fOutxDsrFlow ? SP_DSR_FLOW_CONTROL : SP_DSR_IGNORE;
1088 if (data->dcb.fInX) {
1089 if (data->dcb.fOutX)
1090 config->xon_xoff = SP_XONXOFF_INOUT;
1092 config->xon_xoff = SP_XONXOFF_IN;
1094 if (data->dcb.fOutX)
1095 config->xon_xoff = SP_XONXOFF_OUT;
1097 config->xon_xoff = SP_XONXOFF_DISABLED;
1102 if (tcgetattr(port->fd, &data->term) < 0)
1103 RETURN_FAIL("tcgetattr() failed");
1105 if (ioctl(port->fd, TIOCMGET, &data->controlbits) < 0)
1106 RETURN_FAIL("TIOCMGET ioctl failed");
1109 int ret = get_flow(port->fd, &data->flow);
1111 if (ret == SP_ERR_FAIL && errno == EINVAL)
1112 data->termiox_supported = 0;
1114 RETURN_CODEVAL(ret);
1116 data->termiox_supported = 1;
1118 data->termiox_supported = 0;
1121 for (i = 0; i < NUM_STD_BAUDRATES; i++) {
1122 if (cfgetispeed(&data->term) == std_baudrates[i].index) {
1123 config->baudrate = std_baudrates[i].value;
1128 if (i == NUM_STD_BAUDRATES) {
1130 config->baudrate = (int)data->term.c_ispeed;
1131 #elif defined(__linux__)
1132 TRY(get_baudrate(port->fd, &config->baudrate));
1134 config->baudrate = -1;
1138 switch (data->term.c_cflag & CSIZE) {
1155 if (!(data->term.c_cflag & PARENB) && (data->term.c_iflag & IGNPAR))
1156 config->parity = SP_PARITY_NONE;
1157 else if (!(data->term.c_cflag & PARENB) || (data->term.c_iflag & IGNPAR))
1158 config->parity = -1;
1159 else if (data->term.c_cflag & CMSPAR)
1160 config->parity = (data->term.c_cflag & PARODD) ? SP_PARITY_MARK : SP_PARITY_SPACE;
1162 config->parity = (data->term.c_cflag & PARODD) ? SP_PARITY_ODD : SP_PARITY_EVEN;
1164 config->stopbits = (data->term.c_cflag & CSTOPB) ? 2 : 1;
1166 if (data->term.c_cflag & CRTSCTS) {
1167 config->rts = SP_RTS_FLOW_CONTROL;
1168 config->cts = SP_CTS_FLOW_CONTROL;
1170 if (data->termiox_supported && data->flow & RTS_FLOW)
1171 config->rts = SP_RTS_FLOW_CONTROL;
1173 config->rts = (data->controlbits & TIOCM_RTS) ? SP_RTS_ON : SP_RTS_OFF;
1175 config->cts = (data->termiox_supported && data->flow & CTS_FLOW) ?
1176 SP_CTS_FLOW_CONTROL : SP_CTS_IGNORE;
1179 if (data->termiox_supported && data->flow & DTR_FLOW)
1180 config->dtr = SP_DTR_FLOW_CONTROL;
1182 config->dtr = (data->controlbits & TIOCM_DTR) ? SP_DTR_ON : SP_DTR_OFF;
1184 config->dsr = (data->termiox_supported && data->flow & DSR_FLOW) ?
1185 SP_DSR_FLOW_CONTROL : SP_DSR_IGNORE;
1187 if (data->term.c_iflag & IXOFF) {
1188 if (data->term.c_iflag & IXON)
1189 config->xon_xoff = SP_XONXOFF_INOUT;
1191 config->xon_xoff = SP_XONXOFF_IN;
1193 if (data->term.c_iflag & IXON)
1194 config->xon_xoff = SP_XONXOFF_OUT;
1196 config->xon_xoff = SP_XONXOFF_DISABLED;
1203 static enum sp_return set_config(struct sp_port *port, struct port_data *data,
1204 const struct sp_port_config *config)
1208 BAUD_TYPE baud_nonstd;
1213 int baud_nonstd = 0;
1216 TRACE("%p, %p, %p", port, data, config);
1218 DEBUG("Setting configuration for port %s", port->name);
1221 if (config->baudrate >= 0) {
1222 for (i = 0; i < NUM_STD_BAUDRATES; i++) {
1223 if (config->baudrate == std_baudrates[i].value) {
1224 data->dcb.BaudRate = std_baudrates[i].index;
1229 if (i == NUM_STD_BAUDRATES)
1230 data->dcb.BaudRate = config->baudrate;
1233 if (config->bits >= 0)
1234 data->dcb.ByteSize = config->bits;
1236 if (config->parity >= 0) {
1237 switch (config->parity) {
1238 /* Note: There's also SPACEPARITY, MARKPARITY (unneeded so far). */
1239 case SP_PARITY_NONE:
1240 data->dcb.Parity = NOPARITY;
1243 data->dcb.Parity = ODDPARITY;
1245 case SP_PARITY_EVEN:
1246 data->dcb.Parity = EVENPARITY;
1248 case SP_PARITY_MARK:
1249 data->dcb.Parity = MARKPARITY;
1251 case SP_PARITY_SPACE:
1252 data->dcb.Parity = SPACEPARITY;
1255 RETURN_ERROR(SP_ERR_ARG, "Invalid parity setting");
1259 if (config->stopbits >= 0) {
1260 switch (config->stopbits) {
1261 /* Note: There's also ONE5STOPBITS == 1.5 (unneeded so far). */
1263 data->dcb.StopBits = ONESTOPBIT;
1266 data->dcb.StopBits = TWOSTOPBITS;
1269 RETURN_ERROR(SP_ERR_ARG, "Invalid stop bit setting");
1273 if (config->rts >= 0) {
1274 switch (config->rts) {
1276 data->dcb.fRtsControl = RTS_CONTROL_DISABLE;
1279 data->dcb.fRtsControl = RTS_CONTROL_ENABLE;
1281 case SP_RTS_FLOW_CONTROL:
1282 data->dcb.fRtsControl = RTS_CONTROL_HANDSHAKE;
1285 RETURN_ERROR(SP_ERR_ARG, "Invalid RTS setting");
1289 if (config->cts >= 0) {
1290 switch (config->cts) {
1292 data->dcb.fOutxCtsFlow = FALSE;
1294 case SP_CTS_FLOW_CONTROL:
1295 data->dcb.fOutxCtsFlow = TRUE;
1298 RETURN_ERROR(SP_ERR_ARG, "Invalid CTS setting");
1302 if (config->dtr >= 0) {
1303 switch (config->dtr) {
1305 data->dcb.fDtrControl = DTR_CONTROL_DISABLE;
1308 data->dcb.fDtrControl = DTR_CONTROL_ENABLE;
1310 case SP_DTR_FLOW_CONTROL:
1311 data->dcb.fDtrControl = DTR_CONTROL_HANDSHAKE;
1314 RETURN_ERROR(SP_ERR_ARG, "Invalid DTR setting");
1318 if (config->dsr >= 0) {
1319 switch (config->dsr) {
1321 data->dcb.fOutxDsrFlow = FALSE;
1323 case SP_DSR_FLOW_CONTROL:
1324 data->dcb.fOutxDsrFlow = TRUE;
1327 RETURN_ERROR(SP_ERR_ARG, "Invalid DSR setting");
1331 if (config->xon_xoff >= 0) {
1332 switch (config->xon_xoff) {
1333 case SP_XONXOFF_DISABLED:
1334 data->dcb.fInX = FALSE;
1335 data->dcb.fOutX = FALSE;
1338 data->dcb.fInX = TRUE;
1339 data->dcb.fOutX = FALSE;
1341 case SP_XONXOFF_OUT:
1342 data->dcb.fInX = FALSE;
1343 data->dcb.fOutX = TRUE;
1345 case SP_XONXOFF_INOUT:
1346 data->dcb.fInX = TRUE;
1347 data->dcb.fOutX = TRUE;
1350 RETURN_ERROR(SP_ERR_ARG, "Invalid XON/XOFF setting");
1354 if (!SetCommState(port->hdl, &data->dcb))
1355 RETURN_FAIL("SetCommState() failed");
1361 if (config->baudrate >= 0) {
1362 for (i = 0; i < NUM_STD_BAUDRATES; i++) {
1363 if (config->baudrate == std_baudrates[i].value) {
1364 if (cfsetospeed(&data->term, std_baudrates[i].index) < 0)
1365 RETURN_FAIL("cfsetospeed() failed");
1367 if (cfsetispeed(&data->term, std_baudrates[i].index) < 0)
1368 RETURN_FAIL("cfsetispeed() failed");
1373 /* Non-standard baud rate */
1374 if (i == NUM_STD_BAUDRATES) {
1376 /* Set "dummy" baud rate. */
1377 if (cfsetspeed(&data->term, B9600) < 0)
1378 RETURN_FAIL("cfsetspeed() failed");
1379 baud_nonstd = config->baudrate;
1380 #elif defined(__linux__)
1383 RETURN_ERROR(SP_ERR_SUPP, "Non-standard baudrate not supported");
1388 if (config->bits >= 0) {
1389 data->term.c_cflag &= ~CSIZE;
1390 switch (config->bits) {
1392 data->term.c_cflag |= CS8;
1395 data->term.c_cflag |= CS7;
1398 data->term.c_cflag |= CS6;
1401 data->term.c_cflag |= CS5;
1404 RETURN_ERROR(SP_ERR_ARG, "Invalid data bits setting");
1408 if (config->parity >= 0) {
1409 data->term.c_iflag &= ~IGNPAR;
1410 data->term.c_cflag &= ~(PARENB | PARODD | CMSPAR);
1411 switch (config->parity) {
1412 case SP_PARITY_NONE:
1413 data->term.c_iflag |= IGNPAR;
1415 case SP_PARITY_EVEN:
1416 data->term.c_cflag |= PARENB;
1419 data->term.c_cflag |= PARENB | PARODD;
1421 case SP_PARITY_MARK:
1422 data->term.c_cflag |= PARENB | PARODD | CMSPAR;
1424 case SP_PARITY_SPACE:
1425 data->term.c_cflag |= PARENB | CMSPAR;
1428 RETURN_ERROR(SP_ERR_ARG, "Invalid parity setting");
1432 if (config->stopbits >= 0) {
1433 data->term.c_cflag &= ~CSTOPB;
1434 switch (config->stopbits) {
1436 data->term.c_cflag &= ~CSTOPB;
1439 data->term.c_cflag |= CSTOPB;
1442 RETURN_ERROR(SP_ERR_ARG, "Invalid stop bits setting");
1446 if (config->rts >= 0 || config->cts >= 0) {
1447 if (data->termiox_supported) {
1448 data->flow &= ~(RTS_FLOW | CTS_FLOW);
1449 switch (config->rts) {
1452 controlbits = TIOCM_RTS;
1453 if (ioctl(port->fd, config->rts == SP_RTS_ON ? TIOCMBIS : TIOCMBIC, &controlbits) < 0)
1454 RETURN_FAIL("Setting RTS signal level failed");
1456 case SP_RTS_FLOW_CONTROL:
1457 data->flow |= RTS_FLOW;
1462 if (config->cts == SP_CTS_FLOW_CONTROL)
1463 data->flow |= CTS_FLOW;
1465 if (data->flow & (RTS_FLOW | CTS_FLOW))
1466 data->term.c_iflag |= CRTSCTS;
1468 data->term.c_iflag &= ~CRTSCTS;
1470 /* Asymmetric use of RTS/CTS not supported. */
1471 if (data->term.c_iflag & CRTSCTS) {
1472 /* Flow control can only be disabled for both RTS & CTS together. */
1473 if (config->rts >= 0 && config->rts != SP_RTS_FLOW_CONTROL) {
1474 if (config->cts != SP_CTS_IGNORE)
1475 RETURN_ERROR(SP_ERR_SUPP, "RTS & CTS flow control must be disabled together");
1477 if (config->cts >= 0 && config->cts != SP_CTS_FLOW_CONTROL) {
1478 if (config->rts <= 0 || config->rts == SP_RTS_FLOW_CONTROL)
1479 RETURN_ERROR(SP_ERR_SUPP, "RTS & CTS flow control must be disabled together");
1482 /* Flow control can only be enabled for both RTS & CTS together. */
1483 if (((config->rts == SP_RTS_FLOW_CONTROL) && (config->cts != SP_CTS_FLOW_CONTROL)) ||
1484 ((config->cts == SP_CTS_FLOW_CONTROL) && (config->rts != SP_RTS_FLOW_CONTROL)))
1485 RETURN_ERROR(SP_ERR_SUPP, "RTS & CTS flow control must be enabled together");
1488 if (config->rts >= 0) {
1489 if (config->rts == SP_RTS_FLOW_CONTROL) {
1490 data->term.c_iflag |= CRTSCTS;
1492 controlbits = TIOCM_RTS;
1493 if (ioctl(port->fd, config->rts == SP_RTS_ON ? TIOCMBIS : TIOCMBIC,
1495 RETURN_FAIL("Setting RTS signal level failed");
1501 if (config->dtr >= 0 || config->dsr >= 0) {
1502 if (data->termiox_supported) {
1503 data->flow &= ~(DTR_FLOW | DSR_FLOW);
1504 switch (config->dtr) {
1507 controlbits = TIOCM_DTR;
1508 if (ioctl(port->fd, config->dtr == SP_DTR_ON ? TIOCMBIS : TIOCMBIC, &controlbits) < 0)
1509 RETURN_FAIL("Setting DTR signal level failed");
1511 case SP_DTR_FLOW_CONTROL:
1512 data->flow |= DTR_FLOW;
1517 if (config->dsr == SP_DSR_FLOW_CONTROL)
1518 data->flow |= DSR_FLOW;
1520 /* DTR/DSR flow control not supported. */
1521 if (config->dtr == SP_DTR_FLOW_CONTROL || config->dsr == SP_DSR_FLOW_CONTROL)
1522 RETURN_ERROR(SP_ERR_SUPP, "DTR/DSR flow control not supported");
1524 if (config->dtr >= 0) {
1525 controlbits = TIOCM_DTR;
1526 if (ioctl(port->fd, config->dtr == SP_DTR_ON ? TIOCMBIS : TIOCMBIC,
1528 RETURN_FAIL("Setting DTR signal level failed");
1533 if (config->xon_xoff >= 0) {
1534 data->term.c_iflag &= ~(IXON | IXOFF | IXANY);
1535 switch (config->xon_xoff) {
1536 case SP_XONXOFF_DISABLED:
1539 data->term.c_iflag |= IXOFF;
1541 case SP_XONXOFF_OUT:
1542 data->term.c_iflag |= IXON | IXANY;
1544 case SP_XONXOFF_INOUT:
1545 data->term.c_iflag |= IXON | IXOFF | IXANY;
1548 RETURN_ERROR(SP_ERR_ARG, "Invalid XON/XOFF setting");
1552 if (tcsetattr(port->fd, TCSADRAIN, &data->term) < 0)
1553 RETURN_FAIL("tcsetattr() failed");
1556 if (baud_nonstd != B0) {
1557 if (ioctl(port->fd, IOSSIOSPEED, &baud_nonstd) == -1)
1558 RETURN_FAIL("IOSSIOSPEED ioctl failed");
1559 /* Set baud rates in data->term to correct, but incompatible
1560 * with tcsetattr() value, same as delivered by tcgetattr(). */
1561 if (cfsetspeed(&data->term, baud_nonstd) < 0)
1562 RETURN_FAIL("cfsetspeed() failed");
1564 #elif defined(__linux__)
1566 TRY(set_baudrate(port->fd, config->baudrate));
1568 if (data->termiox_supported)
1569 TRY(set_flow(port->fd, data->flow));
1573 #endif /* !_WIN32 */
1578 enum sp_return sp_new_config(struct sp_port_config **config_ptr)
1580 TRACE("%p", config_ptr);
1581 struct sp_port_config *config;
1584 RETURN_ERROR(SP_ERR_ARG, "Null result pointer");
1588 if (!(config = malloc(sizeof(struct sp_port_config))))
1589 RETURN_ERROR(SP_ERR_MEM, "config malloc failed");
1591 config->baudrate = -1;
1593 config->parity = -1;
1594 config->stopbits = -1;
1600 *config_ptr = config;
1605 void sp_free_config(struct sp_port_config *config)
1607 TRACE("%p", config);
1610 DEBUG("Null config");
1617 enum sp_return sp_get_config(struct sp_port *port, struct sp_port_config *config)
1619 struct port_data data;
1621 TRACE("%p, %p", port, config);
1626 RETURN_ERROR(SP_ERR_ARG, "Null config");
1628 TRY(get_config(port, &data, config));
1633 enum sp_return sp_set_config(struct sp_port *port, const struct sp_port_config *config)
1635 struct port_data data;
1636 struct sp_port_config prev_config;
1638 TRACE("%p, %p", port, config);
1643 RETURN_ERROR(SP_ERR_ARG, "Null config");
1645 TRY(get_config(port, &data, &prev_config));
1646 TRY(set_config(port, &data, config));
1651 #define CREATE_ACCESSORS(x, type) \
1652 enum sp_return sp_set_##x(struct sp_port *port, type x) { \
1653 struct port_data data; \
1654 struct sp_port_config config; \
1655 TRACE("%p, %d", port, x); \
1656 CHECK_OPEN_PORT(); \
1657 TRY(get_config(port, &data, &config)); \
1659 TRY(set_config(port, &data, &config)); \
1662 enum sp_return sp_get_config_##x(const struct sp_port_config *config, type *x) { \
1663 TRACE("%p", config); \
1665 RETURN_ERROR(SP_ERR_ARG, "Null config"); \
1669 enum sp_return sp_set_config_##x(struct sp_port_config *config, type x) { \
1670 TRACE("%p, %d", config, x); \
1672 RETURN_ERROR(SP_ERR_ARG, "Null config"); \
1677 CREATE_ACCESSORS(baudrate, int)
1678 CREATE_ACCESSORS(bits, int)
1679 CREATE_ACCESSORS(parity, enum sp_parity)
1680 CREATE_ACCESSORS(stopbits, int)
1681 CREATE_ACCESSORS(rts, enum sp_rts)
1682 CREATE_ACCESSORS(cts, enum sp_cts)
1683 CREATE_ACCESSORS(dtr, enum sp_dtr)
1684 CREATE_ACCESSORS(dsr, enum sp_dsr)
1685 CREATE_ACCESSORS(xon_xoff, enum sp_xonxoff)
1687 enum sp_return sp_set_config_flowcontrol(struct sp_port_config *config, enum sp_flowcontrol flowcontrol)
1690 RETURN_ERROR(SP_ERR_ARG, "Null configuration");
1692 if (flowcontrol > SP_FLOWCONTROL_DTRDSR)
1693 RETURN_ERROR(SP_ERR_ARG, "Invalid flow control setting");
1695 if (flowcontrol == SP_FLOWCONTROL_XONXOFF)
1696 config->xon_xoff = SP_XONXOFF_INOUT;
1698 config->xon_xoff = SP_XONXOFF_DISABLED;
1700 if (flowcontrol == SP_FLOWCONTROL_RTSCTS) {
1701 config->rts = SP_RTS_FLOW_CONTROL;
1702 config->cts = SP_CTS_FLOW_CONTROL;
1704 if (config->rts == SP_RTS_FLOW_CONTROL)
1705 config->rts = SP_RTS_ON;
1706 config->cts = SP_CTS_IGNORE;
1709 if (flowcontrol == SP_FLOWCONTROL_DTRDSR) {
1710 config->dtr = SP_DTR_FLOW_CONTROL;
1711 config->dsr = SP_DSR_FLOW_CONTROL;
1713 if (config->dtr == SP_DTR_FLOW_CONTROL)
1714 config->dtr = SP_DTR_ON;
1715 config->dsr = SP_DSR_IGNORE;
1721 enum sp_return sp_set_flowcontrol(struct sp_port *port, enum sp_flowcontrol flowcontrol)
1723 struct port_data data;
1724 struct sp_port_config config;
1726 TRACE("%p, %d", port, flowcontrol);
1730 TRY(get_config(port, &data, &config));
1732 TRY(sp_set_config_flowcontrol(&config, flowcontrol));
1734 TRY(set_config(port, &data, &config));
1739 enum sp_return sp_get_signals(struct sp_port *port, enum sp_signal *signals)
1741 TRACE("%p, %p", port, signals);
1746 RETURN_ERROR(SP_ERR_ARG, "Null result pointer");
1748 DEBUG("Getting control signals for port %s", port->name);
1753 if (GetCommModemStatus(port->hdl, &bits) == 0)
1754 RETURN_FAIL("GetCommModemStatus() failed");
1755 if (bits & MS_CTS_ON)
1756 *signals |= SP_SIG_CTS;
1757 if (bits & MS_DSR_ON)
1758 *signals |= SP_SIG_DSR;
1759 if (bits & MS_RLSD_ON)
1760 *signals |= SP_SIG_DCD;
1761 if (bits & MS_RING_ON)
1762 *signals |= SP_SIG_RI;
1765 if (ioctl(port->fd, TIOCMGET, &bits) < 0)
1766 RETURN_FAIL("TIOCMGET ioctl failed");
1767 if (bits & TIOCM_CTS)
1768 *signals |= SP_SIG_CTS;
1769 if (bits & TIOCM_DSR)
1770 *signals |= SP_SIG_DSR;
1771 if (bits & TIOCM_CAR)
1772 *signals |= SP_SIG_DCD;
1773 if (bits & TIOCM_RNG)
1774 *signals |= SP_SIG_RI;
1779 enum sp_return sp_start_break(struct sp_port *port)
1785 if (SetCommBreak(port->hdl) == 0)
1786 RETURN_FAIL("SetCommBreak() failed");
1788 if (ioctl(port->fd, TIOCSBRK, 1) < 0)
1789 RETURN_FAIL("TIOCSBRK ioctl failed");
1795 enum sp_return sp_end_break(struct sp_port *port)
1801 if (ClearCommBreak(port->hdl) == 0)
1802 RETURN_FAIL("ClearCommBreak() failed");
1804 if (ioctl(port->fd, TIOCCBRK, 1) < 0)
1805 RETURN_FAIL("TIOCCBRK ioctl failed");
1811 int sp_last_error_code(void)
1815 RETURN_VALUE("%d", GetLastError());
1817 RETURN_VALUE("%d", errno);
1821 char *sp_last_error_message(void)
1827 DWORD error = GetLastError();
1830 FORMAT_MESSAGE_ALLOCATE_BUFFER |
1831 FORMAT_MESSAGE_FROM_SYSTEM |
1832 FORMAT_MESSAGE_IGNORE_INSERTS,
1835 MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
1839 RETURN_VALUE("%s", message);
1841 RETURN_VALUE("%s", strerror(errno));
1845 void sp_free_error_message(char *message)
1847 TRACE("%s", message);
1858 void sp_set_debug_handler(void (*handler)(const char *format, ...))
1860 TRACE("%p", handler);
1862 sp_debug_handler = handler;
1867 void sp_default_debug_handler(const char *format, ...)
1870 va_start(args, format);
1871 if (getenv("LIBSERIALPORT_DEBUG")) {
1872 fputs("libserialport: ", stderr);
1873 vfprintf(stderr, format, args);