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