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