]> sigrok.org Git - libserialport.git/blob - serialport.c
Change debug message to "Port not open" when a closed port is used.
[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, "Port not open"); \
393 } while (0)
394 #else
395 #define CHECK_PORT_HANDLE() do { \
396         if (port->fd < 0) \
397                 RETURN_ERROR(SP_ERR_ARG, "Port not open"); \
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                 if (GetLastError() != ERROR_IO_PENDING)
1238                         RETURN_FAIL("ReadFile() failed");
1239
1240         /* Get number of bytes read. */
1241         if (GetOverlappedResult(port->hdl, &port->read_ovl, &bytes_read, FALSE) == 0)
1242                 RETURN_FAIL("GetOverlappedResult() failed");
1243
1244         TRY(restart_wait_if_needed(port, bytes_read));
1245
1246         RETURN_INT(bytes_read);
1247 #else
1248         ssize_t bytes_read;
1249
1250         /* Returns the number of bytes read, or -1 upon failure. */
1251         if ((bytes_read = read(port->fd, buf, count)) < 0) {
1252                 if (errno == EAGAIN)
1253                         /* No bytes available. */
1254                         bytes_read = 0;
1255                 else
1256                         /* This is an actual failure. */
1257                         RETURN_FAIL("read() failed");
1258         }
1259         RETURN_INT(bytes_read);
1260 #endif
1261 }
1262
1263 SP_API enum sp_return sp_input_waiting(struct sp_port *port)
1264 {
1265         TRACE("%p", port);
1266
1267         CHECK_OPEN_PORT();
1268
1269         DEBUG_FMT("Checking input bytes waiting on port %s", port->name);
1270
1271 #ifdef _WIN32
1272         DWORD errors;
1273         COMSTAT comstat;
1274
1275         if (ClearCommError(port->hdl, &errors, &comstat) == 0)
1276                 RETURN_FAIL("ClearCommError() failed");
1277         RETURN_INT(comstat.cbInQue);
1278 #else
1279         int bytes_waiting;
1280         if (ioctl(port->fd, TIOCINQ, &bytes_waiting) < 0)
1281                 RETURN_FAIL("TIOCINQ ioctl failed");
1282         RETURN_INT(bytes_waiting);
1283 #endif
1284 }
1285
1286 SP_API enum sp_return sp_output_waiting(struct sp_port *port)
1287 {
1288         TRACE("%p", port);
1289
1290         CHECK_OPEN_PORT();
1291
1292         DEBUG_FMT("Checking output bytes waiting on port %s", port->name);
1293
1294 #ifdef _WIN32
1295         DWORD errors;
1296         COMSTAT comstat;
1297
1298         if (ClearCommError(port->hdl, &errors, &comstat) == 0)
1299                 RETURN_FAIL("ClearCommError() failed");
1300         RETURN_INT(comstat.cbOutQue);
1301 #else
1302         int bytes_waiting;
1303         if (ioctl(port->fd, TIOCOUTQ, &bytes_waiting) < 0)
1304                 RETURN_FAIL("TIOCOUTQ ioctl failed");
1305         RETURN_INT(bytes_waiting);
1306 #endif
1307 }
1308
1309 SP_API enum sp_return sp_new_event_set(struct sp_event_set **result_ptr)
1310 {
1311         struct sp_event_set *result;
1312
1313         TRACE("%p", result_ptr);
1314
1315         if (!result_ptr)
1316                 RETURN_ERROR(SP_ERR_ARG, "Null result");
1317
1318         *result_ptr = NULL;
1319
1320         if (!(result = malloc(sizeof(struct sp_event_set))))
1321                 RETURN_ERROR(SP_ERR_MEM, "sp_event_set malloc() failed");
1322
1323         memset(result, 0, sizeof(struct sp_event_set));
1324
1325         *result_ptr = result;
1326
1327         RETURN_OK();
1328 }
1329
1330 static enum sp_return add_handle(struct sp_event_set *event_set,
1331                 event_handle handle, enum sp_event mask)
1332 {
1333         void *new_handles;
1334         enum sp_event *new_masks;
1335
1336         TRACE("%p, %d, %d", event_set, handle, mask);
1337
1338         if (!(new_handles = realloc(event_set->handles,
1339                         sizeof(event_handle) * (event_set->count + 1))))
1340                 RETURN_ERROR(SP_ERR_MEM, "Handle array realloc() failed");
1341
1342         event_set->handles = new_handles;
1343
1344         if (!(new_masks = realloc(event_set->masks,
1345                         sizeof(enum sp_event) * (event_set->count + 1))))
1346                 RETURN_ERROR(SP_ERR_MEM, "Mask array realloc() failed");
1347
1348         event_set->masks = new_masks;
1349
1350         ((event_handle *) event_set->handles)[event_set->count] = handle;
1351         event_set->masks[event_set->count] = mask;
1352
1353         event_set->count++;
1354
1355         RETURN_OK();
1356 }
1357
1358 SP_API enum sp_return sp_add_port_events(struct sp_event_set *event_set,
1359         const struct sp_port *port, enum sp_event mask)
1360 {
1361         TRACE("%p, %p, %d", event_set, port, mask);
1362
1363         if (!event_set)
1364                 RETURN_ERROR(SP_ERR_ARG, "Null event set");
1365
1366         if (!port)
1367                 RETURN_ERROR(SP_ERR_ARG, "Null port");
1368
1369         if (mask > (SP_EVENT_RX_READY | SP_EVENT_TX_READY | SP_EVENT_ERROR))
1370                 RETURN_ERROR(SP_ERR_ARG, "Invalid event mask");
1371
1372         if (!mask)
1373                 RETURN_OK();
1374
1375 #ifdef _WIN32
1376         enum sp_event handle_mask;
1377         if ((handle_mask = mask & SP_EVENT_TX_READY))
1378                 TRY(add_handle(event_set, port->write_ovl.hEvent, handle_mask));
1379         if ((handle_mask = mask & (SP_EVENT_RX_READY | SP_EVENT_ERROR)))
1380                 TRY(add_handle(event_set, port->wait_ovl.hEvent, handle_mask));
1381 #else
1382         TRY(add_handle(event_set, port->fd, mask));
1383 #endif
1384
1385         RETURN_OK();
1386 }
1387
1388 SP_API void sp_free_event_set(struct sp_event_set *event_set)
1389 {
1390         TRACE("%p", event_set);
1391
1392         if (!event_set) {
1393                 DEBUG("Null event set");
1394                 RETURN();
1395         }
1396
1397         DEBUG("Freeing event set");
1398
1399         if (event_set->handles)
1400                 free(event_set->handles);
1401         if (event_set->masks)
1402                 free(event_set->masks);
1403
1404         free(event_set);
1405
1406         RETURN();
1407 }
1408
1409 SP_API enum sp_return sp_wait(struct sp_event_set *event_set,
1410                               unsigned int timeout_ms)
1411 {
1412         TRACE("%p, %d", event_set, timeout_ms);
1413
1414         if (!event_set)
1415                 RETURN_ERROR(SP_ERR_ARG, "Null event set");
1416
1417 #ifdef _WIN32
1418         if (WaitForMultipleObjects(event_set->count, event_set->handles, FALSE,
1419                         timeout_ms ? timeout_ms : INFINITE) == WAIT_FAILED)
1420                 RETURN_FAIL("WaitForMultipleObjects() failed");
1421
1422         RETURN_OK();
1423 #else
1424         struct timeval start, delta, now, end = {0, 0};
1425         const struct timeval max_delta = {
1426                 (INT_MAX / 1000), (INT_MAX % 1000) * 1000};
1427         int started = 0, timeout_overflow = 0;
1428         int result, timeout_remaining_ms;
1429         struct pollfd *pollfds;
1430         unsigned int i;
1431
1432         if (!(pollfds = malloc(sizeof(struct pollfd) * event_set->count)))
1433                 RETURN_ERROR(SP_ERR_MEM, "pollfds malloc() failed");
1434
1435         for (i = 0; i < event_set->count; i++) {
1436                 pollfds[i].fd = ((int *) event_set->handles)[i];
1437                 pollfds[i].events = 0;
1438                 pollfds[i].revents = 0;
1439                 if (event_set->masks[i] & SP_EVENT_RX_READY)
1440                         pollfds[i].events |= POLLIN;
1441                 if (event_set->masks[i] & SP_EVENT_TX_READY)
1442                         pollfds[i].events |= POLLOUT;
1443                 if (event_set->masks[i] & SP_EVENT_ERROR)
1444                         pollfds[i].events |= POLLERR;
1445         }
1446
1447         if (timeout_ms) {
1448                 /* Get time at start of operation. */
1449                 gettimeofday(&start, NULL);
1450                 /* Define duration of timeout. */
1451                 delta.tv_sec = timeout_ms / 1000;
1452                 delta.tv_usec = (timeout_ms % 1000) * 1000;
1453                 /* Calculate time at which we should give up. */
1454                 timeradd(&start, &delta, &end);
1455         }
1456
1457         /* Loop until an event occurs. */
1458         while (1) {
1459                 /*
1460                  * Check timeout only if we have run poll() at least once,
1461                  * to avoid any issues if a short timeout is reached before
1462                  * poll() is even run.
1463                  */
1464                 if (!timeout_ms) {
1465                         timeout_remaining_ms = -1;
1466                 } else if (!started) {
1467                         timeout_overflow = (timeout_ms > INT_MAX);
1468                         timeout_remaining_ms = timeout_overflow ? INT_MAX : timeout_ms;
1469                 } else {
1470                         gettimeofday(&now, NULL);
1471                         if (timercmp(&now, &end, >)) {
1472                                 DEBUG("Wait timed out");
1473                                 break;
1474                         }
1475                         timersub(&end, &now, &delta);
1476                         if ((timeout_overflow = timercmp(&delta, &max_delta, >)))
1477                                 delta = max_delta;
1478                         timeout_remaining_ms = delta.tv_sec * 1000 + delta.tv_usec / 1000;
1479                 }
1480
1481                 result = poll(pollfds, event_set->count, timeout_remaining_ms);
1482                 started = 1;
1483
1484                 if (result < 0) {
1485                         if (errno == EINTR) {
1486                                 DEBUG("poll() call was interrupted, repeating");
1487                                 continue;
1488                         } else {
1489                                 free(pollfds);
1490                                 RETURN_FAIL("poll() failed");
1491                         }
1492                 } else if (result == 0) {
1493                         DEBUG("poll() timed out");
1494                         if (!timeout_overflow)
1495                                 break;
1496                 } else {
1497                         DEBUG("poll() completed");
1498                         break;
1499                 }
1500         }
1501
1502         free(pollfds);
1503         RETURN_OK();
1504 #endif
1505 }
1506
1507 #ifdef USE_TERMIOS_SPEED
1508 static enum sp_return get_baudrate(int fd, int *baudrate)
1509 {
1510         void *data;
1511
1512         TRACE("%d, %p", fd, baudrate);
1513
1514         DEBUG("Getting baud rate");
1515
1516         if (!(data = malloc(get_termios_size())))
1517                 RETURN_ERROR(SP_ERR_MEM, "termios malloc failed");
1518
1519         if (ioctl(fd, get_termios_get_ioctl(), data) < 0) {
1520                 free(data);
1521                 RETURN_FAIL("Getting termios failed");
1522         }
1523
1524         *baudrate = get_termios_speed(data);
1525
1526         free(data);
1527
1528         RETURN_OK();
1529 }
1530
1531 static enum sp_return set_baudrate(int fd, int baudrate)
1532 {
1533         void *data;
1534
1535         TRACE("%d, %d", fd, baudrate);
1536
1537         DEBUG("Getting baud rate");
1538
1539         if (!(data = malloc(get_termios_size())))
1540                 RETURN_ERROR(SP_ERR_MEM, "termios malloc failed");
1541
1542         if (ioctl(fd, get_termios_get_ioctl(), data) < 0) {
1543                 free(data);
1544                 RETURN_FAIL("Getting termios failed");
1545         }
1546
1547         DEBUG("Setting baud rate");
1548
1549         set_termios_speed(data, baudrate);
1550
1551         if (ioctl(fd, get_termios_set_ioctl(), data) < 0) {
1552                 free(data);
1553                 RETURN_FAIL("Setting termios failed");
1554         }
1555
1556         free(data);
1557
1558         RETURN_OK();
1559 }
1560 #endif /* USE_TERMIOS_SPEED */
1561
1562 #ifdef USE_TERMIOX
1563 static enum sp_return get_flow(int fd, struct port_data *data)
1564 {
1565         void *termx;
1566
1567         TRACE("%d, %p", fd, data);
1568
1569         DEBUG("Getting advanced flow control");
1570
1571         if (!(termx = malloc(get_termiox_size())))
1572                 RETURN_ERROR(SP_ERR_MEM, "termiox malloc failed");
1573
1574         if (ioctl(fd, TCGETX, termx) < 0) {
1575                 free(termx);
1576                 RETURN_FAIL("Getting termiox failed");
1577         }
1578
1579         get_termiox_flow(termx, &data->rts_flow, &data->cts_flow,
1580                         &data->dtr_flow, &data->dsr_flow);
1581
1582         free(termx);
1583
1584         RETURN_OK();
1585 }
1586
1587 static enum sp_return set_flow(int fd, struct port_data *data)
1588 {
1589         void *termx;
1590
1591         TRACE("%d, %p", fd, data);
1592
1593         DEBUG("Getting advanced flow control");
1594
1595         if (!(termx = malloc(get_termiox_size())))
1596                 RETURN_ERROR(SP_ERR_MEM, "termiox malloc failed");
1597
1598         if (ioctl(fd, TCGETX, termx) < 0) {
1599                 free(termx);
1600                 RETURN_FAIL("Getting termiox failed");
1601         }
1602
1603         DEBUG("Setting advanced flow control");
1604
1605         set_termiox_flow(termx, data->rts_flow, data->cts_flow,
1606                         data->dtr_flow, data->dsr_flow);
1607
1608         if (ioctl(fd, TCSETX, termx) < 0) {
1609                 free(termx);
1610                 RETURN_FAIL("Setting termiox failed");
1611         }
1612
1613         free(termx);
1614
1615         RETURN_OK();
1616 }
1617 #endif /* USE_TERMIOX */
1618
1619 static enum sp_return get_config(struct sp_port *port, struct port_data *data,
1620         struct sp_port_config *config)
1621 {
1622         unsigned int i;
1623
1624         TRACE("%p, %p, %p", port, data, config);
1625
1626         DEBUG_FMT("Getting configuration for port %s", port->name);
1627
1628 #ifdef _WIN32
1629         if (!GetCommState(port->hdl, &data->dcb))
1630                 RETURN_FAIL("GetCommState() failed");
1631
1632         for (i = 0; i < NUM_STD_BAUDRATES; i++) {
1633                 if (data->dcb.BaudRate == std_baudrates[i].index) {
1634                         config->baudrate = std_baudrates[i].value;
1635                         break;
1636                 }
1637         }
1638
1639         if (i == NUM_STD_BAUDRATES)
1640                 /* BaudRate field can be either an index or a custom baud rate. */
1641                 config->baudrate = data->dcb.BaudRate;
1642
1643         config->bits = data->dcb.ByteSize;
1644
1645         if (data->dcb.fParity)
1646                 switch (data->dcb.Parity) {
1647                 case NOPARITY:
1648                         config->parity = SP_PARITY_NONE;
1649                         break;
1650                 case ODDPARITY:
1651                         config->parity = SP_PARITY_ODD;
1652                         break;
1653                 case EVENPARITY:
1654                         config->parity = SP_PARITY_EVEN;
1655                         break;
1656                 case MARKPARITY:
1657                         config->parity = SP_PARITY_MARK;
1658                         break;
1659                 case SPACEPARITY:
1660                         config->parity = SP_PARITY_SPACE;
1661                         break;
1662                 default:
1663                         config->parity = -1;
1664                 }
1665         else
1666                 config->parity = SP_PARITY_NONE;
1667
1668         switch (data->dcb.StopBits) {
1669         case ONESTOPBIT:
1670                 config->stopbits = 1;
1671                 break;
1672         case TWOSTOPBITS:
1673                 config->stopbits = 2;
1674                 break;
1675         default:
1676                 config->stopbits = -1;
1677         }
1678
1679         switch (data->dcb.fRtsControl) {
1680         case RTS_CONTROL_DISABLE:
1681                 config->rts = SP_RTS_OFF;
1682                 break;
1683         case RTS_CONTROL_ENABLE:
1684                 config->rts = SP_RTS_ON;
1685                 break;
1686         case RTS_CONTROL_HANDSHAKE:
1687                 config->rts = SP_RTS_FLOW_CONTROL;
1688                 break;
1689         default:
1690                 config->rts = -1;
1691         }
1692
1693         config->cts = data->dcb.fOutxCtsFlow ? SP_CTS_FLOW_CONTROL : SP_CTS_IGNORE;
1694
1695         switch (data->dcb.fDtrControl) {
1696         case DTR_CONTROL_DISABLE:
1697                 config->dtr = SP_DTR_OFF;
1698                 break;
1699         case DTR_CONTROL_ENABLE:
1700                 config->dtr = SP_DTR_ON;
1701                 break;
1702         case DTR_CONTROL_HANDSHAKE:
1703                 config->dtr = SP_DTR_FLOW_CONTROL;
1704                 break;
1705         default:
1706                 config->dtr = -1;
1707         }
1708
1709         config->dsr = data->dcb.fOutxDsrFlow ? SP_DSR_FLOW_CONTROL : SP_DSR_IGNORE;
1710
1711         if (data->dcb.fInX) {
1712                 if (data->dcb.fOutX)
1713                         config->xon_xoff = SP_XONXOFF_INOUT;
1714                 else
1715                         config->xon_xoff = SP_XONXOFF_IN;
1716         } else {
1717                 if (data->dcb.fOutX)
1718                         config->xon_xoff = SP_XONXOFF_OUT;
1719                 else
1720                         config->xon_xoff = SP_XONXOFF_DISABLED;
1721         }
1722
1723 #else // !_WIN32
1724
1725         if (tcgetattr(port->fd, &data->term) < 0)
1726                 RETURN_FAIL("tcgetattr() failed");
1727
1728         if (ioctl(port->fd, TIOCMGET, &data->controlbits) < 0)
1729                 RETURN_FAIL("TIOCMGET ioctl failed");
1730
1731 #ifdef USE_TERMIOX
1732         int ret = get_flow(port->fd, data);
1733
1734         if (ret == SP_ERR_FAIL && errno == EINVAL)
1735                 data->termiox_supported = 0;
1736         else if (ret < 0)
1737                 RETURN_CODEVAL(ret);
1738         else
1739                 data->termiox_supported = 1;
1740 #else
1741         data->termiox_supported = 0;
1742 #endif
1743
1744         for (i = 0; i < NUM_STD_BAUDRATES; i++) {
1745                 if (cfgetispeed(&data->term) == std_baudrates[i].index) {
1746                         config->baudrate = std_baudrates[i].value;
1747                         break;
1748                 }
1749         }
1750
1751         if (i == NUM_STD_BAUDRATES) {
1752 #ifdef __APPLE__
1753                 config->baudrate = (int)data->term.c_ispeed;
1754 #elif defined(USE_TERMIOS_SPEED)
1755                 TRY(get_baudrate(port->fd, &config->baudrate));
1756 #else
1757                 config->baudrate = -1;
1758 #endif
1759         }
1760
1761         switch (data->term.c_cflag & CSIZE) {
1762         case CS8:
1763                 config->bits = 8;
1764                 break;
1765         case CS7:
1766                 config->bits = 7;
1767                 break;
1768         case CS6:
1769                 config->bits = 6;
1770                 break;
1771         case CS5:
1772                 config->bits = 5;
1773                 break;
1774         default:
1775                 config->bits = -1;
1776         }
1777
1778         if (!(data->term.c_cflag & PARENB) && (data->term.c_iflag & IGNPAR))
1779                 config->parity = SP_PARITY_NONE;
1780         else if (!(data->term.c_cflag & PARENB) || (data->term.c_iflag & IGNPAR))
1781                 config->parity = -1;
1782 #ifdef CMSPAR
1783         else if (data->term.c_cflag & CMSPAR)
1784                 config->parity = (data->term.c_cflag & PARODD) ? SP_PARITY_MARK : SP_PARITY_SPACE;
1785 #endif
1786         else
1787                 config->parity = (data->term.c_cflag & PARODD) ? SP_PARITY_ODD : SP_PARITY_EVEN;
1788
1789         config->stopbits = (data->term.c_cflag & CSTOPB) ? 2 : 1;
1790
1791         if (data->term.c_cflag & CRTSCTS) {
1792                 config->rts = SP_RTS_FLOW_CONTROL;
1793                 config->cts = SP_CTS_FLOW_CONTROL;
1794         } else {
1795                 if (data->termiox_supported && data->rts_flow)
1796                         config->rts = SP_RTS_FLOW_CONTROL;
1797                 else
1798                         config->rts = (data->controlbits & TIOCM_RTS) ? SP_RTS_ON : SP_RTS_OFF;
1799
1800                 config->cts = (data->termiox_supported && data->cts_flow) ?
1801                         SP_CTS_FLOW_CONTROL : SP_CTS_IGNORE;
1802         }
1803
1804         if (data->termiox_supported && data->dtr_flow)
1805                 config->dtr = SP_DTR_FLOW_CONTROL;
1806         else
1807                 config->dtr = (data->controlbits & TIOCM_DTR) ? SP_DTR_ON : SP_DTR_OFF;
1808
1809         config->dsr = (data->termiox_supported && data->dsr_flow) ?
1810                 SP_DSR_FLOW_CONTROL : SP_DSR_IGNORE;
1811
1812         if (data->term.c_iflag & IXOFF) {
1813                 if (data->term.c_iflag & IXON)
1814                         config->xon_xoff = SP_XONXOFF_INOUT;
1815                 else
1816                         config->xon_xoff = SP_XONXOFF_IN;
1817         } else {
1818                 if (data->term.c_iflag & IXON)
1819                         config->xon_xoff = SP_XONXOFF_OUT;
1820                 else
1821                         config->xon_xoff = SP_XONXOFF_DISABLED;
1822         }
1823 #endif
1824
1825         RETURN_OK();
1826 }
1827
1828 static enum sp_return set_config(struct sp_port *port, struct port_data *data,
1829         const struct sp_port_config *config)
1830 {
1831         unsigned int i;
1832 #ifdef __APPLE__
1833         BAUD_TYPE baud_nonstd;
1834
1835         baud_nonstd = B0;
1836 #endif
1837 #ifdef USE_TERMIOS_SPEED
1838         int baud_nonstd = 0;
1839 #endif
1840
1841         TRACE("%p, %p, %p", port, data, config);
1842
1843         DEBUG_FMT("Setting configuration for port %s", port->name);
1844
1845 #ifdef _WIN32
1846         if (config->baudrate >= 0) {
1847                 for (i = 0; i < NUM_STD_BAUDRATES; i++) {
1848                         if (config->baudrate == std_baudrates[i].value) {
1849                                 data->dcb.BaudRate = std_baudrates[i].index;
1850                                 break;
1851                         }
1852                 }
1853
1854                 if (i == NUM_STD_BAUDRATES)
1855                         data->dcb.BaudRate = config->baudrate;
1856         }
1857
1858         if (config->bits >= 0)
1859                 data->dcb.ByteSize = config->bits;
1860
1861         if (config->parity >= 0) {
1862                 switch (config->parity) {
1863                 case SP_PARITY_NONE:
1864                         data->dcb.Parity = NOPARITY;
1865                         break;
1866                 case SP_PARITY_ODD:
1867                         data->dcb.Parity = ODDPARITY;
1868                         break;
1869                 case SP_PARITY_EVEN:
1870                         data->dcb.Parity = EVENPARITY;
1871                         break;
1872                 case SP_PARITY_MARK:
1873                         data->dcb.Parity = MARKPARITY;
1874                         break;
1875                 case SP_PARITY_SPACE:
1876                         data->dcb.Parity = SPACEPARITY;
1877                         break;
1878                 default:
1879                         RETURN_ERROR(SP_ERR_ARG, "Invalid parity setting");
1880                 }
1881         }
1882
1883         if (config->stopbits >= 0) {
1884                 switch (config->stopbits) {
1885                 /* Note: There's also ONE5STOPBITS == 1.5 (unneeded so far). */
1886                 case 1:
1887                         data->dcb.StopBits = ONESTOPBIT;
1888                         break;
1889                 case 2:
1890                         data->dcb.StopBits = TWOSTOPBITS;
1891                         break;
1892                 default:
1893                         RETURN_ERROR(SP_ERR_ARG, "Invalid stop bit setting");
1894                 }
1895         }
1896
1897         if (config->rts >= 0) {
1898                 switch (config->rts) {
1899                 case SP_RTS_OFF:
1900                         data->dcb.fRtsControl = RTS_CONTROL_DISABLE;
1901                         break;
1902                 case SP_RTS_ON:
1903                         data->dcb.fRtsControl = RTS_CONTROL_ENABLE;
1904                         break;
1905                 case SP_RTS_FLOW_CONTROL:
1906                         data->dcb.fRtsControl = RTS_CONTROL_HANDSHAKE;
1907                         break;
1908                 default:
1909                         RETURN_ERROR(SP_ERR_ARG, "Invalid RTS setting");
1910                 }
1911         }
1912
1913         if (config->cts >= 0) {
1914                 switch (config->cts) {
1915                 case SP_CTS_IGNORE:
1916                         data->dcb.fOutxCtsFlow = FALSE;
1917                         break;
1918                 case SP_CTS_FLOW_CONTROL:
1919                         data->dcb.fOutxCtsFlow = TRUE;
1920                         break;
1921                 default:
1922                         RETURN_ERROR(SP_ERR_ARG, "Invalid CTS setting");
1923                 }
1924         }
1925
1926         if (config->dtr >= 0) {
1927                 switch (config->dtr) {
1928                 case SP_DTR_OFF:
1929                         data->dcb.fDtrControl = DTR_CONTROL_DISABLE;
1930                         break;
1931                 case SP_DTR_ON:
1932                         data->dcb.fDtrControl = DTR_CONTROL_ENABLE;
1933                         break;
1934                 case SP_DTR_FLOW_CONTROL:
1935                         data->dcb.fDtrControl = DTR_CONTROL_HANDSHAKE;
1936                         break;
1937                 default:
1938                         RETURN_ERROR(SP_ERR_ARG, "Invalid DTR setting");
1939                 }
1940         }
1941
1942         if (config->dsr >= 0) {
1943                 switch (config->dsr) {
1944                 case SP_DSR_IGNORE:
1945                         data->dcb.fOutxDsrFlow = FALSE;
1946                         break;
1947                 case SP_DSR_FLOW_CONTROL:
1948                         data->dcb.fOutxDsrFlow = TRUE;
1949                         break;
1950                 default:
1951                         RETURN_ERROR(SP_ERR_ARG, "Invalid DSR setting");
1952                 }
1953         }
1954
1955         if (config->xon_xoff >= 0) {
1956                 switch (config->xon_xoff) {
1957                 case SP_XONXOFF_DISABLED:
1958                         data->dcb.fInX = FALSE;
1959                         data->dcb.fOutX = FALSE;
1960                         break;
1961                 case SP_XONXOFF_IN:
1962                         data->dcb.fInX = TRUE;
1963                         data->dcb.fOutX = FALSE;
1964                         break;
1965                 case SP_XONXOFF_OUT:
1966                         data->dcb.fInX = FALSE;
1967                         data->dcb.fOutX = TRUE;
1968                         break;
1969                 case SP_XONXOFF_INOUT:
1970                         data->dcb.fInX = TRUE;
1971                         data->dcb.fOutX = TRUE;
1972                         break;
1973                 default:
1974                         RETURN_ERROR(SP_ERR_ARG, "Invalid XON/XOFF setting");
1975                 }
1976         }
1977
1978         if (!SetCommState(port->hdl, &data->dcb))
1979                 RETURN_FAIL("SetCommState() failed");
1980
1981 #else /* !_WIN32 */
1982
1983         int controlbits;
1984
1985         if (config->baudrate >= 0) {
1986                 for (i = 0; i < NUM_STD_BAUDRATES; i++) {
1987                         if (config->baudrate == std_baudrates[i].value) {
1988                                 if (cfsetospeed(&data->term, std_baudrates[i].index) < 0)
1989                                         RETURN_FAIL("cfsetospeed() failed");
1990
1991                                 if (cfsetispeed(&data->term, std_baudrates[i].index) < 0)
1992                                         RETURN_FAIL("cfsetispeed() failed");
1993                                 break;
1994                         }
1995                 }
1996
1997                 /* Non-standard baud rate */
1998                 if (i == NUM_STD_BAUDRATES) {
1999 #ifdef __APPLE__
2000                         /* Set "dummy" baud rate. */
2001                         if (cfsetspeed(&data->term, B9600) < 0)
2002                                 RETURN_FAIL("cfsetspeed() failed");
2003                         baud_nonstd = config->baudrate;
2004 #elif defined(USE_TERMIOS_SPEED)
2005                         baud_nonstd = 1;
2006 #else
2007                         RETURN_ERROR(SP_ERR_SUPP, "Non-standard baudrate not supported");
2008 #endif
2009                 }
2010         }
2011
2012         if (config->bits >= 0) {
2013                 data->term.c_cflag &= ~CSIZE;
2014                 switch (config->bits) {
2015                 case 8:
2016                         data->term.c_cflag |= CS8;
2017                         break;
2018                 case 7:
2019                         data->term.c_cflag |= CS7;
2020                         break;
2021                 case 6:
2022                         data->term.c_cflag |= CS6;
2023                         break;
2024                 case 5:
2025                         data->term.c_cflag |= CS5;
2026                         break;
2027                 default:
2028                         RETURN_ERROR(SP_ERR_ARG, "Invalid data bits setting");
2029                 }
2030         }
2031
2032         if (config->parity >= 0) {
2033                 data->term.c_iflag &= ~IGNPAR;
2034                 data->term.c_cflag &= ~(PARENB | PARODD);
2035 #ifdef CMSPAR
2036                 data->term.c_cflag &= ~CMSPAR;
2037 #endif
2038                 switch (config->parity) {
2039                 case SP_PARITY_NONE:
2040                         data->term.c_iflag |= IGNPAR;
2041                         break;
2042                 case SP_PARITY_EVEN:
2043                         data->term.c_cflag |= PARENB;
2044                         break;
2045                 case SP_PARITY_ODD:
2046                         data->term.c_cflag |= PARENB | PARODD;
2047                         break;
2048 #ifdef CMSPAR
2049                 case SP_PARITY_MARK:
2050                         data->term.c_cflag |= PARENB | PARODD;
2051                         data->term.c_cflag |= CMSPAR;
2052                         break;
2053                 case SP_PARITY_SPACE:
2054                         data->term.c_cflag |= PARENB;
2055                         data->term.c_cflag |= CMSPAR;
2056                         break;
2057 #else
2058                 case SP_PARITY_MARK:
2059                 case SP_PARITY_SPACE:
2060                         RETURN_ERROR(SP_ERR_SUPP, "Mark/space parity not supported");
2061 #endif
2062                 default:
2063                         RETURN_ERROR(SP_ERR_ARG, "Invalid parity setting");
2064                 }
2065         }
2066
2067         if (config->stopbits >= 0) {
2068                 data->term.c_cflag &= ~CSTOPB;
2069                 switch (config->stopbits) {
2070                 case 1:
2071                         data->term.c_cflag &= ~CSTOPB;
2072                         break;
2073                 case 2:
2074                         data->term.c_cflag |= CSTOPB;
2075                         break;
2076                 default:
2077                         RETURN_ERROR(SP_ERR_ARG, "Invalid stop bits setting");
2078                 }
2079         }
2080
2081         if (config->rts >= 0 || config->cts >= 0) {
2082                 if (data->termiox_supported) {
2083                         data->rts_flow = data->cts_flow = 0;
2084                         switch (config->rts) {
2085                         case SP_RTS_OFF:
2086                         case SP_RTS_ON:
2087                                 controlbits = TIOCM_RTS;
2088                                 if (ioctl(port->fd, config->rts == SP_RTS_ON ? TIOCMBIS : TIOCMBIC, &controlbits) < 0)
2089                                         RETURN_FAIL("Setting RTS signal level failed");
2090                                 break;
2091                         case SP_RTS_FLOW_CONTROL:
2092                                 data->rts_flow = 1;
2093                                 break;
2094                         default:
2095                                 break;
2096                         }
2097                         if (config->cts == SP_CTS_FLOW_CONTROL)
2098                                 data->cts_flow = 1;
2099
2100                         if (data->rts_flow && data->cts_flow)
2101                                 data->term.c_iflag |= CRTSCTS;
2102                         else
2103                                 data->term.c_iflag &= ~CRTSCTS;
2104                 } else {
2105                         /* Asymmetric use of RTS/CTS not supported. */
2106                         if (data->term.c_iflag & CRTSCTS) {
2107                                 /* Flow control can only be disabled for both RTS & CTS together. */
2108                                 if (config->rts >= 0 && config->rts != SP_RTS_FLOW_CONTROL) {
2109                                         if (config->cts != SP_CTS_IGNORE)
2110                                                 RETURN_ERROR(SP_ERR_SUPP, "RTS & CTS flow control must be disabled together");
2111                                 }
2112                                 if (config->cts >= 0 && config->cts != SP_CTS_FLOW_CONTROL) {
2113                                         if (config->rts <= 0 || config->rts == SP_RTS_FLOW_CONTROL)
2114                                                 RETURN_ERROR(SP_ERR_SUPP, "RTS & CTS flow control must be disabled together");
2115                                 }
2116                         } else {
2117                                 /* Flow control can only be enabled for both RTS & CTS together. */
2118                                 if (((config->rts == SP_RTS_FLOW_CONTROL) && (config->cts != SP_CTS_FLOW_CONTROL)) ||
2119                                         ((config->cts == SP_CTS_FLOW_CONTROL) && (config->rts != SP_RTS_FLOW_CONTROL)))
2120                                         RETURN_ERROR(SP_ERR_SUPP, "RTS & CTS flow control must be enabled together");
2121                         }
2122
2123                         if (config->rts >= 0) {
2124                                 if (config->rts == SP_RTS_FLOW_CONTROL) {
2125                                         data->term.c_iflag |= CRTSCTS;
2126                                 } else {
2127                                         controlbits = TIOCM_RTS;
2128                                         if (ioctl(port->fd, config->rts == SP_RTS_ON ? TIOCMBIS : TIOCMBIC,
2129                                                         &controlbits) < 0)
2130                                                 RETURN_FAIL("Setting RTS signal level failed");
2131                                 }
2132                         }
2133                 }
2134         }
2135
2136         if (config->dtr >= 0 || config->dsr >= 0) {
2137                 if (data->termiox_supported) {
2138                         data->dtr_flow = data->dsr_flow = 0;
2139                         switch (config->dtr) {
2140                         case SP_DTR_OFF:
2141                         case SP_DTR_ON:
2142                                 controlbits = TIOCM_DTR;
2143                                 if (ioctl(port->fd, config->dtr == SP_DTR_ON ? TIOCMBIS : TIOCMBIC, &controlbits) < 0)
2144                                         RETURN_FAIL("Setting DTR signal level failed");
2145                                 break;
2146                         case SP_DTR_FLOW_CONTROL:
2147                                 data->dtr_flow = 1;
2148                                 break;
2149                         default:
2150                                 break;
2151                         }
2152                         if (config->dsr == SP_DSR_FLOW_CONTROL)
2153                                 data->dsr_flow = 1;
2154                 } else {
2155                         /* DTR/DSR flow control not supported. */
2156                         if (config->dtr == SP_DTR_FLOW_CONTROL || config->dsr == SP_DSR_FLOW_CONTROL)
2157                                 RETURN_ERROR(SP_ERR_SUPP, "DTR/DSR flow control not supported");
2158
2159                         if (config->dtr >= 0) {
2160                                 controlbits = TIOCM_DTR;
2161                                 if (ioctl(port->fd, config->dtr == SP_DTR_ON ? TIOCMBIS : TIOCMBIC,
2162                                                 &controlbits) < 0)
2163                                         RETURN_FAIL("Setting DTR signal level failed");
2164                         }
2165                 }
2166         }
2167
2168         if (config->xon_xoff >= 0) {
2169                 data->term.c_iflag &= ~(IXON | IXOFF | IXANY);
2170                 switch (config->xon_xoff) {
2171                 case SP_XONXOFF_DISABLED:
2172                         break;
2173                 case SP_XONXOFF_IN:
2174                         data->term.c_iflag |= IXOFF;
2175                         break;
2176                 case SP_XONXOFF_OUT:
2177                         data->term.c_iflag |= IXON | IXANY;
2178                         break;
2179                 case SP_XONXOFF_INOUT:
2180                         data->term.c_iflag |= IXON | IXOFF | IXANY;
2181                         break;
2182                 default:
2183                         RETURN_ERROR(SP_ERR_ARG, "Invalid XON/XOFF setting");
2184                 }
2185         }
2186
2187         if (tcsetattr(port->fd, TCSANOW, &data->term) < 0)
2188                 RETURN_FAIL("tcsetattr() failed");
2189
2190 #ifdef __APPLE__
2191         if (baud_nonstd != B0) {
2192                 if (ioctl(port->fd, IOSSIOSPEED, &baud_nonstd) == -1)
2193                         RETURN_FAIL("IOSSIOSPEED ioctl failed");
2194                 /*
2195                  * Set baud rates in data->term to correct, but incompatible
2196                  * with tcsetattr() value, same as delivered by tcgetattr().
2197                  */
2198                 if (cfsetspeed(&data->term, baud_nonstd) < 0)
2199                         RETURN_FAIL("cfsetspeed() failed");
2200         }
2201 #elif defined(__linux__)
2202 #ifdef USE_TERMIOS_SPEED
2203         if (baud_nonstd)
2204                 TRY(set_baudrate(port->fd, config->baudrate));
2205 #endif
2206 #ifdef USE_TERMIOX
2207         if (data->termiox_supported)
2208                 TRY(set_flow(port->fd, data));
2209 #endif
2210 #endif
2211
2212 #endif /* !_WIN32 */
2213
2214         RETURN_OK();
2215 }
2216
2217 SP_API enum sp_return sp_new_config(struct sp_port_config **config_ptr)
2218 {
2219         struct sp_port_config *config;
2220
2221         TRACE("%p", config_ptr);
2222
2223         if (!config_ptr)
2224                 RETURN_ERROR(SP_ERR_ARG, "Null result pointer");
2225
2226         *config_ptr = NULL;
2227
2228         if (!(config = malloc(sizeof(struct sp_port_config))))
2229                 RETURN_ERROR(SP_ERR_MEM, "Config malloc failed");
2230
2231         config->baudrate = -1;
2232         config->bits = -1;
2233         config->parity = -1;
2234         config->stopbits = -1;
2235         config->rts = -1;
2236         config->cts = -1;
2237         config->dtr = -1;
2238         config->dsr = -1;
2239
2240         *config_ptr = config;
2241
2242         RETURN_OK();
2243 }
2244
2245 SP_API void sp_free_config(struct sp_port_config *config)
2246 {
2247         TRACE("%p", config);
2248
2249         if (!config)
2250                 DEBUG("Null config");
2251         else
2252                 free(config);
2253
2254         RETURN();
2255 }
2256
2257 SP_API enum sp_return sp_get_config(struct sp_port *port,
2258                                     struct sp_port_config *config)
2259 {
2260         struct port_data data;
2261
2262         TRACE("%p, %p", port, config);
2263
2264         CHECK_OPEN_PORT();
2265
2266         if (!config)
2267                 RETURN_ERROR(SP_ERR_ARG, "Null config");
2268
2269         TRY(get_config(port, &data, config));
2270
2271         RETURN_OK();
2272 }
2273
2274 SP_API enum sp_return sp_set_config(struct sp_port *port,
2275                                     const struct sp_port_config *config)
2276 {
2277         struct port_data data;
2278         struct sp_port_config prev_config;
2279
2280         TRACE("%p, %p", port, config);
2281
2282         CHECK_OPEN_PORT();
2283
2284         if (!config)
2285                 RETURN_ERROR(SP_ERR_ARG, "Null config");
2286
2287         TRY(get_config(port, &data, &prev_config));
2288         TRY(set_config(port, &data, config));
2289
2290         RETURN_OK();
2291 }
2292
2293 #define CREATE_ACCESSORS(x, type) \
2294 SP_API enum sp_return sp_set_##x(struct sp_port *port, type x) { \
2295         struct port_data data; \
2296         struct sp_port_config config; \
2297         TRACE("%p, %d", port, x); \
2298         CHECK_OPEN_PORT(); \
2299         TRY(get_config(port, &data, &config)); \
2300         config.x = x; \
2301         TRY(set_config(port, &data, &config)); \
2302         RETURN_OK(); \
2303 } \
2304 SP_API enum sp_return sp_get_config_##x(const struct sp_port_config *config, \
2305                                         type *x) { \
2306         TRACE("%p, %p", config, x); \
2307         if (!x) \
2308                 RETURN_ERROR(SP_ERR_ARG, "Null result pointer"); \
2309         if (!config) \
2310                 RETURN_ERROR(SP_ERR_ARG, "Null config"); \
2311         *x = config->x; \
2312         RETURN_OK(); \
2313 } \
2314 SP_API enum sp_return sp_set_config_##x(struct sp_port_config *config, \
2315                                         type x) { \
2316         TRACE("%p, %d", config, x); \
2317         if (!config) \
2318                 RETURN_ERROR(SP_ERR_ARG, "Null config"); \
2319         config->x = x; \
2320         RETURN_OK(); \
2321 }
2322
2323 CREATE_ACCESSORS(baudrate, int)
2324 CREATE_ACCESSORS(bits, int)
2325 CREATE_ACCESSORS(parity, enum sp_parity)
2326 CREATE_ACCESSORS(stopbits, int)
2327 CREATE_ACCESSORS(rts, enum sp_rts)
2328 CREATE_ACCESSORS(cts, enum sp_cts)
2329 CREATE_ACCESSORS(dtr, enum sp_dtr)
2330 CREATE_ACCESSORS(dsr, enum sp_dsr)
2331 CREATE_ACCESSORS(xon_xoff, enum sp_xonxoff)
2332
2333 SP_API enum sp_return sp_set_config_flowcontrol(struct sp_port_config *config,
2334                                                 enum sp_flowcontrol flowcontrol)
2335 {
2336         if (!config)
2337                 RETURN_ERROR(SP_ERR_ARG, "Null configuration");
2338
2339         if (flowcontrol > SP_FLOWCONTROL_DTRDSR)
2340                 RETURN_ERROR(SP_ERR_ARG, "Invalid flow control setting");
2341
2342         if (flowcontrol == SP_FLOWCONTROL_XONXOFF)
2343                 config->xon_xoff = SP_XONXOFF_INOUT;
2344         else
2345                 config->xon_xoff = SP_XONXOFF_DISABLED;
2346
2347         if (flowcontrol == SP_FLOWCONTROL_RTSCTS) {
2348                 config->rts = SP_RTS_FLOW_CONTROL;
2349                 config->cts = SP_CTS_FLOW_CONTROL;
2350         } else {
2351                 if (config->rts == SP_RTS_FLOW_CONTROL)
2352                         config->rts = SP_RTS_ON;
2353                 config->cts = SP_CTS_IGNORE;
2354         }
2355
2356         if (flowcontrol == SP_FLOWCONTROL_DTRDSR) {
2357                 config->dtr = SP_DTR_FLOW_CONTROL;
2358                 config->dsr = SP_DSR_FLOW_CONTROL;
2359         } else {
2360                 if (config->dtr == SP_DTR_FLOW_CONTROL)
2361                         config->dtr = SP_DTR_ON;
2362                 config->dsr = SP_DSR_IGNORE;
2363         }
2364
2365         RETURN_OK();
2366 }
2367
2368 SP_API enum sp_return sp_set_flowcontrol(struct sp_port *port,
2369                                          enum sp_flowcontrol flowcontrol)
2370 {
2371         struct port_data data;
2372         struct sp_port_config config;
2373
2374         TRACE("%p, %d", port, flowcontrol);
2375
2376         CHECK_OPEN_PORT();
2377
2378         TRY(get_config(port, &data, &config));
2379
2380         TRY(sp_set_config_flowcontrol(&config, flowcontrol));
2381
2382         TRY(set_config(port, &data, &config));
2383
2384         RETURN_OK();
2385 }
2386
2387 SP_API enum sp_return sp_get_signals(struct sp_port *port,
2388                                      enum sp_signal *signals)
2389 {
2390         TRACE("%p, %p", port, signals);
2391
2392         CHECK_OPEN_PORT();
2393
2394         if (!signals)
2395                 RETURN_ERROR(SP_ERR_ARG, "Null result pointer");
2396
2397         DEBUG_FMT("Getting control signals for port %s", port->name);
2398
2399         *signals = 0;
2400 #ifdef _WIN32
2401         DWORD bits;
2402         if (GetCommModemStatus(port->hdl, &bits) == 0)
2403                 RETURN_FAIL("GetCommModemStatus() failed");
2404         if (bits & MS_CTS_ON)
2405                 *signals |= SP_SIG_CTS;
2406         if (bits & MS_DSR_ON)
2407                 *signals |= SP_SIG_DSR;
2408         if (bits & MS_RLSD_ON)
2409                 *signals |= SP_SIG_DCD;
2410         if (bits & MS_RING_ON)
2411                 *signals |= SP_SIG_RI;
2412 #else
2413         int bits;
2414         if (ioctl(port->fd, TIOCMGET, &bits) < 0)
2415                 RETURN_FAIL("TIOCMGET ioctl failed");
2416         if (bits & TIOCM_CTS)
2417                 *signals |= SP_SIG_CTS;
2418         if (bits & TIOCM_DSR)
2419                 *signals |= SP_SIG_DSR;
2420         if (bits & TIOCM_CAR)
2421                 *signals |= SP_SIG_DCD;
2422         if (bits & TIOCM_RNG)
2423                 *signals |= SP_SIG_RI;
2424 #endif
2425         RETURN_OK();
2426 }
2427
2428 SP_API enum sp_return sp_start_break(struct sp_port *port)
2429 {
2430         TRACE("%p", port);
2431
2432         CHECK_OPEN_PORT();
2433 #ifdef _WIN32
2434         if (SetCommBreak(port->hdl) == 0)
2435                 RETURN_FAIL("SetCommBreak() failed");
2436 #else
2437         if (ioctl(port->fd, TIOCSBRK, 1) < 0)
2438                 RETURN_FAIL("TIOCSBRK ioctl failed");
2439 #endif
2440
2441         RETURN_OK();
2442 }
2443
2444 SP_API enum sp_return sp_end_break(struct sp_port *port)
2445 {
2446         TRACE("%p", port);
2447
2448         CHECK_OPEN_PORT();
2449 #ifdef _WIN32
2450         if (ClearCommBreak(port->hdl) == 0)
2451                 RETURN_FAIL("ClearCommBreak() failed");
2452 #else
2453         if (ioctl(port->fd, TIOCCBRK, 1) < 0)
2454                 RETURN_FAIL("TIOCCBRK ioctl failed");
2455 #endif
2456
2457         RETURN_OK();
2458 }
2459
2460 SP_API int sp_last_error_code(void)
2461 {
2462         TRACE_VOID();
2463 #ifdef _WIN32
2464         RETURN_INT(GetLastError());
2465 #else
2466         RETURN_INT(errno);
2467 #endif
2468 }
2469
2470 SP_API char *sp_last_error_message(void)
2471 {
2472         TRACE_VOID();
2473
2474 #ifdef _WIN32
2475         TCHAR *message;
2476         DWORD error = GetLastError();
2477
2478         DWORD length = FormatMessage(
2479                 FORMAT_MESSAGE_ALLOCATE_BUFFER |
2480                 FORMAT_MESSAGE_FROM_SYSTEM |
2481                 FORMAT_MESSAGE_IGNORE_INSERTS,
2482                 NULL,
2483                 error,
2484                 MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
2485                 (LPTSTR) &message,
2486                 0, NULL );
2487
2488         if (length >= 2 && message[length - 2] == '\r')
2489                 message[length - 2] = '\0';
2490
2491         RETURN_STRING(message);
2492 #else
2493         RETURN_STRING(strerror(errno));
2494 #endif
2495 }
2496
2497 SP_API void sp_free_error_message(char *message)
2498 {
2499         TRACE("%s", message);
2500
2501 #ifdef _WIN32
2502         LocalFree(message);
2503 #else
2504         (void)message;
2505 #endif
2506
2507         RETURN();
2508 }
2509
2510 SP_API void sp_set_debug_handler(void (*handler)(const char *format, ...))
2511 {
2512         TRACE("%p", handler);
2513
2514         sp_debug_handler = handler;
2515
2516         RETURN();
2517 }
2518
2519 SP_API void sp_default_debug_handler(const char *format, ...)
2520 {
2521         va_list args;
2522         va_start(args, format);
2523         if (getenv("LIBSERIALPORT_DEBUG")) {
2524                 fputs("sp: ", stderr);
2525                 vfprintf(stderr, format, args);
2526         }
2527         va_end(args);
2528 }
2529
2530 SP_API int sp_get_major_package_version(void)
2531 {
2532         return SP_PACKAGE_VERSION_MAJOR;
2533 }
2534
2535 SP_API int sp_get_minor_package_version(void)
2536 {
2537         return SP_PACKAGE_VERSION_MINOR;
2538 }
2539
2540 SP_API int sp_get_micro_package_version(void)
2541 {
2542         return SP_PACKAGE_VERSION_MICRO;
2543 }
2544
2545 SP_API const char *sp_get_package_version_string(void)
2546 {
2547         return SP_PACKAGE_VERSION_STRING;
2548 }
2549
2550 SP_API int sp_get_current_lib_version(void)
2551 {
2552         return SP_LIB_VERSION_CURRENT;
2553 }
2554
2555 SP_API int sp_get_revision_lib_version(void)
2556 {
2557         return SP_LIB_VERSION_REVISION;
2558 }
2559
2560 SP_API int sp_get_age_lib_version(void)
2561 {
2562         return SP_LIB_VERSION_AGE;
2563 }
2564
2565 SP_API const char *sp_get_lib_version_string(void)
2566 {
2567         return SP_LIB_VERSION_STRING;
2568 }
2569
2570 /** @} */