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