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