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