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