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