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