2 * This file is part of the libserialport project.
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>
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.
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.
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/>.
23 #include <sys/types.h>
35 #include <sys/ioctl.h>
38 #include <IOKit/IOKitLib.h>
39 #include <IOKit/serial/IOSerialKeys.h>
40 #include <sys/syslimits.h>
44 #include "linux/serial.h"
47 #include "libserialport.h"
60 int sp_get_port_by_name(const char *portname
, struct sp_port
**port_ptr
)
73 if (!(port
= malloc(sizeof(struct sp_port
))))
76 len
= strlen(portname
) + 1;
78 if (!(port
->name
= malloc(len
)))
84 memcpy(port
->name
, portname
, len
);
91 int sp_copy_port(const struct sp_port
*port
, struct sp_port
**copy_ptr
)
98 if (!port
|| !port
->name
)
101 return sp_get_port_by_name(port
->name
, copy_ptr
);
104 void sp_free_port(struct sp_port
*port
)
115 static struct sp_port
**sp_list_append(struct sp_port
**list
, const char *portname
)
120 for (count
= 0; list
[count
]; count
++);
121 if (!(tmp
= realloc(list
, sizeof(struct sp_port
*) * (count
+ 2))))
124 if (sp_get_port_by_name(portname
, &list
[count
]) != SP_OK
)
126 list
[count
+ 1] = NULL
;
130 sp_free_port_list(list
);
134 int sp_list_ports(struct sp_port
***list_ptr
)
136 struct sp_port
**list
;
139 if (!(list
= malloc(sizeof(struct sp_port
**))))
147 DWORD max_value_len
, max_data_size
, max_data_len
;
148 DWORD value_len
, data_size
, data_len
;
149 DWORD type
, index
= 0;
153 if (RegOpenKeyEx(HKEY_LOCAL_MACHINE
, _T("HARDWARE\\DEVICEMAP\\SERIALCOMM"),
154 0, KEY_QUERY_VALUE
, &key
) != ERROR_SUCCESS
)
159 if (RegQueryInfoKey(key
, NULL
, NULL
, NULL
, NULL
, NULL
, NULL
, NULL
,
160 &max_value_len
, &max_data_size
, NULL
, NULL
) != ERROR_SUCCESS
)
165 max_data_len
= max_data_size
/ sizeof(TCHAR
);
166 if (!(value
= malloc((max_value_len
+ 1) * sizeof(TCHAR
))))
171 if (!(data
= malloc((max_data_len
+ 1) * sizeof(TCHAR
))))
177 value_len
= max_value_len
+ 1,
178 data_size
= max_data_size
,
179 RegEnumValue(key
, index
, value
, &value_len
,
180 NULL
, &type
, (LPBYTE
)data
, &data_size
) == ERROR_SUCCESS
)
182 data_len
= data_size
/ sizeof(TCHAR
);
183 data
[data_len
] = '\0';
185 name_len
= WideCharToMultiByte(CP_ACP
, 0, data
, -1, NULL
, 0, NULL
, NULL
)
187 name_len
= data_len
+ 1;
189 if (!(name
= malloc(name_len
)))
195 WideCharToMultiByte(CP_ACP
, 0, data
, -1, name
, name_len
, NULL
, NULL
);
199 if (type
== REG_SZ
&& !(list
= sp_list_append(list
, name
)))
216 CFMutableDictionaryRef classes
;
223 if (IOMasterPort(MACH_PORT_NULL
, &master
) != KERN_SUCCESS
)
229 if (!(classes
= IOServiceMatching(kIOSerialBSDServiceValue
)))
235 CFDictionarySetValue(classes
,
236 CFSTR(kIOSerialBSDTypeKey
), CFSTR(kIOSerialBSDAllTypes
));
238 if (IOServiceGetMatchingServices(master
, classes
, &iter
) != KERN_SUCCESS
)
244 if (!(path
= malloc(PATH_MAX
)))
250 while ((port
= IOIteratorNext(iter
))) {
251 cf_path
= IORegistryEntryCreateCFProperty(port
,
252 CFSTR(kIOCalloutDeviceKey
), kCFAllocatorDefault
, 0);
254 result
= CFStringGetCString(cf_path
,
255 path
, PATH_MAX
, kCFStringEncodingASCII
);
257 if (result
&& !(list
= sp_list_append(list
, path
)))
260 IOObjectRelease(port
);
264 IOObjectRelease(port
);
269 IOObjectRelease(iter
);
274 struct udev_enumerate
*ud_enumerate
;
275 struct udev_list_entry
*ud_list
;
276 struct udev_list_entry
*ud_entry
;
278 struct udev_device
*ud_dev
, *ud_parent
;
281 int fd
, ioctl_result
;
282 struct serial_struct serial_info
;
285 ud_enumerate
= udev_enumerate_new(ud
);
286 udev_enumerate_add_match_subsystem(ud_enumerate
, "tty");
287 udev_enumerate_scan_devices(ud_enumerate
);
288 ud_list
= udev_enumerate_get_list_entry(ud_enumerate
);
289 udev_list_entry_foreach(ud_entry
, ud_list
)
291 path
= udev_list_entry_get_name(ud_entry
);
292 ud_dev
= udev_device_new_from_syspath(ud
, path
);
293 /* If there is no parent device, this is a virtual tty. */
294 ud_parent
= udev_device_get_parent(ud_dev
);
295 if (ud_parent
== NULL
)
297 udev_device_unref(ud_dev
);
300 name
= udev_device_get_devnode(ud_dev
);
301 /* The serial8250 driver has a hardcoded number of ports.
302 * The only way to tell which actually exist on a given system
303 * is to try to open them and make an ioctl call. */
304 driver
= udev_device_get_driver(ud_parent
);
305 if (driver
&& !strcmp(driver
, "serial8250"))
307 if ((fd
= open(name
, O_RDWR
| O_NONBLOCK
| O_NOCTTY
)) < 0)
309 ioctl_result
= ioctl(fd
, TIOCGSERIAL
, &serial_info
);
311 if (ioctl_result
!= 0)
313 if (serial_info
.type
== PORT_UNKNOWN
)
316 list
= sp_list_append(list
, name
);
318 udev_device_unref(ud_dev
);
326 udev_enumerate_unref(ud_enumerate
);
337 sp_free_port_list(list
);
345 void sp_free_port_list(struct sp_port
**list
)
349 for (i
= 0; list
[i
]; i
++)
350 sp_free_port(list
[i
]);
354 static int sp_validate_port(struct sp_port
*port
)
359 if (port
->hdl
== INVALID_HANDLE_VALUE
)
368 #define CHECK_PORT() do { if (!sp_validate_port(port)) return SP_ERR_ARG; } while (0)
370 int sp_open(struct sp_port
*port
, int flags
)
376 DWORD desired_access
= 0, flags_and_attributes
= 0;
377 char *escaped_port_name
;
379 /* Prefix port name with '\\.\' to work with ports above COM9. */
380 if (!(escaped_port_name
= malloc(strlen(port
->name
+ 5))))
382 sprintf(escaped_port_name
, "\\\\.\\%s", port
->name
);
384 /* Map 'flags' to the OS-specific settings. */
385 desired_access
|= GENERIC_READ
;
386 flags_and_attributes
= FILE_ATTRIBUTE_NORMAL
;
387 if (flags
& SP_MODE_RDWR
)
388 desired_access
|= GENERIC_WRITE
;
389 if (flags
& SP_MODE_NONBLOCK
)
390 flags_and_attributes
|= FILE_FLAG_OVERLAPPED
;
392 port
->hdl
= CreateFile(escaped_port_name
, desired_access
, 0, 0,
393 OPEN_EXISTING
, flags_and_attributes
, 0);
395 free(escaped_port_name
);
397 if (port
->hdl
== INVALID_HANDLE_VALUE
)
402 /* Map 'flags' to the OS-specific settings. */
403 if (flags
& SP_MODE_RDWR
)
404 flags_local
|= O_RDWR
;
405 if (flags
& SP_MODE_RDONLY
)
406 flags_local
|= O_RDONLY
;
407 if (flags
& SP_MODE_NONBLOCK
)
408 flags_local
|= O_NONBLOCK
;
410 if ((port
->fd
= open(port
->name
, flags_local
)) < 0)
417 int sp_close(struct sp_port
*port
)
422 /* Returns non-zero upon success, 0 upon failure. */
423 if (CloseHandle(port
->hdl
) == 0)
426 /* Returns 0 upon success, -1 upon failure. */
427 if (close(port
->fd
) == -1)
434 int sp_flush(struct sp_port
*port
)
439 /* Returns non-zero upon success, 0 upon failure. */
440 if (PurgeComm(port
->hdl
, PURGE_RXCLEAR
| PURGE_TXCLEAR
) == 0)
443 /* Returns 0 upon success, -1 upon failure. */
444 if (tcflush(port
->fd
, TCIOFLUSH
) < 0)
450 int sp_write(struct sp_port
*port
, const void *buf
, size_t count
)
460 /* Returns non-zero upon success, 0 upon failure. */
461 if (WriteFile(port
->hdl
, buf
, count
, &written
, NULL
) == 0)
465 /* Returns the number of bytes written, or -1 upon failure. */
466 ssize_t written
= write(port
->fd
, buf
, count
);
475 int sp_read(struct sp_port
*port
, void *buf
, size_t count
)
483 DWORD bytes_read
= 0;
485 /* Returns non-zero upon success, 0 upon failure. */
486 if (ReadFile(port
->hdl
, buf
, count
, &bytes_read
, NULL
) == 0)
492 /* Returns the number of bytes read, or -1 upon failure. */
493 if ((bytes_read
= read(port
->fd
, buf
, count
)) < 0)
499 static int start_config(struct sp_port
*port
, struct sp_port_data
*data
)
503 if (!GetCommState(port
->hdl
, &data
->dcb
))
506 if (tcgetattr(port
->fd
, &data
->term
) < 0)
512 static int set_baudrate(struct sp_port_data
*data
, int baudrate
)
517 * The baudrates 50/75/134/150/200/1800/230400/460800 do not seem to
518 * have documented CBR_* macros.
521 data
->dcb
.BaudRate
= CBR_110
;
524 data
->dcb
.BaudRate
= CBR_300
;
527 data
->dcb
.BaudRate
= CBR_600
;
530 data
->dcb
.BaudRate
= CBR_1200
;
533 data
->dcb
.BaudRate
= CBR_2400
;
536 data
->dcb
.BaudRate
= CBR_4800
;
539 data
->dcb
.BaudRate
= CBR_9600
;
542 data
->dcb
.BaudRate
= CBR_14400
; /* Not available on Unix? */
545 data
->dcb
.BaudRate
= CBR_19200
;
548 data
->dcb
.BaudRate
= CBR_38400
;
551 data
->dcb
.BaudRate
= CBR_57600
;
554 data
->dcb
.BaudRate
= CBR_115200
;
557 data
->dcb
.BaudRate
= CBR_128000
; /* Not available on Unix? */
560 data
->dcb
.BaudRate
= CBR_256000
; /* Not available on Unix? */
616 data
->baud
= B115200
;
619 data
->baud
= B230400
;
621 #if !defined(__APPLE__) && !defined(__OpenBSD__)
623 data
->baud
= B460800
;
633 static int set_bits(struct sp_port_data
*data
, int bits
)
636 data
->dcb
.ByteSize
= bits
;
638 data
->term
.c_cflag
&= ~CSIZE
;
641 data
->term
.c_cflag
|= CS8
;
644 data
->term
.c_cflag
|= CS7
;
647 data
->term
.c_cflag
|= CS6
;
656 static int set_parity(struct sp_port_data
*data
, int parity
)
660 /* Note: There's also SPACEPARITY, MARKPARITY (unneeded so far). */
662 data
->dcb
.Parity
= NOPARITY
;
665 data
->dcb
.Parity
= EVENPARITY
;
668 data
->dcb
.Parity
= ODDPARITY
;
674 data
->term
.c_iflag
&= ~IGNPAR
;
675 data
->term
.c_cflag
&= ~(PARENB
| PARODD
);
678 data
->term
.c_iflag
|= IGNPAR
;
681 data
->term
.c_cflag
|= PARENB
;
684 data
->term
.c_cflag
|= PARENB
| PARODD
;
693 static int set_stopbits(struct sp_port_data
*data
, int stopbits
)
697 /* Note: There's also ONE5STOPBITS == 1.5 (unneeded so far). */
699 data
->dcb
.StopBits
= ONESTOPBIT
;
702 data
->dcb
.StopBits
= TWOSTOPBITS
;
708 data
->term
.c_cflag
&= ~CSTOPB
;
711 data
->term
.c_cflag
&= ~CSTOPB
;
714 data
->term
.c_cflag
|= CSTOPB
;
723 static int set_flowcontrol(struct sp_port_data
*data
, int flowcontrol
)
726 data
->term
.c_iflag
&= ~(IXON
| IXOFF
| IXANY
);
727 data
->term
.c_cflag
&= ~CRTSCTS
;
728 switch (flowcontrol
) {
730 /* No flow control. */
733 data
->term
.c_cflag
|= CRTSCTS
;
736 data
->term
.c_iflag
|= IXON
| IXOFF
| IXANY
;
745 static int set_rts(struct sp_port_data
*data
, int rts
)
750 data
->dcb
.fRtsControl
= RTS_CONTROL_ENABLE
;
752 data
->dcb
.fRtsControl
= RTS_CONTROL_DISABLE
;
760 static int set_dtr(struct sp_port_data
*data
, int dtr
)
765 data
->dcb
.fDtrControl
= DTR_CONTROL_ENABLE
;
767 data
->dcb
.fDtrControl
= DTR_CONTROL_DISABLE
;
775 static int apply_config(struct sp_port
*port
, struct sp_port_data
*data
)
778 if (!SetCommState(port
->hdl
, &data
->dcb
))
783 /* Turn off all serial port cooking. */
784 data
->term
.c_iflag
&= ~(ISTRIP
| INLCR
| ICRNL
);
785 data
->term
.c_oflag
&= ~(ONLCR
| OCRNL
| ONOCR
);
786 #if !defined(__FreeBSD__) && !defined(__OpenBSD__) && !defined(__NetBSD__)
787 data
->term
.c_oflag
&= ~OFILL
;
789 /* Disable canonical mode, and don't echo input characters. */
790 data
->term
.c_lflag
&= ~(ICANON
| ECHO
);
792 /* Ignore modem status lines; enable receiver */
793 data
->term
.c_cflag
|= (CLOCAL
| CREAD
);
795 /* Write the configured settings. */
796 if (tcsetattr(port
->fd
, TCSADRAIN
, &data
->term
) < 0)
799 if (cfsetospeed(&data
->term
, data
->baud
) < 0)
802 if (cfsetispeed(&data
->term
, data
->baud
) < 0)
805 if (data
->rts
!= -1) {
806 controlbits
= TIOCM_RTS
;
807 if (ioctl(port
->fd
, data
->rts
? TIOCMBIS
: TIOCMBIC
,
812 if (data
->dtr
!= -1) {
813 controlbits
= TIOCM_DTR
;
814 if (ioctl(port
->fd
, data
->dtr
? TIOCMBIS
: TIOCMBIC
,
822 #define TRY(x) do { int ret = x; if (ret != SP_OK) return ret; } while (0)
824 int sp_set_params(struct sp_port
*port
, int baudrate
, int bits
, int parity
,
825 int stopbits
, int flowcontrol
, int rts
, int dtr
)
827 struct sp_port_data data
;
829 TRY(start_config(port
, &data
));
830 TRY(set_baudrate(&data
, baudrate
));
831 TRY(set_bits(&data
, bits
));
832 TRY(set_parity(&data
, parity
));
833 TRY(set_stopbits(&data
, stopbits
));
834 TRY(set_flowcontrol(&data
, flowcontrol
));
835 TRY(set_rts(&data
, rts
));
836 TRY(set_dtr(&data
, dtr
));
837 TRY(apply_config(port
, &data
));
842 int sp_last_error_code(void)
845 return GetLastError();
851 char *sp_last_error_message(void)
855 DWORD error
= GetLastError();
858 FORMAT_MESSAGE_ALLOCATE_BUFFER
|
859 FORMAT_MESSAGE_FROM_SYSTEM
|
860 FORMAT_MESSAGE_IGNORE_INSERTS
,
863 MAKELANGID(LANG_NEUTRAL
, SUBLANG_DEFAULT
),
869 return strerror(errno
);
873 void sp_free_error_message(char *message
)