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