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