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