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>
8 * Copyright (C) 2014 Aurelien Jacobs <aurel@gnuage.org>
10 * This program is free software: you can redistribute it and/or modify
11 * it under the terms of the GNU Lesser General Public License as
12 * published by the Free Software Foundation, either version 3 of the
13 * License, or (at your option) any later version.
15 * This program is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 * GNU General Public License for more details.
20 * You should have received a copy of the GNU Lesser General Public License
21 * along with this program. If not, see <http://www.gnu.org/licenses/>.
24 #include "libserialport.h"
25 #include "libserialport_internal.h"
27 const struct std_baudrate std_baudrates[] = {
30 * The baudrates 50/75/134/150/200/1800/230400/460800 do not seem to
31 * have documented CBR_* macros.
33 BAUD(110), BAUD(300), BAUD(600), BAUD(1200), BAUD(2400), BAUD(4800),
34 BAUD(9600), BAUD(14400), BAUD(19200), BAUD(38400), BAUD(57600),
35 BAUD(115200), BAUD(128000), BAUD(256000),
37 BAUD(50), BAUD(75), BAUD(110), BAUD(134), BAUD(150), BAUD(200),
38 BAUD(300), BAUD(600), BAUD(1200), BAUD(1800), BAUD(2400), BAUD(4800),
39 BAUD(9600), BAUD(19200), BAUD(38400), BAUD(57600), BAUD(115200),
41 #if !defined(__APPLE__) && !defined(__OpenBSD__)
47 void (*sp_debug_handler)(const char *format, ...) = sp_default_debug_handler;
49 static enum sp_return get_config(struct sp_port *port, struct port_data *data,
50 struct sp_port_config *config);
52 static enum sp_return set_config(struct sp_port *port, struct port_data *data,
53 const struct sp_port_config *config);
55 enum sp_return sp_get_port_by_name(const char *portname, struct sp_port **port_ptr)
61 TRACE("%s, %p", portname, port_ptr);
64 RETURN_ERROR(SP_ERR_ARG, "Null result pointer");
69 RETURN_ERROR(SP_ERR_ARG, "Null port name");
71 DEBUG("Building structure for port %s", portname);
73 if (!(port = malloc(sizeof(struct sp_port))))
74 RETURN_ERROR(SP_ERR_MEM, "Port structure malloc failed");
76 len = strlen(portname) + 1;
78 if (!(port->name = malloc(len))) {
80 RETURN_ERROR(SP_ERR_MEM, "Port name malloc failed");
83 memcpy(port->name, portname, len);
86 port->hdl = INVALID_HANDLE_VALUE;
91 port->description = NULL;
92 port->transport = SP_TRANSPORT_NATIVE;
94 port->usb_address = -1;
97 port->usb_manufacturer = NULL;
98 port->usb_product = NULL;
99 port->usb_serial = NULL;
100 port->bluetooth_address = NULL;
102 if ((ret = get_port_details(port)) != SP_OK) {
112 char *sp_get_port_name(const struct sp_port *port)
119 RETURN_VALUE("%s", port->name);
122 char *sp_get_port_description(struct sp_port *port)
126 if (!port || !port->description)
129 RETURN_VALUE("%s", port->description);
132 enum sp_transport sp_get_port_transport(struct sp_port *port)
137 RETURN_ERROR(SP_ERR_ARG, "Null port");
139 RETURN_VALUE("%d", port->transport);
142 enum sp_return sp_get_port_usb_bus_address(const struct sp_port *port,
143 int *usb_bus, int *usb_address)
148 RETURN_ERROR(SP_ERR_ARG, "Null port");
149 if (port->transport != SP_TRANSPORT_USB)
150 RETURN_ERROR(SP_ERR_ARG, "Port does not use USB transport");
152 if (usb_bus) *usb_bus = port->usb_bus;
153 if (usb_address) *usb_address = port->usb_address;
158 enum sp_return sp_get_port_usb_vid_pid(const struct sp_port *port,
159 int *usb_vid, int *usb_pid)
164 RETURN_ERROR(SP_ERR_ARG, "Null port");
165 if (port->transport != SP_TRANSPORT_USB)
166 RETURN_ERROR(SP_ERR_ARG, "Port does not use USB transport");
168 if (usb_vid) *usb_vid = port->usb_vid;
169 if (usb_pid) *usb_pid = port->usb_pid;
174 char *sp_get_port_usb_manufacturer(const struct sp_port *port)
178 if (!port || port->transport != SP_TRANSPORT_USB || !port->usb_manufacturer)
181 RETURN_VALUE("%s", port->usb_manufacturer);
184 char *sp_get_port_usb_product(const struct sp_port *port)
188 if (!port || port->transport != SP_TRANSPORT_USB || !port->usb_product)
191 RETURN_VALUE("%s", port->usb_product);
194 char *sp_get_port_usb_serial(const struct sp_port *port)
198 if (!port || port->transport != SP_TRANSPORT_USB || !port->usb_serial)
201 RETURN_VALUE("%s", port->usb_serial);
204 char *sp_get_port_bluetooth_address(const struct sp_port *port)
208 if (!port || port->transport != SP_TRANSPORT_BLUETOOTH
209 || !port->bluetooth_address)
212 RETURN_VALUE("%s", port->bluetooth_address);
215 enum sp_return sp_get_port_handle(const struct sp_port *port, void *result_ptr)
217 TRACE("%p, %p", port, result_ptr);
220 RETURN_ERROR(SP_ERR_ARG, "Null port");
223 HANDLE *handle_ptr = result_ptr;
224 *handle_ptr = port->hdl;
226 int *fd_ptr = result_ptr;
233 enum sp_return sp_copy_port(const struct sp_port *port, struct sp_port **copy_ptr)
235 TRACE("%p, %p", port, copy_ptr);
238 RETURN_ERROR(SP_ERR_ARG, "Null result pointer");
243 RETURN_ERROR(SP_ERR_ARG, "Null port");
246 RETURN_ERROR(SP_ERR_ARG, "Null port name");
248 DEBUG("Copying port structure");
250 RETURN_VALUE("%p", sp_get_port_by_name(port->name, copy_ptr));
253 void sp_free_port(struct sp_port *port)
262 DEBUG("Freeing port structure");
266 if (port->description)
267 free(port->description);
268 if (port->usb_manufacturer)
269 free(port->usb_manufacturer);
270 if (port->usb_product)
271 free(port->usb_product);
272 if (port->usb_serial)
273 free(port->usb_serial);
274 if (port->bluetooth_address)
275 free(port->bluetooth_address);
278 free(port->usb_path);
286 static struct sp_port **list_append(struct sp_port **list, const char *portname)
291 for (count = 0; list[count]; count++);
292 if (!(tmp = realloc(list, sizeof(struct sp_port *) * (count + 2))))
295 if (sp_get_port_by_name(portname, &list[count]) != SP_OK)
297 list[count + 1] = NULL;
301 sp_free_port_list(list);
305 enum sp_return sp_list_ports(struct sp_port ***list_ptr)
307 struct sp_port **list;
308 int ret = SP_ERR_SUPP;
310 TRACE("%p", list_ptr);
313 RETURN_ERROR(SP_ERR_ARG, "Null result pointer");
315 DEBUG("Enumerating ports");
317 if (!(list = malloc(sizeof(struct sp_port **))))
318 RETURN_ERROR(SP_ERR_MEM, "Port list malloc failed");
325 DWORD max_value_len, max_data_size, max_data_len;
326 DWORD value_len, data_size, data_len;
327 DWORD type, index = 0;
333 DEBUG("Opening registry key");
334 if (RegOpenKeyEx(HKEY_LOCAL_MACHINE, _T("HARDWARE\\DEVICEMAP\\SERIALCOMM"),
335 0, KEY_QUERY_VALUE, &key) != ERROR_SUCCESS) {
336 SET_FAIL(ret, "RegOpenKeyEx() failed");
339 DEBUG("Querying registry key value and data sizes");
340 if (RegQueryInfoKey(key, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
341 &max_value_len, &max_data_size, NULL, NULL) != ERROR_SUCCESS) {
342 SET_FAIL(ret, "RegQueryInfoKey() failed");
345 max_data_len = max_data_size / sizeof(TCHAR);
346 if (!(value = malloc((max_value_len + 1) * sizeof(TCHAR)))) {
347 SET_ERROR(ret, SP_ERR_MEM, "registry value malloc failed");
350 if (!(data = malloc((max_data_len + 1) * sizeof(TCHAR)))) {
351 SET_ERROR(ret, SP_ERR_MEM, "registry data malloc failed");
354 DEBUG("Iterating over values");
356 value_len = max_value_len + 1,
357 data_size = max_data_size,
358 RegEnumValue(key, index, value, &value_len,
359 NULL, &type, (LPBYTE)data, &data_size) == ERROR_SUCCESS)
361 data_len = data_size / sizeof(TCHAR);
362 data[data_len] = '\0';
364 name_len = WideCharToMultiByte(CP_ACP, 0, data, -1, NULL, 0, NULL, NULL);
366 name_len = data_len + 1;
368 if (!(name = malloc(name_len))) {
369 SET_ERROR(ret, SP_ERR_MEM, "registry port name malloc failed");
373 WideCharToMultiByte(CP_ACP, 0, data, -1, name, name_len, NULL, NULL);
377 if (type == REG_SZ) {
378 DEBUG("Found port %s", name);
379 if (!(list = list_append(list, name))) {
380 SET_ERROR(ret, SP_ERR_MEM, "list append failed");
395 CFMutableDictionaryRef classes;
404 DEBUG("Creating matching dictionary");
405 if (!(classes = IOServiceMatching(kIOSerialBSDServiceValue))) {
406 SET_FAIL(ret, "IOServiceMatching() failed");
410 DEBUG("Getting matching services");
411 if (IOServiceGetMatchingServices(kIOMasterPortDefault, classes,
412 &iter) != KERN_SUCCESS) {
413 SET_FAIL(ret, "IOServiceGetMatchingServices() failed");
417 DEBUG("Iterating over results");
418 while ((port = IOIteratorNext(iter))) {
419 cf_path = IORegistryEntryCreateCFProperty(port,
420 CFSTR(kIOCalloutDeviceKey), kCFAllocatorDefault, 0);
422 result = CFStringGetCString(cf_path, path, sizeof(path),
423 kCFStringEncodingASCII);
426 DEBUG("Found port %s", path);
427 if (!(list = list_append(list, path))) {
428 SET_ERROR(ret, SP_ERR_MEM, "list append failed");
429 IOObjectRelease(port);
434 IOObjectRelease(port);
437 IOObjectRelease(iter);
441 char name[PATH_MAX], target[PATH_MAX];
442 struct dirent entry, *result;
443 struct serial_struct serial_info;
444 int len, fd, ioctl_result;
449 DEBUG("Enumerating tty devices");
450 if (!(dir = opendir("/sys/class/tty")))
451 RETURN_FAIL("could not open /sys/class/tty");
453 DEBUG("Iterating over results");
454 while (!readdir_r(dir, &entry, &result) && result) {
455 len = readlinkat(dirfd(dir), entry.d_name, target, sizeof(target));
456 if (len <= 0 || len >= (int) sizeof(target)-1)
459 if (strstr(target, "virtual"))
461 snprintf(name, sizeof(name), "/dev/%s", entry.d_name);
462 DEBUG("Found device %s", name);
463 if (strstr(target, "serial8250")) {
464 /* The serial8250 driver has a hardcoded number of ports.
465 * The only way to tell which actually exist on a given system
466 * is to try to open them and make an ioctl call. */
467 DEBUG("serial8250 device, attempting to open");
468 if ((fd = open(name, O_RDWR | O_NONBLOCK | O_NOCTTY)) < 0) {
469 DEBUG("open failed, skipping");
472 ioctl_result = ioctl(fd, TIOCGSERIAL, &serial_info);
474 if (ioctl_result != 0) {
475 DEBUG("ioctl failed, skipping");
478 if (serial_info.type == PORT_UNKNOWN) {
479 DEBUG("port type is unknown, skipping");
483 DEBUG("Found port %s", name);
484 list = list_append(list, name);
486 SET_ERROR(ret, SP_ERR_MEM, "list append failed");
498 DEBUG_ERROR(SP_ERR_SUPP, "Enumeration not supported on this platform");
501 sp_free_port_list(list);
507 void sp_free_port_list(struct sp_port **list)
518 DEBUG("Freeing port list");
520 for (i = 0; list[i]; i++)
521 sp_free_port(list[i]);
527 #define CHECK_PORT() do { \
529 RETURN_ERROR(SP_ERR_ARG, "Null port"); \
530 if (port->name == NULL) \
531 RETURN_ERROR(SP_ERR_ARG, "Null port name"); \
534 #define CHECK_PORT_HANDLE() do { \
535 if (port->hdl == INVALID_HANDLE_VALUE) \
536 RETURN_ERROR(SP_ERR_ARG, "Invalid port handle"); \
539 #define CHECK_PORT_HANDLE() do { \
541 RETURN_ERROR(SP_ERR_ARG, "Invalid port fd"); \
544 #define CHECK_OPEN_PORT() do { \
546 CHECK_PORT_HANDLE(); \
549 enum sp_return sp_open(struct sp_port *port, enum sp_mode flags)
551 struct port_data data;
552 struct sp_port_config config;
555 TRACE("%p, 0x%x", port, flags);
559 if (flags > (SP_MODE_READ | SP_MODE_WRITE))
560 RETURN_ERROR(SP_ERR_ARG, "Invalid flags");
562 DEBUG("Opening port %s", port->name);
565 DWORD desired_access = 0, flags_and_attributes = 0, errors;
566 char *escaped_port_name;
569 /* Prefix port name with '\\.\' to work with ports above COM9. */
570 if (!(escaped_port_name = malloc(strlen(port->name) + 5)))
571 RETURN_ERROR(SP_ERR_MEM, "Escaped port name malloc failed");
572 sprintf(escaped_port_name, "\\\\.\\%s", port->name);
574 /* Map 'flags' to the OS-specific settings. */
575 flags_and_attributes = FILE_ATTRIBUTE_NORMAL | FILE_FLAG_OVERLAPPED;
576 if (flags & SP_MODE_READ)
577 desired_access |= GENERIC_READ;
578 if (flags & SP_MODE_WRITE)
579 desired_access |= GENERIC_WRITE;
581 port->hdl = CreateFile(escaped_port_name, desired_access, 0, 0,
582 OPEN_EXISTING, flags_and_attributes, 0);
584 free(escaped_port_name);
586 if (port->hdl == INVALID_HANDLE_VALUE)
587 RETURN_FAIL("port CreateFile() failed");
589 /* All timeouts initially disabled. */
590 port->timeouts.ReadIntervalTimeout = 0;
591 port->timeouts.ReadTotalTimeoutMultiplier = 0;
592 port->timeouts.ReadTotalTimeoutConstant = 0;
593 port->timeouts.WriteTotalTimeoutMultiplier = 0;
594 port->timeouts.WriteTotalTimeoutConstant = 0;
596 if (SetCommTimeouts(port->hdl, &port->timeouts) == 0) {
598 RETURN_FAIL("SetCommTimeouts() failed");
601 /* Prepare OVERLAPPED structures. */
602 #define INIT_OVERLAPPED(ovl) do { \
603 memset(&port->ovl, 0, sizeof(port->ovl)); \
604 port->ovl.hEvent = INVALID_HANDLE_VALUE; \
605 if ((port->ovl.hEvent = CreateEvent(NULL, TRUE, TRUE, NULL)) \
606 == INVALID_HANDLE_VALUE) { \
608 RETURN_FAIL(#ovl "CreateEvent() failed"); \
612 INIT_OVERLAPPED(read_ovl);
613 INIT_OVERLAPPED(write_ovl);
614 INIT_OVERLAPPED(wait_ovl);
616 /* Set event mask for RX and error events. */
617 if (SetCommMask(port->hdl, EV_RXCHAR | EV_ERR) == 0) {
619 RETURN_FAIL("SetCommMask() failed");
622 /* Start background operation for RX and error events. */
623 if (WaitCommEvent(port->hdl, &port->events, &port->wait_ovl) == 0) {
624 if (GetLastError() != ERROR_IO_PENDING) {
626 RETURN_FAIL("WaitCommEvent() failed");
630 port->writing = FALSE;
633 int flags_local = O_NONBLOCK | O_NOCTTY;
635 /* Map 'flags' to the OS-specific settings. */
636 if (flags & (SP_MODE_READ | SP_MODE_WRITE))
637 flags_local |= O_RDWR;
638 else if (flags & SP_MODE_READ)
639 flags_local |= O_RDONLY;
640 else if (flags & SP_MODE_WRITE)
641 flags_local |= O_WRONLY;
643 if ((port->fd = open(port->name, flags_local)) < 0)
644 RETURN_FAIL("open() failed");
647 ret = get_config(port, &data, &config);
654 /* Set sane port settings. */
656 data.dcb.fBinary = TRUE;
657 data.dcb.fDsrSensitivity = FALSE;
658 data.dcb.fErrorChar = FALSE;
659 data.dcb.fNull = FALSE;
660 data.dcb.fAbortOnError = TRUE;
662 /* Turn off all fancy termios tricks, give us a raw channel. */
663 data.term.c_iflag &= ~(IGNBRK | BRKINT | PARMRK | ISTRIP | INLCR | IGNCR | ICRNL | IMAXBEL);
665 data.term.c_iflag &= ~IUCLC;
667 data.term.c_oflag &= ~(OPOST | ONLCR | OCRNL | ONOCR | ONLRET);
669 data.term.c_oflag &= ~OLCUC;
672 data.term.c_oflag &= ~NLDLY;
675 data.term.c_oflag &= ~CRDLY;
678 data.term.c_oflag &= ~TABDLY;
681 data.term.c_oflag &= ~BSDLY;
684 data.term.c_oflag &= ~VTDLY;
687 data.term.c_oflag &= ~FFDLY;
690 data.term.c_oflag &= ~OFILL;
692 data.term.c_lflag &= ~(ISIG | ICANON | ECHO | IEXTEN);
693 data.term.c_cc[VMIN] = 0;
694 data.term.c_cc[VTIME] = 0;
696 /* Ignore modem status lines; enable receiver; leave control lines alone on close. */
697 data.term.c_cflag |= (CLOCAL | CREAD | HUPCL);
701 if (ClearCommError(port->hdl, &errors, &status) == 0)
702 RETURN_FAIL("ClearCommError() failed");
705 ret = set_config(port, &data, &config);
715 enum sp_return sp_close(struct sp_port *port)
721 DEBUG("Closing port %s", port->name);
724 /* Returns non-zero upon success, 0 upon failure. */
725 if (CloseHandle(port->hdl) == 0)
726 RETURN_FAIL("port CloseHandle() failed");
727 port->hdl = INVALID_HANDLE_VALUE;
729 /* Close event handles for overlapped structures. */
730 #define CLOSE_OVERLAPPED(ovl) do { \
731 if (port->ovl.hEvent != INVALID_HANDLE_VALUE && \
732 CloseHandle(port->ovl.hEvent) == 0) \
733 RETURN_FAIL(# ovl "event CloseHandle() failed"); \
735 CLOSE_OVERLAPPED(read_ovl);
736 CLOSE_OVERLAPPED(write_ovl);
737 CLOSE_OVERLAPPED(wait_ovl);
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");
806 result = ioctl(port->fd, TCSBRK, &arg);
808 result = tcdrain(port->fd);
811 if (errno == EINTR) {
812 DEBUG("tcdrain() was interrupted");
815 RETURN_FAIL("tcdrain() failed");
824 enum sp_return sp_blocking_write(struct sp_port *port, const void *buf, size_t count, unsigned int timeout)
826 TRACE("%p, %p, %d, %d", port, buf, count, timeout);
831 RETURN_ERROR(SP_ERR_ARG, "Null buffer");
834 DEBUG("Writing %d bytes to port %s, timeout %d ms", count, port->name, timeout);
836 DEBUG("Writing %d bytes to port %s, no timeout", count, port->name);
839 RETURN_VALUE("0", 0);
842 DWORD bytes_written = 0;
845 /* Wait for previous non-blocking write to complete, if any. */
847 DEBUG("Waiting for previous write to complete");
848 result = GetOverlappedResult(port->hdl, &port->write_ovl, &bytes_written, TRUE);
851 RETURN_FAIL("Previous write failed to complete");
852 DEBUG("Previous write completed");
856 port->timeouts.WriteTotalTimeoutConstant = timeout;
857 if (SetCommTimeouts(port->hdl, &port->timeouts) == 0)
858 RETURN_FAIL("SetCommTimeouts() failed");
861 if (WriteFile(port->hdl, buf, count, NULL, &port->write_ovl) == 0) {
862 if (GetLastError() == ERROR_IO_PENDING) {
863 DEBUG("Waiting for write to complete");
864 GetOverlappedResult(port->hdl, &port->write_ovl, &bytes_written, TRUE);
865 DEBUG("Write completed, %d/%d bytes written", bytes_written, count);
866 RETURN_VALUE("%d", bytes_written);
868 RETURN_FAIL("WriteFile() failed");
871 DEBUG("Write completed immediately");
872 RETURN_VALUE("%d", count);
875 size_t bytes_written = 0;
876 unsigned char *ptr = (unsigned char *) buf;
877 struct timeval start, delta, now, end = {0, 0};
882 /* Get time at start of operation. */
883 gettimeofday(&start, NULL);
884 /* Define duration of timeout. */
885 delta.tv_sec = timeout / 1000;
886 delta.tv_usec = (timeout % 1000) * 1000;
887 /* Calculate time at which we should give up. */
888 timeradd(&start, &delta, &end);
891 /* Loop until we have written the requested number of bytes. */
892 while (bytes_written < count)
894 /* Wait until space is available. */
896 FD_SET(port->fd, &fds);
898 gettimeofday(&now, NULL);
899 if (timercmp(&now, &end, >)) {
900 DEBUG("write timed out");
901 RETURN_VALUE("%d", bytes_written);
903 timersub(&end, &now, &delta);
905 result = select(port->fd + 1, NULL, &fds, NULL, timeout ? &delta : NULL);
907 if (errno == EINTR) {
908 DEBUG("select() call was interrupted, repeating");
911 RETURN_FAIL("select() failed");
913 } else if (result == 0) {
914 DEBUG("write timed out");
915 RETURN_VALUE("%d", bytes_written);
919 result = write(port->fd, ptr, count - bytes_written);
923 /* This shouldn't happen because we did a select() first, but handle anyway. */
926 /* This is an actual failure. */
927 RETURN_FAIL("write() failed");
930 bytes_written += result;
934 RETURN_VALUE("%d", bytes_written);
938 enum sp_return sp_nonblocking_write(struct sp_port *port, const void *buf, size_t count)
940 TRACE("%p, %p, %d", port, buf, count);
945 RETURN_ERROR(SP_ERR_ARG, "Null buffer");
947 DEBUG("Writing up to %d bytes to port %s", count, port->name);
950 RETURN_VALUE("0", 0);
954 BYTE *ptr = (BYTE *) buf;
956 /* Check whether previous write is complete. */
958 if (HasOverlappedIoCompleted(&port->write_ovl)) {
959 DEBUG("Previous write completed");
962 DEBUG("Previous write not complete");
963 /* Can't take a new write until the previous one finishes. */
964 RETURN_VALUE("0", 0);
969 port->timeouts.WriteTotalTimeoutConstant = 0;
970 if (SetCommTimeouts(port->hdl, &port->timeouts) == 0)
971 RETURN_FAIL("SetCommTimeouts() failed");
973 /* Keep writing data until the OS has to actually start an async IO for it.
974 * At that point we know the buffer is full. */
975 while (written < count)
977 /* Copy first byte of user buffer. */
978 port->pending_byte = *ptr++;
980 /* Start asynchronous write. */
981 if (WriteFile(port->hdl, &port->pending_byte, 1, NULL, &port->write_ovl) == 0) {
982 if (GetLastError() == ERROR_IO_PENDING) {
983 if (HasOverlappedIoCompleted(&port->write_ovl)) {
984 DEBUG("Asynchronous write completed immediately");
989 DEBUG("Asynchronous write running");
991 RETURN_VALUE("%d", ++written);
994 /* Actual failure of some kind. */
995 RETURN_FAIL("WriteFile() failed");
998 DEBUG("Single byte written immediately");
1003 DEBUG("All bytes written immediately");
1005 RETURN_VALUE("%d", written);
1007 /* Returns the number of bytes written, or -1 upon failure. */
1008 ssize_t written = write(port->fd, buf, count);
1011 RETURN_FAIL("write() failed");
1013 RETURN_VALUE("%d", written);
1017 enum sp_return sp_blocking_read(struct sp_port *port, void *buf, size_t count, unsigned int timeout)
1019 TRACE("%p, %p, %d, %d", port, buf, count, timeout);
1024 RETURN_ERROR(SP_ERR_ARG, "Null buffer");
1027 DEBUG("Reading %d bytes from port %s, timeout %d ms", count, port->name, timeout);
1029 DEBUG("Reading %d bytes from port %s, no timeout", count, port->name);
1032 RETURN_VALUE("0", 0);
1035 DWORD bytes_read = 0;
1038 port->timeouts.ReadIntervalTimeout = 0;
1039 port->timeouts.ReadTotalTimeoutConstant = timeout;
1040 if (SetCommTimeouts(port->hdl, &port->timeouts) == 0)
1041 RETURN_FAIL("SetCommTimeouts() failed");
1044 if (ReadFile(port->hdl, buf, count, NULL, &port->read_ovl) == 0) {
1045 if (GetLastError() == ERROR_IO_PENDING) {
1046 DEBUG("Waiting for read to complete");
1047 GetOverlappedResult(port->hdl, &port->read_ovl, &bytes_read, TRUE);
1048 DEBUG("Read completed, %d/%d bytes read", bytes_read, count);
1050 RETURN_FAIL("ReadFile() failed");
1053 DEBUG("Read completed immediately");
1057 /* Start background operation for subsequent events. */
1058 if (WaitCommEvent(port->hdl, &port->events, &port->wait_ovl) == 0) {
1059 if (GetLastError() != ERROR_IO_PENDING)
1060 RETURN_FAIL("WaitCommEvent() failed");
1063 RETURN_VALUE("%d", bytes_read);
1066 size_t bytes_read = 0;
1067 unsigned char *ptr = (unsigned char *) buf;
1068 struct timeval start, delta, now, end = {0, 0};
1073 /* Get time at start of operation. */
1074 gettimeofday(&start, NULL);
1075 /* Define duration of timeout. */
1076 delta.tv_sec = timeout / 1000;
1077 delta.tv_usec = (timeout % 1000) * 1000;
1078 /* Calculate time at which we should give up. */
1079 timeradd(&start, &delta, &end);
1082 /* Loop until we have the requested number of bytes. */
1083 while (bytes_read < count)
1085 /* Wait until data is available. */
1087 FD_SET(port->fd, &fds);
1089 gettimeofday(&now, NULL);
1090 if (timercmp(&now, &end, >))
1091 /* Timeout has expired. */
1092 RETURN_VALUE("%d", bytes_read);
1093 timersub(&end, &now, &delta);
1095 result = select(port->fd + 1, &fds, NULL, NULL, timeout ? &delta : NULL);
1097 if (errno == EINTR) {
1098 DEBUG("select() call was interrupted, repeating");
1101 RETURN_FAIL("select() failed");
1103 } else if (result == 0) {
1104 DEBUG("read timed out");
1105 RETURN_VALUE("%d", bytes_read);
1109 result = read(port->fd, ptr, count - bytes_read);
1112 if (errno == EAGAIN)
1113 /* This shouldn't happen because we did a select() first, but handle anyway. */
1116 /* This is an actual failure. */
1117 RETURN_FAIL("read() failed");
1120 bytes_read += result;
1124 RETURN_VALUE("%d", bytes_read);
1128 enum sp_return sp_nonblocking_read(struct sp_port *port, void *buf, size_t count)
1130 TRACE("%p, %p, %d", port, buf, count);
1135 RETURN_ERROR(SP_ERR_ARG, "Null buffer");
1137 DEBUG("Reading up to %d bytes from port %s", count, port->name);
1143 port->timeouts.ReadIntervalTimeout = MAXDWORD;
1144 port->timeouts.ReadTotalTimeoutConstant = 0;
1145 if (SetCommTimeouts(port->hdl, &port->timeouts) == 0)
1146 RETURN_FAIL("SetCommTimeouts() failed");
1149 if (ReadFile(port->hdl, buf, count, NULL, &port->read_ovl) == 0)
1150 RETURN_FAIL("ReadFile() failed");
1152 /* Get number of bytes read. */
1153 if (GetOverlappedResult(port->hdl, &port->read_ovl, &bytes_read, TRUE) == 0)
1154 RETURN_FAIL("GetOverlappedResult() failed");
1156 if (bytes_read > 0) {
1157 /* Start background operation for subsequent events. */
1158 if (WaitCommEvent(port->hdl, &port->events, &port->wait_ovl) == 0) {
1159 if (GetLastError() != ERROR_IO_PENDING)
1160 RETURN_FAIL("WaitCommEvent() failed");
1164 RETURN_VALUE("%d", bytes_read);
1168 /* Returns the number of bytes read, or -1 upon failure. */
1169 if ((bytes_read = read(port->fd, buf, count)) < 0) {
1170 if (errno == EAGAIN)
1171 /* No bytes available. */
1174 /* This is an actual failure. */
1175 RETURN_FAIL("read() failed");
1177 RETURN_VALUE("%d", bytes_read);
1181 enum sp_return sp_input_waiting(struct sp_port *port)
1187 DEBUG("Checking input bytes waiting on port %s", port->name);
1193 if (ClearCommError(port->hdl, &errors, &comstat) == 0)
1194 RETURN_FAIL("ClearCommError() failed");
1195 RETURN_VALUE("%d", comstat.cbInQue);
1198 if (ioctl(port->fd, TIOCINQ, &bytes_waiting) < 0)
1199 RETURN_FAIL("TIOCINQ ioctl failed");
1200 RETURN_VALUE("%d", bytes_waiting);
1204 enum sp_return sp_output_waiting(struct sp_port *port)
1210 DEBUG("Checking output bytes waiting on port %s", port->name);
1216 if (ClearCommError(port->hdl, &errors, &comstat) == 0)
1217 RETURN_FAIL("ClearCommError() failed");
1218 RETURN_VALUE("%d", comstat.cbOutQue);
1221 if (ioctl(port->fd, TIOCOUTQ, &bytes_waiting) < 0)
1222 RETURN_FAIL("TIOCOUTQ ioctl failed");
1223 RETURN_VALUE("%d", bytes_waiting);
1227 enum sp_return sp_new_event_set(struct sp_event_set **result_ptr)
1229 struct sp_event_set *result;
1231 TRACE("%p", result_ptr);
1234 RETURN_ERROR(SP_ERR_ARG, "Null result");
1238 if (!(result = malloc(sizeof(struct sp_event_set))))
1239 RETURN_ERROR(SP_ERR_MEM, "sp_event_set malloc() failed");
1241 memset(result, 0, sizeof(struct sp_event_set));
1243 *result_ptr = result;
1248 static enum sp_return add_handle(struct sp_event_set *event_set,
1249 event_handle handle, enum sp_event mask)
1252 enum sp_event *new_masks;
1254 TRACE("%p, %d, %d", event_set, handle, mask);
1256 if (!(new_handles = realloc(event_set->handles,
1257 sizeof(event_handle) * (event_set->count + 1))))
1258 RETURN_ERROR(SP_ERR_MEM, "handle array realloc() failed");
1260 if (!(new_masks = realloc(event_set->masks,
1261 sizeof(enum sp_event) * (event_set->count + 1))))
1262 RETURN_ERROR(SP_ERR_MEM, "mask array realloc() failed");
1264 event_set->handles = new_handles;
1265 event_set->masks = new_masks;
1267 ((event_handle *) event_set->handles)[event_set->count] = handle;
1268 event_set->masks[event_set->count] = mask;
1275 enum sp_return sp_add_port_events(struct sp_event_set *event_set,
1276 const struct sp_port *port, enum sp_event mask)
1278 TRACE("%p, %p, %d", event_set, port, mask);
1281 RETURN_ERROR(SP_ERR_ARG, "Null event set");
1284 RETURN_ERROR(SP_ERR_ARG, "Null port");
1286 if (mask > (SP_EVENT_RX_READY | SP_EVENT_TX_READY | SP_EVENT_ERROR))
1287 RETURN_ERROR(SP_ERR_ARG, "Invalid event mask");
1293 enum sp_event handle_mask;
1294 if ((handle_mask = mask & SP_EVENT_TX_READY))
1295 TRY(add_handle(event_set, port->write_ovl.hEvent, handle_mask));
1296 if ((handle_mask = mask & (SP_EVENT_RX_READY | SP_EVENT_ERROR)))
1297 TRY(add_handle(event_set, port->wait_ovl.hEvent, handle_mask));
1299 TRY(add_handle(event_set, port->fd, mask));
1305 void sp_free_event_set(struct sp_event_set *event_set)
1307 TRACE("%p", event_set);
1310 DEBUG("Null event set");
1314 DEBUG("Freeing event set");
1316 if (event_set->handles)
1317 free(event_set->handles);
1318 if (event_set->masks)
1319 free(event_set->masks);
1326 enum sp_return sp_wait(struct sp_event_set *event_set, unsigned int timeout)
1328 TRACE("%p, %d", event_set, timeout);
1331 RETURN_ERROR(SP_ERR_ARG, "Null event set");
1334 if (WaitForMultipleObjects(event_set->count, event_set->handles, FALSE,
1335 timeout ? timeout : INFINITE) == WAIT_FAILED)
1336 RETURN_FAIL("WaitForMultipleObjects() failed");
1340 struct timeval start, delta, now, end = {0, 0};
1341 int result, timeout_remaining;
1342 struct pollfd *pollfds;
1345 if (!(pollfds = malloc(sizeof(struct pollfd) * event_set->count)))
1346 RETURN_ERROR(SP_ERR_MEM, "pollfds malloc() failed");
1348 for (i = 0; i < event_set->count; i++) {
1349 pollfds[i].fd = ((int *) event_set->handles)[i];
1350 pollfds[i].events = 0;
1351 pollfds[i].revents = 0;
1352 if (event_set->masks[i] & SP_EVENT_RX_READY)
1353 pollfds[i].events |= POLLIN;
1354 if (event_set->masks[i] & SP_EVENT_TX_READY)
1355 pollfds[i].events |= POLLOUT;
1356 if (event_set->masks[i] & SP_EVENT_ERROR)
1357 pollfds[i].events |= POLLERR;
1361 /* Get time at start of operation. */
1362 gettimeofday(&start, NULL);
1363 /* Define duration of timeout. */
1364 delta.tv_sec = timeout / 1000;
1365 delta.tv_usec = (timeout % 1000) * 1000;
1366 /* Calculate time at which we should give up. */
1367 timeradd(&start, &delta, &end);
1370 /* Loop until an event occurs. */
1374 gettimeofday(&now, NULL);
1375 if (timercmp(&now, &end, >)) {
1376 DEBUG("wait timed out");
1379 timersub(&end, &now, &delta);
1380 timeout_remaining = delta.tv_sec * 1000 + delta.tv_usec / 1000;
1383 result = poll(pollfds, event_set->count, timeout ? timeout_remaining : -1);
1386 if (errno == EINTR) {
1387 DEBUG("poll() call was interrupted, repeating");
1391 RETURN_FAIL("poll() failed");
1393 } else if (result == 0) {
1394 DEBUG("poll() timed out");
1397 DEBUG("poll() completed");
1407 #ifdef USE_TERMIOS_SPEED
1408 static enum sp_return get_baudrate(int fd, int *baudrate)
1412 TRACE("%d, %p", fd, baudrate);
1414 DEBUG("Getting baud rate");
1416 if (!(data = malloc(get_termios_size())))
1417 RETURN_ERROR(SP_ERR_MEM, "termios malloc failed");
1419 if (ioctl(fd, get_termios_get_ioctl(), data) < 0) {
1421 RETURN_FAIL("getting termios failed");
1424 *baudrate = get_termios_speed(data);
1431 static enum sp_return set_baudrate(int fd, int baudrate)
1435 TRACE("%d, %d", fd, baudrate);
1437 DEBUG("Getting baud rate");
1439 if (!(data = malloc(get_termios_size())))
1440 RETURN_ERROR(SP_ERR_MEM, "termios malloc failed");
1442 if (ioctl(fd, get_termios_get_ioctl(), data) < 0) {
1444 RETURN_FAIL("getting termios failed");
1447 DEBUG("Setting baud rate");
1449 set_termios_speed(data, baudrate);
1451 if (ioctl(fd, get_termios_set_ioctl(), data) < 0) {
1453 RETURN_FAIL("setting termios failed");
1460 #endif /* USE_TERMIOS_SPEED */
1463 static enum sp_return get_flow(int fd, struct port_data *data)
1467 TRACE("%d, %p", fd, data);
1469 DEBUG("Getting advanced flow control");
1471 if (!(termx = malloc(get_termiox_size())))
1472 RETURN_ERROR(SP_ERR_MEM, "termiox malloc failed");
1474 if (ioctl(fd, TCGETX, termx) < 0) {
1476 RETURN_FAIL("getting termiox failed");
1479 get_termiox_flow(termx, &data->rts_flow, &data->cts_flow,
1480 &data->dtr_flow, &data->dsr_flow);
1487 static enum sp_return set_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 DEBUG("Setting advanced flow control");
1505 set_termiox_flow(termx, data->rts_flow, data->cts_flow,
1506 data->dtr_flow, data->dsr_flow);
1508 if (ioctl(fd, TCSETX, termx) < 0) {
1510 RETURN_FAIL("setting termiox failed");
1517 #endif /* USE_TERMIOX */
1519 static enum sp_return get_config(struct sp_port *port, struct port_data *data,
1520 struct sp_port_config *config)
1524 TRACE("%p, %p, %p", port, data, config);
1526 DEBUG("Getting configuration for port %s", port->name);
1529 if (!GetCommState(port->hdl, &data->dcb))
1530 RETURN_FAIL("GetCommState() failed");
1532 for (i = 0; i < NUM_STD_BAUDRATES; i++) {
1533 if (data->dcb.BaudRate == std_baudrates[i].index) {
1534 config->baudrate = std_baudrates[i].value;
1539 if (i == NUM_STD_BAUDRATES)
1540 /* BaudRate field can be either an index or a custom baud rate. */
1541 config->baudrate = data->dcb.BaudRate;
1543 config->bits = data->dcb.ByteSize;
1545 if (data->dcb.fParity)
1546 switch (data->dcb.Parity) {
1548 config->parity = SP_PARITY_NONE;
1551 config->parity = SP_PARITY_ODD;
1554 config->parity = SP_PARITY_EVEN;
1557 config->parity = SP_PARITY_MARK;
1560 config->parity = SP_PARITY_SPACE;
1563 config->parity = -1;
1566 config->parity = SP_PARITY_NONE;
1568 switch (data->dcb.StopBits) {
1570 config->stopbits = 1;
1573 config->stopbits = 2;
1576 config->stopbits = -1;
1579 switch (data->dcb.fRtsControl) {
1580 case RTS_CONTROL_DISABLE:
1581 config->rts = SP_RTS_OFF;
1583 case RTS_CONTROL_ENABLE:
1584 config->rts = SP_RTS_ON;
1586 case RTS_CONTROL_HANDSHAKE:
1587 config->rts = SP_RTS_FLOW_CONTROL;
1593 config->cts = data->dcb.fOutxCtsFlow ? SP_CTS_FLOW_CONTROL : SP_CTS_IGNORE;
1595 switch (data->dcb.fDtrControl) {
1596 case DTR_CONTROL_DISABLE:
1597 config->dtr = SP_DTR_OFF;
1599 case DTR_CONTROL_ENABLE:
1600 config->dtr = SP_DTR_ON;
1602 case DTR_CONTROL_HANDSHAKE:
1603 config->dtr = SP_DTR_FLOW_CONTROL;
1609 config->dsr = data->dcb.fOutxDsrFlow ? SP_DSR_FLOW_CONTROL : SP_DSR_IGNORE;
1611 if (data->dcb.fInX) {
1612 if (data->dcb.fOutX)
1613 config->xon_xoff = SP_XONXOFF_INOUT;
1615 config->xon_xoff = SP_XONXOFF_IN;
1617 if (data->dcb.fOutX)
1618 config->xon_xoff = SP_XONXOFF_OUT;
1620 config->xon_xoff = SP_XONXOFF_DISABLED;
1625 if (tcgetattr(port->fd, &data->term) < 0)
1626 RETURN_FAIL("tcgetattr() failed");
1628 if (ioctl(port->fd, TIOCMGET, &data->controlbits) < 0)
1629 RETURN_FAIL("TIOCMGET ioctl failed");
1632 int ret = get_flow(port->fd, data);
1634 if (ret == SP_ERR_FAIL && errno == EINVAL)
1635 data->termiox_supported = 0;
1637 RETURN_CODEVAL(ret);
1639 data->termiox_supported = 1;
1641 data->termiox_supported = 0;
1644 for (i = 0; i < NUM_STD_BAUDRATES; i++) {
1645 if (cfgetispeed(&data->term) == std_baudrates[i].index) {
1646 config->baudrate = std_baudrates[i].value;
1651 if (i == NUM_STD_BAUDRATES) {
1653 config->baudrate = (int)data->term.c_ispeed;
1654 #elif defined(USE_TERMIOS_SPEED)
1655 TRY(get_baudrate(port->fd, &config->baudrate));
1657 config->baudrate = -1;
1661 switch (data->term.c_cflag & CSIZE) {
1678 if (!(data->term.c_cflag & PARENB) && (data->term.c_iflag & IGNPAR))
1679 config->parity = SP_PARITY_NONE;
1680 else if (!(data->term.c_cflag & PARENB) || (data->term.c_iflag & IGNPAR))
1681 config->parity = -1;
1683 else if (data->term.c_cflag & CMSPAR)
1684 config->parity = (data->term.c_cflag & PARODD) ? SP_PARITY_MARK : SP_PARITY_SPACE;
1687 config->parity = (data->term.c_cflag & PARODD) ? SP_PARITY_ODD : SP_PARITY_EVEN;
1689 config->stopbits = (data->term.c_cflag & CSTOPB) ? 2 : 1;
1691 if (data->term.c_cflag & CRTSCTS) {
1692 config->rts = SP_RTS_FLOW_CONTROL;
1693 config->cts = SP_CTS_FLOW_CONTROL;
1695 if (data->termiox_supported && data->rts_flow)
1696 config->rts = SP_RTS_FLOW_CONTROL;
1698 config->rts = (data->controlbits & TIOCM_RTS) ? SP_RTS_ON : SP_RTS_OFF;
1700 config->cts = (data->termiox_supported && data->cts_flow) ?
1701 SP_CTS_FLOW_CONTROL : SP_CTS_IGNORE;
1704 if (data->termiox_supported && data->dtr_flow)
1705 config->dtr = SP_DTR_FLOW_CONTROL;
1707 config->dtr = (data->controlbits & TIOCM_DTR) ? SP_DTR_ON : SP_DTR_OFF;
1709 config->dsr = (data->termiox_supported && data->dsr_flow) ?
1710 SP_DSR_FLOW_CONTROL : SP_DSR_IGNORE;
1712 if (data->term.c_iflag & IXOFF) {
1713 if (data->term.c_iflag & IXON)
1714 config->xon_xoff = SP_XONXOFF_INOUT;
1716 config->xon_xoff = SP_XONXOFF_IN;
1718 if (data->term.c_iflag & IXON)
1719 config->xon_xoff = SP_XONXOFF_OUT;
1721 config->xon_xoff = SP_XONXOFF_DISABLED;
1728 static enum sp_return set_config(struct sp_port *port, struct port_data *data,
1729 const struct sp_port_config *config)
1733 BAUD_TYPE baud_nonstd;
1737 #ifdef USE_TERMIOS_SPEED
1738 int baud_nonstd = 0;
1741 TRACE("%p, %p, %p", port, data, config);
1743 DEBUG("Setting configuration for port %s", port->name);
1746 if (config->baudrate >= 0) {
1747 for (i = 0; i < NUM_STD_BAUDRATES; i++) {
1748 if (config->baudrate == std_baudrates[i].value) {
1749 data->dcb.BaudRate = std_baudrates[i].index;
1754 if (i == NUM_STD_BAUDRATES)
1755 data->dcb.BaudRate = config->baudrate;
1758 if (config->bits >= 0)
1759 data->dcb.ByteSize = config->bits;
1761 if (config->parity >= 0) {
1762 switch (config->parity) {
1763 case SP_PARITY_NONE:
1764 data->dcb.Parity = NOPARITY;
1767 data->dcb.Parity = ODDPARITY;
1769 case SP_PARITY_EVEN:
1770 data->dcb.Parity = EVENPARITY;
1772 case SP_PARITY_MARK:
1773 data->dcb.Parity = MARKPARITY;
1775 case SP_PARITY_SPACE:
1776 data->dcb.Parity = SPACEPARITY;
1779 RETURN_ERROR(SP_ERR_ARG, "Invalid parity setting");
1783 if (config->stopbits >= 0) {
1784 switch (config->stopbits) {
1785 /* Note: There's also ONE5STOPBITS == 1.5 (unneeded so far). */
1787 data->dcb.StopBits = ONESTOPBIT;
1790 data->dcb.StopBits = TWOSTOPBITS;
1793 RETURN_ERROR(SP_ERR_ARG, "Invalid stop bit setting");
1797 if (config->rts >= 0) {
1798 switch (config->rts) {
1800 data->dcb.fRtsControl = RTS_CONTROL_DISABLE;
1803 data->dcb.fRtsControl = RTS_CONTROL_ENABLE;
1805 case SP_RTS_FLOW_CONTROL:
1806 data->dcb.fRtsControl = RTS_CONTROL_HANDSHAKE;
1809 RETURN_ERROR(SP_ERR_ARG, "Invalid RTS setting");
1813 if (config->cts >= 0) {
1814 switch (config->cts) {
1816 data->dcb.fOutxCtsFlow = FALSE;
1818 case SP_CTS_FLOW_CONTROL:
1819 data->dcb.fOutxCtsFlow = TRUE;
1822 RETURN_ERROR(SP_ERR_ARG, "Invalid CTS setting");
1826 if (config->dtr >= 0) {
1827 switch (config->dtr) {
1829 data->dcb.fDtrControl = DTR_CONTROL_DISABLE;
1832 data->dcb.fDtrControl = DTR_CONTROL_ENABLE;
1834 case SP_DTR_FLOW_CONTROL:
1835 data->dcb.fDtrControl = DTR_CONTROL_HANDSHAKE;
1838 RETURN_ERROR(SP_ERR_ARG, "Invalid DTR setting");
1842 if (config->dsr >= 0) {
1843 switch (config->dsr) {
1845 data->dcb.fOutxDsrFlow = FALSE;
1847 case SP_DSR_FLOW_CONTROL:
1848 data->dcb.fOutxDsrFlow = TRUE;
1851 RETURN_ERROR(SP_ERR_ARG, "Invalid DSR setting");
1855 if (config->xon_xoff >= 0) {
1856 switch (config->xon_xoff) {
1857 case SP_XONXOFF_DISABLED:
1858 data->dcb.fInX = FALSE;
1859 data->dcb.fOutX = FALSE;
1862 data->dcb.fInX = TRUE;
1863 data->dcb.fOutX = FALSE;
1865 case SP_XONXOFF_OUT:
1866 data->dcb.fInX = FALSE;
1867 data->dcb.fOutX = TRUE;
1869 case SP_XONXOFF_INOUT:
1870 data->dcb.fInX = TRUE;
1871 data->dcb.fOutX = TRUE;
1874 RETURN_ERROR(SP_ERR_ARG, "Invalid XON/XOFF setting");
1878 if (!SetCommState(port->hdl, &data->dcb))
1879 RETURN_FAIL("SetCommState() failed");
1885 if (config->baudrate >= 0) {
1886 for (i = 0; i < NUM_STD_BAUDRATES; i++) {
1887 if (config->baudrate == std_baudrates[i].value) {
1888 if (cfsetospeed(&data->term, std_baudrates[i].index) < 0)
1889 RETURN_FAIL("cfsetospeed() failed");
1891 if (cfsetispeed(&data->term, std_baudrates[i].index) < 0)
1892 RETURN_FAIL("cfsetispeed() failed");
1897 /* Non-standard baud rate */
1898 if (i == NUM_STD_BAUDRATES) {
1900 /* Set "dummy" baud rate. */
1901 if (cfsetspeed(&data->term, B9600) < 0)
1902 RETURN_FAIL("cfsetspeed() failed");
1903 baud_nonstd = config->baudrate;
1904 #elif defined(USE_TERMIOS_SPEED)
1907 RETURN_ERROR(SP_ERR_SUPP, "Non-standard baudrate not supported");
1912 if (config->bits >= 0) {
1913 data->term.c_cflag &= ~CSIZE;
1914 switch (config->bits) {
1916 data->term.c_cflag |= CS8;
1919 data->term.c_cflag |= CS7;
1922 data->term.c_cflag |= CS6;
1925 data->term.c_cflag |= CS5;
1928 RETURN_ERROR(SP_ERR_ARG, "Invalid data bits setting");
1932 if (config->parity >= 0) {
1933 data->term.c_iflag &= ~IGNPAR;
1934 data->term.c_cflag &= ~(PARENB | PARODD);
1936 data->term.c_cflag &= ~CMSPAR;
1938 switch (config->parity) {
1939 case SP_PARITY_NONE:
1940 data->term.c_iflag |= IGNPAR;
1942 case SP_PARITY_EVEN:
1943 data->term.c_cflag |= PARENB;
1946 data->term.c_cflag |= PARENB | PARODD;
1949 case SP_PARITY_MARK:
1950 data->term.c_cflag |= PARENB | PARODD;
1951 data->term.c_cflag |= CMSPAR;
1953 case SP_PARITY_SPACE:
1954 data->term.c_cflag |= PARENB;
1955 data->term.c_cflag |= CMSPAR;
1958 case SP_PARITY_MARK:
1959 case SP_PARITY_SPACE:
1960 RETURN_ERROR(SP_ERR_SUPP, "Mark/space parity not supported");
1963 RETURN_ERROR(SP_ERR_ARG, "Invalid parity setting");
1967 if (config->stopbits >= 0) {
1968 data->term.c_cflag &= ~CSTOPB;
1969 switch (config->stopbits) {
1971 data->term.c_cflag &= ~CSTOPB;
1974 data->term.c_cflag |= CSTOPB;
1977 RETURN_ERROR(SP_ERR_ARG, "Invalid stop bits setting");
1981 if (config->rts >= 0 || config->cts >= 0) {
1982 if (data->termiox_supported) {
1983 data->rts_flow = data->cts_flow = 0;
1984 switch (config->rts) {
1987 controlbits = TIOCM_RTS;
1988 if (ioctl(port->fd, config->rts == SP_RTS_ON ? TIOCMBIS : TIOCMBIC, &controlbits) < 0)
1989 RETURN_FAIL("Setting RTS signal level failed");
1991 case SP_RTS_FLOW_CONTROL:
1997 if (config->cts == SP_CTS_FLOW_CONTROL)
2000 if (data->rts_flow && data->cts_flow)
2001 data->term.c_iflag |= CRTSCTS;
2003 data->term.c_iflag &= ~CRTSCTS;
2005 /* Asymmetric use of RTS/CTS not supported. */
2006 if (data->term.c_iflag & CRTSCTS) {
2007 /* Flow control can only be disabled for both RTS & CTS together. */
2008 if (config->rts >= 0 && config->rts != SP_RTS_FLOW_CONTROL) {
2009 if (config->cts != SP_CTS_IGNORE)
2010 RETURN_ERROR(SP_ERR_SUPP, "RTS & CTS flow control must be disabled together");
2012 if (config->cts >= 0 && config->cts != SP_CTS_FLOW_CONTROL) {
2013 if (config->rts <= 0 || config->rts == SP_RTS_FLOW_CONTROL)
2014 RETURN_ERROR(SP_ERR_SUPP, "RTS & CTS flow control must be disabled together");
2017 /* Flow control can only be enabled for both RTS & CTS together. */
2018 if (((config->rts == SP_RTS_FLOW_CONTROL) && (config->cts != SP_CTS_FLOW_CONTROL)) ||
2019 ((config->cts == SP_CTS_FLOW_CONTROL) && (config->rts != SP_RTS_FLOW_CONTROL)))
2020 RETURN_ERROR(SP_ERR_SUPP, "RTS & CTS flow control must be enabled together");
2023 if (config->rts >= 0) {
2024 if (config->rts == SP_RTS_FLOW_CONTROL) {
2025 data->term.c_iflag |= CRTSCTS;
2027 controlbits = TIOCM_RTS;
2028 if (ioctl(port->fd, config->rts == SP_RTS_ON ? TIOCMBIS : TIOCMBIC,
2030 RETURN_FAIL("Setting RTS signal level failed");
2036 if (config->dtr >= 0 || config->dsr >= 0) {
2037 if (data->termiox_supported) {
2038 data->dtr_flow = data->dsr_flow = 0;
2039 switch (config->dtr) {
2042 controlbits = TIOCM_DTR;
2043 if (ioctl(port->fd, config->dtr == SP_DTR_ON ? TIOCMBIS : TIOCMBIC, &controlbits) < 0)
2044 RETURN_FAIL("Setting DTR signal level failed");
2046 case SP_DTR_FLOW_CONTROL:
2052 if (config->dsr == SP_DSR_FLOW_CONTROL)
2055 /* DTR/DSR flow control not supported. */
2056 if (config->dtr == SP_DTR_FLOW_CONTROL || config->dsr == SP_DSR_FLOW_CONTROL)
2057 RETURN_ERROR(SP_ERR_SUPP, "DTR/DSR flow control not supported");
2059 if (config->dtr >= 0) {
2060 controlbits = TIOCM_DTR;
2061 if (ioctl(port->fd, config->dtr == SP_DTR_ON ? TIOCMBIS : TIOCMBIC,
2063 RETURN_FAIL("Setting DTR signal level failed");
2068 if (config->xon_xoff >= 0) {
2069 data->term.c_iflag &= ~(IXON | IXOFF | IXANY);
2070 switch (config->xon_xoff) {
2071 case SP_XONXOFF_DISABLED:
2074 data->term.c_iflag |= IXOFF;
2076 case SP_XONXOFF_OUT:
2077 data->term.c_iflag |= IXON | IXANY;
2079 case SP_XONXOFF_INOUT:
2080 data->term.c_iflag |= IXON | IXOFF | IXANY;
2083 RETURN_ERROR(SP_ERR_ARG, "Invalid XON/XOFF setting");
2087 if (tcsetattr(port->fd, TCSANOW, &data->term) < 0)
2088 RETURN_FAIL("tcsetattr() failed");
2091 if (baud_nonstd != B0) {
2092 if (ioctl(port->fd, IOSSIOSPEED, &baud_nonstd) == -1)
2093 RETURN_FAIL("IOSSIOSPEED ioctl failed");
2094 /* Set baud rates in data->term to correct, but incompatible
2095 * with tcsetattr() value, same as delivered by tcgetattr(). */
2096 if (cfsetspeed(&data->term, baud_nonstd) < 0)
2097 RETURN_FAIL("cfsetspeed() failed");
2099 #elif defined(__linux__)
2100 #ifdef USE_TERMIOS_SPEED
2102 TRY(set_baudrate(port->fd, config->baudrate));
2105 if (data->termiox_supported)
2106 TRY(set_flow(port->fd, data));
2110 #endif /* !_WIN32 */
2115 enum sp_return sp_new_config(struct sp_port_config **config_ptr)
2117 struct sp_port_config *config;
2119 TRACE("%p", config_ptr);
2122 RETURN_ERROR(SP_ERR_ARG, "Null result pointer");
2126 if (!(config = malloc(sizeof(struct sp_port_config))))
2127 RETURN_ERROR(SP_ERR_MEM, "config malloc failed");
2129 config->baudrate = -1;
2131 config->parity = -1;
2132 config->stopbits = -1;
2138 *config_ptr = config;
2143 void sp_free_config(struct sp_port_config *config)
2145 TRACE("%p", config);
2148 DEBUG("Null config");
2155 enum sp_return sp_get_config(struct sp_port *port, struct sp_port_config *config)
2157 struct port_data data;
2159 TRACE("%p, %p", port, config);
2164 RETURN_ERROR(SP_ERR_ARG, "Null config");
2166 TRY(get_config(port, &data, config));
2171 enum sp_return sp_set_config(struct sp_port *port, const struct sp_port_config *config)
2173 struct port_data data;
2174 struct sp_port_config prev_config;
2176 TRACE("%p, %p", port, config);
2181 RETURN_ERROR(SP_ERR_ARG, "Null config");
2183 TRY(get_config(port, &data, &prev_config));
2184 TRY(set_config(port, &data, config));
2189 #define CREATE_ACCESSORS(x, type) \
2190 enum sp_return sp_set_##x(struct sp_port *port, type x) { \
2191 struct port_data data; \
2192 struct sp_port_config config; \
2193 TRACE("%p, %d", port, x); \
2194 CHECK_OPEN_PORT(); \
2195 TRY(get_config(port, &data, &config)); \
2197 TRY(set_config(port, &data, &config)); \
2200 enum sp_return sp_get_config_##x(const struct sp_port_config *config, type *x) { \
2201 TRACE("%p, %p", config, x); \
2203 RETURN_ERROR(SP_ERR_ARG, "Null config"); \
2207 enum sp_return sp_set_config_##x(struct sp_port_config *config, type x) { \
2208 TRACE("%p, %d", config, x); \
2210 RETURN_ERROR(SP_ERR_ARG, "Null config"); \
2215 CREATE_ACCESSORS(baudrate, int)
2216 CREATE_ACCESSORS(bits, int)
2217 CREATE_ACCESSORS(parity, enum sp_parity)
2218 CREATE_ACCESSORS(stopbits, int)
2219 CREATE_ACCESSORS(rts, enum sp_rts)
2220 CREATE_ACCESSORS(cts, enum sp_cts)
2221 CREATE_ACCESSORS(dtr, enum sp_dtr)
2222 CREATE_ACCESSORS(dsr, enum sp_dsr)
2223 CREATE_ACCESSORS(xon_xoff, enum sp_xonxoff)
2225 enum sp_return sp_set_config_flowcontrol(struct sp_port_config *config, enum sp_flowcontrol flowcontrol)
2228 RETURN_ERROR(SP_ERR_ARG, "Null configuration");
2230 if (flowcontrol > SP_FLOWCONTROL_DTRDSR)
2231 RETURN_ERROR(SP_ERR_ARG, "Invalid flow control setting");
2233 if (flowcontrol == SP_FLOWCONTROL_XONXOFF)
2234 config->xon_xoff = SP_XONXOFF_INOUT;
2236 config->xon_xoff = SP_XONXOFF_DISABLED;
2238 if (flowcontrol == SP_FLOWCONTROL_RTSCTS) {
2239 config->rts = SP_RTS_FLOW_CONTROL;
2240 config->cts = SP_CTS_FLOW_CONTROL;
2242 if (config->rts == SP_RTS_FLOW_CONTROL)
2243 config->rts = SP_RTS_ON;
2244 config->cts = SP_CTS_IGNORE;
2247 if (flowcontrol == SP_FLOWCONTROL_DTRDSR) {
2248 config->dtr = SP_DTR_FLOW_CONTROL;
2249 config->dsr = SP_DSR_FLOW_CONTROL;
2251 if (config->dtr == SP_DTR_FLOW_CONTROL)
2252 config->dtr = SP_DTR_ON;
2253 config->dsr = SP_DSR_IGNORE;
2259 enum sp_return sp_set_flowcontrol(struct sp_port *port, enum sp_flowcontrol flowcontrol)
2261 struct port_data data;
2262 struct sp_port_config config;
2264 TRACE("%p, %d", port, flowcontrol);
2268 TRY(get_config(port, &data, &config));
2270 TRY(sp_set_config_flowcontrol(&config, flowcontrol));
2272 TRY(set_config(port, &data, &config));
2277 enum sp_return sp_get_signals(struct sp_port *port, enum sp_signal *signals)
2279 TRACE("%p, %p", port, signals);
2284 RETURN_ERROR(SP_ERR_ARG, "Null result pointer");
2286 DEBUG("Getting control signals for port %s", port->name);
2291 if (GetCommModemStatus(port->hdl, &bits) == 0)
2292 RETURN_FAIL("GetCommModemStatus() failed");
2293 if (bits & MS_CTS_ON)
2294 *signals |= SP_SIG_CTS;
2295 if (bits & MS_DSR_ON)
2296 *signals |= SP_SIG_DSR;
2297 if (bits & MS_RLSD_ON)
2298 *signals |= SP_SIG_DCD;
2299 if (bits & MS_RING_ON)
2300 *signals |= SP_SIG_RI;
2303 if (ioctl(port->fd, TIOCMGET, &bits) < 0)
2304 RETURN_FAIL("TIOCMGET ioctl failed");
2305 if (bits & TIOCM_CTS)
2306 *signals |= SP_SIG_CTS;
2307 if (bits & TIOCM_DSR)
2308 *signals |= SP_SIG_DSR;
2309 if (bits & TIOCM_CAR)
2310 *signals |= SP_SIG_DCD;
2311 if (bits & TIOCM_RNG)
2312 *signals |= SP_SIG_RI;
2317 enum sp_return sp_start_break(struct sp_port *port)
2323 if (SetCommBreak(port->hdl) == 0)
2324 RETURN_FAIL("SetCommBreak() failed");
2326 if (ioctl(port->fd, TIOCSBRK, 1) < 0)
2327 RETURN_FAIL("TIOCSBRK ioctl failed");
2333 enum sp_return sp_end_break(struct sp_port *port)
2339 if (ClearCommBreak(port->hdl) == 0)
2340 RETURN_FAIL("ClearCommBreak() failed");
2342 if (ioctl(port->fd, TIOCCBRK, 1) < 0)
2343 RETURN_FAIL("TIOCCBRK ioctl failed");
2349 int sp_last_error_code(void)
2353 RETURN_VALUE("%d", GetLastError());
2355 RETURN_VALUE("%d", errno);
2359 char *sp_last_error_message(void)
2365 DWORD error = GetLastError();
2368 FORMAT_MESSAGE_ALLOCATE_BUFFER |
2369 FORMAT_MESSAGE_FROM_SYSTEM |
2370 FORMAT_MESSAGE_IGNORE_INSERTS,
2373 MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
2377 RETURN_VALUE("%s", message);
2379 RETURN_VALUE("%s", strerror(errno));
2383 void sp_free_error_message(char *message)
2385 TRACE("%s", message);
2396 void sp_set_debug_handler(void (*handler)(const char *format, ...))
2398 TRACE("%p", handler);
2400 sp_debug_handler = handler;
2405 void sp_default_debug_handler(const char *format, ...)
2408 va_start(args, format);
2409 if (getenv("LIBSERIALPORT_DEBUG")) {
2410 fputs("sp: ", stderr);
2411 vfprintf(stderr, format, args);
2416 int sp_get_major_package_version(void)
2418 return SP_PACKAGE_VERSION_MAJOR;
2421 int sp_get_minor_package_version(void)
2423 return SP_PACKAGE_VERSION_MINOR;
2426 int sp_get_micro_package_version(void)
2428 return SP_PACKAGE_VERSION_MICRO;
2431 const char *sp_get_package_version_string(void)
2433 return SP_PACKAGE_VERSION_STRING;
2436 int sp_get_current_lib_version(void)
2438 return SP_LIB_VERSION_CURRENT;
2441 int sp_get_revision_lib_version(void)
2443 return SP_LIB_VERSION_REVISION;
2446 int sp_get_age_lib_version(void)
2448 return SP_LIB_VERSION_AGE;
2451 const char *sp_get_lib_version_string(void)
2453 return SP_LIB_VERSION_STRING;