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