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