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>
44 #include <IOKit/IOKitLib.h>
45 #include <IOKit/serial/IOSerialKeys.h>
46 #include <IOKit/serial/ioss.h>
47 #include <sys/syslimits.h>
52 #include "linux/serial.h"
54 #include "linux_termios.h"
56 /* TCGETX/TCSETX is not available everywhere. */
57 #if defined(TCGETX) && defined(TCSETX) && defined(HAVE_TERMIOX)
62 /* TIOCINQ/TIOCOUTQ is not available everywhere. */
63 #if !defined(TIOCINQ) && defined(FIONREAD)
64 #define TIOCINQ FIONREAD
66 #if !defined(TIOCOUTQ) && defined(FIONWRITE)
67 #define TIOCOUTQ FIONWRITE
70 /* Non-standard baudrates are not available everywhere. */
71 #if defined(HAVE_TERMIOS_SPEED) || defined(HAVE_TERMIOS2_SPEED)
72 #define USE_TERMIOS_SPEED
75 #include "libserialport.h"
81 COMMTIMEOUTS timeouts;
93 struct sp_port_config {
96 enum sp_parity parity;
102 enum sp_xonxoff xon_xoff;
111 int termiox_supported;
120 typedef HANDLE event_handle;
122 typedef int event_handle;
125 /* Standard baud rates. */
127 #define BAUD_TYPE DWORD
128 #define BAUD(n) {CBR_##n, n}
130 #define BAUD_TYPE speed_t
131 #define BAUD(n) {B##n, n}
134 struct std_baudrate {
139 const struct std_baudrate std_baudrates[] = {
142 * The baudrates 50/75/134/150/200/1800/230400/460800 do not seem to
143 * have documented CBR_* macros.
145 BAUD(110), BAUD(300), BAUD(600), BAUD(1200), BAUD(2400), BAUD(4800),
146 BAUD(9600), BAUD(14400), BAUD(19200), BAUD(38400), BAUD(57600),
147 BAUD(115200), BAUD(128000), BAUD(256000),
149 BAUD(50), BAUD(75), BAUD(110), BAUD(134), BAUD(150), BAUD(200),
150 BAUD(300), BAUD(600), BAUD(1200), BAUD(1800), BAUD(2400), BAUD(4800),
151 BAUD(9600), BAUD(19200), BAUD(38400), BAUD(57600), BAUD(115200),
153 #if !defined(__APPLE__) && !defined(__OpenBSD__)
159 void (*sp_debug_handler)(const char *format, ...) = sp_default_debug_handler;
161 #define ARRAY_SIZE(x) (sizeof(x) / sizeof(x[0]))
162 #define NUM_STD_BAUDRATES ARRAY_SIZE(std_baudrates)
164 /* Debug output macros. */
165 #define DEBUG(fmt, ...) do { if (sp_debug_handler) sp_debug_handler(fmt ".\n", ##__VA_ARGS__); } while (0)
166 #define DEBUG_ERROR(err, fmt, ...) DEBUG("%s returning " #err ": " fmt, __func__, ##__VA_ARGS__)
167 #define DEBUG_FAIL(fmt, ...) do { \
168 char *errmsg = sp_last_error_message(); \
169 DEBUG("%s returning SP_ERR_FAIL: "fmt": %s", __func__,##__VA_ARGS__,errmsg); \
170 sp_free_error_message(errmsg); \
172 #define RETURN() do { DEBUG("%s returning", __func__); return; } while(0)
173 #define RETURN_CODE(x) do { DEBUG("%s returning " #x, __func__); return x; } while (0)
174 #define RETURN_CODEVAL(x) do { \
176 case SP_OK: RETURN_CODE(SP_OK); \
177 case SP_ERR_ARG: RETURN_CODE(SP_ERR_ARG); \
178 case SP_ERR_FAIL: RETURN_CODE(SP_ERR_FAIL); \
179 case SP_ERR_MEM: RETURN_CODE(SP_ERR_MEM); \
180 case SP_ERR_SUPP: RETURN_CODE(SP_ERR_SUPP); \
183 #define RETURN_OK() RETURN_CODE(SP_OK);
184 #define RETURN_ERROR(err, ...) do { DEBUG_ERROR(err, __VA_ARGS__); return err; } while (0)
185 #define RETURN_FAIL(...) do { DEBUG_FAIL(__VA_ARGS__); return SP_ERR_FAIL; } while (0)
186 #define RETURN_VALUE(fmt, x) do { \
188 DEBUG("%s returning " fmt, __func__, _x); \
191 #define SET_ERROR(val, err, msg) do { DEBUG_ERROR(err, msg); val = err; } while (0)
192 #define SET_FAIL(val, msg) do { DEBUG_FAIL(msg); val = SP_ERR_FAIL; } while (0)
193 #define TRACE(fmt, ...) DEBUG("%s(" fmt ") called", __func__, ##__VA_ARGS__)
195 #define TRY(x) do { int ret = x; if (ret != SP_OK) RETURN_CODEVAL(ret); } while (0)
197 /* Helper functions. */
198 static enum sp_return get_config(struct sp_port *port, struct port_data *data,
199 struct sp_port_config *config);
200 static enum sp_return set_config(struct sp_port *port, struct port_data *data,
201 const struct sp_port_config *config);
203 enum sp_return sp_get_port_by_name(const char *portname, struct sp_port **port_ptr)
205 struct sp_port *port;
208 TRACE("%s, %p", portname, port_ptr);
211 RETURN_ERROR(SP_ERR_ARG, "Null result pointer");
216 RETURN_ERROR(SP_ERR_ARG, "Null port name");
218 DEBUG("Building structure for port %s", portname);
220 if (!(port = malloc(sizeof(struct sp_port))))
221 RETURN_ERROR(SP_ERR_MEM, "Port structure malloc failed");
223 len = strlen(portname) + 1;
225 if (!(port->name = malloc(len))) {
227 RETURN_ERROR(SP_ERR_MEM, "Port name malloc failed");
230 memcpy(port->name, portname, len);
233 port->hdl = INVALID_HANDLE_VALUE;
243 char *sp_get_port_name(const struct sp_port *port)
250 RETURN_VALUE("%s", port->name);
253 enum sp_return sp_get_port_handle(const struct sp_port *port, void *result_ptr)
255 TRACE("%p, %p", port, result_ptr);
258 RETURN_ERROR(SP_ERR_ARG, "Null port");
261 HANDLE *handle_ptr = result_ptr;
262 *handle_ptr = port->hdl;
264 int *fd_ptr = result_ptr;
271 enum sp_return sp_copy_port(const struct sp_port *port, struct sp_port **copy_ptr)
273 TRACE("%p, %p", port, copy_ptr);
276 RETURN_ERROR(SP_ERR_ARG, "Null result pointer");
281 RETURN_ERROR(SP_ERR_ARG, "Null port");
284 RETURN_ERROR(SP_ERR_ARG, "Null port name");
286 DEBUG("Copying port structure");
288 RETURN_VALUE("%p", sp_get_port_by_name(port->name, copy_ptr));
291 void sp_free_port(struct sp_port *port)
300 DEBUG("Freeing port structure");
310 static struct sp_port **list_append(struct sp_port **list, const char *portname)
315 for (count = 0; list[count]; count++);
316 if (!(tmp = realloc(list, sizeof(struct sp_port *) * (count + 2))))
319 if (sp_get_port_by_name(portname, &list[count]) != SP_OK)
321 list[count + 1] = NULL;
325 sp_free_port_list(list);
329 enum sp_return sp_list_ports(struct sp_port ***list_ptr)
331 struct sp_port **list;
332 int ret = SP_ERR_SUPP;
334 TRACE("%p", list_ptr);
337 RETURN_ERROR(SP_ERR_ARG, "Null result pointer");
339 DEBUG("Enumerating ports");
341 if (!(list = malloc(sizeof(struct sp_port **))))
342 RETURN_ERROR(SP_ERR_MEM, "Port list malloc failed");
349 DWORD max_value_len, max_data_size, max_data_len;
350 DWORD value_len, data_size, data_len;
351 DWORD type, index = 0;
357 DEBUG("Opening registry key");
358 if (RegOpenKeyEx(HKEY_LOCAL_MACHINE, _T("HARDWARE\\DEVICEMAP\\SERIALCOMM"),
359 0, KEY_QUERY_VALUE, &key) != ERROR_SUCCESS) {
360 SET_FAIL(ret, "RegOpenKeyEx() failed");
363 DEBUG("Querying registry key value and data sizes");
364 if (RegQueryInfoKey(key, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
365 &max_value_len, &max_data_size, NULL, NULL) != ERROR_SUCCESS) {
366 SET_FAIL(ret, "RegQueryInfoKey() failed");
369 max_data_len = max_data_size / sizeof(TCHAR);
370 if (!(value = malloc((max_value_len + 1) * sizeof(TCHAR)))) {
371 SET_ERROR(ret, SP_ERR_MEM, "registry value malloc failed");
374 if (!(data = malloc((max_data_len + 1) * sizeof(TCHAR)))) {
375 SET_ERROR(ret, SP_ERR_MEM, "registry data malloc failed");
378 DEBUG("Iterating over values");
380 value_len = max_value_len + 1,
381 data_size = max_data_size,
382 RegEnumValue(key, index, value, &value_len,
383 NULL, &type, (LPBYTE)data, &data_size) == ERROR_SUCCESS)
385 data_len = data_size / sizeof(TCHAR);
386 data[data_len] = '\0';
388 name_len = WideCharToMultiByte(CP_ACP, 0, data, -1, NULL, 0, NULL, NULL);
390 name_len = data_len + 1;
392 if (!(name = malloc(name_len))) {
393 SET_ERROR(ret, SP_ERR_MEM, "registry port name malloc failed");
397 WideCharToMultiByte(CP_ACP, 0, data, -1, name, name_len, NULL, NULL);
401 if (type == REG_SZ) {
402 DEBUG("Found port %s", name);
403 if (!(list = list_append(list, name))) {
404 SET_ERROR(ret, SP_ERR_MEM, "list append failed");
419 CFMutableDictionaryRef classes;
428 DEBUG("Creating matching dictionary");
429 if (!(classes = IOServiceMatching(kIOSerialBSDServiceValue))) {
430 SET_FAIL(ret, "IOServiceMatching() failed");
434 DEBUG("Getting matching services");
435 if (IOServiceGetMatchingServices(kIOMasterPortDefault, classes,
436 &iter) != KERN_SUCCESS) {
437 SET_FAIL(ret, "IOServiceGetMatchingServices() failed");
441 DEBUG("Iterating over results");
442 while ((port = IOIteratorNext(iter))) {
443 cf_path = IORegistryEntryCreateCFProperty(port,
444 CFSTR(kIOCalloutDeviceKey), kCFAllocatorDefault, 0);
446 result = CFStringGetCString(cf_path, path, sizeof(path),
447 kCFStringEncodingASCII);
450 DEBUG("Found port %s", path);
451 if (!(list = list_append(list, path))) {
452 SET_ERROR(ret, SP_ERR_MEM, "list append failed");
453 IOObjectRelease(port);
458 IOObjectRelease(port);
461 IOObjectRelease(iter);
465 char name[PATH_MAX], target[PATH_MAX];
466 struct dirent entry, *result;
467 struct serial_struct serial_info;
468 int len, fd, ioctl_result;
473 DEBUG("Enumerating tty devices");
474 if (!(dir = opendir("/sys/class/tty")))
475 RETURN_FAIL("could not open /sys/class/tty");
477 DEBUG("Iterating over results");
478 while (!readdir_r(dir, &entry, &result) && result) {
479 len = readlinkat(dirfd(dir), entry.d_name, target, sizeof(target));
480 if (len <= 0 || len >= (int) sizeof(target)-1)
483 if (strstr(target, "virtual"))
485 snprintf(name, sizeof(name), "/dev/%s", entry.d_name);
486 DEBUG("Found device %s", name);
487 if (strstr(target, "serial8250")) {
488 /* The serial8250 driver has a hardcoded number of ports.
489 * The only way to tell which actually exist on a given system
490 * is to try to open them and make an ioctl call. */
491 DEBUG("serial8250 device, attempting to open");
492 if ((fd = open(name, O_RDWR | O_NONBLOCK | O_NOCTTY)) < 0) {
493 DEBUG("open failed, skipping");
496 ioctl_result = ioctl(fd, TIOCGSERIAL, &serial_info);
498 if (ioctl_result != 0) {
499 DEBUG("ioctl failed, skipping");
502 if (serial_info.type == PORT_UNKNOWN) {
503 DEBUG("port type is unknown, skipping");
507 DEBUG("Found port %s", name);
508 list = list_append(list, name);
510 SET_ERROR(ret, SP_ERR_MEM, "list append failed");
522 DEBUG_ERROR(SP_ERR_SUPP, "Enumeration not supported on this platform");
525 sp_free_port_list(list);
531 void sp_free_port_list(struct sp_port **list)
542 DEBUG("Freeing port list");
544 for (i = 0; list[i]; i++)
545 sp_free_port(list[i]);
551 #define CHECK_PORT() do { \
553 RETURN_ERROR(SP_ERR_ARG, "Null port"); \
554 if (port->name == NULL) \
555 RETURN_ERROR(SP_ERR_ARG, "Null port name"); \
558 #define CHECK_PORT_HANDLE() do { \
559 if (port->hdl == INVALID_HANDLE_VALUE) \
560 RETURN_ERROR(SP_ERR_ARG, "Invalid port handle"); \
563 #define CHECK_PORT_HANDLE() do { \
565 RETURN_ERROR(SP_ERR_ARG, "Invalid port fd"); \
568 #define CHECK_OPEN_PORT() do { \
570 CHECK_PORT_HANDLE(); \
573 enum sp_return sp_open(struct sp_port *port, enum sp_mode flags)
575 struct port_data data;
576 struct sp_port_config config;
579 TRACE("%p, 0x%x", port, flags);
583 if (flags > (SP_MODE_READ | SP_MODE_WRITE))
584 RETURN_ERROR(SP_ERR_ARG, "Invalid flags");
586 DEBUG("Opening port %s", port->name);
589 DWORD desired_access = 0, flags_and_attributes = 0, errors;
590 char *escaped_port_name;
593 /* Prefix port name with '\\.\' to work with ports above COM9. */
594 if (!(escaped_port_name = malloc(strlen(port->name) + 5)))
595 RETURN_ERROR(SP_ERR_MEM, "Escaped port name malloc failed");
596 sprintf(escaped_port_name, "\\\\.\\%s", port->name);
598 /* Map 'flags' to the OS-specific settings. */
599 flags_and_attributes = FILE_ATTRIBUTE_NORMAL | FILE_FLAG_OVERLAPPED;
600 if (flags & SP_MODE_READ)
601 desired_access |= GENERIC_READ;
602 if (flags & SP_MODE_WRITE)
603 desired_access |= GENERIC_WRITE;
605 port->hdl = CreateFile(escaped_port_name, desired_access, 0, 0,
606 OPEN_EXISTING, flags_and_attributes, 0);
608 free(escaped_port_name);
610 if (port->hdl == INVALID_HANDLE_VALUE)
611 RETURN_FAIL("port CreateFile() failed");
613 /* All timeouts initially disabled. */
614 port->timeouts.ReadIntervalTimeout = 0;
615 port->timeouts.ReadTotalTimeoutMultiplier = 0;
616 port->timeouts.ReadTotalTimeoutConstant = 0;
617 port->timeouts.WriteTotalTimeoutMultiplier = 0;
618 port->timeouts.WriteTotalTimeoutConstant = 0;
620 if (SetCommTimeouts(port->hdl, &port->timeouts) == 0) {
622 RETURN_FAIL("SetCommTimeouts() failed");
625 /* Prepare OVERLAPPED structures. */
626 #define INIT_OVERLAPPED(ovl) do { \
627 memset(&port->ovl, 0, sizeof(port->ovl)); \
628 port->ovl.hEvent = INVALID_HANDLE_VALUE; \
629 if ((port->ovl.hEvent = CreateEvent(NULL, TRUE, TRUE, NULL)) \
630 == INVALID_HANDLE_VALUE) { \
632 RETURN_FAIL(#ovl "CreateEvent() failed"); \
636 INIT_OVERLAPPED(read_ovl);
637 INIT_OVERLAPPED(write_ovl);
638 INIT_OVERLAPPED(wait_ovl);
640 /* Set event mask for RX and error events. */
641 if (SetCommMask(port->hdl, EV_RXCHAR | EV_ERR) == 0) {
643 RETURN_FAIL("SetCommMask() failed");
646 /* Start background operation for RX and error events. */
647 if (WaitCommEvent(port->hdl, &port->events, &port->wait_ovl) == 0) {
648 if (GetLastError() != ERROR_IO_PENDING) {
650 RETURN_FAIL("WaitCommEvent() failed");
654 port->writing = FALSE;
657 int flags_local = O_NONBLOCK | O_NOCTTY;
659 /* Map 'flags' to the OS-specific settings. */
660 if (flags & (SP_MODE_READ | SP_MODE_WRITE))
661 flags_local |= O_RDWR;
662 else if (flags & SP_MODE_READ)
663 flags_local |= O_RDONLY;
664 else if (flags & SP_MODE_WRITE)
665 flags_local |= O_WRONLY;
667 if ((port->fd = open(port->name, flags_local)) < 0)
668 RETURN_FAIL("open() failed");
671 ret = get_config(port, &data, &config);
678 /* Set sane port settings. */
680 data.dcb.fBinary = TRUE;
681 data.dcb.fDsrSensitivity = FALSE;
682 data.dcb.fErrorChar = FALSE;
683 data.dcb.fNull = FALSE;
684 data.dcb.fAbortOnError = TRUE;
686 /* Turn off all fancy termios tricks, give us a raw channel. */
687 data.term.c_iflag &= ~(IGNBRK | BRKINT | PARMRK | ISTRIP | INLCR | IGNCR | ICRNL | IMAXBEL);
689 data.term.c_iflag &= ~IUCLC;
691 data.term.c_oflag &= ~(OPOST | ONLCR | OCRNL | ONOCR | ONLRET);
693 data.term.c_oflag &= ~OLCUC;
696 data.term.c_oflag &= ~NLDLY;
699 data.term.c_oflag &= ~CRDLY;
702 data.term.c_oflag &= ~TABDLY;
705 data.term.c_oflag &= ~BSDLY;
708 data.term.c_oflag &= ~VTDLY;
711 data.term.c_oflag &= ~FFDLY;
714 data.term.c_oflag &= ~OFILL;
716 data.term.c_lflag &= ~(ISIG | ICANON | ECHO | IEXTEN);
717 data.term.c_cc[VMIN] = 0;
718 data.term.c_cc[VTIME] = 0;
720 /* Ignore modem status lines; enable receiver; leave control lines alone on close. */
721 data.term.c_cflag |= (CLOCAL | CREAD | HUPCL);
725 if (ClearCommError(port->hdl, &errors, &status) == 0)
726 RETURN_FAIL("ClearCommError() failed");
729 ret = set_config(port, &data, &config);
739 enum sp_return sp_close(struct sp_port *port)
745 DEBUG("Closing port %s", port->name);
748 /* Returns non-zero upon success, 0 upon failure. */
749 if (CloseHandle(port->hdl) == 0)
750 RETURN_FAIL("port CloseHandle() failed");
751 port->hdl = INVALID_HANDLE_VALUE;
753 /* Close event handles for overlapped structures. */
754 #define CLOSE_OVERLAPPED(ovl) do { \
755 if (port->ovl.hEvent != INVALID_HANDLE_VALUE && \
756 CloseHandle(port->ovl.hEvent) == 0) \
757 RETURN_FAIL(# ovl "event CloseHandle() failed"); \
759 CLOSE_OVERLAPPED(read_ovl);
760 CLOSE_OVERLAPPED(write_ovl);
761 CLOSE_OVERLAPPED(wait_ovl);
764 /* Returns 0 upon success, -1 upon failure. */
765 if (close(port->fd) == -1)
766 RETURN_FAIL("close() failed");
773 enum sp_return sp_flush(struct sp_port *port, enum sp_buffer buffers)
775 TRACE("%p, 0x%x", port, buffers);
779 if (buffers > SP_BUF_BOTH)
780 RETURN_ERROR(SP_ERR_ARG, "Invalid buffer selection");
782 const char *buffer_names[] = {"no", "input", "output", "both"};
784 DEBUG("Flushing %s buffers on port %s", buffer_names[buffers], port->name);
788 if (buffers & SP_BUF_INPUT)
789 flags |= PURGE_RXCLEAR;
790 if (buffers & SP_BUF_OUTPUT)
791 flags |= PURGE_TXCLEAR;
793 /* Returns non-zero upon success, 0 upon failure. */
794 if (PurgeComm(port->hdl, flags) == 0)
795 RETURN_FAIL("PurgeComm() failed");
798 if (buffers & SP_BUF_BOTH)
800 else if (buffers & SP_BUF_INPUT)
802 else if (buffers & SP_BUF_OUTPUT)
805 /* Returns 0 upon success, -1 upon failure. */
806 if (tcflush(port->fd, flags) < 0)
807 RETURN_FAIL("tcflush() failed");
812 enum sp_return sp_drain(struct sp_port *port)
818 DEBUG("Draining port %s", port->name);
821 /* Returns non-zero upon success, 0 upon failure. */
822 if (FlushFileBuffers(port->hdl) == 0)
823 RETURN_FAIL("FlushFileBuffers() failed");
830 result = ioctl(port->fd, TCSBRK, &arg);
832 result = tcdrain(port->fd);
835 if (errno == EINTR) {
836 DEBUG("tcdrain() was interrupted");
839 RETURN_FAIL("tcdrain() failed");
848 enum sp_return sp_blocking_write(struct sp_port *port, const void *buf, size_t count, unsigned int timeout)
850 TRACE("%p, %p, %d, %d", port, buf, count, timeout);
855 RETURN_ERROR(SP_ERR_ARG, "Null buffer");
858 DEBUG("Writing %d bytes to port %s, timeout %d ms", count, port->name, timeout);
860 DEBUG("Writing %d bytes to port %s, no timeout", count, port->name);
863 RETURN_VALUE("0", 0);
866 DWORD bytes_written = 0;
869 /* Wait for previous non-blocking write to complete, if any. */
871 DEBUG("Waiting for previous write to complete");
872 result = GetOverlappedResult(port->hdl, &port->write_ovl, &bytes_written, TRUE);
875 RETURN_FAIL("Previous write failed to complete");
876 DEBUG("Previous write completed");
880 port->timeouts.WriteTotalTimeoutConstant = timeout;
881 if (SetCommTimeouts(port->hdl, &port->timeouts) == 0)
882 RETURN_FAIL("SetCommTimeouts() failed");
885 if (WriteFile(port->hdl, buf, count, NULL, &port->write_ovl) == 0) {
886 if (GetLastError() == ERROR_IO_PENDING) {
887 DEBUG("Waiting for write to complete");
888 GetOverlappedResult(port->hdl, &port->write_ovl, &bytes_written, TRUE);
889 DEBUG("Write completed, %d/%d bytes written", bytes_written, count);
890 RETURN_VALUE("%d", bytes_written);
892 RETURN_FAIL("WriteFile() failed");
895 DEBUG("Write completed immediately");
896 RETURN_VALUE("%d", count);
899 size_t bytes_written = 0;
900 unsigned char *ptr = (unsigned char *) buf;
901 struct timeval start, delta, now, end = {0, 0};
906 /* Get time at start of operation. */
907 gettimeofday(&start, NULL);
908 /* Define duration of timeout. */
909 delta.tv_sec = timeout / 1000;
910 delta.tv_usec = (timeout % 1000) * 1000;
911 /* Calculate time at which we should give up. */
912 timeradd(&start, &delta, &end);
915 /* Loop until we have written the requested number of bytes. */
916 while (bytes_written < count)
918 /* Wait until space is available. */
920 FD_SET(port->fd, &fds);
922 gettimeofday(&now, NULL);
923 if (timercmp(&now, &end, >)) {
924 DEBUG("write timed out");
925 RETURN_VALUE("%d", bytes_written);
927 timersub(&end, &now, &delta);
929 result = select(port->fd + 1, NULL, &fds, NULL, timeout ? &delta : NULL);
931 if (errno == EINTR) {
932 DEBUG("select() call was interrupted, repeating");
935 RETURN_FAIL("select() failed");
937 } else if (result == 0) {
938 DEBUG("write timed out");
939 RETURN_VALUE("%d", bytes_written);
943 result = write(port->fd, ptr, count - bytes_written);
947 /* This shouldn't happen because we did a select() first, but handle anyway. */
950 /* This is an actual failure. */
951 RETURN_FAIL("write() failed");
954 bytes_written += result;
958 RETURN_VALUE("%d", bytes_written);
962 enum sp_return sp_nonblocking_write(struct sp_port *port, const void *buf, size_t count)
964 TRACE("%p, %p, %d", port, buf, count);
969 RETURN_ERROR(SP_ERR_ARG, "Null buffer");
971 DEBUG("Writing up to %d bytes to port %s", count, port->name);
974 RETURN_VALUE("0", 0);
978 BYTE *ptr = (BYTE *) buf;
980 /* Check whether previous write is complete. */
982 if (HasOverlappedIoCompleted(&port->write_ovl)) {
983 DEBUG("Previous write completed");
986 DEBUG("Previous write not complete");
987 /* Can't take a new write until the previous one finishes. */
988 RETURN_VALUE("0", 0);
993 port->timeouts.WriteTotalTimeoutConstant = 0;
994 if (SetCommTimeouts(port->hdl, &port->timeouts) == 0)
995 RETURN_FAIL("SetCommTimeouts() failed");
997 /* Keep writing data until the OS has to actually start an async IO for it.
998 * At that point we know the buffer is full. */
999 while (written < count)
1001 /* Copy first byte of user buffer. */
1002 port->pending_byte = *ptr++;
1004 /* Start asynchronous write. */
1005 if (WriteFile(port->hdl, &port->pending_byte, 1, NULL, &port->write_ovl) == 0) {
1006 if (GetLastError() == ERROR_IO_PENDING) {
1007 if (HasOverlappedIoCompleted(&port->write_ovl)) {
1008 DEBUG("Asynchronous write completed immediately");
1013 DEBUG("Asynchronous write running");
1015 RETURN_VALUE("%d", ++written);
1018 /* Actual failure of some kind. */
1019 RETURN_FAIL("WriteFile() failed");
1022 DEBUG("Single byte written immediately");
1027 DEBUG("All bytes written immediately");
1029 RETURN_VALUE("%d", written);
1031 /* Returns the number of bytes written, or -1 upon failure. */
1032 ssize_t written = write(port->fd, buf, count);
1035 RETURN_FAIL("write() failed");
1037 RETURN_VALUE("%d", written);
1041 enum sp_return sp_blocking_read(struct sp_port *port, void *buf, size_t count, unsigned int timeout)
1043 TRACE("%p, %p, %d, %d", port, buf, count, timeout);
1048 RETURN_ERROR(SP_ERR_ARG, "Null buffer");
1051 DEBUG("Reading %d bytes from port %s, timeout %d ms", count, port->name, timeout);
1053 DEBUG("Reading %d bytes from port %s, no timeout", count, port->name);
1056 RETURN_VALUE("0", 0);
1059 DWORD bytes_read = 0;
1062 port->timeouts.ReadIntervalTimeout = 0;
1063 port->timeouts.ReadTotalTimeoutConstant = timeout;
1064 if (SetCommTimeouts(port->hdl, &port->timeouts) == 0)
1065 RETURN_FAIL("SetCommTimeouts() failed");
1068 if (ReadFile(port->hdl, buf, count, NULL, &port->read_ovl) == 0) {
1069 if (GetLastError() == ERROR_IO_PENDING) {
1070 DEBUG("Waiting for read to complete");
1071 GetOverlappedResult(port->hdl, &port->read_ovl, &bytes_read, TRUE);
1072 DEBUG("Read completed, %d/%d bytes read", bytes_read, count);
1074 RETURN_FAIL("ReadFile() failed");
1077 DEBUG("Read completed immediately");
1081 /* Start background operation for subsequent events. */
1082 if (WaitCommEvent(port->hdl, &port->events, &port->wait_ovl) == 0) {
1083 if (GetLastError() != ERROR_IO_PENDING)
1084 RETURN_FAIL("WaitCommEvent() failed");
1087 RETURN_VALUE("%d", bytes_read);
1090 size_t bytes_read = 0;
1091 unsigned char *ptr = (unsigned char *) buf;
1092 struct timeval start, delta, now, end = {0, 0};
1097 /* Get time at start of operation. */
1098 gettimeofday(&start, NULL);
1099 /* Define duration of timeout. */
1100 delta.tv_sec = timeout / 1000;
1101 delta.tv_usec = (timeout % 1000) * 1000;
1102 /* Calculate time at which we should give up. */
1103 timeradd(&start, &delta, &end);
1106 /* Loop until we have the requested number of bytes. */
1107 while (bytes_read < count)
1109 /* Wait until data is available. */
1111 FD_SET(port->fd, &fds);
1113 gettimeofday(&now, NULL);
1114 if (timercmp(&now, &end, >))
1115 /* Timeout has expired. */
1116 RETURN_VALUE("%d", bytes_read);
1117 timersub(&end, &now, &delta);
1119 result = select(port->fd + 1, &fds, NULL, NULL, timeout ? &delta : NULL);
1121 if (errno == EINTR) {
1122 DEBUG("select() call was interrupted, repeating");
1125 RETURN_FAIL("select() failed");
1127 } else if (result == 0) {
1128 DEBUG("read timed out");
1129 RETURN_VALUE("%d", bytes_read);
1133 result = read(port->fd, ptr, count - bytes_read);
1136 if (errno == EAGAIN)
1137 /* This shouldn't happen because we did a select() first, but handle anyway. */
1140 /* This is an actual failure. */
1141 RETURN_FAIL("read() failed");
1144 bytes_read += result;
1148 RETURN_VALUE("%d", bytes_read);
1152 enum sp_return sp_nonblocking_read(struct sp_port *port, void *buf, size_t count)
1154 TRACE("%p, %p, %d", port, buf, count);
1159 RETURN_ERROR(SP_ERR_ARG, "Null buffer");
1161 DEBUG("Reading up to %d bytes from port %s", count, port->name);
1167 port->timeouts.ReadIntervalTimeout = MAXDWORD;
1168 port->timeouts.ReadTotalTimeoutConstant = 0;
1169 if (SetCommTimeouts(port->hdl, &port->timeouts) == 0)
1170 RETURN_FAIL("SetCommTimeouts() failed");
1173 if (ReadFile(port->hdl, buf, count, NULL, &port->read_ovl) == 0)
1174 RETURN_FAIL("ReadFile() failed");
1176 /* Get number of bytes read. */
1177 if (GetOverlappedResult(port->hdl, &port->read_ovl, &bytes_read, TRUE) == 0)
1178 RETURN_FAIL("GetOverlappedResult() failed");
1180 if (bytes_read > 0) {
1181 /* Start background operation for subsequent events. */
1182 if (WaitCommEvent(port->hdl, &port->events, &port->wait_ovl) == 0) {
1183 if (GetLastError() != ERROR_IO_PENDING)
1184 RETURN_FAIL("WaitCommEvent() failed");
1188 RETURN_VALUE("%d", bytes_read);
1192 /* Returns the number of bytes read, or -1 upon failure. */
1193 if ((bytes_read = read(port->fd, buf, count)) < 0) {
1194 if (errno == EAGAIN)
1195 /* No bytes available. */
1198 /* This is an actual failure. */
1199 RETURN_FAIL("read() failed");
1201 RETURN_VALUE("%d", bytes_read);
1205 enum sp_return sp_input_waiting(struct sp_port *port)
1211 DEBUG("Checking input bytes waiting on port %s", port->name);
1217 if (ClearCommError(port->hdl, &errors, &comstat) == 0)
1218 RETURN_FAIL("ClearCommError() failed");
1219 RETURN_VALUE("%d", comstat.cbInQue);
1222 if (ioctl(port->fd, TIOCINQ, &bytes_waiting) < 0)
1223 RETURN_FAIL("TIOCINQ ioctl failed");
1224 RETURN_VALUE("%d", bytes_waiting);
1228 enum sp_return sp_output_waiting(struct sp_port *port)
1234 DEBUG("Checking output bytes waiting on port %s", port->name);
1240 if (ClearCommError(port->hdl, &errors, &comstat) == 0)
1241 RETURN_FAIL("ClearCommError() failed");
1242 RETURN_VALUE("%d", comstat.cbOutQue);
1245 if (ioctl(port->fd, TIOCOUTQ, &bytes_waiting) < 0)
1246 RETURN_FAIL("TIOCOUTQ ioctl failed");
1247 RETURN_VALUE("%d", bytes_waiting);
1251 enum sp_return sp_new_event_set(struct sp_event_set **result_ptr)
1253 struct sp_event_set *result;
1255 TRACE("%p", result_ptr);
1258 RETURN_ERROR(SP_ERR_ARG, "Null result");
1262 if (!(result = malloc(sizeof(struct sp_event_set))))
1263 RETURN_ERROR(SP_ERR_MEM, "sp_event_set malloc() failed");
1265 memset(result, 0, sizeof(struct sp_event_set));
1267 *result_ptr = result;
1272 static enum sp_return add_handle(struct sp_event_set *event_set,
1273 event_handle handle, enum sp_event mask)
1276 enum sp_event *new_masks;
1278 TRACE("%p, %d, %d", event_set, handle, mask);
1280 if (!(new_handles = realloc(event_set->handles,
1281 sizeof(event_handle) * (event_set->count + 1))))
1282 RETURN_ERROR(SP_ERR_MEM, "handle array realloc() failed");
1284 if (!(new_masks = realloc(event_set->masks,
1285 sizeof(enum sp_event) * (event_set->count + 1))))
1286 RETURN_ERROR(SP_ERR_MEM, "mask array realloc() failed");
1288 event_set->handles = new_handles;
1289 event_set->masks = new_masks;
1291 ((event_handle *) event_set->handles)[event_set->count] = handle;
1292 event_set->masks[event_set->count] = mask;
1299 enum sp_return sp_add_port_events(struct sp_event_set *event_set,
1300 const struct sp_port *port, enum sp_event mask)
1302 TRACE("%p, %p, %d", event_set, port, mask);
1305 RETURN_ERROR(SP_ERR_ARG, "Null event set");
1308 RETURN_ERROR(SP_ERR_ARG, "Null port");
1310 if (mask > (SP_EVENT_RX_READY | SP_EVENT_TX_READY | SP_EVENT_ERROR))
1311 RETURN_ERROR(SP_ERR_ARG, "Invalid event mask");
1317 enum sp_event handle_mask;
1318 if ((handle_mask = mask & SP_EVENT_TX_READY))
1319 TRY(add_handle(event_set, port->write_ovl.hEvent, handle_mask));
1320 if ((handle_mask = mask & (SP_EVENT_RX_READY | SP_EVENT_ERROR)))
1321 TRY(add_handle(event_set, port->wait_ovl.hEvent, handle_mask));
1323 TRY(add_handle(event_set, port->fd, mask));
1329 void sp_free_event_set(struct sp_event_set *event_set)
1331 TRACE("%p", event_set);
1334 DEBUG("Null event set");
1338 DEBUG("Freeing event set");
1340 if (event_set->handles)
1341 free(event_set->handles);
1342 if (event_set->masks)
1343 free(event_set->masks);
1350 enum sp_return sp_wait(struct sp_event_set *event_set, unsigned int timeout)
1352 TRACE("%p, %d", event_set, timeout);
1355 RETURN_ERROR(SP_ERR_ARG, "Null event set");
1358 if (WaitForMultipleObjects(event_set->count, event_set->handles, FALSE,
1359 timeout ? timeout : INFINITE) == WAIT_FAILED)
1360 RETURN_FAIL("WaitForMultipleObjects() failed");
1364 struct timeval start, delta, now, end = {0, 0};
1365 int result, timeout_remaining;
1366 struct pollfd *pollfds;
1369 if (!(pollfds = malloc(sizeof(struct pollfd) * event_set->count)))
1370 RETURN_ERROR(SP_ERR_MEM, "pollfds malloc() failed");
1372 for (i = 0; i < event_set->count; i++) {
1373 pollfds[i].fd = ((int *) event_set->handles)[i];
1374 pollfds[i].events = 0;
1375 pollfds[i].revents = 0;
1376 if (event_set->masks[i] & SP_EVENT_RX_READY)
1377 pollfds[i].events |= POLLIN;
1378 if (event_set->masks[i] & SP_EVENT_TX_READY)
1379 pollfds[i].events |= POLLOUT;
1380 if (event_set->masks[i] & SP_EVENT_ERROR)
1381 pollfds[i].events |= POLLERR;
1385 /* Get time at start of operation. */
1386 gettimeofday(&start, NULL);
1387 /* Define duration of timeout. */
1388 delta.tv_sec = timeout / 1000;
1389 delta.tv_usec = (timeout % 1000) * 1000;
1390 /* Calculate time at which we should give up. */
1391 timeradd(&start, &delta, &end);
1394 /* Loop until an event occurs. */
1398 gettimeofday(&now, NULL);
1399 if (timercmp(&now, &end, >)) {
1400 DEBUG("wait timed out");
1403 timersub(&end, &now, &delta);
1404 timeout_remaining = delta.tv_sec * 1000 + delta.tv_usec / 1000;
1407 result = poll(pollfds, event_set->count, timeout ? timeout_remaining : -1);
1410 if (errno == EINTR) {
1411 DEBUG("poll() call was interrupted, repeating");
1415 RETURN_FAIL("poll() failed");
1417 } else if (result == 0) {
1418 DEBUG("poll() timed out");
1421 DEBUG("poll() completed");
1431 #ifdef USE_TERMIOS_SPEED
1432 static enum sp_return get_baudrate(int fd, int *baudrate)
1436 TRACE("%d, %p", fd, baudrate);
1438 DEBUG("Getting baud rate");
1440 if (!(data = malloc(get_termios_size())))
1441 RETURN_ERROR(SP_ERR_MEM, "termios malloc failed");
1443 if (ioctl(fd, get_termios_get_ioctl(), data) < 0) {
1445 RETURN_FAIL("getting termios failed");
1448 *baudrate = get_termios_speed(data);
1455 static enum sp_return set_baudrate(int fd, int baudrate)
1459 TRACE("%d, %d", fd, baudrate);
1461 DEBUG("Getting baud rate");
1463 if (!(data = malloc(get_termios_size())))
1464 RETURN_ERROR(SP_ERR_MEM, "termios malloc failed");
1466 if (ioctl(fd, get_termios_get_ioctl(), data) < 0) {
1468 RETURN_FAIL("getting termios failed");
1471 DEBUG("Setting baud rate");
1473 set_termios_speed(data, baudrate);
1475 if (ioctl(fd, get_termios_set_ioctl(), data) < 0) {
1477 RETURN_FAIL("setting termios failed");
1484 #endif /* USE_TERMIOS_SPEED */
1487 static enum sp_return get_flow(int fd, struct port_data *data)
1491 TRACE("%d, %p", fd, data);
1493 DEBUG("Getting advanced flow control");
1495 if (!(termx = malloc(get_termiox_size())))
1496 RETURN_ERROR(SP_ERR_MEM, "termiox malloc failed");
1498 if (ioctl(fd, TCGETX, termx) < 0) {
1500 RETURN_FAIL("getting termiox failed");
1503 get_termiox_flow(termx, &data->rts_flow, &data->cts_flow,
1504 &data->dtr_flow, &data->dsr_flow);
1511 static enum sp_return set_flow(int fd, struct port_data *data)
1515 TRACE("%d, %p", fd, data);
1517 DEBUG("Getting advanced flow control");
1519 if (!(termx = malloc(get_termiox_size())))
1520 RETURN_ERROR(SP_ERR_MEM, "termiox malloc failed");
1522 if (ioctl(fd, TCGETX, termx) < 0) {
1524 RETURN_FAIL("getting termiox failed");
1527 DEBUG("Setting advanced flow control");
1529 set_termiox_flow(termx, data->rts_flow, data->cts_flow,
1530 data->dtr_flow, data->dsr_flow);
1532 if (ioctl(fd, TCSETX, termx) < 0) {
1534 RETURN_FAIL("setting termiox failed");
1541 #endif /* USE_TERMIOX */
1543 static enum sp_return get_config(struct sp_port *port, struct port_data *data,
1544 struct sp_port_config *config)
1548 TRACE("%p, %p, %p", port, data, config);
1550 DEBUG("Getting configuration for port %s", port->name);
1553 if (!GetCommState(port->hdl, &data->dcb))
1554 RETURN_FAIL("GetCommState() failed");
1556 for (i = 0; i < NUM_STD_BAUDRATES; i++) {
1557 if (data->dcb.BaudRate == std_baudrates[i].index) {
1558 config->baudrate = std_baudrates[i].value;
1563 if (i == NUM_STD_BAUDRATES)
1564 /* BaudRate field can be either an index or a custom baud rate. */
1565 config->baudrate = data->dcb.BaudRate;
1567 config->bits = data->dcb.ByteSize;
1569 if (data->dcb.fParity)
1570 switch (data->dcb.Parity) {
1572 config->parity = SP_PARITY_NONE;
1575 config->parity = SP_PARITY_ODD;
1578 config->parity = SP_PARITY_EVEN;
1581 config->parity = SP_PARITY_MARK;
1584 config->parity = SP_PARITY_SPACE;
1587 config->parity = -1;
1590 config->parity = SP_PARITY_NONE;
1592 switch (data->dcb.StopBits) {
1594 config->stopbits = 1;
1597 config->stopbits = 2;
1600 config->stopbits = -1;
1603 switch (data->dcb.fRtsControl) {
1604 case RTS_CONTROL_DISABLE:
1605 config->rts = SP_RTS_OFF;
1607 case RTS_CONTROL_ENABLE:
1608 config->rts = SP_RTS_ON;
1610 case RTS_CONTROL_HANDSHAKE:
1611 config->rts = SP_RTS_FLOW_CONTROL;
1617 config->cts = data->dcb.fOutxCtsFlow ? SP_CTS_FLOW_CONTROL : SP_CTS_IGNORE;
1619 switch (data->dcb.fDtrControl) {
1620 case DTR_CONTROL_DISABLE:
1621 config->dtr = SP_DTR_OFF;
1623 case DTR_CONTROL_ENABLE:
1624 config->dtr = SP_DTR_ON;
1626 case DTR_CONTROL_HANDSHAKE:
1627 config->dtr = SP_DTR_FLOW_CONTROL;
1633 config->dsr = data->dcb.fOutxDsrFlow ? SP_DSR_FLOW_CONTROL : SP_DSR_IGNORE;
1635 if (data->dcb.fInX) {
1636 if (data->dcb.fOutX)
1637 config->xon_xoff = SP_XONXOFF_INOUT;
1639 config->xon_xoff = SP_XONXOFF_IN;
1641 if (data->dcb.fOutX)
1642 config->xon_xoff = SP_XONXOFF_OUT;
1644 config->xon_xoff = SP_XONXOFF_DISABLED;
1649 if (tcgetattr(port->fd, &data->term) < 0)
1650 RETURN_FAIL("tcgetattr() failed");
1652 if (ioctl(port->fd, TIOCMGET, &data->controlbits) < 0)
1653 RETURN_FAIL("TIOCMGET ioctl failed");
1656 int ret = get_flow(port->fd, data);
1658 if (ret == SP_ERR_FAIL && errno == EINVAL)
1659 data->termiox_supported = 0;
1661 RETURN_CODEVAL(ret);
1663 data->termiox_supported = 1;
1665 data->termiox_supported = 0;
1668 for (i = 0; i < NUM_STD_BAUDRATES; i++) {
1669 if (cfgetispeed(&data->term) == std_baudrates[i].index) {
1670 config->baudrate = std_baudrates[i].value;
1675 if (i == NUM_STD_BAUDRATES) {
1677 config->baudrate = (int)data->term.c_ispeed;
1678 #elif defined(USE_TERMIOS_SPEED)
1679 TRY(get_baudrate(port->fd, &config->baudrate));
1681 config->baudrate = -1;
1685 switch (data->term.c_cflag & CSIZE) {
1702 if (!(data->term.c_cflag & PARENB) && (data->term.c_iflag & IGNPAR))
1703 config->parity = SP_PARITY_NONE;
1704 else if (!(data->term.c_cflag & PARENB) || (data->term.c_iflag & IGNPAR))
1705 config->parity = -1;
1707 else if (data->term.c_cflag & CMSPAR)
1708 config->parity = (data->term.c_cflag & PARODD) ? SP_PARITY_MARK : SP_PARITY_SPACE;
1711 config->parity = (data->term.c_cflag & PARODD) ? SP_PARITY_ODD : SP_PARITY_EVEN;
1713 config->stopbits = (data->term.c_cflag & CSTOPB) ? 2 : 1;
1715 if (data->term.c_cflag & CRTSCTS) {
1716 config->rts = SP_RTS_FLOW_CONTROL;
1717 config->cts = SP_CTS_FLOW_CONTROL;
1719 if (data->termiox_supported && data->rts_flow)
1720 config->rts = SP_RTS_FLOW_CONTROL;
1722 config->rts = (data->controlbits & TIOCM_RTS) ? SP_RTS_ON : SP_RTS_OFF;
1724 config->cts = (data->termiox_supported && data->cts_flow) ?
1725 SP_CTS_FLOW_CONTROL : SP_CTS_IGNORE;
1728 if (data->termiox_supported && data->dtr_flow)
1729 config->dtr = SP_DTR_FLOW_CONTROL;
1731 config->dtr = (data->controlbits & TIOCM_DTR) ? SP_DTR_ON : SP_DTR_OFF;
1733 config->dsr = (data->termiox_supported && data->dsr_flow) ?
1734 SP_DSR_FLOW_CONTROL : SP_DSR_IGNORE;
1736 if (data->term.c_iflag & IXOFF) {
1737 if (data->term.c_iflag & IXON)
1738 config->xon_xoff = SP_XONXOFF_INOUT;
1740 config->xon_xoff = SP_XONXOFF_IN;
1742 if (data->term.c_iflag & IXON)
1743 config->xon_xoff = SP_XONXOFF_OUT;
1745 config->xon_xoff = SP_XONXOFF_DISABLED;
1752 static enum sp_return set_config(struct sp_port *port, struct port_data *data,
1753 const struct sp_port_config *config)
1757 BAUD_TYPE baud_nonstd;
1761 #ifdef USE_TERMIOS_SPEED
1762 int baud_nonstd = 0;
1765 TRACE("%p, %p, %p", port, data, config);
1767 DEBUG("Setting configuration for port %s", port->name);
1770 if (config->baudrate >= 0) {
1771 for (i = 0; i < NUM_STD_BAUDRATES; i++) {
1772 if (config->baudrate == std_baudrates[i].value) {
1773 data->dcb.BaudRate = std_baudrates[i].index;
1778 if (i == NUM_STD_BAUDRATES)
1779 data->dcb.BaudRate = config->baudrate;
1782 if (config->bits >= 0)
1783 data->dcb.ByteSize = config->bits;
1785 if (config->parity >= 0) {
1786 switch (config->parity) {
1787 case SP_PARITY_NONE:
1788 data->dcb.Parity = NOPARITY;
1791 data->dcb.Parity = ODDPARITY;
1793 case SP_PARITY_EVEN:
1794 data->dcb.Parity = EVENPARITY;
1796 case SP_PARITY_MARK:
1797 data->dcb.Parity = MARKPARITY;
1799 case SP_PARITY_SPACE:
1800 data->dcb.Parity = SPACEPARITY;
1803 RETURN_ERROR(SP_ERR_ARG, "Invalid parity setting");
1807 if (config->stopbits >= 0) {
1808 switch (config->stopbits) {
1809 /* Note: There's also ONE5STOPBITS == 1.5 (unneeded so far). */
1811 data->dcb.StopBits = ONESTOPBIT;
1814 data->dcb.StopBits = TWOSTOPBITS;
1817 RETURN_ERROR(SP_ERR_ARG, "Invalid stop bit setting");
1821 if (config->rts >= 0) {
1822 switch (config->rts) {
1824 data->dcb.fRtsControl = RTS_CONTROL_DISABLE;
1827 data->dcb.fRtsControl = RTS_CONTROL_ENABLE;
1829 case SP_RTS_FLOW_CONTROL:
1830 data->dcb.fRtsControl = RTS_CONTROL_HANDSHAKE;
1833 RETURN_ERROR(SP_ERR_ARG, "Invalid RTS setting");
1837 if (config->cts >= 0) {
1838 switch (config->cts) {
1840 data->dcb.fOutxCtsFlow = FALSE;
1842 case SP_CTS_FLOW_CONTROL:
1843 data->dcb.fOutxCtsFlow = TRUE;
1846 RETURN_ERROR(SP_ERR_ARG, "Invalid CTS setting");
1850 if (config->dtr >= 0) {
1851 switch (config->dtr) {
1853 data->dcb.fDtrControl = DTR_CONTROL_DISABLE;
1856 data->dcb.fDtrControl = DTR_CONTROL_ENABLE;
1858 case SP_DTR_FLOW_CONTROL:
1859 data->dcb.fDtrControl = DTR_CONTROL_HANDSHAKE;
1862 RETURN_ERROR(SP_ERR_ARG, "Invalid DTR setting");
1866 if (config->dsr >= 0) {
1867 switch (config->dsr) {
1869 data->dcb.fOutxDsrFlow = FALSE;
1871 case SP_DSR_FLOW_CONTROL:
1872 data->dcb.fOutxDsrFlow = TRUE;
1875 RETURN_ERROR(SP_ERR_ARG, "Invalid DSR setting");
1879 if (config->xon_xoff >= 0) {
1880 switch (config->xon_xoff) {
1881 case SP_XONXOFF_DISABLED:
1882 data->dcb.fInX = FALSE;
1883 data->dcb.fOutX = FALSE;
1886 data->dcb.fInX = TRUE;
1887 data->dcb.fOutX = FALSE;
1889 case SP_XONXOFF_OUT:
1890 data->dcb.fInX = FALSE;
1891 data->dcb.fOutX = TRUE;
1893 case SP_XONXOFF_INOUT:
1894 data->dcb.fInX = TRUE;
1895 data->dcb.fOutX = TRUE;
1898 RETURN_ERROR(SP_ERR_ARG, "Invalid XON/XOFF setting");
1902 if (!SetCommState(port->hdl, &data->dcb))
1903 RETURN_FAIL("SetCommState() failed");
1909 if (config->baudrate >= 0) {
1910 for (i = 0; i < NUM_STD_BAUDRATES; i++) {
1911 if (config->baudrate == std_baudrates[i].value) {
1912 if (cfsetospeed(&data->term, std_baudrates[i].index) < 0)
1913 RETURN_FAIL("cfsetospeed() failed");
1915 if (cfsetispeed(&data->term, std_baudrates[i].index) < 0)
1916 RETURN_FAIL("cfsetispeed() failed");
1921 /* Non-standard baud rate */
1922 if (i == NUM_STD_BAUDRATES) {
1924 /* Set "dummy" baud rate. */
1925 if (cfsetspeed(&data->term, B9600) < 0)
1926 RETURN_FAIL("cfsetspeed() failed");
1927 baud_nonstd = config->baudrate;
1928 #elif defined(USE_TERMIOS_SPEED)
1931 RETURN_ERROR(SP_ERR_SUPP, "Non-standard baudrate not supported");
1936 if (config->bits >= 0) {
1937 data->term.c_cflag &= ~CSIZE;
1938 switch (config->bits) {
1940 data->term.c_cflag |= CS8;
1943 data->term.c_cflag |= CS7;
1946 data->term.c_cflag |= CS6;
1949 data->term.c_cflag |= CS5;
1952 RETURN_ERROR(SP_ERR_ARG, "Invalid data bits setting");
1956 if (config->parity >= 0) {
1957 data->term.c_iflag &= ~IGNPAR;
1958 data->term.c_cflag &= ~(PARENB | PARODD);
1960 data->term.c_cflag &= ~CMSPAR;
1962 switch (config->parity) {
1963 case SP_PARITY_NONE:
1964 data->term.c_iflag |= IGNPAR;
1966 case SP_PARITY_EVEN:
1967 data->term.c_cflag |= PARENB;
1970 data->term.c_cflag |= PARENB | PARODD;
1973 case SP_PARITY_MARK:
1974 data->term.c_cflag |= PARENB | PARODD;
1975 data->term.c_cflag |= CMSPAR;
1977 case SP_PARITY_SPACE:
1978 data->term.c_cflag |= PARENB;
1979 data->term.c_cflag |= CMSPAR;
1982 case SP_PARITY_MARK:
1983 case SP_PARITY_SPACE:
1984 RETURN_ERROR(SP_ERR_SUPP, "Mark/space parity not supported");
1987 RETURN_ERROR(SP_ERR_ARG, "Invalid parity setting");
1991 if (config->stopbits >= 0) {
1992 data->term.c_cflag &= ~CSTOPB;
1993 switch (config->stopbits) {
1995 data->term.c_cflag &= ~CSTOPB;
1998 data->term.c_cflag |= CSTOPB;
2001 RETURN_ERROR(SP_ERR_ARG, "Invalid stop bits setting");
2005 if (config->rts >= 0 || config->cts >= 0) {
2006 if (data->termiox_supported) {
2007 data->rts_flow = data->cts_flow = 0;
2008 switch (config->rts) {
2011 controlbits = TIOCM_RTS;
2012 if (ioctl(port->fd, config->rts == SP_RTS_ON ? TIOCMBIS : TIOCMBIC, &controlbits) < 0)
2013 RETURN_FAIL("Setting RTS signal level failed");
2015 case SP_RTS_FLOW_CONTROL:
2021 if (config->cts == SP_CTS_FLOW_CONTROL)
2024 if (data->rts_flow && data->cts_flow)
2025 data->term.c_iflag |= CRTSCTS;
2027 data->term.c_iflag &= ~CRTSCTS;
2029 /* Asymmetric use of RTS/CTS not supported. */
2030 if (data->term.c_iflag & CRTSCTS) {
2031 /* Flow control can only be disabled for both RTS & CTS together. */
2032 if (config->rts >= 0 && config->rts != SP_RTS_FLOW_CONTROL) {
2033 if (config->cts != SP_CTS_IGNORE)
2034 RETURN_ERROR(SP_ERR_SUPP, "RTS & CTS flow control must be disabled together");
2036 if (config->cts >= 0 && config->cts != SP_CTS_FLOW_CONTROL) {
2037 if (config->rts <= 0 || config->rts == SP_RTS_FLOW_CONTROL)
2038 RETURN_ERROR(SP_ERR_SUPP, "RTS & CTS flow control must be disabled together");
2041 /* Flow control can only be enabled for both RTS & CTS together. */
2042 if (((config->rts == SP_RTS_FLOW_CONTROL) && (config->cts != SP_CTS_FLOW_CONTROL)) ||
2043 ((config->cts == SP_CTS_FLOW_CONTROL) && (config->rts != SP_RTS_FLOW_CONTROL)))
2044 RETURN_ERROR(SP_ERR_SUPP, "RTS & CTS flow control must be enabled together");
2047 if (config->rts >= 0) {
2048 if (config->rts == SP_RTS_FLOW_CONTROL) {
2049 data->term.c_iflag |= CRTSCTS;
2051 controlbits = TIOCM_RTS;
2052 if (ioctl(port->fd, config->rts == SP_RTS_ON ? TIOCMBIS : TIOCMBIC,
2054 RETURN_FAIL("Setting RTS signal level failed");
2060 if (config->dtr >= 0 || config->dsr >= 0) {
2061 if (data->termiox_supported) {
2062 data->dtr_flow = data->dsr_flow = 0;
2063 switch (config->dtr) {
2066 controlbits = TIOCM_DTR;
2067 if (ioctl(port->fd, config->dtr == SP_DTR_ON ? TIOCMBIS : TIOCMBIC, &controlbits) < 0)
2068 RETURN_FAIL("Setting DTR signal level failed");
2070 case SP_DTR_FLOW_CONTROL:
2076 if (config->dsr == SP_DSR_FLOW_CONTROL)
2079 /* DTR/DSR flow control not supported. */
2080 if (config->dtr == SP_DTR_FLOW_CONTROL || config->dsr == SP_DSR_FLOW_CONTROL)
2081 RETURN_ERROR(SP_ERR_SUPP, "DTR/DSR flow control not supported");
2083 if (config->dtr >= 0) {
2084 controlbits = TIOCM_DTR;
2085 if (ioctl(port->fd, config->dtr == SP_DTR_ON ? TIOCMBIS : TIOCMBIC,
2087 RETURN_FAIL("Setting DTR signal level failed");
2092 if (config->xon_xoff >= 0) {
2093 data->term.c_iflag &= ~(IXON | IXOFF | IXANY);
2094 switch (config->xon_xoff) {
2095 case SP_XONXOFF_DISABLED:
2098 data->term.c_iflag |= IXOFF;
2100 case SP_XONXOFF_OUT:
2101 data->term.c_iflag |= IXON | IXANY;
2103 case SP_XONXOFF_INOUT:
2104 data->term.c_iflag |= IXON | IXOFF | IXANY;
2107 RETURN_ERROR(SP_ERR_ARG, "Invalid XON/XOFF setting");
2111 if (tcsetattr(port->fd, TCSANOW, &data->term) < 0)
2112 RETURN_FAIL("tcsetattr() failed");
2115 if (baud_nonstd != B0) {
2116 if (ioctl(port->fd, IOSSIOSPEED, &baud_nonstd) == -1)
2117 RETURN_FAIL("IOSSIOSPEED ioctl failed");
2118 /* Set baud rates in data->term to correct, but incompatible
2119 * with tcsetattr() value, same as delivered by tcgetattr(). */
2120 if (cfsetspeed(&data->term, baud_nonstd) < 0)
2121 RETURN_FAIL("cfsetspeed() failed");
2123 #elif defined(__linux__)
2124 #ifdef USE_TERMIOS_SPEED
2126 TRY(set_baudrate(port->fd, config->baudrate));
2129 if (data->termiox_supported)
2130 TRY(set_flow(port->fd, data));
2134 #endif /* !_WIN32 */
2139 enum sp_return sp_new_config(struct sp_port_config **config_ptr)
2141 struct sp_port_config *config;
2143 TRACE("%p", config_ptr);
2146 RETURN_ERROR(SP_ERR_ARG, "Null result pointer");
2150 if (!(config = malloc(sizeof(struct sp_port_config))))
2151 RETURN_ERROR(SP_ERR_MEM, "config malloc failed");
2153 config->baudrate = -1;
2155 config->parity = -1;
2156 config->stopbits = -1;
2162 *config_ptr = config;
2167 void sp_free_config(struct sp_port_config *config)
2169 TRACE("%p", config);
2172 DEBUG("Null config");
2179 enum sp_return sp_get_config(struct sp_port *port, struct sp_port_config *config)
2181 struct port_data data;
2183 TRACE("%p, %p", port, config);
2188 RETURN_ERROR(SP_ERR_ARG, "Null config");
2190 TRY(get_config(port, &data, config));
2195 enum sp_return sp_set_config(struct sp_port *port, const struct sp_port_config *config)
2197 struct port_data data;
2198 struct sp_port_config prev_config;
2200 TRACE("%p, %p", port, config);
2205 RETURN_ERROR(SP_ERR_ARG, "Null config");
2207 TRY(get_config(port, &data, &prev_config));
2208 TRY(set_config(port, &data, config));
2213 #define CREATE_ACCESSORS(x, type) \
2214 enum sp_return sp_set_##x(struct sp_port *port, type x) { \
2215 struct port_data data; \
2216 struct sp_port_config config; \
2217 TRACE("%p, %d", port, x); \
2218 CHECK_OPEN_PORT(); \
2219 TRY(get_config(port, &data, &config)); \
2221 TRY(set_config(port, &data, &config)); \
2224 enum sp_return sp_get_config_##x(const struct sp_port_config *config, type *x) { \
2225 TRACE("%p, %p", config, x); \
2227 RETURN_ERROR(SP_ERR_ARG, "Null config"); \
2231 enum sp_return sp_set_config_##x(struct sp_port_config *config, type x) { \
2232 TRACE("%p, %d", config, x); \
2234 RETURN_ERROR(SP_ERR_ARG, "Null config"); \
2239 CREATE_ACCESSORS(baudrate, int)
2240 CREATE_ACCESSORS(bits, int)
2241 CREATE_ACCESSORS(parity, enum sp_parity)
2242 CREATE_ACCESSORS(stopbits, int)
2243 CREATE_ACCESSORS(rts, enum sp_rts)
2244 CREATE_ACCESSORS(cts, enum sp_cts)
2245 CREATE_ACCESSORS(dtr, enum sp_dtr)
2246 CREATE_ACCESSORS(dsr, enum sp_dsr)
2247 CREATE_ACCESSORS(xon_xoff, enum sp_xonxoff)
2249 enum sp_return sp_set_config_flowcontrol(struct sp_port_config *config, enum sp_flowcontrol flowcontrol)
2252 RETURN_ERROR(SP_ERR_ARG, "Null configuration");
2254 if (flowcontrol > SP_FLOWCONTROL_DTRDSR)
2255 RETURN_ERROR(SP_ERR_ARG, "Invalid flow control setting");
2257 if (flowcontrol == SP_FLOWCONTROL_XONXOFF)
2258 config->xon_xoff = SP_XONXOFF_INOUT;
2260 config->xon_xoff = SP_XONXOFF_DISABLED;
2262 if (flowcontrol == SP_FLOWCONTROL_RTSCTS) {
2263 config->rts = SP_RTS_FLOW_CONTROL;
2264 config->cts = SP_CTS_FLOW_CONTROL;
2266 if (config->rts == SP_RTS_FLOW_CONTROL)
2267 config->rts = SP_RTS_ON;
2268 config->cts = SP_CTS_IGNORE;
2271 if (flowcontrol == SP_FLOWCONTROL_DTRDSR) {
2272 config->dtr = SP_DTR_FLOW_CONTROL;
2273 config->dsr = SP_DSR_FLOW_CONTROL;
2275 if (config->dtr == SP_DTR_FLOW_CONTROL)
2276 config->dtr = SP_DTR_ON;
2277 config->dsr = SP_DSR_IGNORE;
2283 enum sp_return sp_set_flowcontrol(struct sp_port *port, enum sp_flowcontrol flowcontrol)
2285 struct port_data data;
2286 struct sp_port_config config;
2288 TRACE("%p, %d", port, flowcontrol);
2292 TRY(get_config(port, &data, &config));
2294 TRY(sp_set_config_flowcontrol(&config, flowcontrol));
2296 TRY(set_config(port, &data, &config));
2301 enum sp_return sp_get_signals(struct sp_port *port, enum sp_signal *signals)
2303 TRACE("%p, %p", port, signals);
2308 RETURN_ERROR(SP_ERR_ARG, "Null result pointer");
2310 DEBUG("Getting control signals for port %s", port->name);
2315 if (GetCommModemStatus(port->hdl, &bits) == 0)
2316 RETURN_FAIL("GetCommModemStatus() failed");
2317 if (bits & MS_CTS_ON)
2318 *signals |= SP_SIG_CTS;
2319 if (bits & MS_DSR_ON)
2320 *signals |= SP_SIG_DSR;
2321 if (bits & MS_RLSD_ON)
2322 *signals |= SP_SIG_DCD;
2323 if (bits & MS_RING_ON)
2324 *signals |= SP_SIG_RI;
2327 if (ioctl(port->fd, TIOCMGET, &bits) < 0)
2328 RETURN_FAIL("TIOCMGET ioctl failed");
2329 if (bits & TIOCM_CTS)
2330 *signals |= SP_SIG_CTS;
2331 if (bits & TIOCM_DSR)
2332 *signals |= SP_SIG_DSR;
2333 if (bits & TIOCM_CAR)
2334 *signals |= SP_SIG_DCD;
2335 if (bits & TIOCM_RNG)
2336 *signals |= SP_SIG_RI;
2341 enum sp_return sp_start_break(struct sp_port *port)
2347 if (SetCommBreak(port->hdl) == 0)
2348 RETURN_FAIL("SetCommBreak() failed");
2350 if (ioctl(port->fd, TIOCSBRK, 1) < 0)
2351 RETURN_FAIL("TIOCSBRK ioctl failed");
2357 enum sp_return sp_end_break(struct sp_port *port)
2363 if (ClearCommBreak(port->hdl) == 0)
2364 RETURN_FAIL("ClearCommBreak() failed");
2366 if (ioctl(port->fd, TIOCCBRK, 1) < 0)
2367 RETURN_FAIL("TIOCCBRK ioctl failed");
2373 int sp_last_error_code(void)
2377 RETURN_VALUE("%d", GetLastError());
2379 RETURN_VALUE("%d", errno);
2383 char *sp_last_error_message(void)
2389 DWORD error = GetLastError();
2392 FORMAT_MESSAGE_ALLOCATE_BUFFER |
2393 FORMAT_MESSAGE_FROM_SYSTEM |
2394 FORMAT_MESSAGE_IGNORE_INSERTS,
2397 MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
2401 RETURN_VALUE("%s", message);
2403 RETURN_VALUE("%s", strerror(errno));
2407 void sp_free_error_message(char *message)
2409 TRACE("%s", message);
2420 void sp_set_debug_handler(void (*handler)(const char *format, ...))
2422 TRACE("%p", handler);
2424 sp_debug_handler = handler;
2429 void sp_default_debug_handler(const char *format, ...)
2432 va_start(args, format);
2433 if (getenv("LIBSERIALPORT_DEBUG")) {
2434 fputs("sp: ", stderr);
2435 vfprintf(stderr, format, args);
2440 int sp_get_major_package_version(void)
2442 return SP_PACKAGE_VERSION_MAJOR;
2445 int sp_get_minor_package_version(void)
2447 return SP_PACKAGE_VERSION_MINOR;
2450 int sp_get_micro_package_version(void)
2452 return SP_PACKAGE_VERSION_MICRO;
2455 const char *sp_get_package_version_string(void)
2457 return SP_PACKAGE_VERSION_STRING;
2460 int sp_get_current_lib_version(void)
2462 return SP_LIB_VERSION_CURRENT;
2465 int sp_get_revision_lib_version(void)
2467 return SP_LIB_VERSION_REVISION;
2470 int sp_get_age_lib_version(void)
2472 return SP_LIB_VERSION_AGE;
2475 const char *sp_get_lib_version_string(void)
2477 return SP_LIB_VERSION_STRING;