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