]> sigrok.org Git - libserialport.git/blob - serialport.c
New API and implementation for blocking and non-blocking I/O.
[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 #ifdef __linux__
1135 static enum sp_return get_baudrate(int fd, int *baudrate)
1136 {
1137         void *data;
1138
1139         TRACE("%d, %p", fd, baudrate);
1140
1141         DEBUG("Getting baud rate");
1142
1143         if (!(data = malloc(get_termios_size())))
1144                 RETURN_ERROR(SP_ERR_MEM, "termios malloc failed");
1145
1146         if (ioctl(fd, get_termios_get_ioctl(), data) < 0) {
1147                 free(data);
1148                 RETURN_FAIL("getting termios failed");
1149         }
1150
1151         *baudrate = get_termios_speed(data);
1152
1153         free(data);
1154
1155         RETURN_OK();
1156 }
1157
1158 static enum sp_return set_baudrate(int fd, int baudrate)
1159 {
1160         void *data;
1161
1162         TRACE("%d, %d", fd, baudrate);
1163
1164         DEBUG("Getting baud rate");
1165
1166         if (!(data = malloc(get_termios_size())))
1167                 RETURN_ERROR(SP_ERR_MEM, "termios malloc failed");
1168
1169         if (ioctl(fd, get_termios_get_ioctl(), data) < 0) {
1170                 free(data);
1171                 RETURN_FAIL("getting termios failed");
1172         }
1173
1174         DEBUG("Setting baud rate");
1175
1176         set_termios_speed(data, baudrate);
1177
1178         if (ioctl(fd, get_termios_set_ioctl(), data) < 0) {
1179                 free(data);
1180                 RETURN_FAIL("setting termios failed");
1181         }
1182
1183         free(data);
1184
1185         RETURN_OK();
1186 }
1187
1188 #ifdef USE_TERMIOX
1189 static enum sp_return get_flow(int fd, int *flow)
1190 {
1191         void *data;
1192
1193         TRACE("%d, %p", fd, flow);
1194
1195         DEBUG("Getting advanced flow control");
1196
1197         if (!(data = malloc(get_termiox_size())))
1198                 RETURN_ERROR(SP_ERR_MEM, "termiox malloc failed");
1199
1200         if (ioctl(fd, TCGETX, data) < 0) {
1201                 free(data);
1202                 RETURN_FAIL("getting termiox failed");
1203         }
1204
1205         *flow = get_termiox_flow(data);
1206
1207         free(data);
1208
1209         RETURN_OK();
1210 }
1211
1212 static enum sp_return set_flow(int fd, int flow)
1213 {
1214         void *data;
1215
1216         TRACE("%d, %d", fd, flow);
1217
1218         DEBUG("Getting advanced flow control");
1219
1220         if (!(data = malloc(get_termiox_size())))
1221                 RETURN_ERROR(SP_ERR_MEM, "termiox malloc failed");
1222
1223         if (ioctl(fd, TCGETX, data) < 0) {
1224                 free(data);
1225                 RETURN_FAIL("getting termiox failed");
1226         }
1227
1228         DEBUG("Setting advanced flow control");
1229
1230         set_termiox_flow(data, flow);
1231
1232         if (ioctl(fd, TCSETX, data) < 0) {
1233                 free(data);
1234                 RETURN_FAIL("setting termiox failed");
1235         }
1236
1237         free(data);
1238
1239         RETURN_OK();
1240 }
1241 #endif /* USE_TERMIOX */
1242 #endif /* __linux__ */
1243
1244 static enum sp_return get_config(struct sp_port *port, struct port_data *data,
1245         struct sp_port_config *config)
1246 {
1247         unsigned int i;
1248
1249         TRACE("%p, %p, %p", port, data, config);
1250
1251         DEBUG("Getting configuration for port %s", port->name);
1252
1253 #ifdef _WIN32
1254         if (!GetCommState(port->hdl, &data->dcb))
1255                 RETURN_FAIL("GetCommState() failed");
1256
1257         for (i = 0; i < NUM_STD_BAUDRATES; i++) {
1258                 if (data->dcb.BaudRate == std_baudrates[i].index) {
1259                         config->baudrate = std_baudrates[i].value;
1260                         break;
1261                 }
1262         }
1263
1264         if (i == NUM_STD_BAUDRATES)
1265                 /* BaudRate field can be either an index or a custom baud rate. */
1266                 config->baudrate = data->dcb.BaudRate;
1267
1268         config->bits = data->dcb.ByteSize;
1269
1270         if (data->dcb.fParity)
1271                 switch (data->dcb.Parity) {
1272                 case NOPARITY:
1273                         config->parity = SP_PARITY_NONE;
1274                         break;
1275                 case ODDPARITY:
1276                         config->parity = SP_PARITY_ODD;
1277                         break;
1278                 case EVENPARITY:
1279                         config->parity = SP_PARITY_EVEN;
1280                         break;
1281                 case MARKPARITY:
1282                         config->parity = SP_PARITY_MARK;
1283                         break;
1284                 case SPACEPARITY:
1285                         config->parity = SP_PARITY_SPACE;
1286                         break;
1287                 default:
1288                         config->parity = -1;
1289                 }
1290         else
1291                 config->parity = SP_PARITY_NONE;
1292
1293         switch (data->dcb.StopBits) {
1294         case ONESTOPBIT:
1295                 config->stopbits = 1;
1296                 break;
1297         case TWOSTOPBITS:
1298                 config->stopbits = 2;
1299                 break;
1300         default:
1301                 config->stopbits = -1;
1302         }
1303
1304         switch (data->dcb.fRtsControl) {
1305         case RTS_CONTROL_DISABLE:
1306                 config->rts = SP_RTS_OFF;
1307                 break;
1308         case RTS_CONTROL_ENABLE:
1309                 config->rts = SP_RTS_ON;
1310                 break;
1311         case RTS_CONTROL_HANDSHAKE:
1312                 config->rts = SP_RTS_FLOW_CONTROL;
1313                 break;
1314         default:
1315                 config->rts = -1;
1316         }
1317
1318         config->cts = data->dcb.fOutxCtsFlow ? SP_CTS_FLOW_CONTROL : SP_CTS_IGNORE;
1319
1320         switch (data->dcb.fDtrControl) {
1321         case DTR_CONTROL_DISABLE:
1322                 config->dtr = SP_DTR_OFF;
1323                 break;
1324         case DTR_CONTROL_ENABLE:
1325                 config->dtr = SP_DTR_ON;
1326                 break;
1327         case DTR_CONTROL_HANDSHAKE:
1328                 config->dtr = SP_DTR_FLOW_CONTROL;
1329                 break;
1330         default:
1331                 config->dtr = -1;
1332         }
1333
1334         config->dsr = data->dcb.fOutxDsrFlow ? SP_DSR_FLOW_CONTROL : SP_DSR_IGNORE;
1335
1336         if (data->dcb.fInX) {
1337                 if (data->dcb.fOutX)
1338                         config->xon_xoff = SP_XONXOFF_INOUT;
1339                 else
1340                         config->xon_xoff = SP_XONXOFF_IN;
1341         } else {
1342                 if (data->dcb.fOutX)
1343                         config->xon_xoff = SP_XONXOFF_OUT;
1344                 else
1345                         config->xon_xoff = SP_XONXOFF_DISABLED;
1346         }
1347
1348 #else // !_WIN32
1349
1350         if (tcgetattr(port->fd, &data->term) < 0)
1351                 RETURN_FAIL("tcgetattr() failed");
1352
1353         if (ioctl(port->fd, TIOCMGET, &data->controlbits) < 0)
1354                 RETURN_FAIL("TIOCMGET ioctl failed");
1355
1356 #ifdef USE_TERMIOX
1357         int ret = get_flow(port->fd, &data->flow);
1358
1359         if (ret == SP_ERR_FAIL && errno == EINVAL)
1360                 data->termiox_supported = 0;
1361         else if (ret < 0)
1362                 RETURN_CODEVAL(ret);
1363         else
1364                 data->termiox_supported = 1;
1365 #else
1366         data->termiox_supported = 0;
1367 #endif
1368
1369         for (i = 0; i < NUM_STD_BAUDRATES; i++) {
1370                 if (cfgetispeed(&data->term) == std_baudrates[i].index) {
1371                         config->baudrate = std_baudrates[i].value;
1372                         break;
1373                 }
1374         }
1375
1376         if (i == NUM_STD_BAUDRATES) {
1377 #ifdef __APPLE__
1378                 config->baudrate = (int)data->term.c_ispeed;
1379 #elif defined(__linux__)
1380                 TRY(get_baudrate(port->fd, &config->baudrate));
1381 #else
1382                 config->baudrate = -1;
1383 #endif
1384         }
1385
1386         switch (data->term.c_cflag & CSIZE) {
1387         case CS8:
1388                 config->bits = 8;
1389                 break;
1390         case CS7:
1391                 config->bits = 7;
1392                 break;
1393         case CS6:
1394                 config->bits = 6;
1395                 break;
1396         case CS5:
1397                 config->bits = 5;
1398                 break;
1399         default:
1400                 config->bits = -1;
1401         }
1402
1403         if (!(data->term.c_cflag & PARENB) && (data->term.c_iflag & IGNPAR))
1404                 config->parity = SP_PARITY_NONE;
1405         else if (!(data->term.c_cflag & PARENB) || (data->term.c_iflag & IGNPAR))
1406                 config->parity = -1;
1407 #ifdef CMSPAR
1408         else if (data->term.c_cflag & CMSPAR)
1409                 config->parity = (data->term.c_cflag & PARODD) ? SP_PARITY_MARK : SP_PARITY_SPACE;
1410 #endif
1411         else
1412                 config->parity = (data->term.c_cflag & PARODD) ? SP_PARITY_ODD : SP_PARITY_EVEN;
1413
1414         config->stopbits = (data->term.c_cflag & CSTOPB) ? 2 : 1;
1415
1416         if (data->term.c_cflag & CRTSCTS) {
1417                 config->rts = SP_RTS_FLOW_CONTROL;
1418                 config->cts = SP_CTS_FLOW_CONTROL;
1419         } else {
1420                 if (data->termiox_supported && data->flow & RTS_FLOW)
1421                         config->rts = SP_RTS_FLOW_CONTROL;
1422                 else
1423                         config->rts = (data->controlbits & TIOCM_RTS) ? SP_RTS_ON : SP_RTS_OFF;
1424
1425                 config->cts = (data->termiox_supported && data->flow & CTS_FLOW) ?
1426                         SP_CTS_FLOW_CONTROL : SP_CTS_IGNORE;
1427         }
1428
1429         if (data->termiox_supported && data->flow & DTR_FLOW)
1430                 config->dtr = SP_DTR_FLOW_CONTROL;
1431         else
1432                 config->dtr = (data->controlbits & TIOCM_DTR) ? SP_DTR_ON : SP_DTR_OFF;
1433
1434         config->dsr = (data->termiox_supported && data->flow & DSR_FLOW) ?
1435                 SP_DSR_FLOW_CONTROL : SP_DSR_IGNORE;
1436
1437         if (data->term.c_iflag & IXOFF) {
1438                 if (data->term.c_iflag & IXON)
1439                         config->xon_xoff = SP_XONXOFF_INOUT;
1440                 else
1441                         config->xon_xoff = SP_XONXOFF_IN;
1442         } else {
1443                 if (data->term.c_iflag & IXON)
1444                         config->xon_xoff = SP_XONXOFF_OUT;
1445                 else
1446                         config->xon_xoff = SP_XONXOFF_DISABLED;
1447         }
1448 #endif
1449
1450         RETURN_OK();
1451 }
1452
1453 static enum sp_return set_config(struct sp_port *port, struct port_data *data,
1454         const struct sp_port_config *config)
1455 {
1456         unsigned int i;
1457 #ifdef __APPLE__
1458         BAUD_TYPE baud_nonstd;
1459
1460         baud_nonstd = B0;
1461 #endif
1462 #ifdef __linux__
1463         int baud_nonstd = 0;
1464 #endif
1465
1466         TRACE("%p, %p, %p", port, data, config);
1467
1468         DEBUG("Setting configuration for port %s", port->name);
1469
1470 #ifdef _WIN32
1471         if (config->baudrate >= 0) {
1472                 for (i = 0; i < NUM_STD_BAUDRATES; i++) {
1473                         if (config->baudrate == std_baudrates[i].value) {
1474                                 data->dcb.BaudRate = std_baudrates[i].index;
1475                                 break;
1476                         }
1477                 }
1478
1479                 if (i == NUM_STD_BAUDRATES)
1480                         data->dcb.BaudRate = config->baudrate;
1481         }
1482
1483         if (config->bits >= 0)
1484                 data->dcb.ByteSize = config->bits;
1485
1486         if (config->parity >= 0) {
1487                 switch (config->parity) {
1488                 /* Note: There's also SPACEPARITY, MARKPARITY (unneeded so far). */
1489                 case SP_PARITY_NONE:
1490                         data->dcb.Parity = NOPARITY;
1491                         break;
1492                 case SP_PARITY_ODD:
1493                         data->dcb.Parity = ODDPARITY;
1494                         break;
1495                 case SP_PARITY_EVEN:
1496                         data->dcb.Parity = EVENPARITY;
1497                         break;
1498                 case SP_PARITY_MARK:
1499                         data->dcb.Parity = MARKPARITY;
1500                         break;
1501                 case SP_PARITY_SPACE:
1502                         data->dcb.Parity = SPACEPARITY;
1503                         break;
1504                 default:
1505                         RETURN_ERROR(SP_ERR_ARG, "Invalid parity setting");
1506                 }
1507         }
1508
1509         if (config->stopbits >= 0) {
1510                 switch (config->stopbits) {
1511                 /* Note: There's also ONE5STOPBITS == 1.5 (unneeded so far). */
1512                 case 1:
1513                         data->dcb.StopBits = ONESTOPBIT;
1514                         break;
1515                 case 2:
1516                         data->dcb.StopBits = TWOSTOPBITS;
1517                         break;
1518                 default:
1519                         RETURN_ERROR(SP_ERR_ARG, "Invalid stop bit setting");
1520                 }
1521         }
1522
1523         if (config->rts >= 0) {
1524                 switch (config->rts) {
1525                 case SP_RTS_OFF:
1526                         data->dcb.fRtsControl = RTS_CONTROL_DISABLE;
1527                         break;
1528                 case SP_RTS_ON:
1529                         data->dcb.fRtsControl = RTS_CONTROL_ENABLE;
1530                         break;
1531                 case SP_RTS_FLOW_CONTROL:
1532                         data->dcb.fRtsControl = RTS_CONTROL_HANDSHAKE;
1533                         break;
1534                 default:
1535                         RETURN_ERROR(SP_ERR_ARG, "Invalid RTS setting");
1536                 }
1537         }
1538
1539         if (config->cts >= 0) {
1540                 switch (config->cts) {
1541                 case SP_CTS_IGNORE:
1542                         data->dcb.fOutxCtsFlow = FALSE;
1543                         break;
1544                 case SP_CTS_FLOW_CONTROL:
1545                         data->dcb.fOutxCtsFlow = TRUE;
1546                         break;
1547                 default:
1548                         RETURN_ERROR(SP_ERR_ARG, "Invalid CTS setting");
1549                 }
1550         }
1551
1552         if (config->dtr >= 0) {
1553                 switch (config->dtr) {
1554                 case SP_DTR_OFF:
1555                         data->dcb.fDtrControl = DTR_CONTROL_DISABLE;
1556                         break;
1557                 case SP_DTR_ON:
1558                         data->dcb.fDtrControl = DTR_CONTROL_ENABLE;
1559                         break;
1560                 case SP_DTR_FLOW_CONTROL:
1561                         data->dcb.fDtrControl = DTR_CONTROL_HANDSHAKE;
1562                         break;
1563                 default:
1564                         RETURN_ERROR(SP_ERR_ARG, "Invalid DTR setting");
1565                 }
1566         }
1567
1568         if (config->dsr >= 0) {
1569                 switch (config->dsr) {
1570                 case SP_DSR_IGNORE:
1571                         data->dcb.fOutxDsrFlow = FALSE;
1572                         break;
1573                 case SP_DSR_FLOW_CONTROL:
1574                         data->dcb.fOutxDsrFlow = TRUE;
1575                         break;
1576                 default:
1577                         RETURN_ERROR(SP_ERR_ARG, "Invalid DSR setting");
1578                 }
1579         }
1580
1581         if (config->xon_xoff >= 0) {
1582                 switch (config->xon_xoff) {
1583                 case SP_XONXOFF_DISABLED:
1584                         data->dcb.fInX = FALSE;
1585                         data->dcb.fOutX = FALSE;
1586                         break;
1587                 case SP_XONXOFF_IN:
1588                         data->dcb.fInX = TRUE;
1589                         data->dcb.fOutX = FALSE;
1590                         break;
1591                 case SP_XONXOFF_OUT:
1592                         data->dcb.fInX = FALSE;
1593                         data->dcb.fOutX = TRUE;
1594                         break;
1595                 case SP_XONXOFF_INOUT:
1596                         data->dcb.fInX = TRUE;
1597                         data->dcb.fOutX = TRUE;
1598                         break;
1599                 default:
1600                         RETURN_ERROR(SP_ERR_ARG, "Invalid XON/XOFF setting");
1601                 }
1602         }
1603
1604         if (!SetCommState(port->hdl, &data->dcb))
1605                 RETURN_FAIL("SetCommState() failed");
1606
1607 #else /* !_WIN32 */
1608
1609         int controlbits;
1610
1611         if (config->baudrate >= 0) {
1612                 for (i = 0; i < NUM_STD_BAUDRATES; i++) {
1613                         if (config->baudrate == std_baudrates[i].value) {
1614                                 if (cfsetospeed(&data->term, std_baudrates[i].index) < 0)
1615                                         RETURN_FAIL("cfsetospeed() failed");
1616
1617                                 if (cfsetispeed(&data->term, std_baudrates[i].index) < 0)
1618                                         RETURN_FAIL("cfsetispeed() failed");
1619                                 break;
1620                         }
1621                 }
1622
1623                 /* Non-standard baud rate */
1624                 if (i == NUM_STD_BAUDRATES) {
1625 #ifdef __APPLE__
1626                         /* Set "dummy" baud rate. */
1627                         if (cfsetspeed(&data->term, B9600) < 0)
1628                                 RETURN_FAIL("cfsetspeed() failed");
1629                         baud_nonstd = config->baudrate;
1630 #elif defined(__linux__)
1631                         baud_nonstd = 1;
1632 #else
1633                         RETURN_ERROR(SP_ERR_SUPP, "Non-standard baudrate not supported");
1634 #endif
1635                 }
1636         }
1637
1638         if (config->bits >= 0) {
1639                 data->term.c_cflag &= ~CSIZE;
1640                 switch (config->bits) {
1641                 case 8:
1642                         data->term.c_cflag |= CS8;
1643                         break;
1644                 case 7:
1645                         data->term.c_cflag |= CS7;
1646                         break;
1647                 case 6:
1648                         data->term.c_cflag |= CS6;
1649                         break;
1650                 case 5:
1651                         data->term.c_cflag |= CS5;
1652                         break;
1653                 default:
1654                         RETURN_ERROR(SP_ERR_ARG, "Invalid data bits setting");
1655                 }
1656         }
1657
1658         if (config->parity >= 0) {
1659                 data->term.c_iflag &= ~IGNPAR;
1660                 data->term.c_cflag &= ~(PARENB | PARODD);
1661 #ifdef CMSPAR
1662                 data->term.c_cflag &= ~CMSPAR;
1663 #endif
1664                 switch (config->parity) {
1665                 case SP_PARITY_NONE:
1666                         data->term.c_iflag |= IGNPAR;
1667                         break;
1668                 case SP_PARITY_EVEN:
1669                         data->term.c_cflag |= PARENB;
1670                         break;
1671                 case SP_PARITY_ODD:
1672                         data->term.c_cflag |= PARENB | PARODD;
1673                         break;
1674 #ifdef CMSPAR
1675                 case SP_PARITY_MARK:
1676                         data->term.c_cflag |= PARENB | PARODD;
1677                         data->term.c_cflag |= CMSPAR;
1678                         break;
1679                 case SP_PARITY_SPACE:
1680                         data->term.c_cflag |= PARENB;
1681                         data->term.c_cflag |= CMSPAR;
1682                         break;
1683 #else
1684                 case SP_PARITY_MARK:
1685                 case SP_PARITY_SPACE:
1686                         RETURN_ERROR(SP_ERR_SUPP, "Mark/space parity not supported");
1687 #endif
1688                 default:
1689                         RETURN_ERROR(SP_ERR_ARG, "Invalid parity setting");
1690                 }
1691         }
1692
1693         if (config->stopbits >= 0) {
1694                 data->term.c_cflag &= ~CSTOPB;
1695                 switch (config->stopbits) {
1696                 case 1:
1697                         data->term.c_cflag &= ~CSTOPB;
1698                         break;
1699                 case 2:
1700                         data->term.c_cflag |= CSTOPB;
1701                         break;
1702                 default:
1703                         RETURN_ERROR(SP_ERR_ARG, "Invalid stop bits setting");
1704                 }
1705         }
1706
1707         if (config->rts >= 0 || config->cts >= 0) {
1708                 if (data->termiox_supported) {
1709                         data->flow &= ~(RTS_FLOW | CTS_FLOW);
1710                         switch (config->rts) {
1711                         case SP_RTS_OFF:
1712                         case SP_RTS_ON:
1713                                 controlbits = TIOCM_RTS;
1714                                 if (ioctl(port->fd, config->rts == SP_RTS_ON ? TIOCMBIS : TIOCMBIC, &controlbits) < 0)
1715                                         RETURN_FAIL("Setting RTS signal level failed");
1716                                 break;
1717                         case SP_RTS_FLOW_CONTROL:
1718                                 data->flow |= RTS_FLOW;
1719                                 break;
1720                         default:
1721                                 break;
1722                         }
1723                         if (config->cts == SP_CTS_FLOW_CONTROL)
1724                                 data->flow |= CTS_FLOW;
1725
1726                         if (data->flow & (RTS_FLOW | CTS_FLOW))
1727                                 data->term.c_iflag |= CRTSCTS;
1728                         else
1729                                 data->term.c_iflag &= ~CRTSCTS;
1730                 } else {
1731                         /* Asymmetric use of RTS/CTS not supported. */
1732                         if (data->term.c_iflag & CRTSCTS) {
1733                                 /* Flow control can only be disabled for both RTS & CTS together. */
1734                                 if (config->rts >= 0 && config->rts != SP_RTS_FLOW_CONTROL) {
1735                                         if (config->cts != SP_CTS_IGNORE)
1736                                                 RETURN_ERROR(SP_ERR_SUPP, "RTS & CTS flow control must be disabled together");
1737                                 }
1738                                 if (config->cts >= 0 && config->cts != SP_CTS_FLOW_CONTROL) {
1739                                         if (config->rts <= 0 || config->rts == SP_RTS_FLOW_CONTROL)
1740                                                 RETURN_ERROR(SP_ERR_SUPP, "RTS & CTS flow control must be disabled together");
1741                                 }
1742                         } else {
1743                                 /* Flow control can only be enabled for both RTS & CTS together. */
1744                                 if (((config->rts == SP_RTS_FLOW_CONTROL) && (config->cts != SP_CTS_FLOW_CONTROL)) ||
1745                                         ((config->cts == SP_CTS_FLOW_CONTROL) && (config->rts != SP_RTS_FLOW_CONTROL)))
1746                                         RETURN_ERROR(SP_ERR_SUPP, "RTS & CTS flow control must be enabled together");
1747                         }
1748
1749                         if (config->rts >= 0) {
1750                                 if (config->rts == SP_RTS_FLOW_CONTROL) {
1751                                         data->term.c_iflag |= CRTSCTS;
1752                                 } else {
1753                                         controlbits = TIOCM_RTS;
1754                                         if (ioctl(port->fd, config->rts == SP_RTS_ON ? TIOCMBIS : TIOCMBIC,
1755                                                         &controlbits) < 0)
1756                                                 RETURN_FAIL("Setting RTS signal level failed");
1757                                 }
1758                         }
1759                 }
1760         }
1761
1762         if (config->dtr >= 0 || config->dsr >= 0) {
1763                 if (data->termiox_supported) {
1764                         data->flow &= ~(DTR_FLOW | DSR_FLOW);
1765                         switch (config->dtr) {
1766                         case SP_DTR_OFF:
1767                         case SP_DTR_ON:
1768                                 controlbits = TIOCM_DTR;
1769                                 if (ioctl(port->fd, config->dtr == SP_DTR_ON ? TIOCMBIS : TIOCMBIC, &controlbits) < 0)
1770                                         RETURN_FAIL("Setting DTR signal level failed");
1771                                 break;
1772                         case SP_DTR_FLOW_CONTROL:
1773                                 data->flow |= DTR_FLOW;
1774                                 break;
1775                         default:
1776                                 break;
1777                         }
1778                         if (config->dsr == SP_DSR_FLOW_CONTROL)
1779                                 data->flow |= DSR_FLOW;
1780                 } else {
1781                         /* DTR/DSR flow control not supported. */
1782                         if (config->dtr == SP_DTR_FLOW_CONTROL || config->dsr == SP_DSR_FLOW_CONTROL)
1783                                 RETURN_ERROR(SP_ERR_SUPP, "DTR/DSR flow control not supported");
1784
1785                         if (config->dtr >= 0) {
1786                                 controlbits = TIOCM_DTR;
1787                                 if (ioctl(port->fd, config->dtr == SP_DTR_ON ? TIOCMBIS : TIOCMBIC,
1788                                                 &controlbits) < 0)
1789                                         RETURN_FAIL("Setting DTR signal level failed");
1790                         }
1791                 }
1792         }
1793
1794         if (config->xon_xoff >= 0) {
1795                 data->term.c_iflag &= ~(IXON | IXOFF | IXANY);
1796                 switch (config->xon_xoff) {
1797                 case SP_XONXOFF_DISABLED:
1798                         break;
1799                 case SP_XONXOFF_IN:
1800                         data->term.c_iflag |= IXOFF;
1801                         break;
1802                 case SP_XONXOFF_OUT:
1803                         data->term.c_iflag |= IXON | IXANY;
1804                         break;
1805                 case SP_XONXOFF_INOUT:
1806                         data->term.c_iflag |= IXON | IXOFF | IXANY;
1807                         break;
1808                 default:
1809                         RETURN_ERROR(SP_ERR_ARG, "Invalid XON/XOFF setting");
1810                 }
1811         }
1812
1813         if (tcsetattr(port->fd, TCSANOW, &data->term) < 0)
1814                 RETURN_FAIL("tcsetattr() failed");
1815
1816 #ifdef __APPLE__
1817         if (baud_nonstd != B0) {
1818                 if (ioctl(port->fd, IOSSIOSPEED, &baud_nonstd) == -1)
1819                         RETURN_FAIL("IOSSIOSPEED ioctl failed");
1820                 /* Set baud rates in data->term to correct, but incompatible
1821                  * with tcsetattr() value, same as delivered by tcgetattr(). */
1822                 if (cfsetspeed(&data->term, baud_nonstd) < 0)
1823                         RETURN_FAIL("cfsetspeed() failed");
1824         }
1825 #elif defined(__linux__)
1826         if (baud_nonstd)
1827                 TRY(set_baudrate(port->fd, config->baudrate));
1828 #ifdef USE_TERMIOX
1829         if (data->termiox_supported)
1830                 TRY(set_flow(port->fd, data->flow));
1831 #endif
1832 #endif
1833
1834 #endif /* !_WIN32 */
1835
1836         RETURN_OK();
1837 }
1838
1839 enum sp_return sp_new_config(struct sp_port_config **config_ptr)
1840 {
1841         struct sp_port_config *config;
1842
1843         TRACE("%p", config_ptr);
1844
1845         if (!config_ptr)
1846                 RETURN_ERROR(SP_ERR_ARG, "Null result pointer");
1847
1848         *config_ptr = NULL;
1849
1850         if (!(config = malloc(sizeof(struct sp_port_config))))
1851                 RETURN_ERROR(SP_ERR_MEM, "config malloc failed");
1852
1853         config->baudrate = -1;
1854         config->bits = -1;
1855         config->parity = -1;
1856         config->stopbits = -1;
1857         config->rts = -1;
1858         config->cts = -1;
1859         config->dtr = -1;
1860         config->dsr = -1;
1861
1862         *config_ptr = config;
1863
1864         RETURN_OK();
1865 }
1866
1867 void sp_free_config(struct sp_port_config *config)
1868 {
1869         TRACE("%p", config);
1870
1871         if (!config)
1872                 DEBUG("Null config");
1873         else
1874                 free(config);
1875
1876         RETURN();
1877 }
1878
1879 enum sp_return sp_get_config(struct sp_port *port, struct sp_port_config *config)
1880 {
1881         struct port_data data;
1882
1883         TRACE("%p, %p", port, config);
1884
1885         CHECK_OPEN_PORT();
1886
1887         if (!config)
1888                 RETURN_ERROR(SP_ERR_ARG, "Null config");
1889
1890         TRY(get_config(port, &data, config));
1891
1892         RETURN_OK();
1893 }
1894
1895 enum sp_return sp_set_config(struct sp_port *port, const struct sp_port_config *config)
1896 {
1897         struct port_data data;
1898         struct sp_port_config prev_config;
1899
1900         TRACE("%p, %p", port, config);
1901
1902         CHECK_OPEN_PORT();
1903
1904         if (!config)
1905                 RETURN_ERROR(SP_ERR_ARG, "Null config");
1906
1907         TRY(get_config(port, &data, &prev_config));
1908         TRY(set_config(port, &data, config));
1909
1910         RETURN_OK();
1911 }
1912
1913 #define CREATE_ACCESSORS(x, type) \
1914 enum sp_return sp_set_##x(struct sp_port *port, type x) { \
1915         struct port_data data; \
1916         struct sp_port_config config; \
1917         TRACE("%p, %d", port, x); \
1918         CHECK_OPEN_PORT(); \
1919         TRY(get_config(port, &data, &config)); \
1920         config.x = x; \
1921         TRY(set_config(port, &data, &config)); \
1922         RETURN_OK(); \
1923 } \
1924 enum sp_return sp_get_config_##x(const struct sp_port_config *config, type *x) { \
1925         TRACE("%p, %p", config, x); \
1926         if (!config) \
1927                 RETURN_ERROR(SP_ERR_ARG, "Null config"); \
1928         *x = config->x; \
1929         RETURN_OK(); \
1930 } \
1931 enum sp_return sp_set_config_##x(struct sp_port_config *config, type x) { \
1932         TRACE("%p, %d", config, x); \
1933         if (!config) \
1934                 RETURN_ERROR(SP_ERR_ARG, "Null config"); \
1935         config->x = x; \
1936         RETURN_OK(); \
1937 }
1938
1939 CREATE_ACCESSORS(baudrate, int)
1940 CREATE_ACCESSORS(bits, int)
1941 CREATE_ACCESSORS(parity, enum sp_parity)
1942 CREATE_ACCESSORS(stopbits, int)
1943 CREATE_ACCESSORS(rts, enum sp_rts)
1944 CREATE_ACCESSORS(cts, enum sp_cts)
1945 CREATE_ACCESSORS(dtr, enum sp_dtr)
1946 CREATE_ACCESSORS(dsr, enum sp_dsr)
1947 CREATE_ACCESSORS(xon_xoff, enum sp_xonxoff)
1948
1949 enum sp_return sp_set_config_flowcontrol(struct sp_port_config *config, enum sp_flowcontrol flowcontrol)
1950 {
1951         if (!config)
1952                 RETURN_ERROR(SP_ERR_ARG, "Null configuration");
1953
1954         if (flowcontrol > SP_FLOWCONTROL_DTRDSR)
1955                 RETURN_ERROR(SP_ERR_ARG, "Invalid flow control setting");
1956
1957         if (flowcontrol == SP_FLOWCONTROL_XONXOFF)
1958                 config->xon_xoff = SP_XONXOFF_INOUT;
1959         else
1960                 config->xon_xoff = SP_XONXOFF_DISABLED;
1961
1962         if (flowcontrol == SP_FLOWCONTROL_RTSCTS) {
1963                 config->rts = SP_RTS_FLOW_CONTROL;
1964                 config->cts = SP_CTS_FLOW_CONTROL;
1965         } else {
1966                 if (config->rts == SP_RTS_FLOW_CONTROL)
1967                         config->rts = SP_RTS_ON;
1968                 config->cts = SP_CTS_IGNORE;
1969         }
1970
1971         if (flowcontrol == SP_FLOWCONTROL_DTRDSR) {
1972                 config->dtr = SP_DTR_FLOW_CONTROL;
1973                 config->dsr = SP_DSR_FLOW_CONTROL;
1974         } else {
1975                 if (config->dtr == SP_DTR_FLOW_CONTROL)
1976                         config->dtr = SP_DTR_ON;
1977                 config->dsr = SP_DSR_IGNORE;
1978         }
1979
1980         RETURN_OK();
1981 }
1982
1983 enum sp_return sp_set_flowcontrol(struct sp_port *port, enum sp_flowcontrol flowcontrol)
1984 {
1985         struct port_data data;
1986         struct sp_port_config config;
1987
1988         TRACE("%p, %d", port, flowcontrol);
1989
1990         CHECK_OPEN_PORT();
1991
1992         TRY(get_config(port, &data, &config));
1993
1994         TRY(sp_set_config_flowcontrol(&config, flowcontrol));
1995
1996         TRY(set_config(port, &data, &config));
1997
1998         RETURN_OK();
1999 }
2000
2001 enum sp_return sp_get_signals(struct sp_port *port, enum sp_signal *signals)
2002 {
2003         TRACE("%p, %p", port, signals);
2004
2005         CHECK_OPEN_PORT();
2006
2007         if (!signals)
2008                 RETURN_ERROR(SP_ERR_ARG, "Null result pointer");
2009
2010         DEBUG("Getting control signals for port %s", port->name);
2011
2012         *signals = 0;
2013 #ifdef _WIN32
2014         DWORD bits;
2015         if (GetCommModemStatus(port->hdl, &bits) == 0)
2016                 RETURN_FAIL("GetCommModemStatus() failed");
2017         if (bits & MS_CTS_ON)
2018                 *signals |= SP_SIG_CTS;
2019         if (bits & MS_DSR_ON)
2020                 *signals |= SP_SIG_DSR;
2021         if (bits & MS_RLSD_ON)
2022                 *signals |= SP_SIG_DCD;
2023         if (bits & MS_RING_ON)
2024                 *signals |= SP_SIG_RI;
2025 #else
2026         int bits;
2027         if (ioctl(port->fd, TIOCMGET, &bits) < 0)
2028                 RETURN_FAIL("TIOCMGET ioctl failed");
2029         if (bits & TIOCM_CTS)
2030                 *signals |= SP_SIG_CTS;
2031         if (bits & TIOCM_DSR)
2032                 *signals |= SP_SIG_DSR;
2033         if (bits & TIOCM_CAR)
2034                 *signals |= SP_SIG_DCD;
2035         if (bits & TIOCM_RNG)
2036                 *signals |= SP_SIG_RI;
2037 #endif
2038         RETURN_OK();
2039 }
2040
2041 enum sp_return sp_start_break(struct sp_port *port)
2042 {
2043         TRACE("%p", port);
2044
2045         CHECK_OPEN_PORT();
2046 #ifdef _WIN32
2047         if (SetCommBreak(port->hdl) == 0)
2048                 RETURN_FAIL("SetCommBreak() failed");
2049 #else
2050         if (ioctl(port->fd, TIOCSBRK, 1) < 0)
2051                 RETURN_FAIL("TIOCSBRK ioctl failed");
2052 #endif
2053
2054         RETURN_OK();
2055 }
2056
2057 enum sp_return sp_end_break(struct sp_port *port)
2058 {
2059         TRACE("%p", port);
2060
2061         CHECK_OPEN_PORT();
2062 #ifdef _WIN32
2063         if (ClearCommBreak(port->hdl) == 0)
2064                 RETURN_FAIL("ClearCommBreak() failed");
2065 #else
2066         if (ioctl(port->fd, TIOCCBRK, 1) < 0)
2067                 RETURN_FAIL("TIOCCBRK ioctl failed");
2068 #endif
2069
2070         RETURN_OK();
2071 }
2072
2073 int sp_last_error_code(void)
2074 {
2075         TRACE("");
2076 #ifdef _WIN32
2077         RETURN_VALUE("%d", GetLastError());
2078 #else
2079         RETURN_VALUE("%d", errno);
2080 #endif
2081 }
2082
2083 char *sp_last_error_message(void)
2084 {
2085         TRACE("");
2086
2087 #ifdef _WIN32
2088         LPVOID message;
2089         DWORD error = GetLastError();
2090
2091         FormatMessage(
2092                 FORMAT_MESSAGE_ALLOCATE_BUFFER |
2093                 FORMAT_MESSAGE_FROM_SYSTEM |
2094                 FORMAT_MESSAGE_IGNORE_INSERTS,
2095                 NULL,
2096                 error,
2097                 MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
2098                 (LPTSTR) &message,
2099                 0, NULL );
2100
2101         RETURN_VALUE("%s", message);
2102 #else
2103         RETURN_VALUE("%s", strerror(errno));
2104 #endif
2105 }
2106
2107 void sp_free_error_message(char *message)
2108 {
2109         TRACE("%s", message);
2110
2111 #ifdef _WIN32
2112         LocalFree(message);
2113 #else
2114         (void)message;
2115 #endif
2116
2117         RETURN();
2118 }
2119
2120 void sp_set_debug_handler(void (*handler)(const char *format, ...))
2121 {
2122         TRACE("%p", handler);
2123
2124         sp_debug_handler = handler;
2125
2126         RETURN();
2127 }
2128
2129 void sp_default_debug_handler(const char *format, ...)
2130 {
2131         va_list args;
2132         va_start(args, format);
2133         if (getenv("LIBSERIALPORT_DEBUG")) {
2134                 fputs("sp: ", stderr);
2135                 vfprintf(stderr, format, args);
2136         }
2137         va_end(args);
2138 }