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