]> sigrok.org Git - libserialport.git/blob - serialport.c
Move all gettimeofday() calls into a wrapper function.
[libserialport.git] / serialport.c
1 /*
2  * This file is part of the libserialport project.
3  *
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>
9  *
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.
14  *
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.
19  *
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/>.
22  */
23
24 #include <config.h>
25 #include "libserialport.h"
26 #include "libserialport_internal.h"
27
28 static const struct std_baudrate std_baudrates[] = {
29 #ifdef _WIN32
30         /*
31          * The baudrates 50/75/134/150/200/1800/230400/460800 do not seem to
32          * have documented CBR_* macros.
33          */
34         BAUD(110), BAUD(300), BAUD(600), BAUD(1200), BAUD(2400), BAUD(4800),
35         BAUD(9600), BAUD(14400), BAUD(19200), BAUD(38400), BAUD(57600),
36         BAUD(115200), BAUD(128000), BAUD(256000),
37 #else
38         BAUD(50), BAUD(75), BAUD(110), BAUD(134), BAUD(150), BAUD(200),
39         BAUD(300), BAUD(600), BAUD(1200), BAUD(1800), BAUD(2400), BAUD(4800),
40         BAUD(9600), BAUD(19200), BAUD(38400), BAUD(57600), BAUD(115200),
41         BAUD(230400),
42 #if !defined(__APPLE__) && !defined(__OpenBSD__)
43         BAUD(460800),
44 #endif
45 #endif
46 };
47
48 #define NUM_STD_BAUDRATES ARRAY_SIZE(std_baudrates)
49
50 void (*sp_debug_handler)(const char *format, ...) = sp_default_debug_handler;
51
52 static void get_time(struct timeval *time);
53
54 static enum sp_return get_config(struct sp_port *port, struct port_data *data,
55         struct sp_port_config *config);
56
57 static enum sp_return set_config(struct sp_port *port, struct port_data *data,
58         const struct sp_port_config *config);
59
60 static void get_time(struct timeval *time)
61 {
62         gettimeofday(time, NULL);
63 }
64
65 SP_API enum sp_return sp_get_port_by_name(const char *portname, struct sp_port **port_ptr)
66 {
67         struct sp_port *port;
68 #ifndef NO_PORT_METADATA
69         enum sp_return ret;
70 #endif
71         int len;
72
73         TRACE("%s, %p", portname, port_ptr);
74
75         if (!port_ptr)
76                 RETURN_ERROR(SP_ERR_ARG, "Null result pointer");
77
78         *port_ptr = NULL;
79
80         if (!portname)
81                 RETURN_ERROR(SP_ERR_ARG, "Null port name");
82
83         DEBUG_FMT("Building structure for port %s", portname);
84
85 #if !defined(_WIN32) && defined(HAVE_REALPATH)
86         /*
87          * get_port_details() below tries to be too smart and figure out
88          * some transport properties from the port name which breaks with
89          * symlinks. Therefore we canonicalize the portname first.
90          */
91         char pathbuf[PATH_MAX + 1];
92         char *res = realpath(portname, pathbuf);
93         if (!res)
94                 RETURN_ERROR(SP_ERR_ARG, "Could not retrieve realpath behind port name");
95
96         portname = pathbuf;
97 #endif
98
99         if (!(port = malloc(sizeof(struct sp_port))))
100                 RETURN_ERROR(SP_ERR_MEM, "Port structure malloc failed");
101
102         len = strlen(portname) + 1;
103
104         if (!(port->name = malloc(len))) {
105                 free(port);
106                 RETURN_ERROR(SP_ERR_MEM, "Port name malloc failed");
107         }
108
109         memcpy(port->name, portname, len);
110
111 #ifdef _WIN32
112         port->usb_path = NULL;
113         port->hdl = INVALID_HANDLE_VALUE;
114         port->write_buf = NULL;
115         port->write_buf_size = 0;
116 #else
117         port->fd = -1;
118 #endif
119
120         port->description = NULL;
121         port->transport = SP_TRANSPORT_NATIVE;
122         port->usb_bus = -1;
123         port->usb_address = -1;
124         port->usb_vid = -1;
125         port->usb_pid = -1;
126         port->usb_manufacturer = NULL;
127         port->usb_product = NULL;
128         port->usb_serial = NULL;
129         port->bluetooth_address = NULL;
130
131 #ifndef NO_PORT_METADATA
132         if ((ret = get_port_details(port)) != SP_OK) {
133                 sp_free_port(port);
134                 return ret;
135         }
136 #endif
137
138         *port_ptr = port;
139
140         RETURN_OK();
141 }
142
143 SP_API char *sp_get_port_name(const struct sp_port *port)
144 {
145         TRACE("%p", port);
146
147         if (!port)
148                 return NULL;
149
150         RETURN_STRING(port->name);
151 }
152
153 SP_API char *sp_get_port_description(const struct sp_port *port)
154 {
155         TRACE("%p", port);
156
157         if (!port || !port->description)
158                 return NULL;
159
160         RETURN_STRING(port->description);
161 }
162
163 SP_API enum sp_transport sp_get_port_transport(const struct sp_port *port)
164 {
165         TRACE("%p", port);
166
167         if (!port)
168                 RETURN_ERROR(SP_ERR_ARG, "Null port");
169
170         RETURN_INT(port->transport);
171 }
172
173 SP_API enum sp_return sp_get_port_usb_bus_address(const struct sp_port *port,
174                                                   int *usb_bus,int *usb_address)
175 {
176         TRACE("%p", port);
177
178         if (!port)
179                 RETURN_ERROR(SP_ERR_ARG, "Null port");
180         if (port->transport != SP_TRANSPORT_USB)
181                 RETURN_ERROR(SP_ERR_ARG, "Port does not use USB transport");
182         if (port->usb_bus < 0 || port->usb_address < 0)
183                 RETURN_ERROR(SP_ERR_SUPP, "Bus and address values are not available");
184
185         if (usb_bus)
186                 *usb_bus = port->usb_bus;
187         if (usb_address)
188                 *usb_address = port->usb_address;
189
190         RETURN_OK();
191 }
192
193 SP_API enum sp_return sp_get_port_usb_vid_pid(const struct sp_port *port,
194                                               int *usb_vid, int *usb_pid)
195 {
196         TRACE("%p", port);
197
198         if (!port)
199                 RETURN_ERROR(SP_ERR_ARG, "Null port");
200         if (port->transport != SP_TRANSPORT_USB)
201                 RETURN_ERROR(SP_ERR_ARG, "Port does not use USB transport");
202         if (port->usb_vid < 0 || port->usb_pid < 0)
203                 RETURN_ERROR(SP_ERR_SUPP, "VID:PID values are not available");
204
205         if (usb_vid)
206                 *usb_vid = port->usb_vid;
207         if (usb_pid)
208                 *usb_pid = port->usb_pid;
209
210         RETURN_OK();
211 }
212
213 SP_API char *sp_get_port_usb_manufacturer(const struct sp_port *port)
214 {
215         TRACE("%p", port);
216
217         if (!port || port->transport != SP_TRANSPORT_USB || !port->usb_manufacturer)
218                 return NULL;
219
220         RETURN_STRING(port->usb_manufacturer);
221 }
222
223 SP_API char *sp_get_port_usb_product(const struct sp_port *port)
224 {
225         TRACE("%p", port);
226
227         if (!port || port->transport != SP_TRANSPORT_USB || !port->usb_product)
228                 return NULL;
229
230         RETURN_STRING(port->usb_product);
231 }
232
233 SP_API char *sp_get_port_usb_serial(const struct sp_port *port)
234 {
235         TRACE("%p", port);
236
237         if (!port || port->transport != SP_TRANSPORT_USB || !port->usb_serial)
238                 return NULL;
239
240         RETURN_STRING(port->usb_serial);
241 }
242
243 SP_API char *sp_get_port_bluetooth_address(const struct sp_port *port)
244 {
245         TRACE("%p", port);
246
247         if (!port || port->transport != SP_TRANSPORT_BLUETOOTH
248             || !port->bluetooth_address)
249                 return NULL;
250
251         RETURN_STRING(port->bluetooth_address);
252 }
253
254 SP_API enum sp_return sp_get_port_handle(const struct sp_port *port,
255                                          void *result_ptr)
256 {
257         TRACE("%p, %p", port, result_ptr);
258
259         if (!port)
260                 RETURN_ERROR(SP_ERR_ARG, "Null port");
261         if (!result_ptr)
262                 RETURN_ERROR(SP_ERR_ARG, "Null result pointer");
263
264 #ifdef _WIN32
265         HANDLE *handle_ptr = result_ptr;
266         *handle_ptr = port->hdl;
267 #else
268         int *fd_ptr = result_ptr;
269         *fd_ptr = port->fd;
270 #endif
271
272         RETURN_OK();
273 }
274
275 SP_API enum sp_return sp_copy_port(const struct sp_port *port,
276                                    struct sp_port **copy_ptr)
277 {
278         TRACE("%p, %p", port, copy_ptr);
279
280         if (!copy_ptr)
281                 RETURN_ERROR(SP_ERR_ARG, "Null result pointer");
282
283         *copy_ptr = NULL;
284
285         if (!port)
286                 RETURN_ERROR(SP_ERR_ARG, "Null port");
287
288         if (!port->name)
289                 RETURN_ERROR(SP_ERR_ARG, "Null port name");
290
291         DEBUG("Copying port structure");
292
293         RETURN_INT(sp_get_port_by_name(port->name, copy_ptr));
294 }
295
296 SP_API void sp_free_port(struct sp_port *port)
297 {
298         TRACE("%p", port);
299
300         if (!port) {
301                 DEBUG("Null port");
302                 RETURN();
303         }
304
305         DEBUG("Freeing port structure");
306
307         if (port->name)
308                 free(port->name);
309         if (port->description)
310                 free(port->description);
311         if (port->usb_manufacturer)
312                 free(port->usb_manufacturer);
313         if (port->usb_product)
314                 free(port->usb_product);
315         if (port->usb_serial)
316                 free(port->usb_serial);
317         if (port->bluetooth_address)
318                 free(port->bluetooth_address);
319 #ifdef _WIN32
320         if (port->usb_path)
321                 free(port->usb_path);
322         if (port->write_buf)
323                 free(port->write_buf);
324 #endif
325
326         free(port);
327
328         RETURN();
329 }
330
331 SP_PRIV struct sp_port **list_append(struct sp_port **list,
332                                      const char *portname)
333 {
334         void *tmp;
335         unsigned int count;
336
337         for (count = 0; list[count]; count++)
338                 ;
339         if (!(tmp = realloc(list, sizeof(struct sp_port *) * (count + 2))))
340                 goto fail;
341         list = tmp;
342         if (sp_get_port_by_name(portname, &list[count]) != SP_OK)
343                 goto fail;
344         list[count + 1] = NULL;
345         return list;
346
347 fail:
348         sp_free_port_list(list);
349         return NULL;
350 }
351
352 SP_API enum sp_return sp_list_ports(struct sp_port ***list_ptr)
353 {
354 #ifndef NO_ENUMERATION
355         struct sp_port **list;
356         int ret;
357 #endif
358
359         TRACE("%p", list_ptr);
360
361         if (!list_ptr)
362                 RETURN_ERROR(SP_ERR_ARG, "Null result pointer");
363
364         *list_ptr = NULL;
365
366 #ifdef NO_ENUMERATION
367         RETURN_ERROR(SP_ERR_SUPP, "Enumeration not supported on this platform");
368 #else
369         DEBUG("Enumerating ports");
370
371         if (!(list = malloc(sizeof(struct sp_port *))))
372                 RETURN_ERROR(SP_ERR_MEM, "Port list malloc failed");
373
374         list[0] = NULL;
375
376         ret = list_ports(&list);
377
378         if (ret == SP_OK) {
379                 *list_ptr = list;
380         } else {
381                 sp_free_port_list(list);
382                 *list_ptr = NULL;
383         }
384
385         RETURN_CODEVAL(ret);
386 #endif
387 }
388
389 SP_API void sp_free_port_list(struct sp_port **list)
390 {
391         unsigned int i;
392
393         TRACE("%p", list);
394
395         if (!list) {
396                 DEBUG("Null list");
397                 RETURN();
398         }
399
400         DEBUG("Freeing port list");
401
402         for (i = 0; list[i]; i++)
403                 sp_free_port(list[i]);
404         free(list);
405
406         RETURN();
407 }
408
409 #define CHECK_PORT() do { \
410         if (!port) \
411                 RETURN_ERROR(SP_ERR_ARG, "Null port"); \
412         if (!port->name) \
413                 RETURN_ERROR(SP_ERR_ARG, "Null port name"); \
414 } while (0)
415 #ifdef _WIN32
416 #define CHECK_PORT_HANDLE() do { \
417         if (port->hdl == INVALID_HANDLE_VALUE) \
418                 RETURN_ERROR(SP_ERR_ARG, "Port not open"); \
419 } while (0)
420 #else
421 #define CHECK_PORT_HANDLE() do { \
422         if (port->fd < 0) \
423                 RETURN_ERROR(SP_ERR_ARG, "Port not open"); \
424 } while (0)
425 #endif
426 #define CHECK_OPEN_PORT() do { \
427         CHECK_PORT(); \
428         CHECK_PORT_HANDLE(); \
429 } while (0)
430
431 #ifdef WIN32
432 /** To be called after port receive buffer is emptied. */
433 static enum sp_return restart_wait(struct sp_port *port)
434 {
435         DWORD wait_result;
436
437         if (port->wait_running) {
438                 /* Check status of running wait operation. */
439                 if (GetOverlappedResult(port->hdl, &port->wait_ovl,
440                                 &wait_result, FALSE)) {
441                         DEBUG("Previous wait completed");
442                         port->wait_running = FALSE;
443                 } else if (GetLastError() == ERROR_IO_INCOMPLETE) {
444                         DEBUG("Previous wait still running");
445                         RETURN_OK();
446                 } else {
447                         RETURN_FAIL("GetOverlappedResult() failed");
448                 }
449         }
450
451         if (!port->wait_running) {
452                 /* Start new wait operation. */
453                 if (WaitCommEvent(port->hdl, &port->events,
454                                 &port->wait_ovl)) {
455                         DEBUG("New wait returned, events already pending");
456                 } else if (GetLastError() == ERROR_IO_PENDING) {
457                         DEBUG("New wait running in background");
458                         port->wait_running = TRUE;
459                 } else {
460                         RETURN_FAIL("WaitCommEvent() failed");
461                 }
462         }
463
464         RETURN_OK();
465 }
466 #endif
467
468 SP_API enum sp_return sp_open(struct sp_port *port, enum sp_mode flags)
469 {
470         struct port_data data;
471         struct sp_port_config config;
472         enum sp_return ret;
473
474         TRACE("%p, 0x%x", port, flags);
475
476         CHECK_PORT();
477
478         if (flags > SP_MODE_READ_WRITE)
479                 RETURN_ERROR(SP_ERR_ARG, "Invalid flags");
480
481         DEBUG_FMT("Opening port %s", port->name);
482
483 #ifdef _WIN32
484         DWORD desired_access = 0, flags_and_attributes = 0, errors;
485         char *escaped_port_name;
486         COMSTAT status;
487
488         /* Prefix port name with '\\.\' to work with ports above COM9. */
489         if (!(escaped_port_name = malloc(strlen(port->name) + 5)))
490                 RETURN_ERROR(SP_ERR_MEM, "Escaped port name malloc failed");
491         sprintf(escaped_port_name, "\\\\.\\%s", port->name);
492
493         /* Map 'flags' to the OS-specific settings. */
494         flags_and_attributes = FILE_ATTRIBUTE_NORMAL | FILE_FLAG_OVERLAPPED;
495         if (flags & SP_MODE_READ)
496                 desired_access |= GENERIC_READ;
497         if (flags & SP_MODE_WRITE)
498                 desired_access |= GENERIC_WRITE;
499
500         port->hdl = CreateFile(escaped_port_name, desired_access, 0, 0,
501                          OPEN_EXISTING, flags_and_attributes, 0);
502
503         free(escaped_port_name);
504
505         if (port->hdl == INVALID_HANDLE_VALUE)
506                 RETURN_FAIL("Port CreateFile() failed");
507
508         /* All timeouts initially disabled. */
509         port->timeouts.ReadIntervalTimeout = 0;
510         port->timeouts.ReadTotalTimeoutMultiplier = 0;
511         port->timeouts.ReadTotalTimeoutConstant = 0;
512         port->timeouts.WriteTotalTimeoutMultiplier = 0;
513         port->timeouts.WriteTotalTimeoutConstant = 0;
514
515         if (SetCommTimeouts(port->hdl, &port->timeouts) == 0) {
516                 sp_close(port);
517                 RETURN_FAIL("SetCommTimeouts() failed");
518         }
519
520         /* Prepare OVERLAPPED structures. */
521 #define INIT_OVERLAPPED(ovl) do { \
522         memset(&port->ovl, 0, sizeof(port->ovl)); \
523         port->ovl.hEvent = INVALID_HANDLE_VALUE; \
524         if ((port->ovl.hEvent = CreateEvent(NULL, TRUE, TRUE, NULL)) \
525                         == INVALID_HANDLE_VALUE) { \
526                 sp_close(port); \
527                 RETURN_FAIL(#ovl "CreateEvent() failed"); \
528         } \
529 } while (0)
530
531         INIT_OVERLAPPED(read_ovl);
532         INIT_OVERLAPPED(write_ovl);
533         INIT_OVERLAPPED(wait_ovl);
534
535         /* Set event mask for RX and error events. */
536         if (SetCommMask(port->hdl, EV_RXCHAR | EV_ERR) == 0) {
537                 sp_close(port);
538                 RETURN_FAIL("SetCommMask() failed");
539         }
540
541         port->writing = FALSE;
542         port->wait_running = FALSE;
543
544         ret = restart_wait(port);
545
546         if (ret < 0) {
547                 sp_close(port);
548                 RETURN_CODEVAL(ret);
549         }
550 #else
551         int flags_local = O_NONBLOCK | O_NOCTTY;
552
553         /* Map 'flags' to the OS-specific settings. */
554         if ((flags & SP_MODE_READ_WRITE) == SP_MODE_READ_WRITE)
555                 flags_local |= O_RDWR;
556         else if (flags & SP_MODE_READ)
557                 flags_local |= O_RDONLY;
558         else if (flags & SP_MODE_WRITE)
559                 flags_local |= O_WRONLY;
560
561         if ((port->fd = open(port->name, flags_local)) < 0)
562                 RETURN_FAIL("open() failed");
563 #endif
564
565         ret = get_config(port, &data, &config);
566
567         if (ret < 0) {
568                 sp_close(port);
569                 RETURN_CODEVAL(ret);
570         }
571
572         /* Set sane port settings. */
573 #ifdef _WIN32
574         data.dcb.fBinary = TRUE;
575         data.dcb.fDsrSensitivity = FALSE;
576         data.dcb.fErrorChar = FALSE;
577         data.dcb.fNull = FALSE;
578         data.dcb.fAbortOnError = FALSE;
579 #else
580         /* Turn off all fancy termios tricks, give us a raw channel. */
581         data.term.c_iflag &= ~(IGNBRK | BRKINT | PARMRK | ISTRIP | INLCR | IGNCR | ICRNL | IMAXBEL);
582 #ifdef IUCLC
583         data.term.c_iflag &= ~IUCLC;
584 #endif
585         data.term.c_oflag &= ~(OPOST | ONLCR | OCRNL | ONOCR | ONLRET);
586 #ifdef OLCUC
587         data.term.c_oflag &= ~OLCUC;
588 #endif
589 #ifdef NLDLY
590         data.term.c_oflag &= ~NLDLY;
591 #endif
592 #ifdef CRDLY
593         data.term.c_oflag &= ~CRDLY;
594 #endif
595 #ifdef TABDLY
596         data.term.c_oflag &= ~TABDLY;
597 #endif
598 #ifdef BSDLY
599         data.term.c_oflag &= ~BSDLY;
600 #endif
601 #ifdef VTDLY
602         data.term.c_oflag &= ~VTDLY;
603 #endif
604 #ifdef FFDLY
605         data.term.c_oflag &= ~FFDLY;
606 #endif
607 #ifdef OFILL
608         data.term.c_oflag &= ~OFILL;
609 #endif
610         data.term.c_lflag &= ~(ISIG | ICANON | ECHO | IEXTEN);
611         data.term.c_cc[VMIN] = 0;
612         data.term.c_cc[VTIME] = 0;
613
614         /* Ignore modem status lines; enable receiver; leave control lines alone on close. */
615         data.term.c_cflag |= (CLOCAL | CREAD | HUPCL);
616 #endif
617
618 #ifdef _WIN32
619         if (ClearCommError(port->hdl, &errors, &status) == 0)
620                 RETURN_FAIL("ClearCommError() failed");
621 #endif
622
623         ret = set_config(port, &data, &config);
624
625         if (ret < 0) {
626                 sp_close(port);
627                 RETURN_CODEVAL(ret);
628         }
629
630         RETURN_OK();
631 }
632
633 SP_API enum sp_return sp_close(struct sp_port *port)
634 {
635         TRACE("%p", port);
636
637         CHECK_OPEN_PORT();
638
639         DEBUG_FMT("Closing port %s", port->name);
640
641 #ifdef _WIN32
642         /* Returns non-zero upon success, 0 upon failure. */
643         if (CloseHandle(port->hdl) == 0)
644                 RETURN_FAIL("Port CloseHandle() failed");
645         port->hdl = INVALID_HANDLE_VALUE;
646
647         /* Close event handles for overlapped structures. */
648 #define CLOSE_OVERLAPPED(ovl) do { \
649         if (port->ovl.hEvent != INVALID_HANDLE_VALUE && \
650                 CloseHandle(port->ovl.hEvent) == 0) \
651                 RETURN_FAIL(# ovl "event CloseHandle() failed"); \
652 } while (0)
653         CLOSE_OVERLAPPED(read_ovl);
654         CLOSE_OVERLAPPED(write_ovl);
655         CLOSE_OVERLAPPED(wait_ovl);
656
657         if (port->write_buf) {
658                 free(port->write_buf);
659                 port->write_buf = NULL;
660         }
661 #else
662         /* Returns 0 upon success, -1 upon failure. */
663         if (close(port->fd) == -1)
664                 RETURN_FAIL("close() failed");
665         port->fd = -1;
666 #endif
667
668         RETURN_OK();
669 }
670
671 SP_API enum sp_return sp_flush(struct sp_port *port, enum sp_buffer buffers)
672 {
673         TRACE("%p, 0x%x", port, buffers);
674
675         CHECK_OPEN_PORT();
676
677         if (buffers > SP_BUF_BOTH)
678                 RETURN_ERROR(SP_ERR_ARG, "Invalid buffer selection");
679
680         const char *buffer_names[] = {"no", "input", "output", "both"};
681
682         DEBUG_FMT("Flushing %s buffers on port %s",
683                 buffer_names[buffers], port->name);
684
685 #ifdef _WIN32
686         DWORD flags = 0;
687         if (buffers & SP_BUF_INPUT)
688                 flags |= PURGE_RXCLEAR;
689         if (buffers & SP_BUF_OUTPUT)
690                 flags |= PURGE_TXCLEAR;
691
692         /* Returns non-zero upon success, 0 upon failure. */
693         if (PurgeComm(port->hdl, flags) == 0)
694                 RETURN_FAIL("PurgeComm() failed");
695
696         if (buffers & SP_BUF_INPUT)
697                 TRY(restart_wait(port));
698 #else
699         int flags = 0;
700         if (buffers == SP_BUF_BOTH)
701                 flags = TCIOFLUSH;
702         else if (buffers == SP_BUF_INPUT)
703                 flags = TCIFLUSH;
704         else if (buffers == SP_BUF_OUTPUT)
705                 flags = TCOFLUSH;
706
707         /* Returns 0 upon success, -1 upon failure. */
708         if (tcflush(port->fd, flags) < 0)
709                 RETURN_FAIL("tcflush() failed");
710 #endif
711         RETURN_OK();
712 }
713
714 SP_API enum sp_return sp_drain(struct sp_port *port)
715 {
716         TRACE("%p", port);
717
718         CHECK_OPEN_PORT();
719
720         DEBUG_FMT("Draining port %s", port->name);
721
722 #ifdef _WIN32
723         /* Returns non-zero upon success, 0 upon failure. */
724         if (FlushFileBuffers(port->hdl) == 0)
725                 RETURN_FAIL("FlushFileBuffers() failed");
726         RETURN_OK();
727 #else
728         int result;
729         while (1) {
730 #ifdef __ANDROID__
731                 int arg = 1;
732                 result = ioctl(port->fd, TCSBRK, &arg);
733 #else
734                 result = tcdrain(port->fd);
735 #endif
736                 if (result < 0) {
737                         if (errno == EINTR) {
738                                 DEBUG("tcdrain() was interrupted");
739                                 continue;
740                         } else {
741                                 RETURN_FAIL("tcdrain() failed");
742                         }
743                 } else {
744                         RETURN_OK();
745                 }
746         }
747 #endif
748 }
749
750 #ifdef _WIN32
751 static enum sp_return await_write_completion(struct sp_port *port)
752 {
753         TRACE("%p", port);
754         DWORD bytes_written;
755         BOOL result;
756
757         /* Wait for previous non-blocking write to complete, if any. */
758         if (port->writing) {
759                 DEBUG("Waiting for previous write to complete");
760                 result = GetOverlappedResult(port->hdl, &port->write_ovl, &bytes_written, TRUE);
761                 port->writing = 0;
762                 if (!result)
763                         RETURN_FAIL("Previous write failed to complete");
764                 DEBUG("Previous write completed");
765         }
766
767         RETURN_OK();
768 }
769 #endif
770
771 SP_API enum sp_return sp_blocking_write(struct sp_port *port, const void *buf,
772                                         size_t count, unsigned int timeout_ms)
773 {
774         TRACE("%p, %p, %d, %d", port, buf, count, timeout_ms);
775
776         CHECK_OPEN_PORT();
777
778         if (!buf)
779                 RETURN_ERROR(SP_ERR_ARG, "Null buffer");
780
781         if (timeout_ms)
782                 DEBUG_FMT("Writing %d bytes to port %s, timeout %d ms",
783                         count, port->name, timeout_ms);
784         else
785                 DEBUG_FMT("Writing %d bytes to port %s, no timeout",
786                         count, port->name);
787
788         if (count == 0)
789                 RETURN_INT(0);
790
791 #ifdef _WIN32
792         DWORD bytes_written = 0;
793
794         TRY(await_write_completion(port));
795
796         /* Set timeout. */
797         if (port->timeouts.WriteTotalTimeoutConstant != timeout_ms) {
798                 port->timeouts.WriteTotalTimeoutConstant = timeout_ms;
799                 if (SetCommTimeouts(port->hdl, &port->timeouts) == 0)
800                         RETURN_FAIL("SetCommTimeouts() failed");
801         }
802
803         /* Reduce count if it exceeds the WriteFile limit. */
804         if (count > WRITEFILE_MAX_SIZE)
805                 count = WRITEFILE_MAX_SIZE;
806
807         /* Start write. */
808         if (WriteFile(port->hdl, buf, count, NULL, &port->write_ovl)) {
809                 DEBUG("Write completed immediately");
810                 RETURN_INT(count);
811         } else if (GetLastError() == ERROR_IO_PENDING) {
812                 DEBUG("Waiting for write to complete");
813                 if (GetOverlappedResult(port->hdl, &port->write_ovl, &bytes_written, TRUE) == 0) {
814                         if (GetLastError() == ERROR_SEM_TIMEOUT) {
815                                 DEBUG("Write timed out");
816                                 RETURN_INT(0);
817                         } else {
818                                 RETURN_FAIL("GetOverlappedResult() failed");
819                         }
820                 }
821                 DEBUG_FMT("Write completed, %d/%d bytes written", bytes_written, count);
822                 RETURN_INT(bytes_written);
823         } else {
824                 RETURN_FAIL("WriteFile() failed");
825         }
826 #else
827         size_t bytes_written = 0;
828         unsigned char *ptr = (unsigned char *) buf;
829         struct timeval start, delta, now, end = {0, 0};
830         int started = 0;
831         fd_set fds;
832         int result;
833
834         if (timeout_ms) {
835                 /* Get time at start of operation. */
836                 get_time(&start);
837                 /* Define duration of timeout. */
838                 delta.tv_sec = timeout_ms / 1000;
839                 delta.tv_usec = (timeout_ms % 1000) * 1000;
840                 /* Calculate time at which we should give up. */
841                 timeradd(&start, &delta, &end);
842         }
843
844         FD_ZERO(&fds);
845         FD_SET(port->fd, &fds);
846
847         /* Loop until we have written the requested number of bytes. */
848         while (bytes_written < count) {
849                 /*
850                  * Check timeout only if we have run select() at least once,
851                  * to avoid any issues if a short timeout is reached before
852                  * select() is even run.
853                  */
854                 if (timeout_ms && started) {
855                         get_time(&now);
856                         if (timercmp(&now, &end, >))
857                                 /* Timeout has expired. */
858                                 break;
859                         timersub(&end, &now, &delta);
860                 }
861                 result = select(port->fd + 1, NULL, &fds, NULL, timeout_ms ? &delta : NULL);
862                 started = 1;
863                 if (result < 0) {
864                         if (errno == EINTR) {
865                                 DEBUG("select() call was interrupted, repeating");
866                                 continue;
867                         } else {
868                                 RETURN_FAIL("select() failed");
869                         }
870                 } else if (result == 0) {
871                         /* Timeout has expired. */
872                         break;
873                 }
874
875                 /* Do write. */
876                 result = write(port->fd, ptr, count - bytes_written);
877
878                 if (result < 0) {
879                         if (errno == EAGAIN)
880                                 /* This shouldn't happen because we did a select() first, but handle anyway. */
881                                 continue;
882                         else
883                                 /* This is an actual failure. */
884                                 RETURN_FAIL("write() failed");
885                 }
886
887                 bytes_written += result;
888                 ptr += result;
889         }
890
891         if (bytes_written < count)
892                 DEBUG("Write timed out");
893
894         RETURN_INT(bytes_written);
895 #endif
896 }
897
898 SP_API enum sp_return sp_nonblocking_write(struct sp_port *port,
899                                            const void *buf, size_t count)
900 {
901         TRACE("%p, %p, %d", port, buf, count);
902
903         CHECK_OPEN_PORT();
904
905         if (!buf)
906                 RETURN_ERROR(SP_ERR_ARG, "Null buffer");
907
908         DEBUG_FMT("Writing up to %d bytes to port %s", count, port->name);
909
910         if (count == 0)
911                 RETURN_INT(0);
912
913 #ifdef _WIN32
914         DWORD buf_bytes;
915
916         /* Check whether previous write is complete. */
917         if (port->writing) {
918                 if (HasOverlappedIoCompleted(&port->write_ovl)) {
919                         DEBUG("Previous write completed");
920                         port->writing = 0;
921                 } else {
922                         DEBUG("Previous write not complete");
923                         /* Can't take a new write until the previous one finishes. */
924                         RETURN_INT(0);
925                 }
926         }
927
928         /* Set timeout. */
929         if (port->timeouts.WriteTotalTimeoutConstant != 0) {
930                 port->timeouts.WriteTotalTimeoutConstant = 0;
931                 if (SetCommTimeouts(port->hdl, &port->timeouts) == 0)
932                         RETURN_FAIL("SetCommTimeouts() failed");
933         }
934
935         /* Reduce count if it exceeds the WriteFile limit. */
936         if (count > WRITEFILE_MAX_SIZE)
937                 count = WRITEFILE_MAX_SIZE;
938
939         /* Copy data to our write buffer. */
940         buf_bytes = min(port->write_buf_size, count);
941         memcpy(port->write_buf, buf, buf_bytes);
942
943         /* Start asynchronous write. */
944         if (WriteFile(port->hdl, port->write_buf, buf_bytes, NULL, &port->write_ovl) == 0) {
945                 if (GetLastError() == ERROR_IO_PENDING) {
946                         if ((port->writing = !HasOverlappedIoCompleted(&port->write_ovl)))
947                                 DEBUG("Asynchronous write completed immediately");
948                         else
949                                 DEBUG("Asynchronous write running");
950                 } else {
951                         /* Actual failure of some kind. */
952                         RETURN_FAIL("WriteFile() failed");
953                 }
954         }
955
956         DEBUG("All bytes written immediately");
957
958         RETURN_INT(buf_bytes);
959 #else
960         /* Returns the number of bytes written, or -1 upon failure. */
961         ssize_t written = write(port->fd, buf, count);
962
963         if (written < 0) {
964                 if (errno == EAGAIN)
965                         // Buffer is full, no bytes written.
966                         RETURN_INT(0);
967                 else
968                         RETURN_FAIL("write() failed");
969         } else {
970                 RETURN_INT(written);
971         }
972 #endif
973 }
974
975 #ifdef _WIN32
976 /* Restart wait operation if buffer was emptied. */
977 static enum sp_return restart_wait_if_needed(struct sp_port *port, unsigned int bytes_read)
978 {
979         DWORD errors;
980         COMSTAT comstat;
981
982         if (bytes_read == 0)
983                 RETURN_OK();
984
985         if (ClearCommError(port->hdl, &errors, &comstat) == 0)
986                 RETURN_FAIL("ClearCommError() failed");
987
988         if (comstat.cbInQue == 0)
989                 TRY(restart_wait(port));
990
991         RETURN_OK();
992 }
993 #endif
994
995 SP_API enum sp_return sp_blocking_read(struct sp_port *port, void *buf,
996                                        size_t count, unsigned int timeout_ms)
997 {
998         TRACE("%p, %p, %d, %d", port, buf, count, timeout_ms);
999
1000         CHECK_OPEN_PORT();
1001
1002         if (!buf)
1003                 RETURN_ERROR(SP_ERR_ARG, "Null buffer");
1004
1005         if (timeout_ms)
1006                 DEBUG_FMT("Reading %d bytes from port %s, timeout %d ms",
1007                         count, port->name, timeout_ms);
1008         else
1009                 DEBUG_FMT("Reading %d bytes from port %s, no timeout",
1010                         count, port->name);
1011
1012         if (count == 0)
1013                 RETURN_INT(0);
1014
1015 #ifdef _WIN32
1016         DWORD bytes_read = 0;
1017
1018         /* Set timeout. */
1019         if (port->timeouts.ReadIntervalTimeout != 0 ||
1020                         port->timeouts.ReadTotalTimeoutMultiplier != 0 ||
1021                         port->timeouts.ReadTotalTimeoutConstant != timeout_ms) {
1022                 port->timeouts.ReadIntervalTimeout = 0;
1023                 port->timeouts.ReadTotalTimeoutMultiplier = 0;
1024                 port->timeouts.ReadTotalTimeoutConstant = timeout_ms;
1025                 if (SetCommTimeouts(port->hdl, &port->timeouts) == 0)
1026                         RETURN_FAIL("SetCommTimeouts() failed");
1027         }
1028
1029         /* Start read. */
1030         if (ReadFile(port->hdl, buf, count, NULL, &port->read_ovl)) {
1031                 DEBUG("Read completed immediately");
1032                 bytes_read = count;
1033         } else if (GetLastError() == ERROR_IO_PENDING) {
1034                 DEBUG("Waiting for read to complete");
1035                 if (GetOverlappedResult(port->hdl, &port->read_ovl, &bytes_read, TRUE) == 0)
1036                         RETURN_FAIL("GetOverlappedResult() failed");
1037                 DEBUG_FMT("Read completed, %d/%d bytes read", bytes_read, count);
1038         } else {
1039                 RETURN_FAIL("ReadFile() failed");
1040         }
1041
1042         TRY(restart_wait_if_needed(port, bytes_read));
1043
1044         RETURN_INT(bytes_read);
1045
1046 #else
1047         size_t bytes_read = 0;
1048         unsigned char *ptr = (unsigned char *)buf;
1049         struct timeval start, delta, now, end = {0, 0};
1050         int started = 0;
1051         fd_set fds;
1052         int result;
1053
1054         if (timeout_ms) {
1055                 /* Get time at start of operation. */
1056                 get_time(&start);
1057                 /* Define duration of timeout. */
1058                 delta.tv_sec = timeout_ms / 1000;
1059                 delta.tv_usec = (timeout_ms % 1000) * 1000;
1060                 /* Calculate time at which we should give up. */
1061                 timeradd(&start, &delta, &end);
1062         }
1063
1064         FD_ZERO(&fds);
1065         FD_SET(port->fd, &fds);
1066
1067         /* Loop until we have the requested number of bytes. */
1068         while (bytes_read < count) {
1069                 /*
1070                  * Check timeout only if we have run select() at least once,
1071                  * to avoid any issues if a short timeout is reached before
1072                  * select() is even run.
1073                  */
1074                 if (timeout_ms && started) {
1075                         get_time(&now);
1076                         if (timercmp(&now, &end, >))
1077                                 /* Timeout has expired. */
1078                                 break;
1079                         timersub(&end, &now, &delta);
1080                 }
1081                 result = select(port->fd + 1, &fds, NULL, NULL, timeout_ms ? &delta : NULL);
1082                 started = 1;
1083                 if (result < 0) {
1084                         if (errno == EINTR) {
1085                                 DEBUG("select() call was interrupted, repeating");
1086                                 continue;
1087                         } else {
1088                                 RETURN_FAIL("select() failed");
1089                         }
1090                 } else if (result == 0) {
1091                         /* Timeout has expired. */
1092                         break;
1093                 }
1094
1095                 /* Do read. */
1096                 result = read(port->fd, ptr, count - bytes_read);
1097
1098                 if (result < 0) {
1099                         if (errno == EAGAIN)
1100                                 /*
1101                                  * This shouldn't happen because we did a
1102                                  * select() first, but handle anyway.
1103                                  */
1104                                 continue;
1105                         else
1106                                 /* This is an actual failure. */
1107                                 RETURN_FAIL("read() failed");
1108                 }
1109
1110                 bytes_read += result;
1111                 ptr += result;
1112         }
1113
1114         if (bytes_read < count)
1115                 DEBUG("Read timed out");
1116
1117         RETURN_INT(bytes_read);
1118 #endif
1119 }
1120
1121 SP_API enum sp_return sp_blocking_read_next(struct sp_port *port, void *buf,
1122                                             size_t count, unsigned int timeout_ms)
1123 {
1124         TRACE("%p, %p, %d, %d", port, buf, count, timeout_ms);
1125
1126         CHECK_OPEN_PORT();
1127
1128         if (!buf)
1129                 RETURN_ERROR(SP_ERR_ARG, "Null buffer");
1130
1131         if (count == 0)
1132                 RETURN_ERROR(SP_ERR_ARG, "Zero count");
1133
1134         if (timeout_ms)
1135                 DEBUG_FMT("Reading next max %d bytes from port %s, timeout %d ms",
1136                         count, port->name, timeout_ms);
1137         else
1138                 DEBUG_FMT("Reading next max %d bytes from port %s, no timeout",
1139                         count, port->name);
1140
1141 #ifdef _WIN32
1142         DWORD bytes_read = 0;
1143
1144         /* If timeout_ms == 0, set maximum timeout. */
1145         DWORD timeout_val = (timeout_ms == 0 ? MAXDWORD - 1 : timeout_ms);
1146
1147         /* Set timeout. */
1148         if (port->timeouts.ReadIntervalTimeout != MAXDWORD ||
1149                         port->timeouts.ReadTotalTimeoutMultiplier != MAXDWORD ||
1150                         port->timeouts.ReadTotalTimeoutConstant != timeout_val) {
1151                 port->timeouts.ReadIntervalTimeout = MAXDWORD;
1152                 port->timeouts.ReadTotalTimeoutMultiplier = MAXDWORD;
1153                 port->timeouts.ReadTotalTimeoutConstant = timeout_val;
1154                 if (SetCommTimeouts(port->hdl, &port->timeouts) == 0)
1155                         RETURN_FAIL("SetCommTimeouts() failed");
1156         }
1157
1158         /* Loop until we have at least one byte, or timeout is reached. */
1159         while (bytes_read == 0) {
1160                 /* Start read. */
1161                 if (ReadFile(port->hdl, buf, count, &bytes_read, &port->read_ovl)) {
1162                         DEBUG("Read completed immediately");
1163                 } else if (GetLastError() == ERROR_IO_PENDING) {
1164                         DEBUG("Waiting for read to complete");
1165                         if (GetOverlappedResult(port->hdl, &port->read_ovl, &bytes_read, TRUE) == 0)
1166                                 RETURN_FAIL("GetOverlappedResult() failed");
1167                         if (bytes_read > 0) {
1168                                 DEBUG("Read completed");
1169                         } else if (timeout_ms > 0) {
1170                                 DEBUG("Read timed out");
1171                                 break;
1172                         } else {
1173                                 DEBUG("Restarting read");
1174                         }
1175                 } else {
1176                         RETURN_FAIL("ReadFile() failed");
1177                 }
1178         }
1179
1180         TRY(restart_wait_if_needed(port, bytes_read));
1181
1182         RETURN_INT(bytes_read);
1183
1184 #else
1185         size_t bytes_read = 0;
1186         struct timeval start, delta, now, end = {0, 0};
1187         int started = 0;
1188         fd_set fds;
1189         int result;
1190
1191         if (timeout_ms) {
1192                 /* Get time at start of operation. */
1193                 get_time(&start);
1194                 /* Define duration of timeout. */
1195                 delta.tv_sec = timeout_ms / 1000;
1196                 delta.tv_usec = (timeout_ms % 1000) * 1000;
1197                 /* Calculate time at which we should give up. */
1198                 timeradd(&start, &delta, &end);
1199         }
1200
1201         FD_ZERO(&fds);
1202         FD_SET(port->fd, &fds);
1203
1204         /* Loop until we have at least one byte, or timeout is reached. */
1205         while (bytes_read == 0) {
1206                 /*
1207                  * Check timeout only if we have run select() at least once,
1208                  * to avoid any issues if a short timeout is reached before
1209                  * select() is even run.
1210                  */
1211                 if (timeout_ms && started) {
1212                         get_time(&now);
1213                         if (timercmp(&now, &end, >))
1214                                 /* Timeout has expired. */
1215                                 break;
1216                         timersub(&end, &now, &delta);
1217                 }
1218                 result = select(port->fd + 1, &fds, NULL, NULL, timeout_ms ? &delta : NULL);
1219                 started = 1;
1220                 if (result < 0) {
1221                         if (errno == EINTR) {
1222                                 DEBUG("select() call was interrupted, repeating");
1223                                 continue;
1224                         } else {
1225                                 RETURN_FAIL("select() failed");
1226                         }
1227                 } else if (result == 0) {
1228                         /* Timeout has expired. */
1229                         break;
1230                 }
1231
1232                 /* Do read. */
1233                 result = read(port->fd, buf, count);
1234
1235                 if (result < 0) {
1236                         if (errno == EAGAIN)
1237                                 /* This shouldn't happen because we did a select() first, but handle anyway. */
1238                                 continue;
1239                         else
1240                                 /* This is an actual failure. */
1241                                 RETURN_FAIL("read() failed");
1242                 }
1243
1244                 bytes_read = result;
1245         }
1246
1247         if (bytes_read == 0)
1248                 DEBUG("Read timed out");
1249
1250         RETURN_INT(bytes_read);
1251 #endif
1252 }
1253
1254 SP_API enum sp_return sp_nonblocking_read(struct sp_port *port, void *buf,
1255                                           size_t count)
1256 {
1257         TRACE("%p, %p, %d", port, buf, count);
1258
1259         CHECK_OPEN_PORT();
1260
1261         if (!buf)
1262                 RETURN_ERROR(SP_ERR_ARG, "Null buffer");
1263
1264         DEBUG_FMT("Reading up to %d bytes from port %s", count, port->name);
1265
1266 #ifdef _WIN32
1267         DWORD bytes_read;
1268
1269         /* Set timeout. */
1270         if (port->timeouts.ReadIntervalTimeout != MAXDWORD ||
1271                         port->timeouts.ReadTotalTimeoutMultiplier != 0 ||
1272                         port->timeouts.ReadTotalTimeoutConstant != 0) {
1273                 port->timeouts.ReadIntervalTimeout = MAXDWORD;
1274                 port->timeouts.ReadTotalTimeoutMultiplier = 0;
1275                 port->timeouts.ReadTotalTimeoutConstant = 0;
1276                 if (SetCommTimeouts(port->hdl, &port->timeouts) == 0)
1277                         RETURN_FAIL("SetCommTimeouts() failed");
1278         }
1279
1280         /* Do read. */
1281         if (ReadFile(port->hdl, buf, count, NULL, &port->read_ovl) == 0)
1282                 if (GetLastError() != ERROR_IO_PENDING)
1283                         RETURN_FAIL("ReadFile() failed");
1284
1285         /* Get number of bytes read. */
1286         if (GetOverlappedResult(port->hdl, &port->read_ovl, &bytes_read, FALSE) == 0)
1287                 RETURN_FAIL("GetOverlappedResult() failed");
1288
1289         TRY(restart_wait_if_needed(port, bytes_read));
1290
1291         RETURN_INT(bytes_read);
1292 #else
1293         ssize_t bytes_read;
1294
1295         /* Returns the number of bytes read, or -1 upon failure. */
1296         if ((bytes_read = read(port->fd, buf, count)) < 0) {
1297                 if (errno == EAGAIN)
1298                         /* No bytes available. */
1299                         bytes_read = 0;
1300                 else
1301                         /* This is an actual failure. */
1302                         RETURN_FAIL("read() failed");
1303         }
1304         RETURN_INT(bytes_read);
1305 #endif
1306 }
1307
1308 SP_API enum sp_return sp_input_waiting(struct sp_port *port)
1309 {
1310         TRACE("%p", port);
1311
1312         CHECK_OPEN_PORT();
1313
1314         DEBUG_FMT("Checking input bytes waiting on port %s", port->name);
1315
1316 #ifdef _WIN32
1317         DWORD errors;
1318         COMSTAT comstat;
1319
1320         if (ClearCommError(port->hdl, &errors, &comstat) == 0)
1321                 RETURN_FAIL("ClearCommError() failed");
1322         RETURN_INT(comstat.cbInQue);
1323 #else
1324         int bytes_waiting;
1325         if (ioctl(port->fd, TIOCINQ, &bytes_waiting) < 0)
1326                 RETURN_FAIL("TIOCINQ ioctl failed");
1327         RETURN_INT(bytes_waiting);
1328 #endif
1329 }
1330
1331 SP_API enum sp_return sp_output_waiting(struct sp_port *port)
1332 {
1333         TRACE("%p", port);
1334
1335         CHECK_OPEN_PORT();
1336
1337         DEBUG_FMT("Checking output bytes waiting on port %s", port->name);
1338
1339 #ifdef _WIN32
1340         DWORD errors;
1341         COMSTAT comstat;
1342
1343         if (ClearCommError(port->hdl, &errors, &comstat) == 0)
1344                 RETURN_FAIL("ClearCommError() failed");
1345         RETURN_INT(comstat.cbOutQue);
1346 #else
1347         int bytes_waiting;
1348         if (ioctl(port->fd, TIOCOUTQ, &bytes_waiting) < 0)
1349                 RETURN_FAIL("TIOCOUTQ ioctl failed");
1350         RETURN_INT(bytes_waiting);
1351 #endif
1352 }
1353
1354 SP_API enum sp_return sp_new_event_set(struct sp_event_set **result_ptr)
1355 {
1356         struct sp_event_set *result;
1357
1358         TRACE("%p", result_ptr);
1359
1360         if (!result_ptr)
1361                 RETURN_ERROR(SP_ERR_ARG, "Null result");
1362
1363         *result_ptr = NULL;
1364
1365         if (!(result = malloc(sizeof(struct sp_event_set))))
1366                 RETURN_ERROR(SP_ERR_MEM, "sp_event_set malloc() failed");
1367
1368         memset(result, 0, sizeof(struct sp_event_set));
1369
1370         *result_ptr = result;
1371
1372         RETURN_OK();
1373 }
1374
1375 static enum sp_return add_handle(struct sp_event_set *event_set,
1376                 event_handle handle, enum sp_event mask)
1377 {
1378         void *new_handles;
1379         enum sp_event *new_masks;
1380
1381         TRACE("%p, %d, %d", event_set, handle, mask);
1382
1383         if (!(new_handles = realloc(event_set->handles,
1384                         sizeof(event_handle) * (event_set->count + 1))))
1385                 RETURN_ERROR(SP_ERR_MEM, "Handle array realloc() failed");
1386
1387         event_set->handles = new_handles;
1388
1389         if (!(new_masks = realloc(event_set->masks,
1390                         sizeof(enum sp_event) * (event_set->count + 1))))
1391                 RETURN_ERROR(SP_ERR_MEM, "Mask array realloc() failed");
1392
1393         event_set->masks = new_masks;
1394
1395         ((event_handle *) event_set->handles)[event_set->count] = handle;
1396         event_set->masks[event_set->count] = mask;
1397
1398         event_set->count++;
1399
1400         RETURN_OK();
1401 }
1402
1403 SP_API enum sp_return sp_add_port_events(struct sp_event_set *event_set,
1404         const struct sp_port *port, enum sp_event mask)
1405 {
1406         TRACE("%p, %p, %d", event_set, port, mask);
1407
1408         if (!event_set)
1409                 RETURN_ERROR(SP_ERR_ARG, "Null event set");
1410
1411         if (!port)
1412                 RETURN_ERROR(SP_ERR_ARG, "Null port");
1413
1414         if (mask > (SP_EVENT_RX_READY | SP_EVENT_TX_READY | SP_EVENT_ERROR))
1415                 RETURN_ERROR(SP_ERR_ARG, "Invalid event mask");
1416
1417         if (!mask)
1418                 RETURN_OK();
1419
1420 #ifdef _WIN32
1421         enum sp_event handle_mask;
1422         if ((handle_mask = mask & SP_EVENT_TX_READY))
1423                 TRY(add_handle(event_set, port->write_ovl.hEvent, handle_mask));
1424         if ((handle_mask = mask & (SP_EVENT_RX_READY | SP_EVENT_ERROR)))
1425                 TRY(add_handle(event_set, port->wait_ovl.hEvent, handle_mask));
1426 #else
1427         TRY(add_handle(event_set, port->fd, mask));
1428 #endif
1429
1430         RETURN_OK();
1431 }
1432
1433 SP_API void sp_free_event_set(struct sp_event_set *event_set)
1434 {
1435         TRACE("%p", event_set);
1436
1437         if (!event_set) {
1438                 DEBUG("Null event set");
1439                 RETURN();
1440         }
1441
1442         DEBUG("Freeing event set");
1443
1444         if (event_set->handles)
1445                 free(event_set->handles);
1446         if (event_set->masks)
1447                 free(event_set->masks);
1448
1449         free(event_set);
1450
1451         RETURN();
1452 }
1453
1454 SP_API enum sp_return sp_wait(struct sp_event_set *event_set,
1455                               unsigned int timeout_ms)
1456 {
1457         TRACE("%p, %d", event_set, timeout_ms);
1458
1459         if (!event_set)
1460                 RETURN_ERROR(SP_ERR_ARG, "Null event set");
1461
1462 #ifdef _WIN32
1463         if (WaitForMultipleObjects(event_set->count, event_set->handles, FALSE,
1464                         timeout_ms ? timeout_ms : INFINITE) == WAIT_FAILED)
1465                 RETURN_FAIL("WaitForMultipleObjects() failed");
1466
1467         RETURN_OK();
1468 #else
1469         struct timeval start, delta, now, end = {0, 0};
1470         const struct timeval max_delta = {
1471                 (INT_MAX / 1000), (INT_MAX % 1000) * 1000
1472         };
1473         int started = 0, timeout_overflow = 0;
1474         int result, timeout_remaining_ms;
1475         struct pollfd *pollfds;
1476         unsigned int i;
1477
1478         if (!(pollfds = malloc(sizeof(struct pollfd) * event_set->count)))
1479                 RETURN_ERROR(SP_ERR_MEM, "pollfds malloc() failed");
1480
1481         for (i = 0; i < event_set->count; i++) {
1482                 pollfds[i].fd = ((int *)event_set->handles)[i];
1483                 pollfds[i].events = 0;
1484                 pollfds[i].revents = 0;
1485                 if (event_set->masks[i] & SP_EVENT_RX_READY)
1486                         pollfds[i].events |= POLLIN;
1487                 if (event_set->masks[i] & SP_EVENT_TX_READY)
1488                         pollfds[i].events |= POLLOUT;
1489                 if (event_set->masks[i] & SP_EVENT_ERROR)
1490                         pollfds[i].events |= POLLERR;
1491         }
1492
1493         if (timeout_ms) {
1494                 /* Get time at start of operation. */
1495                 get_time(&start);
1496                 /* Define duration of timeout. */
1497                 delta.tv_sec = timeout_ms / 1000;
1498                 delta.tv_usec = (timeout_ms % 1000) * 1000;
1499                 /* Calculate time at which we should give up. */
1500                 timeradd(&start, &delta, &end);
1501         }
1502
1503         /* Loop until an event occurs. */
1504         while (1) {
1505                 /*
1506                  * Check timeout only if we have run poll() at least once,
1507                  * to avoid any issues if a short timeout is reached before
1508                  * poll() is even run.
1509                  */
1510                 if (!timeout_ms) {
1511                         timeout_remaining_ms = -1;
1512                 } else if (!started) {
1513                         timeout_overflow = (timeout_ms > INT_MAX);
1514                         timeout_remaining_ms = timeout_overflow ? INT_MAX : timeout_ms;
1515                 } else {
1516                         get_time(&now);
1517                         if (timercmp(&now, &end, >)) {
1518                                 DEBUG("Wait timed out");
1519                                 break;
1520                         }
1521                         timersub(&end, &now, &delta);
1522                         if ((timeout_overflow = timercmp(&delta, &max_delta, >)))
1523                                 delta = max_delta;
1524                         timeout_remaining_ms = delta.tv_sec * 1000 + delta.tv_usec / 1000;
1525                 }
1526
1527                 result = poll(pollfds, event_set->count, timeout_remaining_ms);
1528                 started = 1;
1529
1530                 if (result < 0) {
1531                         if (errno == EINTR) {
1532                                 DEBUG("poll() call was interrupted, repeating");
1533                                 continue;
1534                         } else {
1535                                 free(pollfds);
1536                                 RETURN_FAIL("poll() failed");
1537                         }
1538                 } else if (result == 0) {
1539                         DEBUG("poll() timed out");
1540                         if (!timeout_overflow)
1541                                 break;
1542                 } else {
1543                         DEBUG("poll() completed");
1544                         break;
1545                 }
1546         }
1547
1548         free(pollfds);
1549         RETURN_OK();
1550 #endif
1551 }
1552
1553 #ifdef USE_TERMIOS_SPEED
1554 static enum sp_return get_baudrate(int fd, int *baudrate)
1555 {
1556         void *data;
1557
1558         TRACE("%d, %p", fd, baudrate);
1559
1560         DEBUG("Getting baud rate");
1561
1562         if (!(data = malloc(get_termios_size())))
1563                 RETURN_ERROR(SP_ERR_MEM, "termios malloc failed");
1564
1565         if (ioctl(fd, get_termios_get_ioctl(), data) < 0) {
1566                 free(data);
1567                 RETURN_FAIL("Getting termios failed");
1568         }
1569
1570         *baudrate = get_termios_speed(data);
1571
1572         free(data);
1573
1574         RETURN_OK();
1575 }
1576
1577 static enum sp_return set_baudrate(int fd, int baudrate)
1578 {
1579         void *data;
1580
1581         TRACE("%d, %d", fd, baudrate);
1582
1583         DEBUG("Getting baud rate");
1584
1585         if (!(data = malloc(get_termios_size())))
1586                 RETURN_ERROR(SP_ERR_MEM, "termios malloc failed");
1587
1588         if (ioctl(fd, get_termios_get_ioctl(), data) < 0) {
1589                 free(data);
1590                 RETURN_FAIL("Getting termios failed");
1591         }
1592
1593         DEBUG("Setting baud rate");
1594
1595         set_termios_speed(data, baudrate);
1596
1597         if (ioctl(fd, get_termios_set_ioctl(), data) < 0) {
1598                 free(data);
1599                 RETURN_FAIL("Setting termios failed");
1600         }
1601
1602         free(data);
1603
1604         RETURN_OK();
1605 }
1606 #endif /* USE_TERMIOS_SPEED */
1607
1608 #ifdef USE_TERMIOX
1609 static enum sp_return get_flow(int fd, struct port_data *data)
1610 {
1611         void *termx;
1612
1613         TRACE("%d, %p", fd, data);
1614
1615         DEBUG("Getting advanced flow control");
1616
1617         if (!(termx = malloc(get_termiox_size())))
1618                 RETURN_ERROR(SP_ERR_MEM, "termiox malloc failed");
1619
1620         if (ioctl(fd, TCGETX, termx) < 0) {
1621                 free(termx);
1622                 RETURN_FAIL("Getting termiox failed");
1623         }
1624
1625         get_termiox_flow(termx, &data->rts_flow, &data->cts_flow,
1626                         &data->dtr_flow, &data->dsr_flow);
1627
1628         free(termx);
1629
1630         RETURN_OK();
1631 }
1632
1633 static enum sp_return set_flow(int fd, struct port_data *data)
1634 {
1635         void *termx;
1636
1637         TRACE("%d, %p", fd, data);
1638
1639         DEBUG("Getting advanced flow control");
1640
1641         if (!(termx = malloc(get_termiox_size())))
1642                 RETURN_ERROR(SP_ERR_MEM, "termiox malloc failed");
1643
1644         if (ioctl(fd, TCGETX, termx) < 0) {
1645                 free(termx);
1646                 RETURN_FAIL("Getting termiox failed");
1647         }
1648
1649         DEBUG("Setting advanced flow control");
1650
1651         set_termiox_flow(termx, data->rts_flow, data->cts_flow,
1652                         data->dtr_flow, data->dsr_flow);
1653
1654         if (ioctl(fd, TCSETX, termx) < 0) {
1655                 free(termx);
1656                 RETURN_FAIL("Setting termiox failed");
1657         }
1658
1659         free(termx);
1660
1661         RETURN_OK();
1662 }
1663 #endif /* USE_TERMIOX */
1664
1665 static enum sp_return get_config(struct sp_port *port, struct port_data *data,
1666         struct sp_port_config *config)
1667 {
1668         unsigned int i;
1669
1670         TRACE("%p, %p, %p", port, data, config);
1671
1672         DEBUG_FMT("Getting configuration for port %s", port->name);
1673
1674 #ifdef _WIN32
1675         if (!GetCommState(port->hdl, &data->dcb))
1676                 RETURN_FAIL("GetCommState() failed");
1677
1678         for (i = 0; i < NUM_STD_BAUDRATES; i++) {
1679                 if (data->dcb.BaudRate == std_baudrates[i].index) {
1680                         config->baudrate = std_baudrates[i].value;
1681                         break;
1682                 }
1683         }
1684
1685         if (i == NUM_STD_BAUDRATES)
1686                 /* BaudRate field can be either an index or a custom baud rate. */
1687                 config->baudrate = data->dcb.BaudRate;
1688
1689         config->bits = data->dcb.ByteSize;
1690
1691         if (data->dcb.fParity)
1692                 switch (data->dcb.Parity) {
1693                 case NOPARITY:
1694                         config->parity = SP_PARITY_NONE;
1695                         break;
1696                 case ODDPARITY:
1697                         config->parity = SP_PARITY_ODD;
1698                         break;
1699                 case EVENPARITY:
1700                         config->parity = SP_PARITY_EVEN;
1701                         break;
1702                 case MARKPARITY:
1703                         config->parity = SP_PARITY_MARK;
1704                         break;
1705                 case SPACEPARITY:
1706                         config->parity = SP_PARITY_SPACE;
1707                         break;
1708                 default:
1709                         config->parity = -1;
1710                 }
1711         else
1712                 config->parity = SP_PARITY_NONE;
1713
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;
1723         }
1724
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;
1737         }
1738
1739         config->cts = data->dcb.fOutxCtsFlow ? SP_CTS_FLOW_CONTROL : SP_CTS_IGNORE;
1740
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;
1753         }
1754
1755         config->dsr = data->dcb.fOutxDsrFlow ? SP_DSR_FLOW_CONTROL : SP_DSR_IGNORE;
1756
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;
1767         }
1768
1769 #else // !_WIN32
1770
1771         if (tcgetattr(port->fd, &data->term) < 0)
1772                 RETURN_FAIL("tcgetattr() failed");
1773
1774         if (ioctl(port->fd, TIOCMGET, &data->controlbits) < 0)
1775                 RETURN_FAIL("TIOCMGET ioctl failed");
1776
1777 #ifdef USE_TERMIOX
1778         int ret = get_flow(port->fd, data);
1779
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
1789
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;
1794                 }
1795         }
1796
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
1805         }
1806
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;
1822         }
1823
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;
1834
1835         config->stopbits = (data->term.c_cflag & CSTOPB) ? 2 : 1;
1836
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;
1845
1846                 config->cts = (data->termiox_supported && data->cts_flow) ?
1847                         SP_CTS_FLOW_CONTROL : SP_CTS_IGNORE;
1848         }
1849
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;
1854
1855         config->dsr = (data->termiox_supported && data->dsr_flow) ?
1856                 SP_DSR_FLOW_CONTROL : SP_DSR_IGNORE;
1857
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;
1868         }
1869 #endif
1870
1871         RETURN_OK();
1872 }
1873
1874 static enum sp_return set_config(struct sp_port *port, struct port_data *data,
1875         const struct sp_port_config *config)
1876 {
1877         unsigned int i;
1878 #ifdef __APPLE__
1879         BAUD_TYPE baud_nonstd;
1880
1881         baud_nonstd = B0;
1882 #endif
1883 #ifdef USE_TERMIOS_SPEED
1884         int baud_nonstd = 0;
1885 #endif
1886
1887         TRACE("%p, %p, %p", port, data, config);
1888
1889         DEBUG_FMT("Setting configuration for port %s", port->name);
1890
1891 #ifdef _WIN32
1892
1893         TRY(await_write_completion(port));
1894
1895         if (config->baudrate >= 0) {
1896                 for (i = 0; i < NUM_STD_BAUDRATES; i++) {
1897                         if (config->baudrate == std_baudrates[i].value) {
1898                                 data->dcb.BaudRate = std_baudrates[i].index;
1899                                 break;
1900                         }
1901                 }
1902
1903                 if (i == NUM_STD_BAUDRATES)
1904                         data->dcb.BaudRate = config->baudrate;
1905
1906                 /* Allocate write buffer for 50ms of data at baud rate. */
1907                 port->write_buf_size = max(config->baudrate / (8 * 20), 1);
1908                 port->write_buf = realloc(port->write_buf,
1909                                           port->write_buf_size);
1910
1911                 if (!port->write_buf)
1912                         RETURN_ERROR(SP_ERR_MEM, "Allocating write buffer failed");
1913         }
1914
1915         if (config->bits >= 0)
1916                 data->dcb.ByteSize = config->bits;
1917
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");
1937                 }
1938         }
1939
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");
1951                 }
1952         }
1953
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");
1967                 }
1968         }
1969
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");
1980                 }
1981         }
1982
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");
1996                 }
1997         }
1998
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");
2009                 }
2010         }
2011
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");
2032                 }
2033         }
2034
2035         if (!SetCommState(port->hdl, &data->dcb))
2036                 RETURN_FAIL("SetCommState() failed");
2037
2038 #else /* !_WIN32 */
2039
2040         int controlbits;
2041
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");
2047
2048                                 if (cfsetispeed(&data->term, std_baudrates[i].index) < 0)
2049                                         RETURN_FAIL("cfsetispeed() failed");
2050                                 break;
2051                         }
2052                 }
2053
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
2066                 }
2067         }
2068
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");
2086                 }
2087         }
2088
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");
2121                 }
2122         }
2123
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");
2135                 }
2136         }
2137
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;
2153                         }
2154                         if (config->cts == SP_CTS_FLOW_CONTROL)
2155                                 data->cts_flow = 1;
2156
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");
2168                                 }
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");
2172                                 }
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");
2178                         }
2179
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");
2188                                 }
2189                         }
2190                 }
2191         }
2192
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;
2208                         }
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");
2215
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");
2221                         }
2222                 }
2223         }
2224
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");
2241                 }
2242         }
2243
2244         if (tcsetattr(port->fd, TCSANOW, &data->term) < 0)
2245                 RETURN_FAIL("tcsetattr() failed");
2246
2247 #ifdef __APPLE__
2248         if (baud_nonstd != B0) {
2249                 if (ioctl(port->fd, IOSSIOSPEED, &baud_nonstd) == -1)
2250                         RETURN_FAIL("IOSSIOSPEED ioctl failed");
2251                 /*
2252                  * Set baud rates in data->term to correct, but incompatible
2253                  * with tcsetattr() value, same as delivered by tcgetattr().
2254                  */
2255                 if (cfsetspeed(&data->term, baud_nonstd) < 0)
2256                         RETURN_FAIL("cfsetspeed() failed");
2257         }
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
2268
2269 #endif /* !_WIN32 */
2270
2271         RETURN_OK();
2272 }
2273
2274 SP_API enum sp_return sp_new_config(struct sp_port_config **config_ptr)
2275 {
2276         struct sp_port_config *config;
2277
2278         TRACE("%p", config_ptr);
2279
2280         if (!config_ptr)
2281                 RETURN_ERROR(SP_ERR_ARG, "Null result pointer");
2282
2283         *config_ptr = NULL;
2284
2285         if (!(config = malloc(sizeof(struct sp_port_config))))
2286                 RETURN_ERROR(SP_ERR_MEM, "Config malloc failed");
2287
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
2297         *config_ptr = config;
2298
2299         RETURN_OK();
2300 }
2301
2302 SP_API void sp_free_config(struct sp_port_config *config)
2303 {
2304         TRACE("%p", config);
2305
2306         if (!config)
2307                 DEBUG("Null config");
2308         else
2309                 free(config);
2310
2311         RETURN();
2312 }
2313
2314 SP_API enum sp_return sp_get_config(struct sp_port *port,
2315                                     struct sp_port_config *config)
2316 {
2317         struct port_data data;
2318
2319         TRACE("%p, %p", port, config);
2320
2321         CHECK_OPEN_PORT();
2322
2323         if (!config)
2324                 RETURN_ERROR(SP_ERR_ARG, "Null config");
2325
2326         TRY(get_config(port, &data, config));
2327
2328         RETURN_OK();
2329 }
2330
2331 SP_API enum sp_return sp_set_config(struct sp_port *port,
2332                                     const struct sp_port_config *config)
2333 {
2334         struct port_data data;
2335         struct sp_port_config prev_config;
2336
2337         TRACE("%p, %p", port, config);
2338
2339         CHECK_OPEN_PORT();
2340
2341         if (!config)
2342                 RETURN_ERROR(SP_ERR_ARG, "Null config");
2343
2344         TRY(get_config(port, &data, &prev_config));
2345         TRY(set_config(port, &data, config));
2346
2347         RETURN_OK();
2348 }
2349
2350 #define CREATE_ACCESSORS(x, type) \
2351 SP_API enum sp_return sp_set_##x(struct sp_port *port, type x) { \
2352         struct port_data data; \
2353         struct sp_port_config config; \
2354         TRACE("%p, %d", port, x); \
2355         CHECK_OPEN_PORT(); \
2356         TRY(get_config(port, &data, &config)); \
2357         config.x = x; \
2358         TRY(set_config(port, &data, &config)); \
2359         RETURN_OK(); \
2360 } \
2361 SP_API enum sp_return sp_get_config_##x(const struct sp_port_config *config, \
2362                                         type *x) { \
2363         TRACE("%p, %p", config, x); \
2364         if (!x) \
2365                 RETURN_ERROR(SP_ERR_ARG, "Null result pointer"); \
2366         if (!config) \
2367                 RETURN_ERROR(SP_ERR_ARG, "Null config"); \
2368         *x = config->x; \
2369         RETURN_OK(); \
2370 } \
2371 SP_API enum sp_return sp_set_config_##x(struct sp_port_config *config, \
2372                                         type x) { \
2373         TRACE("%p, %d", config, x); \
2374         if (!config) \
2375                 RETURN_ERROR(SP_ERR_ARG, "Null config"); \
2376         config->x = x; \
2377         RETURN_OK(); \
2378 }
2379
2380 CREATE_ACCESSORS(baudrate, int)
2381 CREATE_ACCESSORS(bits, int)
2382 CREATE_ACCESSORS(parity, enum sp_parity)
2383 CREATE_ACCESSORS(stopbits, int)
2384 CREATE_ACCESSORS(rts, enum sp_rts)
2385 CREATE_ACCESSORS(cts, enum sp_cts)
2386 CREATE_ACCESSORS(dtr, enum sp_dtr)
2387 CREATE_ACCESSORS(dsr, enum sp_dsr)
2388 CREATE_ACCESSORS(xon_xoff, enum sp_xonxoff)
2389
2390 SP_API enum sp_return sp_set_config_flowcontrol(struct sp_port_config *config,
2391                                                 enum sp_flowcontrol flowcontrol)
2392 {
2393         if (!config)
2394                 RETURN_ERROR(SP_ERR_ARG, "Null configuration");
2395
2396         if (flowcontrol > SP_FLOWCONTROL_DTRDSR)
2397                 RETURN_ERROR(SP_ERR_ARG, "Invalid flow control setting");
2398
2399         if (flowcontrol == SP_FLOWCONTROL_XONXOFF)
2400                 config->xon_xoff = SP_XONXOFF_INOUT;
2401         else
2402                 config->xon_xoff = SP_XONXOFF_DISABLED;
2403
2404         if (flowcontrol == SP_FLOWCONTROL_RTSCTS) {
2405                 config->rts = SP_RTS_FLOW_CONTROL;
2406                 config->cts = SP_CTS_FLOW_CONTROL;
2407         } else {
2408                 if (config->rts == SP_RTS_FLOW_CONTROL)
2409                         config->rts = SP_RTS_ON;
2410                 config->cts = SP_CTS_IGNORE;
2411         }
2412
2413         if (flowcontrol == SP_FLOWCONTROL_DTRDSR) {
2414                 config->dtr = SP_DTR_FLOW_CONTROL;
2415                 config->dsr = SP_DSR_FLOW_CONTROL;
2416         } else {
2417                 if (config->dtr == SP_DTR_FLOW_CONTROL)
2418                         config->dtr = SP_DTR_ON;
2419                 config->dsr = SP_DSR_IGNORE;
2420         }
2421
2422         RETURN_OK();
2423 }
2424
2425 SP_API enum sp_return sp_set_flowcontrol(struct sp_port *port,
2426                                          enum sp_flowcontrol flowcontrol)
2427 {
2428         struct port_data data;
2429         struct sp_port_config config;
2430
2431         TRACE("%p, %d", port, flowcontrol);
2432
2433         CHECK_OPEN_PORT();
2434
2435         TRY(get_config(port, &data, &config));
2436
2437         TRY(sp_set_config_flowcontrol(&config, flowcontrol));
2438
2439         TRY(set_config(port, &data, &config));
2440
2441         RETURN_OK();
2442 }
2443
2444 SP_API enum sp_return sp_get_signals(struct sp_port *port,
2445                                      enum sp_signal *signals)
2446 {
2447         TRACE("%p, %p", port, signals);
2448
2449         CHECK_OPEN_PORT();
2450
2451         if (!signals)
2452                 RETURN_ERROR(SP_ERR_ARG, "Null result pointer");
2453
2454         DEBUG_FMT("Getting control signals for port %s", port->name);
2455
2456         *signals = 0;
2457 #ifdef _WIN32
2458         DWORD bits;
2459         if (GetCommModemStatus(port->hdl, &bits) == 0)
2460                 RETURN_FAIL("GetCommModemStatus() failed");
2461         if (bits & MS_CTS_ON)
2462                 *signals |= SP_SIG_CTS;
2463         if (bits & MS_DSR_ON)
2464                 *signals |= SP_SIG_DSR;
2465         if (bits & MS_RLSD_ON)
2466                 *signals |= SP_SIG_DCD;
2467         if (bits & MS_RING_ON)
2468                 *signals |= SP_SIG_RI;
2469 #else
2470         int bits;
2471         if (ioctl(port->fd, TIOCMGET, &bits) < 0)
2472                 RETURN_FAIL("TIOCMGET ioctl failed");
2473         if (bits & TIOCM_CTS)
2474                 *signals |= SP_SIG_CTS;
2475         if (bits & TIOCM_DSR)
2476                 *signals |= SP_SIG_DSR;
2477         if (bits & TIOCM_CAR)
2478                 *signals |= SP_SIG_DCD;
2479         if (bits & TIOCM_RNG)
2480                 *signals |= SP_SIG_RI;
2481 #endif
2482         RETURN_OK();
2483 }
2484
2485 SP_API enum sp_return sp_start_break(struct sp_port *port)
2486 {
2487         TRACE("%p", port);
2488
2489         CHECK_OPEN_PORT();
2490 #ifdef _WIN32
2491         if (SetCommBreak(port->hdl) == 0)
2492                 RETURN_FAIL("SetCommBreak() failed");
2493 #else
2494         if (ioctl(port->fd, TIOCSBRK, 1) < 0)
2495                 RETURN_FAIL("TIOCSBRK ioctl failed");
2496 #endif
2497
2498         RETURN_OK();
2499 }
2500
2501 SP_API enum sp_return sp_end_break(struct sp_port *port)
2502 {
2503         TRACE("%p", port);
2504
2505         CHECK_OPEN_PORT();
2506 #ifdef _WIN32
2507         if (ClearCommBreak(port->hdl) == 0)
2508                 RETURN_FAIL("ClearCommBreak() failed");
2509 #else
2510         if (ioctl(port->fd, TIOCCBRK, 1) < 0)
2511                 RETURN_FAIL("TIOCCBRK ioctl failed");
2512 #endif
2513
2514         RETURN_OK();
2515 }
2516
2517 SP_API int sp_last_error_code(void)
2518 {
2519         TRACE_VOID();
2520 #ifdef _WIN32
2521         RETURN_INT(GetLastError());
2522 #else
2523         RETURN_INT(errno);
2524 #endif
2525 }
2526
2527 SP_API char *sp_last_error_message(void)
2528 {
2529         TRACE_VOID();
2530
2531 #ifdef _WIN32
2532         TCHAR *message;
2533         DWORD error = GetLastError();
2534
2535         DWORD length = FormatMessage(
2536                 FORMAT_MESSAGE_ALLOCATE_BUFFER |
2537                 FORMAT_MESSAGE_FROM_SYSTEM |
2538                 FORMAT_MESSAGE_IGNORE_INSERTS,
2539                 NULL,
2540                 error,
2541                 MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
2542                 (LPTSTR) &message,
2543                 0, NULL );
2544
2545         if (length >= 2 && message[length - 2] == '\r')
2546                 message[length - 2] = '\0';
2547
2548         RETURN_STRING(message);
2549 #else
2550         RETURN_STRING(strerror(errno));
2551 #endif
2552 }
2553
2554 SP_API void sp_free_error_message(char *message)
2555 {
2556         TRACE("%s", message);
2557
2558 #ifdef _WIN32
2559         LocalFree(message);
2560 #else
2561         (void)message;
2562 #endif
2563
2564         RETURN();
2565 }
2566
2567 SP_API void sp_set_debug_handler(void (*handler)(const char *format, ...))
2568 {
2569         TRACE("%p", handler);
2570
2571         sp_debug_handler = handler;
2572
2573         RETURN();
2574 }
2575
2576 SP_API void sp_default_debug_handler(const char *format, ...)
2577 {
2578         va_list args;
2579         va_start(args, format);
2580         if (getenv("LIBSERIALPORT_DEBUG")) {
2581                 fputs("sp: ", stderr);
2582                 vfprintf(stderr, format, args);
2583         }
2584         va_end(args);
2585 }
2586
2587 SP_API int sp_get_major_package_version(void)
2588 {
2589         return SP_PACKAGE_VERSION_MAJOR;
2590 }
2591
2592 SP_API int sp_get_minor_package_version(void)
2593 {
2594         return SP_PACKAGE_VERSION_MINOR;
2595 }
2596
2597 SP_API int sp_get_micro_package_version(void)
2598 {
2599         return SP_PACKAGE_VERSION_MICRO;
2600 }
2601
2602 SP_API const char *sp_get_package_version_string(void)
2603 {
2604         return SP_PACKAGE_VERSION_STRING;
2605 }
2606
2607 SP_API int sp_get_current_lib_version(void)
2608 {
2609         return SP_LIB_VERSION_CURRENT;
2610 }
2611
2612 SP_API int sp_get_revision_lib_version(void)
2613 {
2614         return SP_LIB_VERSION_REVISION;
2615 }
2616
2617 SP_API int sp_get_age_lib_version(void)
2618 {
2619         return SP_LIB_VERSION_AGE;
2620 }
2621
2622 SP_API const char *sp_get_lib_version_string(void)
2623 {
2624         return SP_LIB_VERSION_STRING;
2625 }
2626
2627 /** @} */