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