]> sigrok.org Git - libserialport.git/blob - serialport.c
Make sure OS handles are set correctly for unopened / closed ports.
[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  *
8  * This program is free software: you can redistribute it and/or modify
9  * it under the terms of the GNU Lesser General Public License as
10  * published by the Free Software Foundation, either version 3 of the
11  * License, or (at your option) any later version.
12  *
13  * This program is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16  * GNU General Public License for more details.
17  *
18  * You should have received a copy of the GNU Lesser General Public License
19  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
20  */
21
22 #include <string.h>
23 #include <sys/types.h>
24 #include <sys/stat.h>
25 #include <fcntl.h>
26 #include <unistd.h>
27 #include <stdlib.h>
28 #include <errno.h>
29 #ifdef _WIN32
30 #include <windows.h>
31 #include <tchar.h>
32 #include <stdio.h>
33 #else
34 #include <termios.h>
35 #include <sys/ioctl.h>
36 #endif
37 #ifdef __APPLE__
38 #include <IOKit/IOKitLib.h>
39 #include <IOKit/serial/IOSerialKeys.h>
40 #include <sys/syslimits.h>
41 #endif
42 #ifdef __linux__
43 #include "libudev.h"
44 #include "linux/serial.h"
45 #endif
46
47 #include "libserialport.h"
48
49 struct sp_port_data {
50 #ifdef _WIN32
51         DCB dcb;
52 #else
53         struct termios term;
54         int controlbits;
55 #endif
56 };
57
58 /* Standard baud rates. */
59 #ifdef _WIN32
60 #define BAUD_TYPE DWORD
61 #define BAUD(n) {CBR_##n, n}
62 #else
63 #define BAUD_TYPE speed_t
64 #define BAUD(n) {B##n, n}
65 #endif
66
67 struct std_baudrate {
68         BAUD_TYPE index;
69         int value;
70 };
71
72 const struct std_baudrate std_baudrates[] = {
73 #ifdef _WIN32
74         /*
75          * The baudrates 50/75/134/150/200/1800/230400/460800 do not seem to
76          * have documented CBR_* macros.
77          */
78         BAUD(110), BAUD(300), BAUD(600), BAUD(1200), BAUD(2400), BAUD(4800),
79         BAUD(9600), BAUD(14400), BAUD(19200), BAUD(38400), BAUD(57600),
80         BAUD(115200), BAUD(128000), BAUD(256000)
81 #else
82         BAUD(50), BAUD(75), BAUD(110), BAUD(134), BAUD(150), BAUD(200), BAUD(300),
83         BAUD(600), BAUD(1200), BAUD(1800), BAUD(2400), BAUD(4800), BAUD(9600),
84         BAUD(19200), BAUD(38400), BAUD(57600), BAUD(115200), BAUD(230400),
85 #if !defined(__APPLE__) && !defined(__OpenBSD__)
86         BAUD(460800)
87 #endif
88 #endif
89 };
90
91 #define ARRAY_SIZE(x) (sizeof(x) / sizeof(x[0]))
92 #define NUM_STD_BAUDRATES ARRAY_SIZE(std_baudrates)
93
94 /* Helper functions for configuring ports. */
95 static int get_config(struct sp_port *port, struct sp_port_data *data, struct sp_port_config *config);
96 static int set_config(struct sp_port *port, struct sp_port_data *data, struct sp_port_config *config);
97
98 int sp_get_port_by_name(const char *portname, struct sp_port **port_ptr)
99 {
100         struct sp_port *port;
101         int len;
102
103         if (!port_ptr)
104                 return SP_ERR_ARG;
105
106         *port_ptr = NULL;
107
108         if (!portname)
109                 return SP_ERR_ARG;
110
111         if (!(port = malloc(sizeof(struct sp_port))))
112                 return SP_ERR_MEM;
113
114         len = strlen(portname) + 1;
115
116         if (!(port->name = malloc(len)))
117         {
118                 free(port);
119                 return SP_ERR_MEM;
120         }
121
122         memcpy(port->name, portname, len);
123
124 #ifdef _WIN32
125         port->hdl = INVALID_HANDLE_VALUE;
126 #else
127         port->fd = -1;
128 #endif
129
130         *port_ptr = port;
131
132         return SP_OK;
133 }
134
135 int sp_copy_port(const struct sp_port *port, struct sp_port **copy_ptr)
136 {
137         if (!copy_ptr)
138                 return SP_ERR_ARG;
139
140         *copy_ptr = NULL;
141
142         if (!port || !port->name)
143                 return SP_ERR_ARG;
144
145         return sp_get_port_by_name(port->name, copy_ptr);
146 }
147
148 void sp_free_port(struct sp_port *port)
149 {
150         if (!port)
151                 return;
152
153         if (port->name)
154                 free(port->name);
155
156         free(port);
157 }
158
159 static struct sp_port **sp_list_append(struct sp_port **list, const char *portname)
160 {
161         void *tmp;
162         unsigned int count;
163
164         for (count = 0; list[count]; count++);
165         if (!(tmp = realloc(list, sizeof(struct sp_port *) * (count + 2))))
166                 goto fail;
167         list = tmp;
168         if (sp_get_port_by_name(portname, &list[count]) != SP_OK)
169                 goto fail;
170         list[count + 1] = NULL;
171         return list;
172
173 fail:
174         sp_free_port_list(list);
175         return NULL;
176 }
177
178 int sp_list_ports(struct sp_port ***list_ptr)
179 {
180         struct sp_port **list;
181         int ret = SP_OK;
182
183         if (!(list = malloc(sizeof(struct sp_port **))))
184                 return SP_ERR_MEM;
185
186         list[0] = NULL;
187
188 #ifdef _WIN32
189         HKEY key;
190         TCHAR *value, *data;
191         DWORD max_value_len, max_data_size, max_data_len;
192         DWORD value_len, data_size, data_len;
193         DWORD type, index = 0;
194         char *name;
195         int name_len;
196
197         if (RegOpenKeyEx(HKEY_LOCAL_MACHINE, _T("HARDWARE\\DEVICEMAP\\SERIALCOMM"),
198                         0, KEY_QUERY_VALUE, &key) != ERROR_SUCCESS)
199         {
200                 ret = SP_ERR_FAIL;
201                 goto out_done;
202         }
203         if (RegQueryInfoKey(key, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
204                                 &max_value_len, &max_data_size, NULL, NULL) != ERROR_SUCCESS)
205         {
206                 ret = SP_ERR_FAIL;
207                 goto out_close;
208         }
209         max_data_len = max_data_size / sizeof(TCHAR);
210         if (!(value = malloc((max_value_len + 1) * sizeof(TCHAR))))
211         {
212                 ret = SP_ERR_MEM;
213                 goto out_close;
214         }
215         if (!(data = malloc((max_data_len + 1) * sizeof(TCHAR))))
216         {
217                 ret = SP_ERR_MEM;
218                 goto out_free_value;
219         }
220         while (
221                 value_len = max_value_len + 1,
222                 data_size = max_data_size,
223                 RegEnumValue(key, index, value, &value_len,
224                         NULL, &type, (LPBYTE)data, &data_size) == ERROR_SUCCESS)
225         {
226                 data_len = data_size / sizeof(TCHAR);
227                 data[data_len] = '\0';
228 #ifdef UNICODE
229                 name_len = WideCharToMultiByte(CP_ACP, 0, data, -1, NULL, 0, NULL, NULL)
230 #else
231                 name_len = data_len + 1;
232 #endif
233                 if (!(name = malloc(name_len)))
234                 {
235                         ret = SP_ERR_MEM;
236                         goto out;
237                 }
238 #ifdef UNICODE
239                 WideCharToMultiByte(CP_ACP, 0, data, -1, name, name_len, NULL, NULL);
240 #else
241                 strcpy(name, data);
242 #endif
243                 if (type == REG_SZ && !(list = sp_list_append(list, name)))
244                 {
245                         ret = SP_ERR_MEM;
246                         goto out;
247                 }
248                 index++;
249         }
250 out:
251         free(data);
252 out_free_value:
253         free(value);
254 out_close:
255         RegCloseKey(key);
256 out_done:
257 #endif
258 #ifdef __APPLE__
259         mach_port_t master;
260         CFMutableDictionaryRef classes;
261         io_iterator_t iter;
262         char *path;
263         io_object_t port;
264         CFTypeRef cf_path;
265         Boolean result;
266
267         if (IOMasterPort(MACH_PORT_NULL, &master) != KERN_SUCCESS)
268         {
269                 ret = SP_ERR_FAIL;
270                 goto out_done;
271         }
272
273         if (!(classes = IOServiceMatching(kIOSerialBSDServiceValue)))
274         {
275                 ret = SP_ERR_FAIL;
276                 goto out_done;
277         }
278
279         CFDictionarySetValue(classes,
280                         CFSTR(kIOSerialBSDTypeKey), CFSTR(kIOSerialBSDAllTypes));
281
282         if (IOServiceGetMatchingServices(master, classes, &iter) != KERN_SUCCESS)
283         {
284                 ret = SP_ERR_FAIL;
285                 goto out_done;
286         }
287
288         if (!(path = malloc(PATH_MAX)))
289         {
290                 ret = SP_ERR_MEM;
291                 goto out_release;
292         }
293
294         while ((port = IOIteratorNext(iter))) {
295                 cf_path = IORegistryEntryCreateCFProperty(port,
296                                 CFSTR(kIOCalloutDeviceKey), kCFAllocatorDefault, 0);
297                 if (cf_path) {
298                         result = CFStringGetCString(cf_path,
299                                         path, PATH_MAX, kCFStringEncodingASCII);
300                         CFRelease(cf_path);
301                         if (result && !(list = sp_list_append(list, path)))
302                         {
303                                 ret = SP_ERR_MEM;
304                                 IOObjectRelease(port);
305                                 goto out;
306                         }
307                 }
308                 IOObjectRelease(port);
309         }
310 out:
311         free(path);
312 out_release:
313         IOObjectRelease(iter);
314 out_done:
315 #endif
316 #ifdef __linux__
317         struct udev *ud;
318         struct udev_enumerate *ud_enumerate;
319         struct udev_list_entry *ud_list;
320         struct udev_list_entry *ud_entry;
321         const char *path;
322         struct udev_device *ud_dev, *ud_parent;
323         const char *name;
324         const char *driver;
325         int fd, ioctl_result;
326         struct serial_struct serial_info;
327
328         ud = udev_new();
329         ud_enumerate = udev_enumerate_new(ud);
330         udev_enumerate_add_match_subsystem(ud_enumerate, "tty");
331         udev_enumerate_scan_devices(ud_enumerate);
332         ud_list = udev_enumerate_get_list_entry(ud_enumerate);
333         udev_list_entry_foreach(ud_entry, ud_list)
334         {
335                 path = udev_list_entry_get_name(ud_entry);
336                 ud_dev = udev_device_new_from_syspath(ud, path);
337                 /* If there is no parent device, this is a virtual tty. */
338                 ud_parent = udev_device_get_parent(ud_dev);
339                 if (ud_parent == NULL)
340                 {
341                         udev_device_unref(ud_dev);
342                         continue;
343                 }
344                 name = udev_device_get_devnode(ud_dev);
345                 /* The serial8250 driver has a hardcoded number of ports.
346                  * The only way to tell which actually exist on a given system
347                  * is to try to open them and make an ioctl call. */
348                 driver = udev_device_get_driver(ud_parent);
349                 if (driver && !strcmp(driver, "serial8250"))
350                 {
351                         if ((fd = open(name, O_RDWR | O_NONBLOCK | O_NOCTTY)) < 0)
352                                 goto skip;
353                         ioctl_result = ioctl(fd, TIOCGSERIAL, &serial_info);
354                         close(fd);
355                         if (ioctl_result != 0)
356                                 goto skip;
357                         if (serial_info.type == PORT_UNKNOWN)
358                                 goto skip;
359                 }
360                 list = sp_list_append(list, name);
361 skip:
362                 udev_device_unref(ud_dev);
363                 if (!list)
364                 {
365                         ret = SP_ERR_MEM;
366                         goto out;
367                 }
368         }
369 out:
370         udev_enumerate_unref(ud_enumerate);
371         udev_unref(ud);
372 #endif
373
374         if (ret == SP_OK)
375         {
376                 *list_ptr = list;
377         }
378         else
379         {
380                 if (list)
381                         sp_free_port_list(list);
382
383                 *list_ptr = NULL;
384         }
385
386         return ret;
387 }
388
389 void sp_free_port_list(struct sp_port **list)
390 {
391         unsigned int i;
392
393         for (i = 0; list[i]; i++)
394                 sp_free_port(list[i]);
395         free(list);
396 }
397
398 static int sp_validate_port(struct sp_port *port)
399 {
400         if (port == NULL)
401                 return 0;
402 #ifdef _WIN32
403         if (port->hdl == INVALID_HANDLE_VALUE)
404                 return 0;
405 #else
406         if (port->fd < 0)
407                 return 0;
408 #endif
409         return 1;
410 }
411
412 #define CHECK_PORT() do { if (!sp_validate_port(port)) return SP_ERR_ARG; } while (0)
413
414 int sp_open(struct sp_port *port, int flags)
415 {
416         if (!port)
417                 return SP_ERR_ARG;
418
419 #ifdef _WIN32
420         DWORD desired_access = 0, flags_and_attributes = 0;
421         char *escaped_port_name;
422
423         /* Prefix port name with '\\.\' to work with ports above COM9. */
424         if (!(escaped_port_name = malloc(strlen(port->name + 5))))
425                 return SP_ERR_MEM;
426         sprintf(escaped_port_name, "\\\\.\\%s", port->name);
427
428         /* Map 'flags' to the OS-specific settings. */
429         desired_access |= GENERIC_READ;
430         flags_and_attributes = FILE_ATTRIBUTE_NORMAL;
431         if (flags & SP_MODE_RDWR)
432                 desired_access |= GENERIC_WRITE;
433         if (flags & SP_MODE_NONBLOCK)
434                 flags_and_attributes |= FILE_FLAG_OVERLAPPED;
435
436         port->hdl = CreateFile(escaped_port_name, desired_access, 0, 0,
437                          OPEN_EXISTING, flags_and_attributes, 0);
438
439         free(escaped_port_name);
440
441         if (port->hdl == INVALID_HANDLE_VALUE)
442                 return SP_ERR_FAIL;
443 #else
444         int flags_local = 0;
445         struct sp_port_data data;
446         struct sp_port_config config;
447         int ret;
448
449         /* Map 'flags' to the OS-specific settings. */
450         if (flags & SP_MODE_RDWR)
451                 flags_local |= O_RDWR;
452         if (flags & SP_MODE_RDONLY)
453                 flags_local |= O_RDONLY;
454         if (flags & SP_MODE_NONBLOCK)
455                 flags_local |= O_NONBLOCK;
456
457         if ((port->fd = open(port->name, flags_local)) < 0)
458                 return SP_ERR_FAIL;
459
460         ret = get_config(port, &data, &config);
461
462         if (ret < 0)
463         {
464                 sp_close(port);
465                 return ret;
466         }
467
468         /* Turn off all serial port cooking. */
469         data.term.c_iflag &= ~(ISTRIP | INLCR | ICRNL);
470         data.term.c_oflag &= ~(ONLCR | OCRNL | ONOCR);
471 #if !defined(__FreeBSD__) && !defined(__OpenBSD__) && !defined(__NetBSD__)
472         data.term.c_oflag &= ~OFILL;
473 #endif
474         /* Disable canonical mode, and don't echo input characters. */
475         data.term.c_lflag &= ~(ICANON | ECHO);
476
477         /* Ignore modem status lines; enable receiver */
478         data.term.c_cflag |= (CLOCAL | CREAD);
479
480         ret = set_config(port, &data, &config);
481
482         if (ret < 0)
483         {
484                 sp_close(port);
485                 return ret;
486         }
487 #endif
488
489         return SP_OK;
490 }
491
492 int sp_close(struct sp_port *port)
493 {
494         CHECK_PORT();
495
496 #ifdef _WIN32
497         /* Returns non-zero upon success, 0 upon failure. */
498         if (CloseHandle(port->hdl) == 0)
499                 return SP_ERR_FAIL;
500         port->hdl = INVALID_HANDLE_VALUE;
501 #else
502         /* Returns 0 upon success, -1 upon failure. */
503         if (close(port->fd) == -1)
504                 return SP_ERR_FAIL;
505         port->fd = -1;
506 #endif
507
508         return SP_OK;
509 }
510
511 int sp_flush(struct sp_port *port)
512 {
513         CHECK_PORT();
514
515 #ifdef _WIN32
516         /* Returns non-zero upon success, 0 upon failure. */
517         if (PurgeComm(port->hdl, PURGE_RXCLEAR | PURGE_TXCLEAR) == 0)
518                 return SP_ERR_FAIL;
519 #else
520         /* Returns 0 upon success, -1 upon failure. */
521         if (tcflush(port->fd, TCIOFLUSH) < 0)
522                 return SP_ERR_FAIL;
523 #endif
524         return SP_OK;
525 }
526
527 int sp_write(struct sp_port *port, const void *buf, size_t count)
528 {
529         CHECK_PORT();
530
531         if (!buf)
532                 return SP_ERR_ARG;
533
534 #ifdef _WIN32
535         DWORD written = 0;
536
537         /* Returns non-zero upon success, 0 upon failure. */
538         if (WriteFile(port->hdl, buf, count, &written, NULL) == 0)
539                 return SP_ERR_FAIL;
540         return written;
541 #else
542         /* Returns the number of bytes written, or -1 upon failure. */
543         ssize_t written = write(port->fd, buf, count);
544
545         if (written < 0)
546                 return SP_ERR_FAIL;
547         else
548                 return written;
549 #endif
550 }
551
552 int sp_read(struct sp_port *port, void *buf, size_t count)
553 {
554         CHECK_PORT();
555
556         if (!buf)
557                 return SP_ERR_ARG;
558
559 #ifdef _WIN32
560         DWORD bytes_read = 0;
561
562         /* Returns non-zero upon success, 0 upon failure. */
563         if (ReadFile(port->hdl, buf, count, &bytes_read, NULL) == 0)
564                 return SP_ERR_FAIL;
565         return bytes_read;
566 #else
567         ssize_t bytes_read;
568
569         /* Returns the number of bytes read, or -1 upon failure. */
570         if ((bytes_read = read(port->fd, buf, count)) < 0)
571                 return SP_ERR_FAIL;
572         return bytes_read;
573 #endif
574 }
575
576 static int get_config(struct sp_port *port, struct sp_port_data *data, struct sp_port_config *config)
577 {
578         unsigned int i;
579
580 #ifdef _WIN32
581         if (!GetCommState(port->hdl, &data->dcb))
582                 return SP_ERR_FAIL;
583
584         for (i = 0; i < NUM_STD_BAUDRATES; i++) {
585                 if (data->dcb.BaudRate == std_baudrates[i].index) {
586                         config->baudrate = std_baudrates[i].value;
587                         break;
588                 }
589         }
590
591         if (i == NUM_STD_BAUDRATES)
592                 /* BaudRate field can be either an index or a custom baud rate. */
593                 config->baudrate = data->dcb.BaudRate;
594
595         config->bits = data->dcb.ByteSize;
596
597         if (data->dcb.fParity)
598                 switch (data->dcb.Parity) {
599                 case NOPARITY:
600                         config->parity = SP_PARITY_NONE;
601                         break;
602                 case EVENPARITY:
603                         config->parity = SP_PARITY_EVEN;
604                         break;
605                 case ODDPARITY:
606                         config->parity = SP_PARITY_ODD;
607                         break;
608                 default:
609                         config->parity = -1;
610                 }
611         else
612                 config->parity = SP_PARITY_NONE;
613
614         switch (data->dcb.StopBits) {
615         case ONESTOPBIT:
616                 config->stopbits = 1;
617                 break;
618         case TWOSTOPBITS:
619                 config->stopbits = 2;
620                 break;
621         default:
622                 config->stopbits = -1;
623         }
624
625         switch (data->dcb.fRtsControl) {
626                 case RTS_CONTROL_DISABLE:
627                         config->rts = SP_RTS_OFF;
628                         break;
629                 case RTS_CONTROL_ENABLE:
630                         config->rts = SP_RTS_ON;
631                         break;
632                 case RTS_CONTROL_HANDSHAKE:
633                         config->rts = SP_RTS_FLOW_CONTROL;
634                         break;
635                 default:
636                         config->rts = -1;
637         }
638
639         config->cts = data->dcb.fOutxCtsFlow ? SP_CTS_FLOW_CONTROL : SP_CTS_IGNORE;
640
641         switch (data->dcb.fDtrControl) {
642                 case DTR_CONTROL_DISABLE:
643                         config->dtr = SP_DTR_OFF;
644                         break;
645                 case DTR_CONTROL_ENABLE:
646                         config->dtr = SP_DTR_ON;
647                         break;
648                 case DTR_CONTROL_HANDSHAKE:
649                         config->dtr = SP_DTR_FLOW_CONTROL;
650                         break;
651                 default:
652                         config->dtr = -1;
653         }
654
655         config->dsr = data->dcb.fOutxDsrFlow ? SP_DSR_FLOW_CONTROL : SP_DSR_IGNORE;
656
657         if (data->dcb.fInX) {
658                 if (data->dcb.fOutX)
659                         config->xon_xoff = SP_XONXOFF_INOUT;
660                 else
661                         config->xon_xoff = SP_XONXOFF_IN;
662         } else {
663                 if (data->dcb.fOutX)
664                         config->xon_xoff = SP_XONXOFF_OUT;
665                 else
666                         config->xon_xoff = SP_XONXOFF_DISABLED;
667         }
668
669 #else // !_WIN32
670
671         if (tcgetattr(port->fd, &data->term) < 0)
672                 return SP_ERR_FAIL;
673
674         if (ioctl(port->fd, TIOCMGET, &data->controlbits) < 0)
675                 return SP_ERR_FAIL;
676         for (i = 0; i < NUM_STD_BAUDRATES; i++) {
677                 if (cfgetispeed(&data->term) == std_baudrates[i].index) {
678                         config->baudrate = std_baudrates[i].value;
679                         break;
680                 }
681         }
682
683         if (i == NUM_STD_BAUDRATES)
684                 config->baudrate = -1;
685
686         switch (data->term.c_cflag & CSIZE) {
687         case CS8:
688                 config->bits = 8;
689                 break;
690         case CS7:
691                 config->bits = 7;
692                 break;
693         case CS6:
694                 config->bits = 6;
695                 break;
696         case CS5:
697                 config->bits = 5;
698                 break;
699         default:
700                 config->bits = -1;
701         }
702
703         if (!(data->term.c_cflag & PARENB) && (data->term.c_iflag & IGNPAR))
704                 config->parity = SP_PARITY_NONE;
705         else if (!(data->term.c_cflag & PARENB) || (data->term.c_iflag & IGNPAR))
706                 config->parity = -1;
707         else
708                 config->parity = (data->term.c_cflag & PARODD) ? SP_PARITY_ODD : SP_PARITY_EVEN;
709
710         config->stopbits = (data->term.c_cflag & CSTOPB) ? 2 : 1;
711
712         if (data->term.c_cflag & CRTSCTS) {
713                 config->rts = SP_RTS_FLOW_CONTROL;
714                 config->cts = SP_CTS_FLOW_CONTROL;
715         } else {
716                 config->rts = (data->controlbits & TIOCM_RTS) ? SP_RTS_ON : SP_RTS_OFF;
717                 config->cts = SP_CTS_IGNORE;
718         }
719
720         config->dtr = (data->controlbits & TIOCM_DTR) ? SP_DTR_ON : SP_DTR_OFF;
721         config->dsr = SP_DSR_IGNORE;
722 #endif
723
724         return SP_OK;
725 }
726
727 static int set_config(struct sp_port *port, struct sp_port_data *data, struct sp_port_config *config)
728 {
729         unsigned int i;
730
731 #ifdef _WIN32
732         if (config->baudrate >= 0)
733         {
734                 for (i = 0; i < NUM_STD_BAUDRATES; i++) {
735                         if (config->baudrate == std_baudrates[i].value) {
736                                 data->dcb.BaudRate = std_baudrates[i].index;
737                                 break;
738                         }
739                 }
740
741                 if (i == NUM_STD_BAUDRATES)
742                         data->dcb.BaudRate = config->baudrate;
743         }
744
745         if (config->bits >= 0)
746                 data->dcb.ByteSize = config->bits;
747
748         if (config->parity >= 0) {
749                 switch (config->parity) {
750                 /* Note: There's also SPACEPARITY, MARKPARITY (unneeded so far). */
751                 case SP_PARITY_NONE:
752                         data->dcb.Parity = NOPARITY;
753                         break;
754                 case SP_PARITY_EVEN:
755                         data->dcb.Parity = EVENPARITY;
756                         break;
757                 case SP_PARITY_ODD:
758                         data->dcb.Parity = ODDPARITY;
759                         break;
760                 default:
761                         return SP_ERR_ARG;
762                 }
763         }
764
765         if (config->stopbits >= 0) {
766                 switch (config->stopbits) {
767                 /* Note: There's also ONE5STOPBITS == 1.5 (unneeded so far). */
768                 case 1:
769                         data->dcb.StopBits = ONESTOPBIT;
770                         break;
771                 case 2:
772                         data->dcb.StopBits = TWOSTOPBITS;
773                         break;
774                 default:
775                         return SP_ERR_ARG;
776                 }
777         }
778
779         if (config->rts >= 0) {
780                 switch (config->rts) {
781                 case SP_RTS_OFF:
782                         data->dcb.fRtsControl = RTS_CONTROL_DISABLE;
783                         break;
784                 case SP_RTS_ON:
785                         data->dcb.fRtsControl = RTS_CONTROL_ENABLE;
786                         break;
787                 case SP_RTS_FLOW_CONTROL:
788                         data->dcb.fRtsControl = RTS_CONTROL_HANDSHAKE;
789                         break;
790                 default:
791                         return SP_ERR_ARG;
792                 }
793         }
794
795         if (config->cts >= 0) {
796                 switch (config->cts) {
797                 case SP_CTS_IGNORE:
798                         data->dcb.fOutxCtsFlow = FALSE;
799                         break;
800                 case SP_CTS_FLOW_CONTROL:
801                         data->dcb.fOutxCtsFlow = TRUE;
802                         break;
803                 default:
804                         return SP_ERR_ARG;
805                 }
806         }
807
808         if (config->dtr >= 0) {
809                 switch (config->dtr) {
810                 case SP_DTR_OFF:
811                         data->dcb.fDtrControl = DTR_CONTROL_DISABLE;
812                         break;
813                 case SP_DTR_ON:
814                         data->dcb.fDtrControl = DTR_CONTROL_ENABLE;
815                         break;
816                 case SP_DTR_FLOW_CONTROL:
817                         data->dcb.fDtrControl = DTR_CONTROL_HANDSHAKE;
818                         break;
819                 default:
820                         return SP_ERR_ARG;
821                 }
822         }
823
824         if (config->dsr >= 0) {
825                 switch (config->dsr) {
826                 case SP_DSR_IGNORE:
827                         data->dcb.fOutxDsrFlow = FALSE;
828                         break;
829                 case SP_DSR_FLOW_CONTROL:
830                         data->dcb.fOutxDsrFlow = TRUE;
831                         break;
832                 default:
833                         return SP_ERR_ARG;
834                 }
835         }
836
837         if (config->xon_xoff >= 0) {
838                 switch (config->xon_xoff) {
839                 case SP_XONXOFF_DISABLED:
840                         data->dcb.fInX = FALSE;
841                         data->dcb.fOutX = FALSE;
842                         break;
843                 case SP_XONXOFF_IN:
844                         data->dcb.fInX = TRUE;
845                         data->dcb.fOutX = FALSE;
846                         break;
847                 case SP_XONXOFF_OUT:
848                         data->dcb.fInX = FALSE;
849                         data->dcb.fOutX = TRUE;
850                         break;
851                 case SP_XONXOFF_INOUT:
852                         data->dcb.fInX = TRUE;
853                         data->dcb.fOutX = TRUE;
854                         break;
855                 default:
856                         return SP_ERR_ARG;
857                 }
858         }
859
860         if (!SetCommState(port->hdl, &data->dcb))
861                 return SP_ERR_FAIL;
862
863 #else // !_WIN32
864
865         if (config->baudrate >= 0)
866         {
867                 for (i = 0; i < NUM_STD_BAUDRATES; i++) {
868                         if (config->baudrate == std_baudrates[i].value) {
869                                 if (cfsetospeed(&data->term, std_baudrates[i].index) < 0)
870                                         return SP_ERR_FAIL;
871
872                                 if (cfsetispeed(&data->term, std_baudrates[i].index) < 0)
873                                         return SP_ERR_FAIL;
874                                 break;
875                         }
876                 }
877
878                 if (i == NUM_STD_BAUDRATES)
879                         return SP_ERR_ARG;
880         }
881
882         if (config->bits >= 0) {
883                 data->term.c_cflag &= ~CSIZE;
884                 switch (config->bits) {
885                 case 8:
886                         data->term.c_cflag |= CS8;
887                         break;
888                 case 7:
889                         data->term.c_cflag |= CS7;
890                         break;
891                 case 6:
892                         data->term.c_cflag |= CS6;
893                         break;
894                 default:
895                         return SP_ERR_ARG;
896                 }
897         }
898
899         if (config->parity >= 0) {
900                 data->term.c_iflag &= ~IGNPAR;
901                 data->term.c_cflag &= ~(PARENB | PARODD);
902                 switch (config->parity) {
903                 case SP_PARITY_NONE:
904                         data->term.c_iflag |= IGNPAR;
905                         break;
906                 case SP_PARITY_EVEN:
907                         data->term.c_cflag |= PARENB;
908                         break;
909                 case SP_PARITY_ODD:
910                         data->term.c_cflag |= PARENB | PARODD;
911                         break;
912                 default:
913                         return SP_ERR_ARG;
914                 }
915         }
916
917         if (config->stopbits >= 0) {
918                 data->term.c_cflag &= ~CSTOPB;
919                 switch (config->stopbits) {
920                 case 1:
921                         data->term.c_cflag &= ~CSTOPB;
922                         break;
923                 case 2:
924                         data->term.c_cflag |= CSTOPB;
925                         break;
926                 default:
927                         return SP_ERR_ARG;
928                 }
929         }
930
931         if (config->rts >= 0 || config->cts >= 0)
932         {
933                 /* Asymmetric use of RTS/CTS not supported yet. */
934
935                 if (data->term.c_iflag & CRTSCTS) {
936                         /* Flow control can only be disabled for both RTS & CTS together. */
937                         if (config->rts >= 0 && config->rts != SP_RTS_FLOW_CONTROL) {
938                                 if (config->cts != SP_CTS_IGNORE)
939                                         return SP_ERR_ARG;
940                         }
941                         if (config->cts >= 0 && config->cts != SP_CTS_FLOW_CONTROL) {
942                                 if (config->rts <= 0 || config->rts == SP_RTS_FLOW_CONTROL)
943                                         return SP_ERR_ARG;
944                         }
945                 } else {
946                         /* Flow control can only be enabled for both RTS & CTS together. */
947                         if (((config->rts == SP_RTS_FLOW_CONTROL) && (config->cts != SP_CTS_FLOW_CONTROL)) ||
948                                 ((config->cts == SP_CTS_FLOW_CONTROL) && (config->rts != SP_RTS_FLOW_CONTROL)))
949                                 return SP_ERR_ARG;
950                 }
951
952                 if (config->rts >= 0) {
953                         if (config->rts == SP_RTS_FLOW_CONTROL) {
954                                 data->term.c_iflag |= CRTSCTS;
955                         } else {
956                                 int controlbits = TIOCM_RTS;
957                                 if (ioctl(port->fd, config->rts == SP_RTS_ON ? TIOCMBIS : TIOCMBIC,
958                                                 &controlbits) < 0)
959                                         return SP_ERR_FAIL;
960                         }
961                 }
962         }
963
964         if (config->dtr >= 0 || config->dsr >= 0)
965         {
966                 /* DTR/DSR flow control not supported yet. */
967                 if (config->dtr == SP_DTR_FLOW_CONTROL || config->dsr == SP_DSR_FLOW_CONTROL)
968                         return SP_ERR_ARG;
969
970                 if (config->dtr >= 0) {
971                         int controlbits = TIOCM_DTR;
972                         if (ioctl(port->fd, config->dtr == SP_DTR_ON ? TIOCMBIS : TIOCMBIC,
973                                         &controlbits) < 0)
974                                 return SP_ERR_FAIL;
975                 }
976         }
977
978         if (config->xon_xoff >= 0) {
979                 data->term.c_iflag &= ~(IXON | IXOFF | IXANY);
980                 switch (config->xon_xoff) {
981                 case SP_XONXOFF_DISABLED:
982                         break;
983                 case SP_XONXOFF_IN:
984                         data->term.c_iflag |= IXOFF;
985                         break;
986                 case SP_XONXOFF_OUT:
987                         data->term.c_iflag |= IXON | IXANY;
988                         break;
989                 case SP_XONXOFF_INOUT:
990                         data->term.c_iflag |= IXON | IXOFF | IXANY;
991                         break;
992                 default:
993                         return SP_ERR_ARG;
994                 }
995         }
996
997         if (tcsetattr(port->fd, TCSADRAIN, &data->term) < 0)
998                 return SP_ERR_FAIL;
999 #endif
1000
1001         return SP_OK;
1002 }
1003
1004 #define TRY(x) do { int ret = x; if (ret != SP_OK) return ret; } while (0)
1005
1006 int sp_set_config(struct sp_port *port, struct sp_port_config *config)
1007 {
1008         struct sp_port_data data;
1009         struct sp_port_config prev_config;
1010
1011         TRY(get_config(port, &data, &prev_config));
1012         TRY(set_config(port, &data, config));
1013
1014         return SP_OK;
1015 }
1016
1017 #define CREATE_SETTER(x) int sp_set_##x(struct sp_port *port, int x) { \
1018         struct sp_port_data data; \
1019         struct sp_port_config config; \
1020         TRY(get_config(port, &data, &config)); \
1021         config.x = x; \
1022         TRY(set_config(port, &data, &config)); \
1023         return SP_OK; \
1024 }
1025
1026 CREATE_SETTER(baudrate)
1027 CREATE_SETTER(bits)
1028 CREATE_SETTER(parity)
1029 CREATE_SETTER(stopbits)
1030 CREATE_SETTER(rts)
1031 CREATE_SETTER(cts)
1032 CREATE_SETTER(dtr)
1033 CREATE_SETTER(dsr)
1034 CREATE_SETTER(xon_xoff)
1035
1036 int sp_set_flowcontrol(struct sp_port *port, int flowcontrol)
1037 {
1038         struct sp_port_data data;
1039         struct sp_port_config config;
1040
1041         TRY(get_config(port, &data, &config));
1042
1043         if (flowcontrol == SP_FLOWCONTROL_XONXOFF)
1044                 config.xon_xoff = SP_XONXOFF_INOUT;
1045         else
1046                 config.xon_xoff = SP_XONXOFF_DISABLED;
1047
1048         if (flowcontrol == SP_FLOWCONTROL_RTSCTS) {
1049                 config.rts = SP_RTS_FLOW_CONTROL;
1050                 config.cts = SP_CTS_FLOW_CONTROL;
1051         } else {
1052                 if (config.rts == SP_RTS_FLOW_CONTROL)
1053                         config.rts = SP_RTS_ON;
1054                 config.cts = SP_CTS_IGNORE;
1055         }
1056
1057         if (flowcontrol == SP_FLOWCONTROL_DTRDSR) {
1058                 config.dtr = SP_DTR_FLOW_CONTROL;
1059                 config.dsr = SP_DSR_FLOW_CONTROL;
1060         } else {
1061                 if (config.dtr == SP_DTR_FLOW_CONTROL)
1062                         config.dtr = SP_DTR_ON;
1063                 config.dsr = SP_DSR_IGNORE;
1064         }
1065
1066         TRY(set_config(port, &data, &config));
1067
1068         return SP_OK;
1069 }
1070
1071 int sp_last_error_code(void)
1072 {
1073 #ifdef _WIN32
1074         return GetLastError();
1075 #else
1076         return errno;
1077 #endif
1078 }
1079
1080 char *sp_last_error_message(void)
1081 {
1082 #ifdef _WIN32
1083         LPVOID message;
1084         DWORD error = GetLastError();
1085
1086         FormatMessage(
1087                 FORMAT_MESSAGE_ALLOCATE_BUFFER |
1088                 FORMAT_MESSAGE_FROM_SYSTEM |
1089                 FORMAT_MESSAGE_IGNORE_INSERTS,
1090                 NULL,
1091                 error,
1092                 MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
1093                 (LPTSTR) &message,
1094                 0, NULL );
1095
1096         return message;
1097 #else
1098         return strerror(errno);
1099 #endif
1100 }
1101
1102 void sp_free_error_message(char *message)
1103 {
1104 #ifdef _WIN32
1105         LocalFree(message);
1106 #else
1107         (void)message;
1108 #endif
1109 }