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