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