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