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