Fix xon_xoff not initialized
[libserialport.git] / serialport.c
blobd15c664ff1dbfb0a4c58bdca82df945c8c871101
1 /*
2 * This file is part of the libserialport project.
4 * Copyright (C) 2010-2012 Bert Vermeulen <bert@biot.com>
5 * Copyright (C) 2010-2015 Uwe Hermann <uwe@hermann-uwe.de>
6 * Copyright (C) 2013-2015 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_internal.h"
26 static const struct std_baudrate std_baudrates[] = {
27 #ifdef _WIN32
29 * The baudrates 50/75/134/150/200/1800/230400/460800 do not seem to
30 * have documented CBR_* macros.
32 BAUD(110), BAUD(300), BAUD(600), BAUD(1200), BAUD(2400), BAUD(4800),
33 BAUD(9600), BAUD(14400), BAUD(19200), BAUD(38400), BAUD(57600),
34 BAUD(115200), BAUD(128000), BAUD(256000),
35 #else
36 BAUD(50), BAUD(75), BAUD(110), BAUD(134), BAUD(150), BAUD(200),
37 BAUD(300), BAUD(600), BAUD(1200), BAUD(1800), BAUD(2400), BAUD(4800),
38 BAUD(9600), BAUD(19200), BAUD(38400), BAUD(57600), BAUD(115200),
39 BAUD(230400),
40 #if !defined(__APPLE__) && !defined(__OpenBSD__)
41 BAUD(460800),
42 #endif
43 #endif
46 #define NUM_STD_BAUDRATES ARRAY_SIZE(std_baudrates)
48 void (*sp_debug_handler)(const char *format, ...) = sp_default_debug_handler;
50 static enum sp_return get_config(struct sp_port *port, struct port_data *data,
51 struct sp_port_config *config);
53 static enum sp_return set_config(struct sp_port *port, struct port_data *data,
54 const struct sp_port_config *config);
56 SP_API enum sp_return sp_get_port_by_name(const char *portname, struct sp_port **port_ptr)
58 struct sp_port *port;
59 #ifndef NO_PORT_METADATA
60 enum sp_return ret;
61 #endif
62 size_t len;
64 TRACE("%s, %p", portname, port_ptr);
66 if (!port_ptr)
67 RETURN_ERROR(SP_ERR_ARG, "Null result pointer");
69 *port_ptr = NULL;
71 if (!portname)
72 RETURN_ERROR(SP_ERR_ARG, "Null port name");
74 DEBUG_FMT("Building structure for port %s", portname);
76 #if !defined(_WIN32) && defined(HAVE_REALPATH)
78 * get_port_details() below tries to be too smart and figure out
79 * some transport properties from the port name which breaks with
80 * symlinks. Therefore we canonicalize the portname first.
82 char pathbuf[PATH_MAX + 1];
83 char *res = realpath(portname, pathbuf);
84 if (!res)
85 RETURN_ERROR(SP_ERR_ARG, "Could not retrieve realpath behind port name");
87 portname = pathbuf;
88 #endif
90 if (!(port = malloc(sizeof(struct sp_port))))
91 RETURN_ERROR(SP_ERR_MEM, "Port structure malloc failed");
93 len = strlen(portname) + 1;
95 if (!(port->name = malloc(len))) {
96 free(port);
97 RETURN_ERROR(SP_ERR_MEM, "Port name malloc failed");
100 memcpy(port->name, portname, len);
102 #ifdef _WIN32
103 port->usb_path = NULL;
104 port->hdl = INVALID_HANDLE_VALUE;
105 port->write_buf = NULL;
106 port->write_buf_size = 0;
107 #else
108 port->fd = -1;
109 #endif
111 port->description = NULL;
112 port->transport = SP_TRANSPORT_NATIVE;
113 port->usb_bus = -1;
114 port->usb_address = -1;
115 port->usb_vid = -1;
116 port->usb_pid = -1;
117 port->usb_manufacturer = NULL;
118 port->usb_product = NULL;
119 port->usb_serial = NULL;
120 port->bluetooth_address = NULL;
122 #ifndef NO_PORT_METADATA
123 if ((ret = get_port_details(port)) != SP_OK) {
124 sp_free_port(port);
125 return ret;
127 #endif
129 *port_ptr = port;
131 RETURN_OK();
134 SP_API char *sp_get_port_name(const struct sp_port *port)
136 TRACE("%p", port);
138 if (!port)
139 return NULL;
141 RETURN_STRING(port->name);
144 SP_API char *sp_get_port_description(const struct sp_port *port)
146 TRACE("%p", port);
148 if (!port || !port->description)
149 return NULL;
151 RETURN_STRING(port->description);
154 SP_API enum sp_transport sp_get_port_transport(const struct sp_port *port)
156 TRACE("%p", port);
158 RETURN_INT(port ? port->transport : SP_TRANSPORT_NATIVE);
161 SP_API enum sp_return sp_get_port_usb_bus_address(const struct sp_port *port,
162 int *usb_bus,int *usb_address)
164 TRACE("%p", port);
166 if (!port)
167 RETURN_ERROR(SP_ERR_ARG, "Null port");
168 if (port->transport != SP_TRANSPORT_USB)
169 RETURN_ERROR(SP_ERR_ARG, "Port does not use USB transport");
170 if (port->usb_bus < 0 || port->usb_address < 0)
171 RETURN_ERROR(SP_ERR_SUPP, "Bus and address values are not available");
173 if (usb_bus)
174 *usb_bus = port->usb_bus;
175 if (usb_address)
176 *usb_address = port->usb_address;
178 RETURN_OK();
181 SP_API enum sp_return sp_get_port_usb_vid_pid(const struct sp_port *port,
182 int *usb_vid, int *usb_pid)
184 TRACE("%p", port);
186 if (!port)
187 RETURN_ERROR(SP_ERR_ARG, "Null port");
188 if (port->transport != SP_TRANSPORT_USB)
189 RETURN_ERROR(SP_ERR_ARG, "Port does not use USB transport");
190 if (port->usb_vid < 0 || port->usb_pid < 0)
191 RETURN_ERROR(SP_ERR_SUPP, "VID:PID values are not available");
193 if (usb_vid)
194 *usb_vid = port->usb_vid;
195 if (usb_pid)
196 *usb_pid = port->usb_pid;
198 RETURN_OK();
201 SP_API char *sp_get_port_usb_manufacturer(const struct sp_port *port)
203 TRACE("%p", port);
205 if (!port || port->transport != SP_TRANSPORT_USB || !port->usb_manufacturer)
206 return NULL;
208 RETURN_STRING(port->usb_manufacturer);
211 SP_API char *sp_get_port_usb_product(const struct sp_port *port)
213 TRACE("%p", port);
215 if (!port || port->transport != SP_TRANSPORT_USB || !port->usb_product)
216 return NULL;
218 RETURN_STRING(port->usb_product);
221 SP_API char *sp_get_port_usb_serial(const struct sp_port *port)
223 TRACE("%p", port);
225 if (!port || port->transport != SP_TRANSPORT_USB || !port->usb_serial)
226 return NULL;
228 RETURN_STRING(port->usb_serial);
231 SP_API char *sp_get_port_bluetooth_address(const struct sp_port *port)
233 TRACE("%p", port);
235 if (!port || port->transport != SP_TRANSPORT_BLUETOOTH
236 || !port->bluetooth_address)
237 return NULL;
239 RETURN_STRING(port->bluetooth_address);
242 SP_API enum sp_return sp_get_port_handle(const struct sp_port *port,
243 void *result_ptr)
245 TRACE("%p, %p", port, result_ptr);
247 if (!port)
248 RETURN_ERROR(SP_ERR_ARG, "Null port");
249 if (!result_ptr)
250 RETURN_ERROR(SP_ERR_ARG, "Null result pointer");
252 #ifdef _WIN32
253 HANDLE *handle_ptr = result_ptr;
254 *handle_ptr = port->hdl;
255 #else
256 int *fd_ptr = result_ptr;
257 *fd_ptr = port->fd;
258 #endif
260 RETURN_OK();
263 SP_API enum sp_return sp_copy_port(const struct sp_port *port,
264 struct sp_port **copy_ptr)
266 TRACE("%p, %p", port, copy_ptr);
268 if (!copy_ptr)
269 RETURN_ERROR(SP_ERR_ARG, "Null result pointer");
271 *copy_ptr = NULL;
273 if (!port)
274 RETURN_ERROR(SP_ERR_ARG, "Null port");
276 if (!port->name)
277 RETURN_ERROR(SP_ERR_ARG, "Null port name");
279 DEBUG("Copying port structure");
281 RETURN_INT(sp_get_port_by_name(port->name, copy_ptr));
284 SP_API void sp_free_port(struct sp_port *port)
286 TRACE("%p", port);
288 if (!port) {
289 DEBUG("Null port");
290 RETURN();
293 DEBUG("Freeing port structure");
295 if (port->name)
296 free(port->name);
297 if (port->description)
298 free(port->description);
299 if (port->usb_manufacturer)
300 free(port->usb_manufacturer);
301 if (port->usb_product)
302 free(port->usb_product);
303 if (port->usb_serial)
304 free(port->usb_serial);
305 if (port->bluetooth_address)
306 free(port->bluetooth_address);
307 #ifdef _WIN32
308 if (port->usb_path)
309 free(port->usb_path);
310 if (port->write_buf)
311 free(port->write_buf);
312 #endif
314 free(port);
316 RETURN();
319 SP_PRIV struct sp_port **list_append(struct sp_port **list,
320 const char *portname)
322 void *tmp;
323 size_t count;
325 for (count = 0; list[count]; count++)
327 if (!(tmp = realloc(list, sizeof(struct sp_port *) * (count + 2))))
328 goto fail;
329 list = tmp;
330 if (sp_get_port_by_name(portname, &list[count]) != SP_OK)
331 goto fail;
332 list[count + 1] = NULL;
333 return list;
335 fail:
336 sp_free_port_list(list);
337 return NULL;
340 SP_API enum sp_return sp_list_ports(struct sp_port ***list_ptr)
342 #ifndef NO_ENUMERATION
343 struct sp_port **list;
344 int ret;
345 #endif
347 TRACE("%p", list_ptr);
349 if (!list_ptr)
350 RETURN_ERROR(SP_ERR_ARG, "Null result pointer");
352 *list_ptr = NULL;
354 #ifdef NO_ENUMERATION
355 RETURN_ERROR(SP_ERR_SUPP, "Enumeration not supported on this platform");
356 #else
357 DEBUG("Enumerating ports");
359 if (!(list = malloc(sizeof(struct sp_port *))))
360 RETURN_ERROR(SP_ERR_MEM, "Port list malloc failed");
362 list[0] = NULL;
364 ret = list_ports(&list);
366 if (ret == SP_OK) {
367 *list_ptr = list;
368 } else {
369 sp_free_port_list(list);
370 *list_ptr = NULL;
373 RETURN_CODEVAL(ret);
374 #endif
377 SP_API void sp_free_port_list(struct sp_port **list)
379 unsigned int i;
381 TRACE("%p", list);
383 if (!list) {
384 DEBUG("Null list");
385 RETURN();
388 DEBUG("Freeing port list");
390 for (i = 0; list[i]; i++)
391 sp_free_port(list[i]);
392 free(list);
394 RETURN();
397 #define CHECK_PORT() do { \
398 if (!port) \
399 RETURN_ERROR(SP_ERR_ARG, "Null port"); \
400 if (!port->name) \
401 RETURN_ERROR(SP_ERR_ARG, "Null port name"); \
402 } while (0)
403 #ifdef _WIN32
404 #define CHECK_PORT_HANDLE() do { \
405 if (port->hdl == INVALID_HANDLE_VALUE) \
406 RETURN_ERROR(SP_ERR_ARG, "Port not open"); \
407 } while (0)
408 #else
409 #define CHECK_PORT_HANDLE() do { \
410 if (port->fd < 0) \
411 RETURN_ERROR(SP_ERR_ARG, "Port not open"); \
412 } while (0)
413 #endif
414 #define CHECK_OPEN_PORT() do { \
415 CHECK_PORT(); \
416 CHECK_PORT_HANDLE(); \
417 } while (0)
419 #ifdef WIN32
420 /** To be called after port receive buffer is emptied. */
421 static enum sp_return restart_wait(struct sp_port *port)
423 DWORD wait_result, last_error_code;
425 if (port->wait_running) {
426 /* Check status of running wait operation. */
427 if (GetOverlappedResult(port->hdl, &port->wait_ovl,
428 &wait_result, FALSE)) {
429 DEBUG("Previous wait completed");
430 port->wait_running = FALSE;
431 } else if ((last_error_code = GetLastError()) == ERROR_OPERATION_ABORTED) {
432 DEBUG("Previous wait aborted");
433 port->wait_running = FALSE;
434 } else if (last_error_code == ERROR_IO_INCOMPLETE) {
435 DEBUG("Previous wait still running");
436 RETURN_OK();
437 } else {
438 RETURN_FAIL("GetOverlappedResult() failed");
442 if (!port->wait_running) {
443 /* Start new wait operation. */
444 if (WaitCommEvent(port->hdl, &port->events,
445 &port->wait_ovl)) {
446 DEBUG("New wait returned, events already pending");
447 } else if (GetLastError() == ERROR_IO_PENDING) {
448 DEBUG("New wait running in background");
449 port->wait_running = TRUE;
450 } else {
451 RETURN_FAIL("WaitCommEvent() failed");
455 RETURN_OK();
457 #endif
459 SP_API enum sp_return sp_open(struct sp_port *port, enum sp_mode flags)
461 struct port_data data;
462 struct sp_port_config config;
463 enum sp_return ret;
465 TRACE("%p, 0x%x", port, flags);
467 CHECK_PORT();
469 if (flags > SP_MODE_READ_WRITE)
470 RETURN_ERROR(SP_ERR_ARG, "Invalid flags");
472 DEBUG_FMT("Opening port %s", port->name);
474 #ifdef _WIN32
475 DWORD desired_access = 0, flags_and_attributes = 0, errors;
476 char *escaped_port_name;
477 COMSTAT status;
479 /* Prefix port name with '\\.\' to work with ports above COM9. */
480 if (!(escaped_port_name = malloc(strlen(port->name) + 5)))
481 RETURN_ERROR(SP_ERR_MEM, "Escaped port name malloc failed");
482 sprintf(escaped_port_name, "\\\\.\\%s", port->name);
484 /* Map 'flags' to the OS-specific settings. */
485 flags_and_attributes = FILE_ATTRIBUTE_NORMAL | FILE_FLAG_OVERLAPPED;
486 if (flags & SP_MODE_READ)
487 desired_access |= GENERIC_READ;
488 if (flags & SP_MODE_WRITE)
489 desired_access |= GENERIC_WRITE;
491 port->hdl = CreateFileA(escaped_port_name, desired_access, 0, 0,
492 OPEN_EXISTING, flags_and_attributes, 0);
494 free(escaped_port_name);
496 if (port->hdl == INVALID_HANDLE_VALUE)
497 RETURN_FAIL("Port CreateFile() failed");
499 /* All timeouts initially disabled. */
500 port->timeouts.ReadIntervalTimeout = 0;
501 port->timeouts.ReadTotalTimeoutMultiplier = 0;
502 port->timeouts.ReadTotalTimeoutConstant = 0;
503 port->timeouts.WriteTotalTimeoutMultiplier = 0;
504 port->timeouts.WriteTotalTimeoutConstant = 0;
506 if (SetCommTimeouts(port->hdl, &port->timeouts) == 0) {
507 sp_close(port);
508 RETURN_FAIL("SetCommTimeouts() failed");
511 /* Prepare OVERLAPPED structures. */
512 #define INIT_OVERLAPPED(ovl) do { \
513 memset(&port->ovl, 0, sizeof(port->ovl)); \
514 port->ovl.hEvent = INVALID_HANDLE_VALUE; \
515 if ((port->ovl.hEvent = CreateEvent(NULL, TRUE, TRUE, NULL)) \
516 == INVALID_HANDLE_VALUE) { \
517 sp_close(port); \
518 RETURN_FAIL(#ovl "CreateEvent() failed"); \
520 } while (0)
522 INIT_OVERLAPPED(read_ovl);
523 INIT_OVERLAPPED(write_ovl);
524 INIT_OVERLAPPED(wait_ovl);
526 /* Set event mask for RX and error events. */
527 if (SetCommMask(port->hdl, EV_RXCHAR | EV_ERR) == 0) {
528 sp_close(port);
529 RETURN_FAIL("SetCommMask() failed");
532 port->writing = FALSE;
533 port->wait_running = FALSE;
535 ret = restart_wait(port);
537 if (ret < 0) {
538 sp_close(port);
539 RETURN_CODEVAL(ret);
541 #else
542 int flags_local = O_NONBLOCK | O_NOCTTY | O_CLOEXEC;
544 /* Map 'flags' to the OS-specific settings. */
545 if ((flags & SP_MODE_READ_WRITE) == SP_MODE_READ_WRITE)
546 flags_local |= O_RDWR;
547 else if (flags & SP_MODE_READ)
548 flags_local |= O_RDONLY;
549 else if (flags & SP_MODE_WRITE)
550 flags_local |= O_WRONLY;
552 if ((port->fd = open(port->name, flags_local)) < 0)
553 RETURN_FAIL("open() failed");
556 * On POSIX in the default case the file descriptor of a serial port
557 * is not opened exclusively. Therefore the settings of a port are
558 * overwritten if the serial port is opened a second time. Windows
559 * opens all serial ports exclusively.
560 * So the idea is to open the serial ports alike in the exclusive mode.
562 * ioctl(*, TIOCEXCL) defines the file descriptor as exclusive. So all
563 * further open calls on the serial port will fail.
565 * There is a race condition if two processes open the same serial
566 * port. None of the processes will notice the exclusive ownership of
567 * the other process because ioctl() doesn't return an error code if
568 * the file descriptor is already marked as exclusive.
569 * This can be solved with flock(). It returns an error if the file
570 * descriptor is already locked by another process.
572 #ifdef HAVE_FLOCK
573 if (flock(port->fd, LOCK_EX | LOCK_NB) < 0)
574 RETURN_FAIL("flock() failed");
575 #endif
577 #ifdef TIOCEXCL
579 * Before Linux 3.8 ioctl(*, TIOCEXCL) was not implemented and could
580 * lead to EINVAL or ENOTTY.
581 * These errors aren't fatal and can be ignored.
583 if (ioctl(port->fd, TIOCEXCL) < 0 && errno != EINVAL && errno != ENOTTY)
584 RETURN_FAIL("ioctl() failed");
585 #endif
587 #endif
589 ret = get_config(port, &data, &config);
591 if (ret < 0) {
592 sp_close(port);
593 RETURN_CODEVAL(ret);
597 * Assume a default baudrate if the OS does not provide one.
598 * Cannot assign -1 here since Windows holds the baudrate in
599 * the DCB and does not configure the rate individually.
601 if (config.baudrate == 0) {
602 config.baudrate = 9600;
605 /* Set sane port settings. */
606 #ifdef _WIN32
607 data.dcb.fBinary = TRUE;
608 data.dcb.fDsrSensitivity = FALSE;
609 data.dcb.fErrorChar = FALSE;
610 data.dcb.fNull = FALSE;
611 data.dcb.fAbortOnError = FALSE;
612 #else
613 /* Turn off all fancy termios tricks, give us a raw channel. */
614 data.term.c_iflag &= ~(IGNBRK | BRKINT | PARMRK | ISTRIP | INLCR | IGNCR | ICRNL | IMAXBEL);
615 #ifdef IUCLC
616 data.term.c_iflag &= ~IUCLC;
617 #endif
618 data.term.c_oflag &= ~(OPOST | ONLCR | OCRNL | ONOCR | ONLRET);
619 #ifdef OLCUC
620 data.term.c_oflag &= ~OLCUC;
621 #endif
622 #ifdef NLDLY
623 data.term.c_oflag &= ~NLDLY;
624 #endif
625 #ifdef CRDLY
626 data.term.c_oflag &= ~CRDLY;
627 #endif
628 #ifdef TABDLY
629 data.term.c_oflag &= ~TABDLY;
630 #endif
631 #ifdef BSDLY
632 data.term.c_oflag &= ~BSDLY;
633 #endif
634 #ifdef VTDLY
635 data.term.c_oflag &= ~VTDLY;
636 #endif
637 #ifdef FFDLY
638 data.term.c_oflag &= ~FFDLY;
639 #endif
640 #ifdef OFILL
641 data.term.c_oflag &= ~OFILL;
642 #endif
643 data.term.c_lflag &= ~(ISIG | ICANON | ECHO | IEXTEN);
644 data.term.c_cc[VMIN] = 0;
645 data.term.c_cc[VTIME] = 0;
647 /* Ignore modem status lines; enable receiver; leave control lines alone on close. */
648 data.term.c_cflag |= (CLOCAL | CREAD);
649 data.term.c_cflag &= ~(HUPCL);
650 #endif
652 #ifdef _WIN32
653 if (ClearCommError(port->hdl, &errors, &status) == 0)
654 RETURN_FAIL("ClearCommError() failed");
655 #endif
657 ret = set_config(port, &data, &config);
659 if (ret < 0) {
660 sp_close(port);
661 RETURN_CODEVAL(ret);
664 RETURN_OK();
667 SP_API enum sp_return sp_close(struct sp_port *port)
669 TRACE("%p", port);
671 CHECK_OPEN_PORT();
673 DEBUG_FMT("Closing port %s", port->name);
675 #ifdef _WIN32
676 /* Returns non-zero upon success, 0 upon failure. */
677 if (CloseHandle(port->hdl) == 0)
678 RETURN_FAIL("Port CloseHandle() failed");
679 port->hdl = INVALID_HANDLE_VALUE;
681 /* Close event handles for overlapped structures. */
682 #define CLOSE_OVERLAPPED(ovl) do { \
683 if (port->ovl.hEvent != INVALID_HANDLE_VALUE && \
684 CloseHandle(port->ovl.hEvent) == 0) \
685 RETURN_FAIL(# ovl "event CloseHandle() failed"); \
686 } while (0)
687 CLOSE_OVERLAPPED(read_ovl);
688 CLOSE_OVERLAPPED(write_ovl);
689 CLOSE_OVERLAPPED(wait_ovl);
691 if (port->write_buf) {
692 free(port->write_buf);
693 port->write_buf = NULL;
695 #else
696 /* Returns 0 upon success, -1 upon failure. */
697 if (close(port->fd) == -1)
698 RETURN_FAIL("close() failed");
699 port->fd = -1;
700 #endif
702 RETURN_OK();
705 SP_API enum sp_return sp_flush(struct sp_port *port, enum sp_buffer buffers)
707 TRACE("%p, 0x%x", port, buffers);
709 CHECK_OPEN_PORT();
711 if (buffers > SP_BUF_BOTH)
712 RETURN_ERROR(SP_ERR_ARG, "Invalid buffer selection");
714 const char *buffer_names[] = {"no", "input", "output", "both"};
716 DEBUG_FMT("Flushing %s buffers on port %s",
717 buffer_names[buffers], port->name);
719 #ifdef _WIN32
720 DWORD flags = 0;
721 if (buffers & SP_BUF_INPUT)
722 flags |= PURGE_RXCLEAR;
723 if (buffers & SP_BUF_OUTPUT)
724 flags |= PURGE_TXCLEAR;
726 /* Returns non-zero upon success, 0 upon failure. */
727 if (PurgeComm(port->hdl, flags) == 0)
728 RETURN_FAIL("PurgeComm() failed");
730 if (buffers & SP_BUF_INPUT)
731 TRY(restart_wait(port));
732 #else
733 int flags = 0;
734 if (buffers == SP_BUF_BOTH)
735 flags = TCIOFLUSH;
736 else if (buffers == SP_BUF_INPUT)
737 flags = TCIFLUSH;
738 else if (buffers == SP_BUF_OUTPUT)
739 flags = TCOFLUSH;
741 /* Returns 0 upon success, -1 upon failure. */
742 if (tcflush(port->fd, flags) < 0)
743 RETURN_FAIL("tcflush() failed");
744 #endif
745 RETURN_OK();
748 SP_API enum sp_return sp_drain(struct sp_port *port)
750 TRACE("%p", port);
752 CHECK_OPEN_PORT();
754 DEBUG_FMT("Draining port %s", port->name);
756 #ifdef _WIN32
757 /* Returns non-zero upon success, 0 upon failure. */
758 if (FlushFileBuffers(port->hdl) == 0)
759 RETURN_FAIL("FlushFileBuffers() failed");
760 RETURN_OK();
761 #else
762 int result;
763 while (1) {
764 #if defined(__ANDROID__) && (__ANDROID_API__ < 21)
765 /* Android only has tcdrain from platform 21 onwards.
766 * On previous API versions, use the ioctl directly. */
767 int arg = 1;
768 result = ioctl(port->fd, TCSBRK, &arg);
769 #else
770 result = tcdrain(port->fd);
771 #endif
772 if (result < 0) {
773 if (errno == EINTR) {
774 DEBUG("tcdrain() was interrupted");
775 continue;
776 } else {
777 RETURN_FAIL("tcdrain() failed");
779 } else {
780 RETURN_OK();
783 #endif
786 #ifdef _WIN32
787 static enum sp_return await_write_completion(struct sp_port *port)
789 TRACE("%p", port);
790 DWORD bytes_written;
791 BOOL result;
793 /* Wait for previous non-blocking write to complete, if any. */
794 if (port->writing) {
795 DEBUG("Waiting for previous write to complete");
796 result = GetOverlappedResult(port->hdl, &port->write_ovl, &bytes_written, TRUE);
797 port->writing = 0;
798 if (!result)
799 RETURN_FAIL("Previous write failed to complete");
800 DEBUG("Previous write completed");
803 RETURN_OK();
805 #endif
807 SP_API enum sp_return sp_blocking_write(struct sp_port *port, const void *buf,
808 size_t count, unsigned int timeout_ms)
810 TRACE("%p, %p, %d, %d", port, buf, count, timeout_ms);
812 CHECK_OPEN_PORT();
814 if (!buf)
815 RETURN_ERROR(SP_ERR_ARG, "Null buffer");
817 if (timeout_ms)
818 DEBUG_FMT("Writing %d bytes to port %s, timeout %d ms",
819 count, port->name, timeout_ms);
820 else
821 DEBUG_FMT("Writing %d bytes to port %s, no timeout",
822 count, port->name);
824 if (count == 0)
825 RETURN_INT(0);
827 #ifdef _WIN32
828 DWORD remaining_ms, write_size, bytes_written;
829 size_t remaining_bytes, total_bytes_written = 0;
830 const uint8_t *write_ptr = (uint8_t *) buf;
831 bool result;
832 struct timeout timeout;
834 timeout_start(&timeout, timeout_ms);
836 TRY(await_write_completion(port));
838 while (total_bytes_written < count) {
840 if (timeout_check(&timeout))
841 break;
843 remaining_ms = timeout_remaining_ms(&timeout);
845 if (port->timeouts.WriteTotalTimeoutConstant != remaining_ms) {
846 port->timeouts.WriteTotalTimeoutConstant = remaining_ms;
847 if (SetCommTimeouts(port->hdl, &port->timeouts) == 0)
848 RETURN_FAIL("SetCommTimeouts() failed");
851 /* Reduce write size if it exceeds the WriteFile limit. */
852 remaining_bytes = count - total_bytes_written;
853 if (remaining_bytes > WRITEFILE_MAX_SIZE)
854 write_size = WRITEFILE_MAX_SIZE;
855 else
856 write_size = (DWORD) remaining_bytes;
858 /* Start write. */
860 result = WriteFile(port->hdl, write_ptr, write_size, NULL, &port->write_ovl);
862 timeout_update(&timeout);
864 if (result) {
865 DEBUG("Write completed immediately");
866 bytes_written = write_size;
867 } else if (GetLastError() == ERROR_IO_PENDING) {
868 DEBUG("Waiting for write to complete");
869 if (GetOverlappedResult(port->hdl, &port->write_ovl, &bytes_written, TRUE) == 0) {
870 if (GetLastError() == ERROR_SEM_TIMEOUT) {
871 DEBUG("Write timed out");
872 break;
873 } else {
874 RETURN_FAIL("GetOverlappedResult() failed");
877 DEBUG_FMT("Write completed, %d/%d bytes written", bytes_written, write_size);
878 } else {
879 RETURN_FAIL("WriteFile() failed");
882 write_ptr += bytes_written;
883 total_bytes_written += bytes_written;
886 RETURN_INT((int) total_bytes_written);
887 #else
888 size_t bytes_written = 0;
889 unsigned char *ptr = (unsigned char *) buf;
890 struct timeout timeout;
891 fd_set fds;
892 ssize_t result;
894 timeout_start(&timeout, timeout_ms);
896 FD_ZERO(&fds);
897 FD_SET(port->fd, &fds);
899 /* Loop until we have written the requested number of bytes. */
900 while (bytes_written < count) {
902 if (timeout_check(&timeout))
903 break;
905 result = select(port->fd + 1, NULL, &fds, NULL, timeout_timeval(&timeout));
907 timeout_update(&timeout);
909 if (result < 0) {
910 if (errno == EINTR) {
911 DEBUG("select() call was interrupted, repeating");
912 continue;
913 } else {
914 RETURN_FAIL("select() failed");
916 } else if (result == 0) {
917 /* Timeout has expired. */
918 break;
921 /* Do write. */
922 result = write(port->fd, ptr, count - bytes_written);
924 if (result < 0) {
925 if (errno == EAGAIN)
926 /* This shouldn't happen because we did a select() first, but handle anyway. */
927 continue;
928 else
929 /* This is an actual failure. */
930 RETURN_FAIL("write() failed");
933 bytes_written += result;
934 ptr += result;
937 if (bytes_written < count)
938 DEBUG("Write timed out");
940 RETURN_INT(bytes_written);
941 #endif
944 SP_API enum sp_return sp_nonblocking_write(struct sp_port *port,
945 const void *buf, size_t count)
947 TRACE("%p, %p, %d", port, buf, count);
949 CHECK_OPEN_PORT();
951 if (!buf)
952 RETURN_ERROR(SP_ERR_ARG, "Null buffer");
954 DEBUG_FMT("Writing up to %d bytes to port %s", count, port->name);
956 if (count == 0)
957 RETURN_INT(0);
959 #ifdef _WIN32
960 size_t buf_bytes;
962 /* Check whether previous write is complete. */
963 if (port->writing) {
964 if (HasOverlappedIoCompleted(&port->write_ovl)) {
965 DEBUG("Previous write completed");
966 port->writing = 0;
967 } else {
968 DEBUG("Previous write not complete");
969 /* Can't take a new write until the previous one finishes. */
970 RETURN_INT(0);
974 /* Set timeout. */
975 if (port->timeouts.WriteTotalTimeoutConstant != 0) {
976 port->timeouts.WriteTotalTimeoutConstant = 0;
977 if (SetCommTimeouts(port->hdl, &port->timeouts) == 0)
978 RETURN_FAIL("SetCommTimeouts() failed");
981 /* Reduce count if it exceeds the WriteFile limit. */
982 if (count > WRITEFILE_MAX_SIZE)
983 count = WRITEFILE_MAX_SIZE;
985 /* Copy data to our write buffer. */
986 buf_bytes = min(port->write_buf_size, count);
987 memcpy(port->write_buf, buf, buf_bytes);
989 /* Start asynchronous write. */
990 if (WriteFile(port->hdl, port->write_buf, (DWORD) buf_bytes, NULL, &port->write_ovl) == 0) {
991 if (GetLastError() == ERROR_IO_PENDING) {
992 if ((port->writing = !HasOverlappedIoCompleted(&port->write_ovl)))
993 DEBUG("Asynchronous write completed immediately");
994 else
995 DEBUG("Asynchronous write running");
996 } else {
997 /* Actual failure of some kind. */
998 RETURN_FAIL("WriteFile() failed");
1002 DEBUG("All bytes written immediately");
1004 RETURN_INT((int) buf_bytes);
1005 #else
1006 /* Returns the number of bytes written, or -1 upon failure. */
1007 ssize_t written = write(port->fd, buf, count);
1009 if (written < 0) {
1010 if (errno == EAGAIN)
1011 // Buffer is full, no bytes written.
1012 RETURN_INT(0);
1013 else
1014 RETURN_FAIL("write() failed");
1015 } else {
1016 RETURN_INT(written);
1018 #endif
1021 #ifdef _WIN32
1022 /* Restart wait operation if buffer was emptied. */
1023 static enum sp_return restart_wait_if_needed(struct sp_port *port, unsigned int bytes_read)
1025 DWORD errors;
1026 COMSTAT comstat;
1028 if (bytes_read == 0)
1029 RETURN_OK();
1031 if (ClearCommError(port->hdl, &errors, &comstat) == 0)
1032 RETURN_FAIL("ClearCommError() failed");
1034 if (comstat.cbInQue == 0)
1035 TRY(restart_wait(port));
1037 RETURN_OK();
1039 #endif
1041 SP_API enum sp_return sp_blocking_read(struct sp_port *port, void *buf,
1042 size_t count, unsigned int timeout_ms)
1044 TRACE("%p, %p, %d, %d", port, buf, count, timeout_ms);
1046 CHECK_OPEN_PORT();
1048 if (!buf)
1049 RETURN_ERROR(SP_ERR_ARG, "Null buffer");
1051 if (timeout_ms)
1052 DEBUG_FMT("Reading %d bytes from port %s, timeout %d ms",
1053 count, port->name, timeout_ms);
1054 else
1055 DEBUG_FMT("Reading %d bytes from port %s, no timeout",
1056 count, port->name);
1058 if (count == 0)
1059 RETURN_INT(0);
1061 #ifdef _WIN32
1062 DWORD bytes_read;
1064 /* Set timeout. */
1065 if (port->timeouts.ReadIntervalTimeout != 0 ||
1066 port->timeouts.ReadTotalTimeoutMultiplier != 0 ||
1067 port->timeouts.ReadTotalTimeoutConstant != timeout_ms) {
1068 port->timeouts.ReadIntervalTimeout = 0;
1069 port->timeouts.ReadTotalTimeoutMultiplier = 0;
1070 port->timeouts.ReadTotalTimeoutConstant = timeout_ms;
1071 if (SetCommTimeouts(port->hdl, &port->timeouts) == 0)
1072 RETURN_FAIL("SetCommTimeouts() failed");
1075 /* Start read. */
1076 if (ReadFile(port->hdl, buf, (DWORD) count, NULL, &port->read_ovl)) {
1077 DEBUG("Read completed immediately");
1078 bytes_read = (DWORD) count;
1079 } else if (GetLastError() == ERROR_IO_PENDING) {
1080 DEBUG("Waiting for read to complete");
1081 if (GetOverlappedResult(port->hdl, &port->read_ovl, &bytes_read, TRUE) == 0)
1082 RETURN_FAIL("GetOverlappedResult() failed");
1083 DEBUG_FMT("Read completed, %d/%d bytes read", bytes_read, count);
1084 } else {
1085 RETURN_FAIL("ReadFile() failed");
1088 TRY(restart_wait_if_needed(port, bytes_read));
1090 RETURN_INT((int) bytes_read);
1092 #else
1093 size_t bytes_read = 0;
1094 unsigned char *ptr = (unsigned char *) buf;
1095 struct timeout timeout;
1096 fd_set fds;
1097 ssize_t result;
1099 timeout_start(&timeout, timeout_ms);
1101 FD_ZERO(&fds);
1102 FD_SET(port->fd, &fds);
1104 /* Loop until we have the requested number of bytes. */
1105 while (bytes_read < count) {
1107 if (timeout_check(&timeout))
1108 /* Timeout has expired. */
1109 break;
1111 result = select(port->fd + 1, &fds, NULL, NULL, timeout_timeval(&timeout));
1113 timeout_update(&timeout);
1115 if (result < 0) {
1116 if (errno == EINTR) {
1117 DEBUG("select() call was interrupted, repeating");
1118 continue;
1119 } else {
1120 RETURN_FAIL("select() failed");
1122 } else if (result == 0) {
1123 /* Timeout has expired. */
1124 break;
1127 /* Do read. */
1128 result = read(port->fd, ptr, count - bytes_read);
1130 if (result < 0) {
1131 if (errno == EAGAIN)
1133 * This shouldn't happen because we did a
1134 * select() first, but handle anyway.
1136 continue;
1137 else
1138 /* This is an actual failure. */
1139 RETURN_FAIL("read() failed");
1142 bytes_read += result;
1143 ptr += result;
1146 if (bytes_read < count)
1147 DEBUG("Read timed out");
1149 RETURN_INT(bytes_read);
1150 #endif
1153 SP_API enum sp_return sp_blocking_read_next(struct sp_port *port, void *buf,
1154 size_t count, unsigned int timeout_ms)
1156 TRACE("%p, %p, %d, %d", port, buf, count, timeout_ms);
1158 CHECK_OPEN_PORT();
1160 if (!buf)
1161 RETURN_ERROR(SP_ERR_ARG, "Null buffer");
1163 if (count == 0)
1164 RETURN_ERROR(SP_ERR_ARG, "Zero count");
1166 if (timeout_ms)
1167 DEBUG_FMT("Reading next max %d bytes from port %s, timeout %d ms",
1168 count, port->name, timeout_ms);
1169 else
1170 DEBUG_FMT("Reading next max %d bytes from port %s, no timeout",
1171 count, port->name);
1173 #ifdef _WIN32
1174 DWORD bytes_read = 0;
1176 /* If timeout_ms == 0, set maximum timeout. */
1177 DWORD timeout_val = (timeout_ms == 0 ? MAXDWORD - 1 : timeout_ms);
1179 /* Set timeout. */
1180 if (port->timeouts.ReadIntervalTimeout != MAXDWORD ||
1181 port->timeouts.ReadTotalTimeoutMultiplier != MAXDWORD ||
1182 port->timeouts.ReadTotalTimeoutConstant != timeout_val) {
1183 port->timeouts.ReadIntervalTimeout = MAXDWORD;
1184 port->timeouts.ReadTotalTimeoutMultiplier = MAXDWORD;
1185 port->timeouts.ReadTotalTimeoutConstant = timeout_val;
1186 if (SetCommTimeouts(port->hdl, &port->timeouts) == 0)
1187 RETURN_FAIL("SetCommTimeouts() failed");
1190 /* Loop until we have at least one byte, or timeout is reached. */
1191 while (bytes_read == 0) {
1192 /* Start read. */
1193 if (ReadFile(port->hdl, buf, (DWORD) count, &bytes_read, &port->read_ovl)) {
1194 DEBUG("Read completed immediately");
1195 } else if (GetLastError() == ERROR_IO_PENDING) {
1196 DEBUG("Waiting for read to complete");
1197 if (GetOverlappedResult(port->hdl, &port->read_ovl, &bytes_read, TRUE) == 0)
1198 RETURN_FAIL("GetOverlappedResult() failed");
1199 if (bytes_read > 0) {
1200 DEBUG("Read completed");
1201 } else if (timeout_ms > 0) {
1202 DEBUG("Read timed out");
1203 break;
1204 } else {
1205 DEBUG("Restarting read");
1207 } else {
1208 RETURN_FAIL("ReadFile() failed");
1212 TRY(restart_wait_if_needed(port, bytes_read));
1214 RETURN_INT(bytes_read);
1216 #else
1217 size_t bytes_read = 0;
1218 struct timeout timeout;
1219 fd_set fds;
1220 ssize_t result;
1222 timeout_start(&timeout, timeout_ms);
1224 FD_ZERO(&fds);
1225 FD_SET(port->fd, &fds);
1227 /* Loop until we have at least one byte, or timeout is reached. */
1228 while (bytes_read == 0) {
1230 if (timeout_check(&timeout))
1231 /* Timeout has expired. */
1232 break;
1234 result = select(port->fd + 1, &fds, NULL, NULL, timeout_timeval(&timeout));
1236 timeout_update(&timeout);
1238 if (result < 0) {
1239 if (errno == EINTR) {
1240 DEBUG("select() call was interrupted, repeating");
1241 continue;
1242 } else {
1243 RETURN_FAIL("select() failed");
1245 } else if (result == 0) {
1246 /* Timeout has expired. */
1247 break;
1250 /* Do read. */
1251 result = read(port->fd, buf, count);
1253 if (result < 0) {
1254 if (errno == EAGAIN)
1255 /* This shouldn't happen because we did a select() first, but handle anyway. */
1256 continue;
1257 else
1258 /* This is an actual failure. */
1259 RETURN_FAIL("read() failed");
1262 bytes_read = result;
1265 if (bytes_read == 0)
1266 DEBUG("Read timed out");
1268 RETURN_INT(bytes_read);
1269 #endif
1272 SP_API enum sp_return sp_nonblocking_read(struct sp_port *port, void *buf,
1273 size_t count)
1275 TRACE("%p, %p, %d", port, buf, count);
1277 CHECK_OPEN_PORT();
1279 if (!buf)
1280 RETURN_ERROR(SP_ERR_ARG, "Null buffer");
1282 DEBUG_FMT("Reading up to %d bytes from port %s", count, port->name);
1284 #ifdef _WIN32
1285 DWORD bytes_read;
1287 /* Set timeout. */
1288 if (port->timeouts.ReadIntervalTimeout != MAXDWORD ||
1289 port->timeouts.ReadTotalTimeoutMultiplier != 0 ||
1290 port->timeouts.ReadTotalTimeoutConstant != 0) {
1291 port->timeouts.ReadIntervalTimeout = MAXDWORD;
1292 port->timeouts.ReadTotalTimeoutMultiplier = 0;
1293 port->timeouts.ReadTotalTimeoutConstant = 0;
1294 if (SetCommTimeouts(port->hdl, &port->timeouts) == 0)
1295 RETURN_FAIL("SetCommTimeouts() failed");
1298 /* Do read. */
1299 if (ReadFile(port->hdl, buf, (DWORD) count, NULL, &port->read_ovl) == 0)
1300 if (GetLastError() != ERROR_IO_PENDING)
1301 RETURN_FAIL("ReadFile() failed");
1303 /* Get number of bytes read. */
1304 if (GetOverlappedResult(port->hdl, &port->read_ovl, &bytes_read, FALSE) == 0)
1305 RETURN_FAIL("GetOverlappedResult() failed");
1307 TRY(restart_wait_if_needed(port, bytes_read));
1309 RETURN_INT(bytes_read);
1310 #else
1311 ssize_t bytes_read;
1313 /* Returns the number of bytes read, or -1 upon failure. */
1314 if ((bytes_read = read(port->fd, buf, count)) < 0) {
1315 if (errno == EAGAIN)
1316 /* No bytes available. */
1317 bytes_read = 0;
1318 else
1319 /* This is an actual failure. */
1320 RETURN_FAIL("read() failed");
1322 RETURN_INT(bytes_read);
1323 #endif
1326 SP_API enum sp_return sp_input_waiting(struct sp_port *port)
1328 TRACE("%p", port);
1330 CHECK_OPEN_PORT();
1332 DEBUG_FMT("Checking input bytes waiting on port %s", port->name);
1334 #ifdef _WIN32
1335 DWORD errors;
1336 COMSTAT comstat;
1338 if (ClearCommError(port->hdl, &errors, &comstat) == 0)
1339 RETURN_FAIL("ClearCommError() failed");
1340 RETURN_INT(comstat.cbInQue);
1341 #else
1342 int bytes_waiting;
1343 if (ioctl(port->fd, TIOCINQ, &bytes_waiting) < 0)
1344 RETURN_FAIL("TIOCINQ ioctl failed");
1345 RETURN_INT(bytes_waiting);
1346 #endif
1349 SP_API enum sp_return sp_output_waiting(struct sp_port *port)
1351 TRACE("%p", port);
1353 #ifdef __CYGWIN__
1354 /* TIOCOUTQ is not defined in Cygwin headers */
1355 RETURN_ERROR(SP_ERR_SUPP,
1356 "Getting output bytes waiting is not supported on Cygwin");
1357 #else
1358 CHECK_OPEN_PORT();
1360 DEBUG_FMT("Checking output bytes waiting on port %s", port->name);
1362 #ifdef _WIN32
1363 DWORD errors;
1364 COMSTAT comstat;
1366 if (ClearCommError(port->hdl, &errors, &comstat) == 0)
1367 RETURN_FAIL("ClearCommError() failed");
1368 RETURN_INT(comstat.cbOutQue);
1369 #else
1370 int bytes_waiting;
1371 if (ioctl(port->fd, TIOCOUTQ, &bytes_waiting) < 0)
1372 RETURN_FAIL("TIOCOUTQ ioctl failed");
1373 RETURN_INT(bytes_waiting);
1374 #endif
1375 #endif
1378 SP_API enum sp_return sp_new_event_set(struct sp_event_set **result_ptr)
1380 struct sp_event_set *result;
1382 TRACE("%p", result_ptr);
1384 if (!result_ptr)
1385 RETURN_ERROR(SP_ERR_ARG, "Null result");
1387 *result_ptr = NULL;
1389 if (!(result = malloc(sizeof(struct sp_event_set))))
1390 RETURN_ERROR(SP_ERR_MEM, "sp_event_set malloc() failed");
1392 memset(result, 0, sizeof(struct sp_event_set));
1394 *result_ptr = result;
1396 RETURN_OK();
1399 static enum sp_return add_handle(struct sp_event_set *event_set,
1400 event_handle handle, enum sp_event mask)
1402 void *new_handles;
1403 enum sp_event *new_masks;
1405 TRACE("%p, %d, %d", event_set, handle, mask);
1407 if (!(new_handles = realloc(event_set->handles,
1408 sizeof(event_handle) * (event_set->count + 1))))
1409 RETURN_ERROR(SP_ERR_MEM, "Handle array realloc() failed");
1411 event_set->handles = new_handles;
1413 if (!(new_masks = realloc(event_set->masks,
1414 sizeof(enum sp_event) * (event_set->count + 1))))
1415 RETURN_ERROR(SP_ERR_MEM, "Mask array realloc() failed");
1417 event_set->masks = new_masks;
1419 ((event_handle *) event_set->handles)[event_set->count] = handle;
1420 event_set->masks[event_set->count] = mask;
1422 event_set->count++;
1424 RETURN_OK();
1427 SP_API enum sp_return sp_add_port_events(struct sp_event_set *event_set,
1428 const struct sp_port *port, enum sp_event mask)
1430 TRACE("%p, %p, %d", event_set, port, mask);
1432 if (!event_set)
1433 RETURN_ERROR(SP_ERR_ARG, "Null event set");
1435 if (!port)
1436 RETURN_ERROR(SP_ERR_ARG, "Null port");
1438 if (mask > (SP_EVENT_RX_READY | SP_EVENT_TX_READY | SP_EVENT_ERROR))
1439 RETURN_ERROR(SP_ERR_ARG, "Invalid event mask");
1441 if (!mask)
1442 RETURN_OK();
1444 #ifdef _WIN32
1445 enum sp_event handle_mask;
1446 if ((handle_mask = mask & SP_EVENT_TX_READY))
1447 TRY(add_handle(event_set, port->write_ovl.hEvent, handle_mask));
1448 if ((handle_mask = mask & (SP_EVENT_RX_READY | SP_EVENT_ERROR)))
1449 TRY(add_handle(event_set, port->wait_ovl.hEvent, handle_mask));
1450 #else
1451 TRY(add_handle(event_set, port->fd, mask));
1452 #endif
1454 RETURN_OK();
1457 SP_API void sp_free_event_set(struct sp_event_set *event_set)
1459 TRACE("%p", event_set);
1461 if (!event_set) {
1462 DEBUG("Null event set");
1463 RETURN();
1466 DEBUG("Freeing event set");
1468 if (event_set->handles)
1469 free(event_set->handles);
1470 if (event_set->masks)
1471 free(event_set->masks);
1473 free(event_set);
1475 RETURN();
1478 SP_API enum sp_return sp_wait(struct sp_event_set *event_set,
1479 unsigned int timeout_ms)
1481 TRACE("%p, %d", event_set, timeout_ms);
1483 if (!event_set)
1484 RETURN_ERROR(SP_ERR_ARG, "Null event set");
1486 #ifdef _WIN32
1487 if (WaitForMultipleObjects(event_set->count, event_set->handles, FALSE,
1488 timeout_ms ? timeout_ms : INFINITE) == WAIT_FAILED)
1489 RETURN_FAIL("WaitForMultipleObjects() failed");
1491 RETURN_OK();
1492 #else
1493 struct timeout timeout;
1494 int poll_timeout;
1495 int result;
1496 struct pollfd *pollfds;
1497 unsigned int i;
1499 if (!(pollfds = malloc(sizeof(struct pollfd) * event_set->count)))
1500 RETURN_ERROR(SP_ERR_MEM, "pollfds malloc() failed");
1502 for (i = 0; i < event_set->count; i++) {
1503 pollfds[i].fd = ((int *)event_set->handles)[i];
1504 pollfds[i].events = 0;
1505 pollfds[i].revents = 0;
1506 if (event_set->masks[i] & SP_EVENT_RX_READY)
1507 pollfds[i].events |= POLLIN;
1508 if (event_set->masks[i] & SP_EVENT_TX_READY)
1509 pollfds[i].events |= POLLOUT;
1510 if (event_set->masks[i] & SP_EVENT_ERROR)
1511 pollfds[i].events |= POLLERR;
1514 timeout_start(&timeout, timeout_ms);
1515 timeout_limit(&timeout, INT_MAX);
1517 /* Loop until an event occurs. */
1518 while (1) {
1520 if (timeout_check(&timeout)) {
1521 DEBUG("Wait timed out");
1522 break;
1525 poll_timeout = (int) timeout_remaining_ms(&timeout);
1526 if (poll_timeout == 0)
1527 poll_timeout = -1;
1529 result = poll(pollfds, event_set->count, poll_timeout);
1531 timeout_update(&timeout);
1533 if (result < 0) {
1534 if (errno == EINTR) {
1535 DEBUG("poll() call was interrupted, repeating");
1536 continue;
1537 } else {
1538 free(pollfds);
1539 RETURN_FAIL("poll() failed");
1541 } else if (result == 0) {
1542 DEBUG("poll() timed out");
1543 if (!timeout.overflow)
1544 break;
1545 } else {
1546 DEBUG("poll() completed");
1547 break;
1551 free(pollfds);
1552 RETURN_OK();
1553 #endif
1556 #ifdef USE_TERMIOS_SPEED
1557 static enum sp_return get_baudrate(int fd, int *baudrate)
1559 void *data;
1561 TRACE("%d, %p", fd, baudrate);
1563 DEBUG("Getting baud rate");
1565 if (!(data = malloc(get_termios_size())))
1566 RETURN_ERROR(SP_ERR_MEM, "termios malloc failed");
1568 if (ioctl(fd, get_termios_get_ioctl(), data) < 0) {
1569 free(data);
1570 RETURN_FAIL("Getting termios failed");
1573 *baudrate = get_termios_speed(data);
1575 free(data);
1577 RETURN_OK();
1580 static enum sp_return set_baudrate(int fd, int baudrate)
1582 void *data;
1584 TRACE("%d, %d", fd, baudrate);
1586 DEBUG("Getting baud rate");
1588 if (!(data = malloc(get_termios_size())))
1589 RETURN_ERROR(SP_ERR_MEM, "termios malloc failed");
1591 if (ioctl(fd, get_termios_get_ioctl(), data) < 0) {
1592 free(data);
1593 RETURN_FAIL("Getting termios failed");
1596 DEBUG("Setting baud rate");
1598 set_termios_speed(data, baudrate);
1600 if (ioctl(fd, get_termios_set_ioctl(), data) < 0) {
1601 free(data);
1602 RETURN_FAIL("Setting termios failed");
1605 free(data);
1607 RETURN_OK();
1609 #endif /* USE_TERMIOS_SPEED */
1611 #ifdef USE_TERMIOX
1612 static enum sp_return get_flow(int fd, struct port_data *data)
1614 void *termx;
1616 TRACE("%d, %p", fd, data);
1618 DEBUG("Getting advanced flow control");
1620 if (!(termx = malloc(get_termiox_size())))
1621 RETURN_ERROR(SP_ERR_MEM, "termiox malloc failed");
1623 if (ioctl(fd, TCGETX, termx) < 0) {
1624 free(termx);
1625 RETURN_FAIL("Getting termiox failed");
1628 get_termiox_flow(termx, &data->rts_flow, &data->cts_flow,
1629 &data->dtr_flow, &data->dsr_flow);
1631 free(termx);
1633 RETURN_OK();
1636 static enum sp_return set_flow(int fd, struct port_data *data)
1638 void *termx;
1640 TRACE("%d, %p", fd, data);
1642 DEBUG("Getting advanced flow control");
1644 if (!(termx = malloc(get_termiox_size())))
1645 RETURN_ERROR(SP_ERR_MEM, "termiox malloc failed");
1647 if (ioctl(fd, TCGETX, termx) < 0) {
1648 free(termx);
1649 RETURN_FAIL("Getting termiox failed");
1652 DEBUG("Setting advanced flow control");
1654 set_termiox_flow(termx, data->rts_flow, data->cts_flow,
1655 data->dtr_flow, data->dsr_flow);
1657 if (ioctl(fd, TCSETX, termx) < 0) {
1658 free(termx);
1659 RETURN_FAIL("Setting termiox failed");
1662 free(termx);
1664 RETURN_OK();
1666 #endif /* USE_TERMIOX */
1668 static enum sp_return get_config(struct sp_port *port, struct port_data *data,
1669 struct sp_port_config *config)
1671 unsigned int i;
1673 TRACE("%p, %p, %p", port, data, config);
1675 DEBUG_FMT("Getting configuration for port %s", port->name);
1677 #ifdef _WIN32
1678 if (!GetCommState(port->hdl, &data->dcb))
1679 RETURN_FAIL("GetCommState() failed");
1681 for (i = 0; i < NUM_STD_BAUDRATES; i++) {
1682 if (data->dcb.BaudRate == std_baudrates[i].index) {
1683 config->baudrate = std_baudrates[i].value;
1684 break;
1688 if (i == NUM_STD_BAUDRATES)
1689 /* BaudRate field can be either an index or a custom baud rate. */
1690 config->baudrate = data->dcb.BaudRate;
1692 config->bits = data->dcb.ByteSize;
1694 switch (data->dcb.Parity) {
1695 case NOPARITY:
1696 config->parity = SP_PARITY_NONE;
1697 break;
1698 case ODDPARITY:
1699 config->parity = SP_PARITY_ODD;
1700 break;
1701 case EVENPARITY:
1702 config->parity = SP_PARITY_EVEN;
1703 break;
1704 case MARKPARITY:
1705 config->parity = SP_PARITY_MARK;
1706 break;
1707 case SPACEPARITY:
1708 config->parity = SP_PARITY_SPACE;
1709 break;
1710 default:
1711 config->parity = -1;
1714 switch (data->dcb.StopBits) {
1715 case ONESTOPBIT:
1716 config->stopbits = 1;
1717 break;
1718 case TWOSTOPBITS:
1719 config->stopbits = 2;
1720 break;
1721 default:
1722 config->stopbits = -1;
1725 switch (data->dcb.fRtsControl) {
1726 case RTS_CONTROL_DISABLE:
1727 config->rts = SP_RTS_OFF;
1728 break;
1729 case RTS_CONTROL_ENABLE:
1730 config->rts = SP_RTS_ON;
1731 break;
1732 case RTS_CONTROL_HANDSHAKE:
1733 config->rts = SP_RTS_FLOW_CONTROL;
1734 break;
1735 default:
1736 config->rts = -1;
1739 config->cts = data->dcb.fOutxCtsFlow ? SP_CTS_FLOW_CONTROL : SP_CTS_IGNORE;
1741 switch (data->dcb.fDtrControl) {
1742 case DTR_CONTROL_DISABLE:
1743 config->dtr = SP_DTR_OFF;
1744 break;
1745 case DTR_CONTROL_ENABLE:
1746 config->dtr = SP_DTR_ON;
1747 break;
1748 case DTR_CONTROL_HANDSHAKE:
1749 config->dtr = SP_DTR_FLOW_CONTROL;
1750 break;
1751 default:
1752 config->dtr = -1;
1755 config->dsr = data->dcb.fOutxDsrFlow ? SP_DSR_FLOW_CONTROL : SP_DSR_IGNORE;
1757 if (data->dcb.fInX) {
1758 if (data->dcb.fOutX)
1759 config->xon_xoff = SP_XONXOFF_INOUT;
1760 else
1761 config->xon_xoff = SP_XONXOFF_IN;
1762 } else {
1763 if (data->dcb.fOutX)
1764 config->xon_xoff = SP_XONXOFF_OUT;
1765 else
1766 config->xon_xoff = SP_XONXOFF_DISABLED;
1769 #else // !_WIN32
1771 if (tcgetattr(port->fd, &data->term) < 0)
1772 RETURN_FAIL("tcgetattr() failed");
1774 if (ioctl(port->fd, TIOCMGET, &data->controlbits) < 0)
1775 RETURN_FAIL("TIOCMGET ioctl failed");
1777 #ifdef USE_TERMIOX
1778 int ret = get_flow(port->fd, data);
1780 if (ret == SP_ERR_FAIL && errno == EINVAL)
1781 data->termiox_supported = 0;
1782 else if (ret < 0)
1783 RETURN_CODEVAL(ret);
1784 else
1785 data->termiox_supported = 1;
1786 #else
1787 data->termiox_supported = 0;
1788 #endif
1790 for (i = 0; i < NUM_STD_BAUDRATES; i++) {
1791 if (cfgetispeed(&data->term) == std_baudrates[i].index) {
1792 config->baudrate = std_baudrates[i].value;
1793 break;
1797 if (i == NUM_STD_BAUDRATES) {
1798 #ifdef __APPLE__
1799 config->baudrate = (int)data->term.c_ispeed;
1800 #elif defined(USE_TERMIOS_SPEED)
1801 TRY(get_baudrate(port->fd, &config->baudrate));
1802 #else
1803 config->baudrate = -1;
1804 #endif
1807 switch (data->term.c_cflag & CSIZE) {
1808 case CS8:
1809 config->bits = 8;
1810 break;
1811 case CS7:
1812 config->bits = 7;
1813 break;
1814 case CS6:
1815 config->bits = 6;
1816 break;
1817 case CS5:
1818 config->bits = 5;
1819 break;
1820 default:
1821 config->bits = -1;
1824 if (!(data->term.c_cflag & PARENB) && (data->term.c_iflag & IGNPAR))
1825 config->parity = SP_PARITY_NONE;
1826 else if (!(data->term.c_cflag & PARENB) || (data->term.c_iflag & IGNPAR))
1827 config->parity = -1;
1828 #ifdef CMSPAR
1829 else if (data->term.c_cflag & CMSPAR)
1830 config->parity = (data->term.c_cflag & PARODD) ? SP_PARITY_MARK : SP_PARITY_SPACE;
1831 #endif
1832 else
1833 config->parity = (data->term.c_cflag & PARODD) ? SP_PARITY_ODD : SP_PARITY_EVEN;
1835 config->stopbits = (data->term.c_cflag & CSTOPB) ? 2 : 1;
1837 if (data->term.c_cflag & CRTSCTS) {
1838 config->rts = SP_RTS_FLOW_CONTROL;
1839 config->cts = SP_CTS_FLOW_CONTROL;
1840 } else {
1841 if (data->termiox_supported && data->rts_flow)
1842 config->rts = SP_RTS_FLOW_CONTROL;
1843 else
1844 config->rts = (data->controlbits & TIOCM_RTS) ? SP_RTS_ON : SP_RTS_OFF;
1846 config->cts = (data->termiox_supported && data->cts_flow) ?
1847 SP_CTS_FLOW_CONTROL : SP_CTS_IGNORE;
1850 if (data->termiox_supported && data->dtr_flow)
1851 config->dtr = SP_DTR_FLOW_CONTROL;
1852 else
1853 config->dtr = (data->controlbits & TIOCM_DTR) ? SP_DTR_ON : SP_DTR_OFF;
1855 config->dsr = (data->termiox_supported && data->dsr_flow) ?
1856 SP_DSR_FLOW_CONTROL : SP_DSR_IGNORE;
1858 if (data->term.c_iflag & IXOFF) {
1859 if (data->term.c_iflag & IXON)
1860 config->xon_xoff = SP_XONXOFF_INOUT;
1861 else
1862 config->xon_xoff = SP_XONXOFF_IN;
1863 } else {
1864 if (data->term.c_iflag & IXON)
1865 config->xon_xoff = SP_XONXOFF_OUT;
1866 else
1867 config->xon_xoff = SP_XONXOFF_DISABLED;
1869 #endif
1871 RETURN_OK();
1874 static enum sp_return set_config(struct sp_port *port, struct port_data *data,
1875 const struct sp_port_config *config)
1877 unsigned int i;
1878 #ifdef __APPLE__
1879 BAUD_TYPE baud_nonstd;
1881 baud_nonstd = B0;
1882 #endif
1883 #ifdef USE_TERMIOS_SPEED
1884 int baud_nonstd = 0;
1885 #endif
1887 TRACE("%p, %p, %p", port, data, config);
1889 DEBUG_FMT("Setting configuration for port %s", port->name);
1891 #ifdef _WIN32
1892 BYTE* new_buf;
1894 TRY(await_write_completion(port));
1896 if (config->baudrate >= 0) {
1897 for (i = 0; i < NUM_STD_BAUDRATES; i++) {
1898 if (config->baudrate == std_baudrates[i].value) {
1899 data->dcb.BaudRate = std_baudrates[i].index;
1900 break;
1904 if (i == NUM_STD_BAUDRATES)
1905 data->dcb.BaudRate = config->baudrate;
1907 /* Allocate write buffer for 50ms of data at baud rate. */
1908 port->write_buf_size = max(config->baudrate / (8 * 20), 1);
1909 new_buf = realloc(port->write_buf, port->write_buf_size);
1910 if (!new_buf)
1911 RETURN_ERROR(SP_ERR_MEM, "Allocating write buffer failed");
1912 port->write_buf = new_buf;
1915 if (config->bits >= 0)
1916 data->dcb.ByteSize = config->bits;
1918 if (config->parity >= 0) {
1919 switch (config->parity) {
1920 case SP_PARITY_NONE:
1921 data->dcb.Parity = NOPARITY;
1922 break;
1923 case SP_PARITY_ODD:
1924 data->dcb.Parity = ODDPARITY;
1925 break;
1926 case SP_PARITY_EVEN:
1927 data->dcb.Parity = EVENPARITY;
1928 break;
1929 case SP_PARITY_MARK:
1930 data->dcb.Parity = MARKPARITY;
1931 break;
1932 case SP_PARITY_SPACE:
1933 data->dcb.Parity = SPACEPARITY;
1934 break;
1935 default:
1936 RETURN_ERROR(SP_ERR_ARG, "Invalid parity setting");
1940 if (config->stopbits >= 0) {
1941 switch (config->stopbits) {
1942 /* Note: There's also ONE5STOPBITS == 1.5 (unneeded so far). */
1943 case 1:
1944 data->dcb.StopBits = ONESTOPBIT;
1945 break;
1946 case 2:
1947 data->dcb.StopBits = TWOSTOPBITS;
1948 break;
1949 default:
1950 RETURN_ERROR(SP_ERR_ARG, "Invalid stop bit setting");
1954 if (config->rts >= 0) {
1955 switch (config->rts) {
1956 case SP_RTS_OFF:
1957 data->dcb.fRtsControl = RTS_CONTROL_DISABLE;
1958 break;
1959 case SP_RTS_ON:
1960 data->dcb.fRtsControl = RTS_CONTROL_ENABLE;
1961 break;
1962 case SP_RTS_FLOW_CONTROL:
1963 data->dcb.fRtsControl = RTS_CONTROL_HANDSHAKE;
1964 break;
1965 default:
1966 RETURN_ERROR(SP_ERR_ARG, "Invalid RTS setting");
1970 if (config->cts >= 0) {
1971 switch (config->cts) {
1972 case SP_CTS_IGNORE:
1973 data->dcb.fOutxCtsFlow = FALSE;
1974 break;
1975 case SP_CTS_FLOW_CONTROL:
1976 data->dcb.fOutxCtsFlow = TRUE;
1977 break;
1978 default:
1979 RETURN_ERROR(SP_ERR_ARG, "Invalid CTS setting");
1983 if (config->dtr >= 0) {
1984 switch (config->dtr) {
1985 case SP_DTR_OFF:
1986 data->dcb.fDtrControl = DTR_CONTROL_DISABLE;
1987 break;
1988 case SP_DTR_ON:
1989 data->dcb.fDtrControl = DTR_CONTROL_ENABLE;
1990 break;
1991 case SP_DTR_FLOW_CONTROL:
1992 data->dcb.fDtrControl = DTR_CONTROL_HANDSHAKE;
1993 break;
1994 default:
1995 RETURN_ERROR(SP_ERR_ARG, "Invalid DTR setting");
1999 if (config->dsr >= 0) {
2000 switch (config->dsr) {
2001 case SP_DSR_IGNORE:
2002 data->dcb.fOutxDsrFlow = FALSE;
2003 break;
2004 case SP_DSR_FLOW_CONTROL:
2005 data->dcb.fOutxDsrFlow = TRUE;
2006 break;
2007 default:
2008 RETURN_ERROR(SP_ERR_ARG, "Invalid DSR setting");
2012 if (config->xon_xoff >= 0) {
2013 switch (config->xon_xoff) {
2014 case SP_XONXOFF_DISABLED:
2015 data->dcb.fInX = FALSE;
2016 data->dcb.fOutX = FALSE;
2017 break;
2018 case SP_XONXOFF_IN:
2019 data->dcb.fInX = TRUE;
2020 data->dcb.fOutX = FALSE;
2021 break;
2022 case SP_XONXOFF_OUT:
2023 data->dcb.fInX = FALSE;
2024 data->dcb.fOutX = TRUE;
2025 break;
2026 case SP_XONXOFF_INOUT:
2027 data->dcb.fInX = TRUE;
2028 data->dcb.fOutX = TRUE;
2029 break;
2030 default:
2031 RETURN_ERROR(SP_ERR_ARG, "Invalid XON/XOFF setting");
2035 if (!SetCommState(port->hdl, &data->dcb))
2036 RETURN_FAIL("SetCommState() failed");
2038 #else /* !_WIN32 */
2040 int controlbits;
2042 if (config->baudrate >= 0) {
2043 for (i = 0; i < NUM_STD_BAUDRATES; i++) {
2044 if (config->baudrate == std_baudrates[i].value) {
2045 if (cfsetospeed(&data->term, std_baudrates[i].index) < 0)
2046 RETURN_FAIL("cfsetospeed() failed");
2048 if (cfsetispeed(&data->term, std_baudrates[i].index) < 0)
2049 RETURN_FAIL("cfsetispeed() failed");
2050 break;
2054 /* Non-standard baud rate */
2055 if (i == NUM_STD_BAUDRATES) {
2056 #ifdef __APPLE__
2057 /* Set "dummy" baud rate. */
2058 if (cfsetspeed(&data->term, B9600) < 0)
2059 RETURN_FAIL("cfsetspeed() failed");
2060 baud_nonstd = config->baudrate;
2061 #elif defined(USE_TERMIOS_SPEED)
2062 baud_nonstd = 1;
2063 #else
2064 RETURN_ERROR(SP_ERR_SUPP, "Non-standard baudrate not supported");
2065 #endif
2069 if (config->bits >= 0) {
2070 data->term.c_cflag &= ~CSIZE;
2071 switch (config->bits) {
2072 case 8:
2073 data->term.c_cflag |= CS8;
2074 break;
2075 case 7:
2076 data->term.c_cflag |= CS7;
2077 break;
2078 case 6:
2079 data->term.c_cflag |= CS6;
2080 break;
2081 case 5:
2082 data->term.c_cflag |= CS5;
2083 break;
2084 default:
2085 RETURN_ERROR(SP_ERR_ARG, "Invalid data bits setting");
2089 if (config->parity >= 0) {
2090 data->term.c_iflag &= ~IGNPAR;
2091 data->term.c_cflag &= ~(PARENB | PARODD);
2092 #ifdef CMSPAR
2093 data->term.c_cflag &= ~CMSPAR;
2094 #endif
2095 switch (config->parity) {
2096 case SP_PARITY_NONE:
2097 data->term.c_iflag |= IGNPAR;
2098 break;
2099 case SP_PARITY_EVEN:
2100 data->term.c_cflag |= PARENB;
2101 break;
2102 case SP_PARITY_ODD:
2103 data->term.c_cflag |= PARENB | PARODD;
2104 break;
2105 #ifdef CMSPAR
2106 case SP_PARITY_MARK:
2107 data->term.c_cflag |= PARENB | PARODD;
2108 data->term.c_cflag |= CMSPAR;
2109 break;
2110 case SP_PARITY_SPACE:
2111 data->term.c_cflag |= PARENB;
2112 data->term.c_cflag |= CMSPAR;
2113 break;
2114 #else
2115 case SP_PARITY_MARK:
2116 case SP_PARITY_SPACE:
2117 RETURN_ERROR(SP_ERR_SUPP, "Mark/space parity not supported");
2118 #endif
2119 default:
2120 RETURN_ERROR(SP_ERR_ARG, "Invalid parity setting");
2124 if (config->stopbits >= 0) {
2125 data->term.c_cflag &= ~CSTOPB;
2126 switch (config->stopbits) {
2127 case 1:
2128 data->term.c_cflag &= ~CSTOPB;
2129 break;
2130 case 2:
2131 data->term.c_cflag |= CSTOPB;
2132 break;
2133 default:
2134 RETURN_ERROR(SP_ERR_ARG, "Invalid stop bits setting");
2138 if (config->rts >= 0 || config->cts >= 0) {
2139 if (data->termiox_supported) {
2140 data->rts_flow = data->cts_flow = 0;
2141 switch (config->rts) {
2142 case SP_RTS_OFF:
2143 case SP_RTS_ON:
2144 controlbits = TIOCM_RTS;
2145 if (ioctl(port->fd, config->rts == SP_RTS_ON ? TIOCMBIS : TIOCMBIC, &controlbits) < 0)
2146 RETURN_FAIL("Setting RTS signal level failed");
2147 break;
2148 case SP_RTS_FLOW_CONTROL:
2149 data->rts_flow = 1;
2150 break;
2151 default:
2152 break;
2154 if (config->cts == SP_CTS_FLOW_CONTROL)
2155 data->cts_flow = 1;
2157 if (data->rts_flow && data->cts_flow)
2158 data->term.c_iflag |= CRTSCTS;
2159 else
2160 data->term.c_iflag &= ~CRTSCTS;
2161 } else {
2162 /* Asymmetric use of RTS/CTS not supported. */
2163 if (data->term.c_iflag & CRTSCTS) {
2164 /* Flow control can only be disabled for both RTS & CTS together. */
2165 if (config->rts >= 0 && config->rts != SP_RTS_FLOW_CONTROL) {
2166 if (config->cts != SP_CTS_IGNORE)
2167 RETURN_ERROR(SP_ERR_SUPP, "RTS & CTS flow control must be disabled together");
2169 if (config->cts >= 0 && config->cts != SP_CTS_FLOW_CONTROL) {
2170 if (config->rts <= 0 || config->rts == SP_RTS_FLOW_CONTROL)
2171 RETURN_ERROR(SP_ERR_SUPP, "RTS & CTS flow control must be disabled together");
2173 } else {
2174 /* Flow control can only be enabled for both RTS & CTS together. */
2175 if (((config->rts == SP_RTS_FLOW_CONTROL) && (config->cts != SP_CTS_FLOW_CONTROL)) ||
2176 ((config->cts == SP_CTS_FLOW_CONTROL) && (config->rts != SP_RTS_FLOW_CONTROL)))
2177 RETURN_ERROR(SP_ERR_SUPP, "RTS & CTS flow control must be enabled together");
2180 if (config->rts >= 0) {
2181 if (config->rts == SP_RTS_FLOW_CONTROL) {
2182 data->term.c_iflag |= CRTSCTS;
2183 } else {
2184 controlbits = TIOCM_RTS;
2185 if (ioctl(port->fd, config->rts == SP_RTS_ON ? TIOCMBIS : TIOCMBIC,
2186 &controlbits) < 0)
2187 RETURN_FAIL("Setting RTS signal level failed");
2193 if (config->dtr >= 0 || config->dsr >= 0) {
2194 if (data->termiox_supported) {
2195 data->dtr_flow = data->dsr_flow = 0;
2196 switch (config->dtr) {
2197 case SP_DTR_OFF:
2198 case SP_DTR_ON:
2199 controlbits = TIOCM_DTR;
2200 if (ioctl(port->fd, config->dtr == SP_DTR_ON ? TIOCMBIS : TIOCMBIC, &controlbits) < 0)
2201 RETURN_FAIL("Setting DTR signal level failed");
2202 break;
2203 case SP_DTR_FLOW_CONTROL:
2204 data->dtr_flow = 1;
2205 break;
2206 default:
2207 break;
2209 if (config->dsr == SP_DSR_FLOW_CONTROL)
2210 data->dsr_flow = 1;
2211 } else {
2212 /* DTR/DSR flow control not supported. */
2213 if (config->dtr == SP_DTR_FLOW_CONTROL || config->dsr == SP_DSR_FLOW_CONTROL)
2214 RETURN_ERROR(SP_ERR_SUPP, "DTR/DSR flow control not supported");
2216 if (config->dtr >= 0) {
2217 controlbits = TIOCM_DTR;
2218 if (ioctl(port->fd, config->dtr == SP_DTR_ON ? TIOCMBIS : TIOCMBIC,
2219 &controlbits) < 0)
2220 RETURN_FAIL("Setting DTR signal level failed");
2225 if (config->xon_xoff >= 0) {
2226 data->term.c_iflag &= ~(IXON | IXOFF | IXANY);
2227 switch (config->xon_xoff) {
2228 case SP_XONXOFF_DISABLED:
2229 break;
2230 case SP_XONXOFF_IN:
2231 data->term.c_iflag |= IXOFF;
2232 break;
2233 case SP_XONXOFF_OUT:
2234 data->term.c_iflag |= IXON | IXANY;
2235 break;
2236 case SP_XONXOFF_INOUT:
2237 data->term.c_iflag |= IXON | IXOFF | IXANY;
2238 break;
2239 default:
2240 RETURN_ERROR(SP_ERR_ARG, "Invalid XON/XOFF setting");
2244 if (tcsetattr(port->fd, TCSANOW, &data->term) < 0)
2245 RETURN_FAIL("tcsetattr() failed");
2247 #ifdef __APPLE__
2248 if (baud_nonstd != B0) {
2249 if (ioctl(port->fd, IOSSIOSPEED, &baud_nonstd) == -1)
2250 RETURN_FAIL("IOSSIOSPEED ioctl failed");
2252 * Set baud rates in data->term to correct, but incompatible
2253 * with tcsetattr() value, same as delivered by tcgetattr().
2255 if (cfsetspeed(&data->term, baud_nonstd) < 0)
2256 RETURN_FAIL("cfsetspeed() failed");
2258 #elif defined(__linux__)
2259 #ifdef USE_TERMIOS_SPEED
2260 if (baud_nonstd)
2261 TRY(set_baudrate(port->fd, config->baudrate));
2262 #endif
2263 #ifdef USE_TERMIOX
2264 if (data->termiox_supported)
2265 TRY(set_flow(port->fd, data));
2266 #endif
2267 #endif
2269 #endif /* !_WIN32 */
2271 RETURN_OK();
2274 SP_API enum sp_return sp_new_config(struct sp_port_config **config_ptr)
2276 struct sp_port_config *config;
2278 TRACE("%p", config_ptr);
2280 if (!config_ptr)
2281 RETURN_ERROR(SP_ERR_ARG, "Null result pointer");
2283 *config_ptr = NULL;
2285 if (!(config = malloc(sizeof(struct sp_port_config))))
2286 RETURN_ERROR(SP_ERR_MEM, "Config malloc failed");
2288 config->baudrate = -1;
2289 config->bits = -1;
2290 config->parity = -1;
2291 config->stopbits = -1;
2292 config->rts = -1;
2293 config->cts = -1;
2294 config->dtr = -1;
2295 config->dsr = -1;
2296 config->xon_xoff = -1;
2298 *config_ptr = config;
2300 RETURN_OK();
2303 SP_API void sp_free_config(struct sp_port_config *config)
2305 TRACE("%p", config);
2307 if (!config)
2308 DEBUG("Null config");
2309 else
2310 free(config);
2312 RETURN();
2315 SP_API enum sp_return sp_get_config(struct sp_port *port,
2316 struct sp_port_config *config)
2318 struct port_data data;
2320 TRACE("%p, %p", port, config);
2322 CHECK_OPEN_PORT();
2324 if (!config)
2325 RETURN_ERROR(SP_ERR_ARG, "Null config");
2327 TRY(get_config(port, &data, config));
2329 RETURN_OK();
2332 SP_API enum sp_return sp_set_config(struct sp_port *port,
2333 const struct sp_port_config *config)
2335 struct port_data data;
2336 struct sp_port_config prev_config;
2338 TRACE("%p, %p", port, config);
2340 CHECK_OPEN_PORT();
2342 if (!config)
2343 RETURN_ERROR(SP_ERR_ARG, "Null config");
2345 TRY(get_config(port, &data, &prev_config));
2346 TRY(set_config(port, &data, config));
2348 RETURN_OK();
2351 #define CREATE_ACCESSORS(x, type) \
2352 SP_API enum sp_return sp_set_##x(struct sp_port *port, type x) { \
2353 struct port_data data; \
2354 struct sp_port_config config; \
2355 TRACE("%p, %d", port, x); \
2356 CHECK_OPEN_PORT(); \
2357 TRY(get_config(port, &data, &config)); \
2358 config.x = x; \
2359 TRY(set_config(port, &data, &config)); \
2360 RETURN_OK(); \
2362 SP_API enum sp_return sp_get_config_##x(const struct sp_port_config *config, \
2363 type *x) { \
2364 TRACE("%p, %p", config, x); \
2365 if (!x) \
2366 RETURN_ERROR(SP_ERR_ARG, "Null result pointer"); \
2367 if (!config) \
2368 RETURN_ERROR(SP_ERR_ARG, "Null config"); \
2369 *x = config->x; \
2370 RETURN_OK(); \
2372 SP_API enum sp_return sp_set_config_##x(struct sp_port_config *config, \
2373 type x) { \
2374 TRACE("%p, %d", config, x); \
2375 if (!config) \
2376 RETURN_ERROR(SP_ERR_ARG, "Null config"); \
2377 config->x = x; \
2378 RETURN_OK(); \
2381 CREATE_ACCESSORS(baudrate, int)
2382 CREATE_ACCESSORS(bits, int)
2383 CREATE_ACCESSORS(parity, enum sp_parity)
2384 CREATE_ACCESSORS(stopbits, int)
2385 CREATE_ACCESSORS(rts, enum sp_rts)
2386 CREATE_ACCESSORS(cts, enum sp_cts)
2387 CREATE_ACCESSORS(dtr, enum sp_dtr)
2388 CREATE_ACCESSORS(dsr, enum sp_dsr)
2389 CREATE_ACCESSORS(xon_xoff, enum sp_xonxoff)
2391 SP_API enum sp_return sp_set_config_flowcontrol(struct sp_port_config *config,
2392 enum sp_flowcontrol flowcontrol)
2394 if (!config)
2395 RETURN_ERROR(SP_ERR_ARG, "Null configuration");
2397 if (flowcontrol > SP_FLOWCONTROL_DTRDSR)
2398 RETURN_ERROR(SP_ERR_ARG, "Invalid flow control setting");
2400 if (flowcontrol == SP_FLOWCONTROL_XONXOFF)
2401 config->xon_xoff = SP_XONXOFF_INOUT;
2402 else
2403 config->xon_xoff = SP_XONXOFF_DISABLED;
2405 if (flowcontrol == SP_FLOWCONTROL_RTSCTS) {
2406 config->rts = SP_RTS_FLOW_CONTROL;
2407 config->cts = SP_CTS_FLOW_CONTROL;
2408 } else {
2409 if (config->rts == SP_RTS_FLOW_CONTROL)
2410 config->rts = SP_RTS_ON;
2411 config->cts = SP_CTS_IGNORE;
2414 if (flowcontrol == SP_FLOWCONTROL_DTRDSR) {
2415 config->dtr = SP_DTR_FLOW_CONTROL;
2416 config->dsr = SP_DSR_FLOW_CONTROL;
2417 } else {
2418 if (config->dtr == SP_DTR_FLOW_CONTROL)
2419 config->dtr = SP_DTR_ON;
2420 config->dsr = SP_DSR_IGNORE;
2423 RETURN_OK();
2426 SP_API enum sp_return sp_set_flowcontrol(struct sp_port *port,
2427 enum sp_flowcontrol flowcontrol)
2429 struct port_data data;
2430 struct sp_port_config config;
2432 TRACE("%p, %d", port, flowcontrol);
2434 CHECK_OPEN_PORT();
2436 TRY(get_config(port, &data, &config));
2438 TRY(sp_set_config_flowcontrol(&config, flowcontrol));
2440 TRY(set_config(port, &data, &config));
2442 RETURN_OK();
2445 SP_API enum sp_return sp_get_signals(struct sp_port *port,
2446 enum sp_signal *signals)
2448 TRACE("%p, %p", port, signals);
2450 CHECK_OPEN_PORT();
2452 if (!signals)
2453 RETURN_ERROR(SP_ERR_ARG, "Null result pointer");
2455 DEBUG_FMT("Getting control signals for port %s", port->name);
2457 *signals = 0;
2458 #ifdef _WIN32
2459 DWORD bits;
2460 if (GetCommModemStatus(port->hdl, &bits) == 0)
2461 RETURN_FAIL("GetCommModemStatus() failed");
2462 if (bits & MS_CTS_ON)
2463 *signals |= SP_SIG_CTS;
2464 if (bits & MS_DSR_ON)
2465 *signals |= SP_SIG_DSR;
2466 if (bits & MS_RLSD_ON)
2467 *signals |= SP_SIG_DCD;
2468 if (bits & MS_RING_ON)
2469 *signals |= SP_SIG_RI;
2470 #else
2471 int bits;
2472 if (ioctl(port->fd, TIOCMGET, &bits) < 0)
2473 RETURN_FAIL("TIOCMGET ioctl failed");
2474 if (bits & TIOCM_CTS)
2475 *signals |= SP_SIG_CTS;
2476 if (bits & TIOCM_DSR)
2477 *signals |= SP_SIG_DSR;
2478 if (bits & TIOCM_CAR)
2479 *signals |= SP_SIG_DCD;
2480 if (bits & TIOCM_RNG)
2481 *signals |= SP_SIG_RI;
2482 #endif
2483 RETURN_OK();
2486 SP_API enum sp_return sp_start_break(struct sp_port *port)
2488 TRACE("%p", port);
2490 CHECK_OPEN_PORT();
2491 #ifdef _WIN32
2492 if (SetCommBreak(port->hdl) == 0)
2493 RETURN_FAIL("SetCommBreak() failed");
2494 #else
2495 if (ioctl(port->fd, TIOCSBRK, 1) < 0)
2496 RETURN_FAIL("TIOCSBRK ioctl failed");
2497 #endif
2499 RETURN_OK();
2502 SP_API enum sp_return sp_end_break(struct sp_port *port)
2504 TRACE("%p", port);
2506 CHECK_OPEN_PORT();
2507 #ifdef _WIN32
2508 if (ClearCommBreak(port->hdl) == 0)
2509 RETURN_FAIL("ClearCommBreak() failed");
2510 #else
2511 if (ioctl(port->fd, TIOCCBRK, 1) < 0)
2512 RETURN_FAIL("TIOCCBRK ioctl failed");
2513 #endif
2515 RETURN_OK();
2518 SP_API int sp_last_error_code(void)
2520 TRACE_VOID();
2521 #ifdef _WIN32
2522 RETURN_INT(GetLastError());
2523 #else
2524 RETURN_INT(errno);
2525 #endif
2528 SP_API char *sp_last_error_message(void)
2530 TRACE_VOID();
2532 #ifdef _WIN32
2533 char *message;
2534 DWORD error = GetLastError();
2536 DWORD length = FormatMessageA(
2537 FORMAT_MESSAGE_ALLOCATE_BUFFER |
2538 FORMAT_MESSAGE_FROM_SYSTEM |
2539 FORMAT_MESSAGE_IGNORE_INSERTS,
2540 NULL,
2541 error,
2542 MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
2543 (LPSTR) &message,
2544 0, NULL );
2546 if (length >= 2 && message[length - 2] == '\r')
2547 message[length - 2] = '\0';
2549 RETURN_STRING(message);
2550 #else
2551 RETURN_STRING(strerror(errno));
2552 #endif
2555 SP_API void sp_free_error_message(char *message)
2557 TRACE("%s", message);
2559 #ifdef _WIN32
2560 LocalFree(message);
2561 #else
2562 (void)message;
2563 #endif
2565 RETURN();
2568 SP_API void sp_set_debug_handler(void (*handler)(const char *format, ...))
2570 TRACE("%p", handler);
2572 sp_debug_handler = handler;
2574 RETURN();
2577 SP_API void sp_default_debug_handler(const char *format, ...)
2579 va_list args;
2580 va_start(args, format);
2581 if (getenv("LIBSERIALPORT_DEBUG")) {
2582 fputs("sp: ", stderr);
2583 vfprintf(stderr, format, args);
2585 va_end(args);
2588 SP_API int sp_get_major_package_version(void)
2590 return SP_PACKAGE_VERSION_MAJOR;
2593 SP_API int sp_get_minor_package_version(void)
2595 return SP_PACKAGE_VERSION_MINOR;
2598 SP_API int sp_get_micro_package_version(void)
2600 return SP_PACKAGE_VERSION_MICRO;
2603 SP_API const char *sp_get_package_version_string(void)
2605 return SP_PACKAGE_VERSION_STRING;
2608 SP_API int sp_get_current_lib_version(void)
2610 return SP_LIB_VERSION_CURRENT;
2613 SP_API int sp_get_revision_lib_version(void)
2615 return SP_LIB_VERSION_REVISION;
2618 SP_API int sp_get_age_lib_version(void)
2620 return SP_LIB_VERSION_AGE;
2623 SP_API const char *sp_get_lib_version_string(void)
2625 return SP_LIB_VERSION_STRING;
2628 /** @} */