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