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