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