]> sigrok.org Git - libserialport.git/blob - serialport.c
Remove outdated inline documentation, README is now authoritative.
[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 "serialport.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,
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)))
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         /* Map 'flags' to the OS-specific settings. */
347         desired_access |= GENERIC_READ;
348         flags_and_attributes = FILE_ATTRIBUTE_NORMAL;
349         if (flags & SP_MODE_RDWR)
350                 desired_access |= GENERIC_WRITE;
351         if (flags & SP_MODE_NONBLOCK)
352                 flags_and_attributes |= FILE_FLAG_OVERLAPPED;
353
354         port->hdl = CreateFile(port->name, desired_access, 0, 0,
355                          OPEN_EXISTING, flags_and_attributes, 0);
356         if (port->hdl == INVALID_HANDLE_VALUE)
357                 return SP_ERR_FAIL;
358 #else
359         int flags_local = 0;
360         /* Map 'flags' to the OS-specific settings. */
361         if (flags & SP_MODE_RDWR)
362                 flags_local |= O_RDWR;
363         if (flags & SP_MODE_RDONLY)
364                 flags_local |= O_RDONLY;
365         if (flags & SP_MODE_NONBLOCK)
366                 flags_local |= O_NONBLOCK;
367
368         if ((port->fd = open(port->name, flags_local)) < 0)
369                 return SP_ERR_FAIL;
370 #endif
371
372         return SP_OK;
373 }
374
375 int sp_close(struct sp_port *port)
376 {
377         CHECK_PORT();
378
379 #ifdef _WIN32
380         /* Returns non-zero upon success, 0 upon failure. */
381         if (CloseHandle(port->hdl) == 0)
382                 return SP_ERR_FAIL;
383 #else
384         /* Returns 0 upon success, -1 upon failure. */
385         if (close(port->fd) == -1)
386                 return SP_ERR_FAIL;
387 #endif
388
389         return SP_OK;
390 }
391
392 int sp_flush(struct sp_port *port)
393 {
394         CHECK_PORT();
395
396 #ifdef _WIN32
397         /* Returns non-zero upon success, 0 upon failure. */
398         if (PurgeComm(port->hdl, PURGE_RXCLEAR | PURGE_TXCLEAR) == 0)
399                 return SP_ERR_FAIL;
400 #else
401         /* Returns 0 upon success, -1 upon failure. */
402         if (tcflush(port->fd, TCIOFLUSH) < 0)
403                 return SP_ERR_FAIL;
404 #endif
405         return SP_OK;
406 }
407
408 int sp_write(struct sp_port *port, const void *buf, size_t count)
409 {
410         CHECK_PORT();
411
412         if (!buf)
413                 return SP_ERR_ARG;
414
415 #ifdef _WIN32
416         DWORD written = 0;
417         /* Returns non-zero upon success, 0 upon failure. */
418         if (WriteFile(port->hdl, buf, count, &written, NULL) == 0)
419                 return SP_ERR_FAIL;
420         return written;
421 #else
422         /* Returns the number of bytes written, or -1 upon failure. */
423         ssize_t written = write(port->fd, buf, count);
424         if (written < 0)
425                 return SP_ERR_FAIL;
426         else
427                 return written;;
428 #endif
429 }
430
431 int sp_read(struct sp_port *port, void *buf, size_t count)
432 {
433         CHECK_PORT();
434
435         if (!buf)
436                 return SP_ERR_ARG;
437
438 #ifdef _WIN32
439         DWORD bytes_read = 0;
440         /* Returns non-zero upon success, 0 upon failure. */
441         if (ReadFile(port->hdl, buf, count, &bytes_read, NULL) == 0)
442                 return SP_ERR_FAIL;
443         return bytes_read;
444 #else
445         ssize_t bytes_read;
446         /* Returns the number of bytes read, or -1 upon failure. */
447         if ((bytes_read = read(port->fd, buf, count)) < 0)
448                 return SP_ERR_FAIL;
449         return bytes_read;
450 #endif
451 }
452
453 int sp_set_params(struct sp_port *port, int baudrate,
454                               int bits, int parity, int stopbits,
455                               int flowcontrol, int rts, int dtr)
456 {
457         CHECK_PORT();
458
459 #ifdef _WIN32
460         DCB dcb;
461
462         if (!GetCommState(port->hdl, &dcb))
463                 return SP_ERR_FAIL;
464
465         switch (baudrate) {
466         /*
467          * The baudrates 50/75/134/150/200/1800/230400/460800 do not seem to
468          * have documented CBR_* macros.
469          */
470         case 110:
471                 dcb.BaudRate = CBR_110;
472                 break;
473         case 300:
474                 dcb.BaudRate = CBR_300;
475                 break;
476         case 600:
477                 dcb.BaudRate = CBR_600;
478                 break;
479         case 1200:
480                 dcb.BaudRate = CBR_1200;
481                 break;
482         case 2400:
483                 dcb.BaudRate = CBR_2400;
484                 break;
485         case 4800:
486                 dcb.BaudRate = CBR_4800;
487                 break;
488         case 9600:
489                 dcb.BaudRate = CBR_9600;
490                 break;
491         case 14400:
492                 dcb.BaudRate = CBR_14400; /* Not available on Unix? */
493                 break;
494         case 19200:
495                 dcb.BaudRate = CBR_19200;
496                 break;
497         case 38400:
498                 dcb.BaudRate = CBR_38400;
499                 break;
500         case 57600:
501                 dcb.BaudRate = CBR_57600;
502                 break;
503         case 115200:
504                 dcb.BaudRate = CBR_115200;
505                 break;
506         case 128000:
507                 dcb.BaudRate = CBR_128000; /* Not available on Unix? */
508                 break;
509         case 256000:
510                 dcb.BaudRate = CBR_256000; /* Not available on Unix? */
511                 break;
512         default:
513                 return SP_ERR_ARG;
514         }
515
516         switch (stopbits) {
517         /* Note: There's also ONE5STOPBITS == 1.5 (unneeded so far). */
518         case 1:
519                 dcb.StopBits = ONESTOPBIT;
520                 break;
521         case 2:
522                 dcb.StopBits = TWOSTOPBITS;
523                 break;
524         default:
525                 return SP_ERR_ARG;
526         }
527
528         switch (parity) {
529         /* Note: There's also SPACEPARITY, MARKPARITY (unneeded so far). */
530         case SP_PARITY_NONE:
531                 dcb.Parity = NOPARITY;
532                 break;
533         case SP_PARITY_EVEN:
534                 dcb.Parity = EVENPARITY;
535                 break;
536         case SP_PARITY_ODD:
537                 dcb.Parity = ODDPARITY;
538                 break;
539         default:
540                 return SP_ERR_ARG;
541         }
542
543         if (rts != -1) {
544                 if (rts)
545                         dcb.fRtsControl = RTS_CONTROL_ENABLE;
546                 else
547                         dcb.fRtsControl = RTS_CONTROL_DISABLE;
548         }
549
550         if (dtr != -1) {
551                 if (dtr)
552                         dcb.fDtrControl = DTR_CONTROL_ENABLE;
553                 else
554                         dcb.fDtrControl = DTR_CONTROL_DISABLE;
555         }
556
557         if (!SetCommState(port->hdl, &dcb))
558                 return SP_ERR_FAIL;
559 #else
560         struct termios term;
561         speed_t baud;
562         int controlbits;
563
564         if (tcgetattr(port->fd, &term) < 0)
565                 return SP_ERR_FAIL;
566
567         switch (baudrate) {
568         case 50:
569                 baud = B50;
570                 break;
571         case 75:
572                 baud = B75;
573                 break;
574         case 110:
575                 baud = B110;
576                 break;
577         case 134:
578                 baud = B134;
579                 break;
580         case 150:
581                 baud = B150;
582                 break;
583         case 200:
584                 baud = B200;
585                 break;
586         case 300:
587                 baud = B300;
588                 break;
589         case 600:
590                 baud = B600;
591                 break;
592         case 1200:
593                 baud = B1200;
594                 break;
595         case 1800:
596                 baud = B1800;
597                 break;
598         case 2400:
599                 baud = B2400;
600                 break;
601         case 4800:
602                 baud = B4800;
603                 break;
604         case 9600:
605                 baud = B9600;
606                 break;
607         case 19200:
608                 baud = B19200;
609                 break;
610         case 38400:
611                 baud = B38400;
612                 break;
613         case 57600:
614                 baud = B57600;
615                 break;
616         case 115200:
617                 baud = B115200;
618                 break;
619         case 230400:
620                 baud = B230400;
621                 break;
622 #if !defined(__APPLE__) && !defined(__OpenBSD__)
623         case 460800:
624                 baud = B460800;
625                 break;
626 #endif
627         default:
628                 return SP_ERR_ARG;
629         }
630
631         if (cfsetospeed(&term, baud) < 0)
632                 return SP_ERR_FAIL;
633
634         if (cfsetispeed(&term, baud) < 0)
635                 return SP_ERR_FAIL;
636
637         term.c_cflag &= ~CSIZE;
638         switch (bits) {
639         case 8:
640                 term.c_cflag |= CS8;
641                 break;
642         case 7:
643                 term.c_cflag |= CS7;
644                 break;
645         default:
646                 return SP_ERR_ARG;
647         }
648
649         term.c_cflag &= ~CSTOPB;
650         switch (stopbits) {
651         case 1:
652                 term.c_cflag &= ~CSTOPB;
653                 break;
654         case 2:
655                 term.c_cflag |= CSTOPB;
656                 break;
657         default:
658                 return SP_ERR_ARG;
659         }
660
661         term.c_iflag &= ~(IXON | IXOFF | IXANY);
662         term.c_cflag &= ~CRTSCTS;
663         switch (flowcontrol) {
664         case 0:
665                 /* No flow control. */
666                 break;
667         case 1:
668                 term.c_cflag |= CRTSCTS;
669                 break;
670         case 2:
671                 term.c_iflag |= IXON | IXOFF | IXANY;
672                 break;
673         default:
674                 return SP_ERR_ARG;
675         }
676
677         term.c_iflag &= ~IGNPAR;
678         term.c_cflag &= ~(PARENB | PARODD);
679         switch (parity) {
680         case SP_PARITY_NONE:
681                 term.c_iflag |= IGNPAR;
682                 break;
683         case SP_PARITY_EVEN:
684                 term.c_cflag |= PARENB;
685                 break;
686         case SP_PARITY_ODD:
687                 term.c_cflag |= PARENB | PARODD;
688                 break;
689         default:
690                 return SP_ERR_ARG;
691         }
692
693         /* Turn off all serial port cooking. */
694         term.c_iflag &= ~(ISTRIP | INLCR | ICRNL);
695         term.c_oflag &= ~(ONLCR | OCRNL | ONOCR);
696 #if !defined(__FreeBSD__) && !defined(__OpenBSD__) && !defined(__NetBSD__)
697         term.c_oflag &= ~OFILL;
698 #endif
699
700         /* Disable canonical mode, and don't echo input characters. */
701         term.c_lflag &= ~(ICANON | ECHO);
702
703         /* Ignore modem status lines; enable receiver */
704         term.c_cflag |= (CLOCAL | CREAD);
705
706         /* Write the configured settings. */
707         if (tcsetattr(port->fd, TCSADRAIN, &term) < 0)
708                 return SP_ERR_FAIL;
709
710         if (rts != -1) {
711                 controlbits = TIOCM_RTS;
712                 if (ioctl(port->fd, rts ? TIOCMBIS : TIOCMBIC,
713                                 &controlbits) < 0)
714                         return SP_ERR_FAIL;
715         }
716
717         if (dtr != -1) {
718                 controlbits = TIOCM_DTR;
719                 if (ioctl(port->fd, dtr ? TIOCMBIS : TIOCMBIC,
720                                 &controlbits) < 0)
721                         return SP_ERR_FAIL;
722         }
723 #endif
724
725         return SP_OK;
726 }
727
728 int sp_last_error_code(void)
729 {
730 #ifdef _WIN32
731         return GetLastError();
732 #else
733         return errno;
734 #endif
735 }
736
737 char *sp_last_error_message(void)
738 {
739 #ifdef _WIN32
740         LPVOID message;
741         DWORD error = GetLastError();
742
743         FormatMessage(
744                 FORMAT_MESSAGE_ALLOCATE_BUFFER |
745                 FORMAT_MESSAGE_FROM_SYSTEM |
746                 FORMAT_MESSAGE_IGNORE_INSERTS,
747                 NULL,
748                 error,
749                 MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
750                 (LPTSTR) &message,
751                 0, NULL );
752
753         return message;
754 #else
755         return strerror(errno);
756 #endif
757 }
758
759 void sp_free_error_message(char *message)
760 {
761 #ifdef _WIN32
762         LocalFree(message);
763 #else
764         (void)message;
765 #endif
766 }