]> sigrok.org Git - libserialport.git/blob - serialport.c
Handle EINTR by repeating the call.
[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 #else
803         /* Returns 0 upon success, -1 upon failure. */
804         if (tcdrain(port->fd) < 0)
805                 RETURN_FAIL("tcdrain() failed");
806 #endif
807
808         RETURN_OK();
809 }
810
811 enum sp_return sp_blocking_write(struct sp_port *port, const void *buf, size_t count, unsigned int timeout)
812 {
813         TRACE("%p, %p, %d, %d", port, buf, count, timeout);
814
815         CHECK_OPEN_PORT();
816
817         if (!buf)
818                 RETURN_ERROR(SP_ERR_ARG, "Null buffer");
819
820         if (timeout)
821                 DEBUG("Writing %d bytes to port %s, timeout %d ms", count, port->name, timeout);
822         else
823                 DEBUG("Writing %d bytes to port %s, no timeout", count, port->name);
824
825         if (count == 0)
826                 RETURN_VALUE("0", 0);
827
828 #ifdef _WIN32
829         DWORD bytes_written = 0;
830         BOOL result;
831
832         /* Wait for previous non-blocking write to complete, if any. */
833         if (port->writing) {
834                 DEBUG("Waiting for previous write to complete");
835                 result = GetOverlappedResult(port->hdl, &port->write_ovl, &bytes_written, TRUE);
836                 port->writing = 0;
837                 if (!result)
838                         RETURN_FAIL("Previous write failed to complete");
839                 DEBUG("Previous write completed");
840         }
841
842         /* Set timeout. */
843         port->timeouts.WriteTotalTimeoutConstant = timeout;
844         if (SetCommTimeouts(port->hdl, &port->timeouts) == 0)
845                 RETURN_FAIL("SetCommTimeouts() failed");
846
847         /* Start write. */
848         if (WriteFile(port->hdl, buf, count, NULL, &port->write_ovl) == 0) {
849                 if (GetLastError() == ERROR_IO_PENDING) {
850                         DEBUG("Waiting for write to complete");
851                         GetOverlappedResult(port->hdl, &port->write_ovl, &bytes_written, TRUE);
852                         DEBUG("Write completed, %d/%d bytes written", bytes_written, count);
853                         RETURN_VALUE("%d", bytes_written);
854                 } else {
855                         RETURN_FAIL("WriteFile() failed");
856                 }
857         } else {
858                 DEBUG("Write completed immediately");
859                 RETURN_VALUE("%d", count);
860         }
861 #else
862         size_t bytes_written = 0;
863         unsigned char *ptr = (unsigned char *) buf;
864         struct timeval start, delta, now, end = {0, 0};
865         fd_set fds;
866         int result;
867
868         if (timeout) {
869                 /* Get time at start of operation. */
870                 gettimeofday(&start, NULL);
871                 /* Define duration of timeout. */
872                 delta.tv_sec = timeout / 1000;
873                 delta.tv_usec = (timeout % 1000) * 1000;
874                 /* Calculate time at which we should give up. */
875                 timeradd(&start, &delta, &end);
876         }
877
878         /* Loop until we have written the requested number of bytes. */
879         while (bytes_written < count)
880         {
881                 /* Wait until space is available. */
882                 FD_ZERO(&fds);
883                 FD_SET(port->fd, &fds);
884                 if (timeout) {
885                         gettimeofday(&now, NULL);
886                         if (timercmp(&now, &end, >)) {
887                                 DEBUG("write timed out");
888                                 RETURN_VALUE("%d", bytes_written);
889                         }
890                         timersub(&end, &now, &delta);
891                 }
892                 result = select(port->fd + 1, NULL, &fds, NULL, timeout ? &delta : NULL);
893                 if (result < 0) {
894                         if (errno == EINTR) {
895                                 DEBUG("select() call was interrupted, repeating");
896                                 continue;
897                         } else {
898                                 RETURN_FAIL("select() failed");
899                         }
900                 } else if (result == 0) {
901                         DEBUG("write timed out");
902                         RETURN_VALUE("%d", bytes_written);
903                 }
904
905                 /* Do write. */
906                 result = write(port->fd, ptr, count - bytes_written);
907
908                 if (result < 0) {
909                         if (errno == EAGAIN)
910                                 /* This shouldn't happen because we did a select() first, but handle anyway. */
911                                 continue;
912                         else
913                                 /* This is an actual failure. */
914                                 RETURN_FAIL("write() failed");
915                 }
916
917                 bytes_written += result;
918                 ptr += result;
919         }
920
921         RETURN_VALUE("%d", bytes_written);
922 #endif
923 }
924
925 enum sp_return sp_nonblocking_write(struct sp_port *port, const void *buf, size_t count)
926 {
927         TRACE("%p, %p, %d", port, buf, count);
928
929         CHECK_OPEN_PORT();
930
931         if (!buf)
932                 RETURN_ERROR(SP_ERR_ARG, "Null buffer");
933
934         DEBUG("Writing up to %d bytes to port %s", count, port->name);
935
936         if (count == 0)
937                 RETURN_VALUE("0", 0);
938
939 #ifdef _WIN32
940         DWORD written = 0;
941         BYTE *ptr = (BYTE *) buf;
942
943         /* Check whether previous write is complete. */
944         if (port->writing) {
945                 if (HasOverlappedIoCompleted(&port->write_ovl)) {
946                         DEBUG("Previous write completed");
947                         port->writing = 0;
948                 } else {
949                         DEBUG("Previous write not complete");
950                         /* Can't take a new write until the previous one finishes. */
951                         RETURN_VALUE("0", 0);
952                 }
953         }
954
955         /* Set timeout. */
956         port->timeouts.WriteTotalTimeoutConstant = 0;
957         if (SetCommTimeouts(port->hdl, &port->timeouts) == 0)
958                 RETURN_FAIL("SetCommTimeouts() failed");
959
960         /* Keep writing data until the OS has to actually start an async IO for it.
961          * At that point we know the buffer is full. */
962         while (written < count)
963         {
964                 /* Copy first byte of user buffer. */
965                 port->pending_byte = *ptr++;
966
967                 /* Start asynchronous write. */
968                 if (WriteFile(port->hdl, &port->pending_byte, 1, NULL, &port->write_ovl) == 0) {
969                         if (GetLastError() == ERROR_IO_PENDING) {
970                                 DEBUG("Asynchronous write started");
971                                 port->writing = 1;
972                                 RETURN_VALUE("%d", ++written);
973                         } else {
974                                 /* Actual failure of some kind. */
975                                 RETURN_FAIL("WriteFile() failed");
976                         }
977                 } else {
978                         DEBUG("Single byte written immediately.");
979                         written++;
980                 }
981         }
982
983         DEBUG("All bytes written immediately.");
984
985         RETURN_VALUE("%d", written);
986 #else
987         /* Returns the number of bytes written, or -1 upon failure. */
988         ssize_t written = write(port->fd, buf, count);
989
990         if (written < 0)
991                 RETURN_FAIL("write() failed");
992         else
993                 RETURN_VALUE("%d", written);
994 #endif
995 }
996
997 enum sp_return sp_blocking_read(struct sp_port *port, void *buf, size_t count, unsigned int timeout)
998 {
999         TRACE("%p, %p, %d, %d", port, buf, count, timeout);
1000
1001         CHECK_OPEN_PORT();
1002
1003         if (!buf)
1004                 RETURN_ERROR(SP_ERR_ARG, "Null buffer");
1005
1006         if (timeout)
1007                 DEBUG("Reading %d bytes from port %s, timeout %d ms", count, port->name, timeout);
1008         else
1009                 DEBUG("Reading %d bytes from port %s, no timeout", count, port->name);
1010
1011         if (count == 0)
1012                 RETURN_VALUE("0", 0);
1013
1014 #ifdef _WIN32
1015         DWORD bytes_read = 0;
1016
1017         /* Set timeout. */
1018         port->timeouts.ReadIntervalTimeout = 0;
1019         port->timeouts.ReadTotalTimeoutConstant = timeout;
1020         if (SetCommTimeouts(port->hdl, &port->timeouts) == 0)
1021                 RETURN_FAIL("SetCommTimeouts() failed");
1022
1023         /* Start read. */
1024         if (ReadFile(port->hdl, buf, count, NULL, &port->read_ovl) == 0) {
1025                 if (GetLastError() == ERROR_IO_PENDING) {
1026                         DEBUG("Waiting for read to complete");
1027                         GetOverlappedResult(port->hdl, &port->read_ovl, &bytes_read, TRUE);
1028                         DEBUG("Read completed, %d/%d bytes read", bytes_read, count);
1029                         RETURN_VALUE("%d", bytes_read);
1030                 } else {
1031                         RETURN_FAIL("ReadFile() failed");
1032                 }
1033         } else {
1034                 DEBUG("Read completed immediately");
1035                 RETURN_VALUE("%d", count);
1036         }
1037 #else
1038         size_t bytes_read = 0;
1039         unsigned char *ptr = (unsigned char *) buf;
1040         struct timeval start, delta, now, end = {0, 0};
1041         fd_set fds;
1042         int result;
1043
1044         if (timeout) {
1045                 /* Get time at start of operation. */
1046                 gettimeofday(&start, NULL);
1047                 /* Define duration of timeout. */
1048                 delta.tv_sec = timeout / 1000;
1049                 delta.tv_usec = (timeout % 1000) * 1000;
1050                 /* Calculate time at which we should give up. */
1051                 timeradd(&start, &delta, &end);
1052         }
1053
1054         /* Loop until we have the requested number of bytes. */
1055         while (bytes_read < count)
1056         {
1057                 /* Wait until data is available. */
1058                 FD_ZERO(&fds);
1059                 FD_SET(port->fd, &fds);
1060                 if (timeout) {
1061                         gettimeofday(&now, NULL);
1062                         if (timercmp(&now, &end, >))
1063                                 /* Timeout has expired. */
1064                                 RETURN_VALUE("%d", bytes_read);
1065                         timersub(&end, &now, &delta);
1066                 }
1067                 result = select(port->fd + 1, &fds, NULL, NULL, timeout ? &delta : NULL);
1068                 if (result < 0) {
1069                         if (errno == EINTR) {
1070                                 DEBUG("select() call was interrupted, repeating");
1071                                 continue;
1072                         } else {
1073                                 RETURN_FAIL("select() failed");
1074                         }
1075                 } else if (result == 0) {
1076                         DEBUG("read timed out");
1077                         RETURN_VALUE("%d", bytes_read);
1078                 }
1079
1080                 /* Do read. */
1081                 result = read(port->fd, ptr, count - bytes_read);
1082
1083                 if (result < 0) {
1084                         if (errno == EAGAIN)
1085                                 /* This shouldn't happen because we did a select() first, but handle anyway. */
1086                                 continue;
1087                         else
1088                                 /* This is an actual failure. */
1089                                 RETURN_FAIL("read() failed");
1090                 }
1091
1092                 bytes_read += result;
1093                 ptr += result;
1094         }
1095
1096         RETURN_VALUE("%d", bytes_read);
1097 #endif
1098 }
1099
1100 enum sp_return sp_nonblocking_read(struct sp_port *port, void *buf, size_t count)
1101 {
1102         TRACE("%p, %p, %d", port, buf, count);
1103
1104         CHECK_OPEN_PORT();
1105
1106         if (!buf)
1107                 RETURN_ERROR(SP_ERR_ARG, "Null buffer");
1108
1109         DEBUG("Reading up to %d bytes from port %s", count, port->name);
1110
1111 #ifdef _WIN32
1112         DWORD bytes_read;
1113
1114         /* Set timeout. */
1115         port->timeouts.ReadIntervalTimeout = MAXDWORD;
1116         port->timeouts.ReadTotalTimeoutConstant = 0;
1117         if (SetCommTimeouts(port->hdl, &port->timeouts) == 0)
1118                 RETURN_FAIL("SetCommTimeouts() failed");
1119
1120         /* Do read. */
1121         if (ReadFile(port->hdl, buf, count, NULL, &port->read_ovl) == 0)
1122                 RETURN_FAIL("ReadFile() failed");
1123
1124         /* Get number of bytes read. */
1125         GetOverlappedResult(port->hdl, &port->read_ovl, &bytes_read, TRUE);
1126
1127         RETURN_VALUE("%d", bytes_read);
1128 #else
1129         ssize_t bytes_read;
1130
1131         /* Returns the number of bytes read, or -1 upon failure. */
1132         if ((bytes_read = read(port->fd, buf, count)) < 0) {
1133                 if (errno == EAGAIN)
1134                         /* No bytes available. */
1135                         bytes_read = 0;
1136                 else
1137                         /* This is an actual failure. */
1138                         RETURN_FAIL("read() failed");
1139         }
1140         RETURN_VALUE("%d", bytes_read);
1141 #endif
1142 }
1143
1144 enum sp_return sp_input_waiting(struct sp_port *port)
1145 {
1146         TRACE("%p", port);
1147
1148         CHECK_OPEN_PORT();
1149
1150         DEBUG("Checking input bytes waiting on port %s", port->name);
1151
1152 #ifdef _WIN32
1153         DWORD errors;
1154         COMSTAT comstat;
1155
1156         if (ClearCommError(port->hdl, &errors, &comstat) == 0)
1157                 RETURN_FAIL("ClearComError() failed");
1158         RETURN_VALUE("%d", comstat.cbInQue);
1159 #else
1160         int bytes_waiting;
1161         if (ioctl(port->fd, TIOCINQ, &bytes_waiting) < 0)
1162                 RETURN_FAIL("TIOCINQ ioctl failed");
1163         RETURN_VALUE("%d", bytes_waiting);
1164 #endif
1165 }
1166
1167 enum sp_return sp_output_waiting(struct sp_port *port)
1168 {
1169         TRACE("%p", port);
1170
1171         CHECK_OPEN_PORT();
1172
1173         DEBUG("Checking output bytes waiting on port %s", port->name);
1174
1175 #ifdef _WIN32
1176         DWORD errors;
1177         COMSTAT comstat;
1178
1179         if (ClearCommError(port->hdl, &errors, &comstat) == 0)
1180                 RETURN_FAIL("ClearComError() failed");
1181         RETURN_VALUE("%d", comstat.cbOutQue);
1182 #else
1183         int bytes_waiting;
1184         if (ioctl(port->fd, TIOCOUTQ, &bytes_waiting) < 0)
1185                 RETURN_FAIL("TIOCOUTQ ioctl failed");
1186         RETURN_VALUE("%d", bytes_waiting);
1187 #endif
1188 }
1189
1190 #ifdef __linux__
1191 static enum sp_return get_baudrate(int fd, int *baudrate)
1192 {
1193         void *data;
1194
1195         TRACE("%d, %p", fd, baudrate);
1196
1197         DEBUG("Getting baud rate");
1198
1199         if (!(data = malloc(get_termios_size())))
1200                 RETURN_ERROR(SP_ERR_MEM, "termios malloc failed");
1201
1202         if (ioctl(fd, get_termios_get_ioctl(), data) < 0) {
1203                 free(data);
1204                 RETURN_FAIL("getting termios failed");
1205         }
1206
1207         *baudrate = get_termios_speed(data);
1208
1209         free(data);
1210
1211         RETURN_OK();
1212 }
1213
1214 static enum sp_return set_baudrate(int fd, int baudrate)
1215 {
1216         void *data;
1217
1218         TRACE("%d, %d", fd, baudrate);
1219
1220         DEBUG("Getting baud rate");
1221
1222         if (!(data = malloc(get_termios_size())))
1223                 RETURN_ERROR(SP_ERR_MEM, "termios malloc failed");
1224
1225         if (ioctl(fd, get_termios_get_ioctl(), data) < 0) {
1226                 free(data);
1227                 RETURN_FAIL("getting termios failed");
1228         }
1229
1230         DEBUG("Setting baud rate");
1231
1232         set_termios_speed(data, baudrate);
1233
1234         if (ioctl(fd, get_termios_set_ioctl(), data) < 0) {
1235                 free(data);
1236                 RETURN_FAIL("setting termios failed");
1237         }
1238
1239         free(data);
1240
1241         RETURN_OK();
1242 }
1243
1244 #ifdef USE_TERMIOX
1245 static enum sp_return get_flow(int fd, int *flow)
1246 {
1247         void *data;
1248
1249         TRACE("%d, %p", fd, flow);
1250
1251         DEBUG("Getting advanced flow control");
1252
1253         if (!(data = malloc(get_termiox_size())))
1254                 RETURN_ERROR(SP_ERR_MEM, "termiox malloc failed");
1255
1256         if (ioctl(fd, TCGETX, data) < 0) {
1257                 free(data);
1258                 RETURN_FAIL("getting termiox failed");
1259         }
1260
1261         *flow = get_termiox_flow(data);
1262
1263         free(data);
1264
1265         RETURN_OK();
1266 }
1267
1268 static enum sp_return set_flow(int fd, int flow)
1269 {
1270         void *data;
1271
1272         TRACE("%d, %d", fd, flow);
1273
1274         DEBUG("Getting advanced flow control");
1275
1276         if (!(data = malloc(get_termiox_size())))
1277                 RETURN_ERROR(SP_ERR_MEM, "termiox malloc failed");
1278
1279         if (ioctl(fd, TCGETX, data) < 0) {
1280                 free(data);
1281                 RETURN_FAIL("getting termiox failed");
1282         }
1283
1284         DEBUG("Setting advanced flow control");
1285
1286         set_termiox_flow(data, flow);
1287
1288         if (ioctl(fd, TCSETX, data) < 0) {
1289                 free(data);
1290                 RETURN_FAIL("setting termiox failed");
1291         }
1292
1293         free(data);
1294
1295         RETURN_OK();
1296 }
1297 #endif /* USE_TERMIOX */
1298 #endif /* __linux__ */
1299
1300 static enum sp_return get_config(struct sp_port *port, struct port_data *data,
1301         struct sp_port_config *config)
1302 {
1303         unsigned int i;
1304
1305         TRACE("%p, %p, %p", port, data, config);
1306
1307         DEBUG("Getting configuration for port %s", port->name);
1308
1309 #ifdef _WIN32
1310         if (!GetCommState(port->hdl, &data->dcb))
1311                 RETURN_FAIL("GetCommState() failed");
1312
1313         for (i = 0; i < NUM_STD_BAUDRATES; i++) {
1314                 if (data->dcb.BaudRate == std_baudrates[i].index) {
1315                         config->baudrate = std_baudrates[i].value;
1316                         break;
1317                 }
1318         }
1319
1320         if (i == NUM_STD_BAUDRATES)
1321                 /* BaudRate field can be either an index or a custom baud rate. */
1322                 config->baudrate = data->dcb.BaudRate;
1323
1324         config->bits = data->dcb.ByteSize;
1325
1326         if (data->dcb.fParity)
1327                 switch (data->dcb.Parity) {
1328                 case NOPARITY:
1329                         config->parity = SP_PARITY_NONE;
1330                         break;
1331                 case ODDPARITY:
1332                         config->parity = SP_PARITY_ODD;
1333                         break;
1334                 case EVENPARITY:
1335                         config->parity = SP_PARITY_EVEN;
1336                         break;
1337                 case MARKPARITY:
1338                         config->parity = SP_PARITY_MARK;
1339                         break;
1340                 case SPACEPARITY:
1341                         config->parity = SP_PARITY_SPACE;
1342                         break;
1343                 default:
1344                         config->parity = -1;
1345                 }
1346         else
1347                 config->parity = SP_PARITY_NONE;
1348
1349         switch (data->dcb.StopBits) {
1350         case ONESTOPBIT:
1351                 config->stopbits = 1;
1352                 break;
1353         case TWOSTOPBITS:
1354                 config->stopbits = 2;
1355                 break;
1356         default:
1357                 config->stopbits = -1;
1358         }
1359
1360         switch (data->dcb.fRtsControl) {
1361         case RTS_CONTROL_DISABLE:
1362                 config->rts = SP_RTS_OFF;
1363                 break;
1364         case RTS_CONTROL_ENABLE:
1365                 config->rts = SP_RTS_ON;
1366                 break;
1367         case RTS_CONTROL_HANDSHAKE:
1368                 config->rts = SP_RTS_FLOW_CONTROL;
1369                 break;
1370         default:
1371                 config->rts = -1;
1372         }
1373
1374         config->cts = data->dcb.fOutxCtsFlow ? SP_CTS_FLOW_CONTROL : SP_CTS_IGNORE;
1375
1376         switch (data->dcb.fDtrControl) {
1377         case DTR_CONTROL_DISABLE:
1378                 config->dtr = SP_DTR_OFF;
1379                 break;
1380         case DTR_CONTROL_ENABLE:
1381                 config->dtr = SP_DTR_ON;
1382                 break;
1383         case DTR_CONTROL_HANDSHAKE:
1384                 config->dtr = SP_DTR_FLOW_CONTROL;
1385                 break;
1386         default:
1387                 config->dtr = -1;
1388         }
1389
1390         config->dsr = data->dcb.fOutxDsrFlow ? SP_DSR_FLOW_CONTROL : SP_DSR_IGNORE;
1391
1392         if (data->dcb.fInX) {
1393                 if (data->dcb.fOutX)
1394                         config->xon_xoff = SP_XONXOFF_INOUT;
1395                 else
1396                         config->xon_xoff = SP_XONXOFF_IN;
1397         } else {
1398                 if (data->dcb.fOutX)
1399                         config->xon_xoff = SP_XONXOFF_OUT;
1400                 else
1401                         config->xon_xoff = SP_XONXOFF_DISABLED;
1402         }
1403
1404 #else // !_WIN32
1405
1406         if (tcgetattr(port->fd, &data->term) < 0)
1407                 RETURN_FAIL("tcgetattr() failed");
1408
1409         if (ioctl(port->fd, TIOCMGET, &data->controlbits) < 0)
1410                 RETURN_FAIL("TIOCMGET ioctl failed");
1411
1412 #ifdef USE_TERMIOX
1413         int ret = get_flow(port->fd, &data->flow);
1414
1415         if (ret == SP_ERR_FAIL && errno == EINVAL)
1416                 data->termiox_supported = 0;
1417         else if (ret < 0)
1418                 RETURN_CODEVAL(ret);
1419         else
1420                 data->termiox_supported = 1;
1421 #else
1422         data->termiox_supported = 0;
1423 #endif
1424
1425         for (i = 0; i < NUM_STD_BAUDRATES; i++) {
1426                 if (cfgetispeed(&data->term) == std_baudrates[i].index) {
1427                         config->baudrate = std_baudrates[i].value;
1428                         break;
1429                 }
1430         }
1431
1432         if (i == NUM_STD_BAUDRATES) {
1433 #ifdef __APPLE__
1434                 config->baudrate = (int)data->term.c_ispeed;
1435 #elif defined(__linux__)
1436                 TRY(get_baudrate(port->fd, &config->baudrate));
1437 #else
1438                 config->baudrate = -1;
1439 #endif
1440         }
1441
1442         switch (data->term.c_cflag & CSIZE) {
1443         case CS8:
1444                 config->bits = 8;
1445                 break;
1446         case CS7:
1447                 config->bits = 7;
1448                 break;
1449         case CS6:
1450                 config->bits = 6;
1451                 break;
1452         case CS5:
1453                 config->bits = 5;
1454                 break;
1455         default:
1456                 config->bits = -1;
1457         }
1458
1459         if (!(data->term.c_cflag & PARENB) && (data->term.c_iflag & IGNPAR))
1460                 config->parity = SP_PARITY_NONE;
1461         else if (!(data->term.c_cflag & PARENB) || (data->term.c_iflag & IGNPAR))
1462                 config->parity = -1;
1463 #ifdef CMSPAR
1464         else if (data->term.c_cflag & CMSPAR)
1465                 config->parity = (data->term.c_cflag & PARODD) ? SP_PARITY_MARK : SP_PARITY_SPACE;
1466 #endif
1467         else
1468                 config->parity = (data->term.c_cflag & PARODD) ? SP_PARITY_ODD : SP_PARITY_EVEN;
1469
1470         config->stopbits = (data->term.c_cflag & CSTOPB) ? 2 : 1;
1471
1472         if (data->term.c_cflag & CRTSCTS) {
1473                 config->rts = SP_RTS_FLOW_CONTROL;
1474                 config->cts = SP_CTS_FLOW_CONTROL;
1475         } else {
1476                 if (data->termiox_supported && data->flow & RTS_FLOW)
1477                         config->rts = SP_RTS_FLOW_CONTROL;
1478                 else
1479                         config->rts = (data->controlbits & TIOCM_RTS) ? SP_RTS_ON : SP_RTS_OFF;
1480
1481                 config->cts = (data->termiox_supported && data->flow & CTS_FLOW) ?
1482                         SP_CTS_FLOW_CONTROL : SP_CTS_IGNORE;
1483         }
1484
1485         if (data->termiox_supported && data->flow & DTR_FLOW)
1486                 config->dtr = SP_DTR_FLOW_CONTROL;
1487         else
1488                 config->dtr = (data->controlbits & TIOCM_DTR) ? SP_DTR_ON : SP_DTR_OFF;
1489
1490         config->dsr = (data->termiox_supported && data->flow & DSR_FLOW) ?
1491                 SP_DSR_FLOW_CONTROL : SP_DSR_IGNORE;
1492
1493         if (data->term.c_iflag & IXOFF) {
1494                 if (data->term.c_iflag & IXON)
1495                         config->xon_xoff = SP_XONXOFF_INOUT;
1496                 else
1497                         config->xon_xoff = SP_XONXOFF_IN;
1498         } else {
1499                 if (data->term.c_iflag & IXON)
1500                         config->xon_xoff = SP_XONXOFF_OUT;
1501                 else
1502                         config->xon_xoff = SP_XONXOFF_DISABLED;
1503         }
1504 #endif
1505
1506         RETURN_OK();
1507 }
1508
1509 static enum sp_return set_config(struct sp_port *port, struct port_data *data,
1510         const struct sp_port_config *config)
1511 {
1512         unsigned int i;
1513 #ifdef __APPLE__
1514         BAUD_TYPE baud_nonstd;
1515
1516         baud_nonstd = B0;
1517 #endif
1518 #ifdef __linux__
1519         int baud_nonstd = 0;
1520 #endif
1521
1522         TRACE("%p, %p, %p", port, data, config);
1523
1524         DEBUG("Setting configuration for port %s", port->name);
1525
1526 #ifdef _WIN32
1527         if (config->baudrate >= 0) {
1528                 for (i = 0; i < NUM_STD_BAUDRATES; i++) {
1529                         if (config->baudrate == std_baudrates[i].value) {
1530                                 data->dcb.BaudRate = std_baudrates[i].index;
1531                                 break;
1532                         }
1533                 }
1534
1535                 if (i == NUM_STD_BAUDRATES)
1536                         data->dcb.BaudRate = config->baudrate;
1537         }
1538
1539         if (config->bits >= 0)
1540                 data->dcb.ByteSize = config->bits;
1541
1542         if (config->parity >= 0) {
1543                 switch (config->parity) {
1544                 /* Note: There's also SPACEPARITY, MARKPARITY (unneeded so far). */
1545                 case SP_PARITY_NONE:
1546                         data->dcb.Parity = NOPARITY;
1547                         break;
1548                 case SP_PARITY_ODD:
1549                         data->dcb.Parity = ODDPARITY;
1550                         break;
1551                 case SP_PARITY_EVEN:
1552                         data->dcb.Parity = EVENPARITY;
1553                         break;
1554                 case SP_PARITY_MARK:
1555                         data->dcb.Parity = MARKPARITY;
1556                         break;
1557                 case SP_PARITY_SPACE:
1558                         data->dcb.Parity = SPACEPARITY;
1559                         break;
1560                 default:
1561                         RETURN_ERROR(SP_ERR_ARG, "Invalid parity setting");
1562                 }
1563         }
1564
1565         if (config->stopbits >= 0) {
1566                 switch (config->stopbits) {
1567                 /* Note: There's also ONE5STOPBITS == 1.5 (unneeded so far). */
1568                 case 1:
1569                         data->dcb.StopBits = ONESTOPBIT;
1570                         break;
1571                 case 2:
1572                         data->dcb.StopBits = TWOSTOPBITS;
1573                         break;
1574                 default:
1575                         RETURN_ERROR(SP_ERR_ARG, "Invalid stop bit setting");
1576                 }
1577         }
1578
1579         if (config->rts >= 0) {
1580                 switch (config->rts) {
1581                 case SP_RTS_OFF:
1582                         data->dcb.fRtsControl = RTS_CONTROL_DISABLE;
1583                         break;
1584                 case SP_RTS_ON:
1585                         data->dcb.fRtsControl = RTS_CONTROL_ENABLE;
1586                         break;
1587                 case SP_RTS_FLOW_CONTROL:
1588                         data->dcb.fRtsControl = RTS_CONTROL_HANDSHAKE;
1589                         break;
1590                 default:
1591                         RETURN_ERROR(SP_ERR_ARG, "Invalid RTS setting");
1592                 }
1593         }
1594
1595         if (config->cts >= 0) {
1596                 switch (config->cts) {
1597                 case SP_CTS_IGNORE:
1598                         data->dcb.fOutxCtsFlow = FALSE;
1599                         break;
1600                 case SP_CTS_FLOW_CONTROL:
1601                         data->dcb.fOutxCtsFlow = TRUE;
1602                         break;
1603                 default:
1604                         RETURN_ERROR(SP_ERR_ARG, "Invalid CTS setting");
1605                 }
1606         }
1607
1608         if (config->dtr >= 0) {
1609                 switch (config->dtr) {
1610                 case SP_DTR_OFF:
1611                         data->dcb.fDtrControl = DTR_CONTROL_DISABLE;
1612                         break;
1613                 case SP_DTR_ON:
1614                         data->dcb.fDtrControl = DTR_CONTROL_ENABLE;
1615                         break;
1616                 case SP_DTR_FLOW_CONTROL:
1617                         data->dcb.fDtrControl = DTR_CONTROL_HANDSHAKE;
1618                         break;
1619                 default:
1620                         RETURN_ERROR(SP_ERR_ARG, "Invalid DTR setting");
1621                 }
1622         }
1623
1624         if (config->dsr >= 0) {
1625                 switch (config->dsr) {
1626                 case SP_DSR_IGNORE:
1627                         data->dcb.fOutxDsrFlow = FALSE;
1628                         break;
1629                 case SP_DSR_FLOW_CONTROL:
1630                         data->dcb.fOutxDsrFlow = TRUE;
1631                         break;
1632                 default:
1633                         RETURN_ERROR(SP_ERR_ARG, "Invalid DSR setting");
1634                 }
1635         }
1636
1637         if (config->xon_xoff >= 0) {
1638                 switch (config->xon_xoff) {
1639                 case SP_XONXOFF_DISABLED:
1640                         data->dcb.fInX = FALSE;
1641                         data->dcb.fOutX = FALSE;
1642                         break;
1643                 case SP_XONXOFF_IN:
1644                         data->dcb.fInX = TRUE;
1645                         data->dcb.fOutX = FALSE;
1646                         break;
1647                 case SP_XONXOFF_OUT:
1648                         data->dcb.fInX = FALSE;
1649                         data->dcb.fOutX = TRUE;
1650                         break;
1651                 case SP_XONXOFF_INOUT:
1652                         data->dcb.fInX = TRUE;
1653                         data->dcb.fOutX = TRUE;
1654                         break;
1655                 default:
1656                         RETURN_ERROR(SP_ERR_ARG, "Invalid XON/XOFF setting");
1657                 }
1658         }
1659
1660         if (!SetCommState(port->hdl, &data->dcb))
1661                 RETURN_FAIL("SetCommState() failed");
1662
1663 #else /* !_WIN32 */
1664
1665         int controlbits;
1666
1667         if (config->baudrate >= 0) {
1668                 for (i = 0; i < NUM_STD_BAUDRATES; i++) {
1669                         if (config->baudrate == std_baudrates[i].value) {
1670                                 if (cfsetospeed(&data->term, std_baudrates[i].index) < 0)
1671                                         RETURN_FAIL("cfsetospeed() failed");
1672
1673                                 if (cfsetispeed(&data->term, std_baudrates[i].index) < 0)
1674                                         RETURN_FAIL("cfsetispeed() failed");
1675                                 break;
1676                         }
1677                 }
1678
1679                 /* Non-standard baud rate */
1680                 if (i == NUM_STD_BAUDRATES) {
1681 #ifdef __APPLE__
1682                         /* Set "dummy" baud rate. */
1683                         if (cfsetspeed(&data->term, B9600) < 0)
1684                                 RETURN_FAIL("cfsetspeed() failed");
1685                         baud_nonstd = config->baudrate;
1686 #elif defined(__linux__)
1687                         baud_nonstd = 1;
1688 #else
1689                         RETURN_ERROR(SP_ERR_SUPP, "Non-standard baudrate not supported");
1690 #endif
1691                 }
1692         }
1693
1694         if (config->bits >= 0) {
1695                 data->term.c_cflag &= ~CSIZE;
1696                 switch (config->bits) {
1697                 case 8:
1698                         data->term.c_cflag |= CS8;
1699                         break;
1700                 case 7:
1701                         data->term.c_cflag |= CS7;
1702                         break;
1703                 case 6:
1704                         data->term.c_cflag |= CS6;
1705                         break;
1706                 case 5:
1707                         data->term.c_cflag |= CS5;
1708                         break;
1709                 default:
1710                         RETURN_ERROR(SP_ERR_ARG, "Invalid data bits setting");
1711                 }
1712         }
1713
1714         if (config->parity >= 0) {
1715                 data->term.c_iflag &= ~IGNPAR;
1716                 data->term.c_cflag &= ~(PARENB | PARODD);
1717 #ifdef CMSPAR
1718                 data->term.c_cflag &= ~CMSPAR;
1719 #endif
1720                 switch (config->parity) {
1721                 case SP_PARITY_NONE:
1722                         data->term.c_iflag |= IGNPAR;
1723                         break;
1724                 case SP_PARITY_EVEN:
1725                         data->term.c_cflag |= PARENB;
1726                         break;
1727                 case SP_PARITY_ODD:
1728                         data->term.c_cflag |= PARENB | PARODD;
1729                         break;
1730 #ifdef CMSPAR
1731                 case SP_PARITY_MARK:
1732                         data->term.c_cflag |= PARENB | PARODD;
1733                         data->term.c_cflag |= CMSPAR;
1734                         break;
1735                 case SP_PARITY_SPACE:
1736                         data->term.c_cflag |= PARENB;
1737                         data->term.c_cflag |= CMSPAR;
1738                         break;
1739 #else
1740                 case SP_PARITY_MARK:
1741                 case SP_PARITY_SPACE:
1742                         RETURN_ERROR(SP_ERR_SUPP, "Mark/space parity not supported");
1743 #endif
1744                 default:
1745                         RETURN_ERROR(SP_ERR_ARG, "Invalid parity setting");
1746                 }
1747         }
1748
1749         if (config->stopbits >= 0) {
1750                 data->term.c_cflag &= ~CSTOPB;
1751                 switch (config->stopbits) {
1752                 case 1:
1753                         data->term.c_cflag &= ~CSTOPB;
1754                         break;
1755                 case 2:
1756                         data->term.c_cflag |= CSTOPB;
1757                         break;
1758                 default:
1759                         RETURN_ERROR(SP_ERR_ARG, "Invalid stop bits setting");
1760                 }
1761         }
1762
1763         if (config->rts >= 0 || config->cts >= 0) {
1764                 if (data->termiox_supported) {
1765                         data->flow &= ~(RTS_FLOW | CTS_FLOW);
1766                         switch (config->rts) {
1767                         case SP_RTS_OFF:
1768                         case SP_RTS_ON:
1769                                 controlbits = TIOCM_RTS;
1770                                 if (ioctl(port->fd, config->rts == SP_RTS_ON ? TIOCMBIS : TIOCMBIC, &controlbits) < 0)
1771                                         RETURN_FAIL("Setting RTS signal level failed");
1772                                 break;
1773                         case SP_RTS_FLOW_CONTROL:
1774                                 data->flow |= RTS_FLOW;
1775                                 break;
1776                         default:
1777                                 break;
1778                         }
1779                         if (config->cts == SP_CTS_FLOW_CONTROL)
1780                                 data->flow |= CTS_FLOW;
1781
1782                         if (data->flow & (RTS_FLOW | CTS_FLOW))
1783                                 data->term.c_iflag |= CRTSCTS;
1784                         else
1785                                 data->term.c_iflag &= ~CRTSCTS;
1786                 } else {
1787                         /* Asymmetric use of RTS/CTS not supported. */
1788                         if (data->term.c_iflag & CRTSCTS) {
1789                                 /* Flow control can only be disabled for both RTS & CTS together. */
1790                                 if (config->rts >= 0 && config->rts != SP_RTS_FLOW_CONTROL) {
1791                                         if (config->cts != SP_CTS_IGNORE)
1792                                                 RETURN_ERROR(SP_ERR_SUPP, "RTS & CTS flow control must be disabled together");
1793                                 }
1794                                 if (config->cts >= 0 && config->cts != SP_CTS_FLOW_CONTROL) {
1795                                         if (config->rts <= 0 || config->rts == SP_RTS_FLOW_CONTROL)
1796                                                 RETURN_ERROR(SP_ERR_SUPP, "RTS & CTS flow control must be disabled together");
1797                                 }
1798                         } else {
1799                                 /* Flow control can only be enabled for both RTS & CTS together. */
1800                                 if (((config->rts == SP_RTS_FLOW_CONTROL) && (config->cts != SP_CTS_FLOW_CONTROL)) ||
1801                                         ((config->cts == SP_CTS_FLOW_CONTROL) && (config->rts != SP_RTS_FLOW_CONTROL)))
1802                                         RETURN_ERROR(SP_ERR_SUPP, "RTS & CTS flow control must be enabled together");
1803                         }
1804
1805                         if (config->rts >= 0) {
1806                                 if (config->rts == SP_RTS_FLOW_CONTROL) {
1807                                         data->term.c_iflag |= CRTSCTS;
1808                                 } else {
1809                                         controlbits = TIOCM_RTS;
1810                                         if (ioctl(port->fd, config->rts == SP_RTS_ON ? TIOCMBIS : TIOCMBIC,
1811                                                         &controlbits) < 0)
1812                                                 RETURN_FAIL("Setting RTS signal level failed");
1813                                 }
1814                         }
1815                 }
1816         }
1817
1818         if (config->dtr >= 0 || config->dsr >= 0) {
1819                 if (data->termiox_supported) {
1820                         data->flow &= ~(DTR_FLOW | DSR_FLOW);
1821                         switch (config->dtr) {
1822                         case SP_DTR_OFF:
1823                         case SP_DTR_ON:
1824                                 controlbits = TIOCM_DTR;
1825                                 if (ioctl(port->fd, config->dtr == SP_DTR_ON ? TIOCMBIS : TIOCMBIC, &controlbits) < 0)
1826                                         RETURN_FAIL("Setting DTR signal level failed");
1827                                 break;
1828                         case SP_DTR_FLOW_CONTROL:
1829                                 data->flow |= DTR_FLOW;
1830                                 break;
1831                         default:
1832                                 break;
1833                         }
1834                         if (config->dsr == SP_DSR_FLOW_CONTROL)
1835                                 data->flow |= DSR_FLOW;
1836                 } else {
1837                         /* DTR/DSR flow control not supported. */
1838                         if (config->dtr == SP_DTR_FLOW_CONTROL || config->dsr == SP_DSR_FLOW_CONTROL)
1839                                 RETURN_ERROR(SP_ERR_SUPP, "DTR/DSR flow control not supported");
1840
1841                         if (config->dtr >= 0) {
1842                                 controlbits = TIOCM_DTR;
1843                                 if (ioctl(port->fd, config->dtr == SP_DTR_ON ? TIOCMBIS : TIOCMBIC,
1844                                                 &controlbits) < 0)
1845                                         RETURN_FAIL("Setting DTR signal level failed");
1846                         }
1847                 }
1848         }
1849
1850         if (config->xon_xoff >= 0) {
1851                 data->term.c_iflag &= ~(IXON | IXOFF | IXANY);
1852                 switch (config->xon_xoff) {
1853                 case SP_XONXOFF_DISABLED:
1854                         break;
1855                 case SP_XONXOFF_IN:
1856                         data->term.c_iflag |= IXOFF;
1857                         break;
1858                 case SP_XONXOFF_OUT:
1859                         data->term.c_iflag |= IXON | IXANY;
1860                         break;
1861                 case SP_XONXOFF_INOUT:
1862                         data->term.c_iflag |= IXON | IXOFF | IXANY;
1863                         break;
1864                 default:
1865                         RETURN_ERROR(SP_ERR_ARG, "Invalid XON/XOFF setting");
1866                 }
1867         }
1868
1869         if (tcsetattr(port->fd, TCSANOW, &data->term) < 0)
1870                 RETURN_FAIL("tcsetattr() failed");
1871
1872 #ifdef __APPLE__
1873         if (baud_nonstd != B0) {
1874                 if (ioctl(port->fd, IOSSIOSPEED, &baud_nonstd) == -1)
1875                         RETURN_FAIL("IOSSIOSPEED ioctl failed");
1876                 /* Set baud rates in data->term to correct, but incompatible
1877                  * with tcsetattr() value, same as delivered by tcgetattr(). */
1878                 if (cfsetspeed(&data->term, baud_nonstd) < 0)
1879                         RETURN_FAIL("cfsetspeed() failed");
1880         }
1881 #elif defined(__linux__)
1882         if (baud_nonstd)
1883                 TRY(set_baudrate(port->fd, config->baudrate));
1884 #ifdef USE_TERMIOX
1885         if (data->termiox_supported)
1886                 TRY(set_flow(port->fd, data->flow));
1887 #endif
1888 #endif
1889
1890 #endif /* !_WIN32 */
1891
1892         RETURN_OK();
1893 }
1894
1895 enum sp_return sp_new_config(struct sp_port_config **config_ptr)
1896 {
1897         struct sp_port_config *config;
1898
1899         TRACE("%p", config_ptr);
1900
1901         if (!config_ptr)
1902                 RETURN_ERROR(SP_ERR_ARG, "Null result pointer");
1903
1904         *config_ptr = NULL;
1905
1906         if (!(config = malloc(sizeof(struct sp_port_config))))
1907                 RETURN_ERROR(SP_ERR_MEM, "config malloc failed");
1908
1909         config->baudrate = -1;
1910         config->bits = -1;
1911         config->parity = -1;
1912         config->stopbits = -1;
1913         config->rts = -1;
1914         config->cts = -1;
1915         config->dtr = -1;
1916         config->dsr = -1;
1917
1918         *config_ptr = config;
1919
1920         RETURN_OK();
1921 }
1922
1923 void sp_free_config(struct sp_port_config *config)
1924 {
1925         TRACE("%p", config);
1926
1927         if (!config)
1928                 DEBUG("Null config");
1929         else
1930                 free(config);
1931
1932         RETURN();
1933 }
1934
1935 enum sp_return sp_get_config(struct sp_port *port, struct sp_port_config *config)
1936 {
1937         struct port_data data;
1938
1939         TRACE("%p, %p", port, config);
1940
1941         CHECK_OPEN_PORT();
1942
1943         if (!config)
1944                 RETURN_ERROR(SP_ERR_ARG, "Null config");
1945
1946         TRY(get_config(port, &data, config));
1947
1948         RETURN_OK();
1949 }
1950
1951 enum sp_return sp_set_config(struct sp_port *port, const struct sp_port_config *config)
1952 {
1953         struct port_data data;
1954         struct sp_port_config prev_config;
1955
1956         TRACE("%p, %p", port, config);
1957
1958         CHECK_OPEN_PORT();
1959
1960         if (!config)
1961                 RETURN_ERROR(SP_ERR_ARG, "Null config");
1962
1963         TRY(get_config(port, &data, &prev_config));
1964         TRY(set_config(port, &data, config));
1965
1966         RETURN_OK();
1967 }
1968
1969 #define CREATE_ACCESSORS(x, type) \
1970 enum sp_return sp_set_##x(struct sp_port *port, type x) { \
1971         struct port_data data; \
1972         struct sp_port_config config; \
1973         TRACE("%p, %d", port, x); \
1974         CHECK_OPEN_PORT(); \
1975         TRY(get_config(port, &data, &config)); \
1976         config.x = x; \
1977         TRY(set_config(port, &data, &config)); \
1978         RETURN_OK(); \
1979 } \
1980 enum sp_return sp_get_config_##x(const struct sp_port_config *config, type *x) { \
1981         TRACE("%p, %p", config, x); \
1982         if (!config) \
1983                 RETURN_ERROR(SP_ERR_ARG, "Null config"); \
1984         *x = config->x; \
1985         RETURN_OK(); \
1986 } \
1987 enum sp_return sp_set_config_##x(struct sp_port_config *config, type x) { \
1988         TRACE("%p, %d", config, x); \
1989         if (!config) \
1990                 RETURN_ERROR(SP_ERR_ARG, "Null config"); \
1991         config->x = x; \
1992         RETURN_OK(); \
1993 }
1994
1995 CREATE_ACCESSORS(baudrate, int)
1996 CREATE_ACCESSORS(bits, int)
1997 CREATE_ACCESSORS(parity, enum sp_parity)
1998 CREATE_ACCESSORS(stopbits, int)
1999 CREATE_ACCESSORS(rts, enum sp_rts)
2000 CREATE_ACCESSORS(cts, enum sp_cts)
2001 CREATE_ACCESSORS(dtr, enum sp_dtr)
2002 CREATE_ACCESSORS(dsr, enum sp_dsr)
2003 CREATE_ACCESSORS(xon_xoff, enum sp_xonxoff)
2004
2005 enum sp_return sp_set_config_flowcontrol(struct sp_port_config *config, enum sp_flowcontrol flowcontrol)
2006 {
2007         if (!config)
2008                 RETURN_ERROR(SP_ERR_ARG, "Null configuration");
2009
2010         if (flowcontrol > SP_FLOWCONTROL_DTRDSR)
2011                 RETURN_ERROR(SP_ERR_ARG, "Invalid flow control setting");
2012
2013         if (flowcontrol == SP_FLOWCONTROL_XONXOFF)
2014                 config->xon_xoff = SP_XONXOFF_INOUT;
2015         else
2016                 config->xon_xoff = SP_XONXOFF_DISABLED;
2017
2018         if (flowcontrol == SP_FLOWCONTROL_RTSCTS) {
2019                 config->rts = SP_RTS_FLOW_CONTROL;
2020                 config->cts = SP_CTS_FLOW_CONTROL;
2021         } else {
2022                 if (config->rts == SP_RTS_FLOW_CONTROL)
2023                         config->rts = SP_RTS_ON;
2024                 config->cts = SP_CTS_IGNORE;
2025         }
2026
2027         if (flowcontrol == SP_FLOWCONTROL_DTRDSR) {
2028                 config->dtr = SP_DTR_FLOW_CONTROL;
2029                 config->dsr = SP_DSR_FLOW_CONTROL;
2030         } else {
2031                 if (config->dtr == SP_DTR_FLOW_CONTROL)
2032                         config->dtr = SP_DTR_ON;
2033                 config->dsr = SP_DSR_IGNORE;
2034         }
2035
2036         RETURN_OK();
2037 }
2038
2039 enum sp_return sp_set_flowcontrol(struct sp_port *port, enum sp_flowcontrol flowcontrol)
2040 {
2041         struct port_data data;
2042         struct sp_port_config config;
2043
2044         TRACE("%p, %d", port, flowcontrol);
2045
2046         CHECK_OPEN_PORT();
2047
2048         TRY(get_config(port, &data, &config));
2049
2050         TRY(sp_set_config_flowcontrol(&config, flowcontrol));
2051
2052         TRY(set_config(port, &data, &config));
2053
2054         RETURN_OK();
2055 }
2056
2057 enum sp_return sp_get_signals(struct sp_port *port, enum sp_signal *signals)
2058 {
2059         TRACE("%p, %p", port, signals);
2060
2061         CHECK_OPEN_PORT();
2062
2063         if (!signals)
2064                 RETURN_ERROR(SP_ERR_ARG, "Null result pointer");
2065
2066         DEBUG("Getting control signals for port %s", port->name);
2067
2068         *signals = 0;
2069 #ifdef _WIN32
2070         DWORD bits;
2071         if (GetCommModemStatus(port->hdl, &bits) == 0)
2072                 RETURN_FAIL("GetCommModemStatus() failed");
2073         if (bits & MS_CTS_ON)
2074                 *signals |= SP_SIG_CTS;
2075         if (bits & MS_DSR_ON)
2076                 *signals |= SP_SIG_DSR;
2077         if (bits & MS_RLSD_ON)
2078                 *signals |= SP_SIG_DCD;
2079         if (bits & MS_RING_ON)
2080                 *signals |= SP_SIG_RI;
2081 #else
2082         int bits;
2083         if (ioctl(port->fd, TIOCMGET, &bits) < 0)
2084                 RETURN_FAIL("TIOCMGET ioctl failed");
2085         if (bits & TIOCM_CTS)
2086                 *signals |= SP_SIG_CTS;
2087         if (bits & TIOCM_DSR)
2088                 *signals |= SP_SIG_DSR;
2089         if (bits & TIOCM_CAR)
2090                 *signals |= SP_SIG_DCD;
2091         if (bits & TIOCM_RNG)
2092                 *signals |= SP_SIG_RI;
2093 #endif
2094         RETURN_OK();
2095 }
2096
2097 enum sp_return sp_start_break(struct sp_port *port)
2098 {
2099         TRACE("%p", port);
2100
2101         CHECK_OPEN_PORT();
2102 #ifdef _WIN32
2103         if (SetCommBreak(port->hdl) == 0)
2104                 RETURN_FAIL("SetCommBreak() failed");
2105 #else
2106         if (ioctl(port->fd, TIOCSBRK, 1) < 0)
2107                 RETURN_FAIL("TIOCSBRK ioctl failed");
2108 #endif
2109
2110         RETURN_OK();
2111 }
2112
2113 enum sp_return sp_end_break(struct sp_port *port)
2114 {
2115         TRACE("%p", port);
2116
2117         CHECK_OPEN_PORT();
2118 #ifdef _WIN32
2119         if (ClearCommBreak(port->hdl) == 0)
2120                 RETURN_FAIL("ClearCommBreak() failed");
2121 #else
2122         if (ioctl(port->fd, TIOCCBRK, 1) < 0)
2123                 RETURN_FAIL("TIOCCBRK ioctl failed");
2124 #endif
2125
2126         RETURN_OK();
2127 }
2128
2129 int sp_last_error_code(void)
2130 {
2131         TRACE("");
2132 #ifdef _WIN32
2133         RETURN_VALUE("%d", GetLastError());
2134 #else
2135         RETURN_VALUE("%d", errno);
2136 #endif
2137 }
2138
2139 char *sp_last_error_message(void)
2140 {
2141         TRACE("");
2142
2143 #ifdef _WIN32
2144         LPVOID message;
2145         DWORD error = GetLastError();
2146
2147         FormatMessage(
2148                 FORMAT_MESSAGE_ALLOCATE_BUFFER |
2149                 FORMAT_MESSAGE_FROM_SYSTEM |
2150                 FORMAT_MESSAGE_IGNORE_INSERTS,
2151                 NULL,
2152                 error,
2153                 MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
2154                 (LPTSTR) &message,
2155                 0, NULL );
2156
2157         RETURN_VALUE("%s", message);
2158 #else
2159         RETURN_VALUE("%s", strerror(errno));
2160 #endif
2161 }
2162
2163 void sp_free_error_message(char *message)
2164 {
2165         TRACE("%s", message);
2166
2167 #ifdef _WIN32
2168         LocalFree(message);
2169 #else
2170         (void)message;
2171 #endif
2172
2173         RETURN();
2174 }
2175
2176 void sp_set_debug_handler(void (*handler)(const char *format, ...))
2177 {
2178         TRACE("%p", handler);
2179
2180         sp_debug_handler = handler;
2181
2182         RETURN();
2183 }
2184
2185 void sp_default_debug_handler(const char *format, ...)
2186 {
2187         va_list args;
2188         va_start(args, format);
2189         if (getenv("LIBSERIALPORT_DEBUG")) {
2190                 fputs("sp: ", stderr);
2191                 vfprintf(stderr, format, args);
2192         }
2193         va_end(args);
2194 }