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