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>
7 * Copyright (C) 2013 Matthias Heidbrink <m-sigrok@heidbrink.biz>
9 * This program is free software: you can redistribute it and/or modify
10 * it under the terms of the GNU Lesser General Public License as
11 * published by the Free Software Foundation, either version 3 of the
12 * License, or (at your option) any later version.
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU General Public License for more details.
19 * You should have received a copy of the GNU Lesser General Public License
20 * along with this program. If not, see <http://www.gnu.org/licenses/>.
24 #include <sys/types.h>
39 #include <sys/ioctl.h>
45 #include <IOKit/IOKitLib.h>
46 #include <IOKit/serial/IOSerialKeys.h>
47 #include <IOKit/serial/ioss.h>
48 #include <sys/syslimits.h>
55 #include "linux/serial.h"
57 #include "linux_termios.h"
59 /* TCGETX/TCSETX is not available everywhere. */
60 #if defined(TCGETX) && defined(TCSETX) && defined(HAVE_TERMIOX)
65 /* TIOCINQ/TIOCOUTQ is not available everywhere. */
66 #if !defined(TIOCINQ) && defined(FIONREAD)
67 #define TIOCINQ FIONREAD
69 #if !defined(TIOCOUTQ) && defined(FIONWRITE)
70 #define TIOCOUTQ FIONWRITE
74 #include "linux_termios.h"
77 #include "libserialport.h"
83 COMMTIMEOUTS timeouts
;
95 struct sp_port_config
{
98 enum sp_parity parity
;
104 enum sp_xonxoff xon_xoff
;
113 int termiox_supported
;
119 typedef HANDLE event_handle
;
121 typedef int event_handle
;
124 /* Standard baud rates. */
126 #define BAUD_TYPE DWORD
127 #define BAUD(n) {CBR_##n, n}
129 #define BAUD_TYPE speed_t
130 #define BAUD(n) {B##n, n}
133 struct std_baudrate
{
138 const struct std_baudrate std_baudrates
[] = {
141 * The baudrates 50/75/134/150/200/1800/230400/460800 do not seem to
142 * have documented CBR_* macros.
144 BAUD(110), BAUD(300), BAUD(600), BAUD(1200), BAUD(2400), BAUD(4800),
145 BAUD(9600), BAUD(14400), BAUD(19200), BAUD(38400), BAUD(57600),
146 BAUD(115200), BAUD(128000), BAUD(256000),
148 BAUD(50), BAUD(75), BAUD(110), BAUD(134), BAUD(150), BAUD(200),
149 BAUD(300), BAUD(600), BAUD(1200), BAUD(1800), BAUD(2400), BAUD(4800),
150 BAUD(9600), BAUD(19200), BAUD(38400), BAUD(57600), BAUD(115200),
152 #if !defined(__APPLE__) && !defined(__OpenBSD__)
158 void (*sp_debug_handler
)(const char *format
, ...) = sp_default_debug_handler
;
160 #define ARRAY_SIZE(x) (sizeof(x) / sizeof(x[0]))
161 #define NUM_STD_BAUDRATES ARRAY_SIZE(std_baudrates)
163 /* Debug output macros. */
164 #define DEBUG(fmt, ...) do { if (sp_debug_handler) sp_debug_handler(fmt ".\n", ##__VA_ARGS__); } while (0)
165 #define DEBUG_ERROR(err, msg) DEBUG("%s returning " #err ": " msg, __func__)
166 #define DEBUG_FAIL(msg) do { \
167 char *errmsg = sp_last_error_message(); \
168 DEBUG("%s returning SP_ERR_FAIL: " msg ": %s", __func__, errmsg); \
169 sp_free_error_message(errmsg); \
171 #define RETURN() do { DEBUG("%s returning", __func__); return; } while(0)
172 #define RETURN_CODE(x) do { DEBUG("%s returning " #x, __func__); return x; } while (0)
173 #define RETURN_CODEVAL(x) do { \
175 case SP_OK: RETURN_CODE(SP_OK); \
176 case SP_ERR_ARG: RETURN_CODE(SP_ERR_ARG); \
177 case SP_ERR_FAIL: RETURN_CODE(SP_ERR_FAIL); \
178 case SP_ERR_MEM: RETURN_CODE(SP_ERR_MEM); \
179 case SP_ERR_SUPP: RETURN_CODE(SP_ERR_SUPP); \
182 #define RETURN_OK() RETURN_CODE(SP_OK);
183 #define RETURN_ERROR(err, msg) do { DEBUG_ERROR(err, msg); return err; } while (0)
184 #define RETURN_FAIL(msg) do { DEBUG_FAIL(msg); return SP_ERR_FAIL; } while (0)
185 #define RETURN_VALUE(fmt, x) do { \
187 DEBUG("%s returning " fmt, __func__, _x); \
190 #define SET_ERROR(val, err, msg) do { DEBUG_ERROR(err, msg); val = err; } while (0)
191 #define SET_FAIL(val, msg) do { DEBUG_FAIL(msg); val = SP_ERR_FAIL; } while (0)
192 #define TRACE(fmt, ...) DEBUG("%s(" fmt ") called", __func__, ##__VA_ARGS__)
194 #define TRY(x) do { int ret = x; if (ret != SP_OK) RETURN_CODEVAL(ret); } while (0)
196 /* Helper functions. */
197 static struct sp_port
**list_append(struct sp_port
**list
, const char *portname
);
198 static enum sp_return
get_config(struct sp_port
*port
, struct port_data
*data
,
199 struct sp_port_config
*config
);
200 static enum sp_return
set_config(struct sp_port
*port
, struct port_data
*data
,
201 const struct sp_port_config
*config
);
203 enum sp_return
sp_get_port_by_name(const char *portname
, struct sp_port
**port_ptr
)
205 struct sp_port
*port
;
208 TRACE("%s, %p", portname
, port_ptr
);
211 RETURN_ERROR(SP_ERR_ARG
, "Null result pointer");
216 RETURN_ERROR(SP_ERR_ARG
, "Null port name");
218 DEBUG("Building structure for port %s", portname
);
220 if (!(port
= malloc(sizeof(struct sp_port
))))
221 RETURN_ERROR(SP_ERR_MEM
, "Port structure malloc failed");
223 len
= strlen(portname
) + 1;
225 if (!(port
->name
= malloc(len
))) {
227 RETURN_ERROR(SP_ERR_MEM
, "Port name malloc failed");
230 memcpy(port
->name
, portname
, len
);
233 port
->hdl
= INVALID_HANDLE_VALUE
;
243 char *sp_get_port_name(const struct sp_port
*port
)
250 RETURN_VALUE("%s", port
->name
);
253 enum sp_return
sp_get_port_handle(const struct sp_port
*port
, void *result_ptr
)
255 TRACE("%p, %p", port
, result_ptr
);
258 RETURN_ERROR(SP_ERR_ARG
, "Null port");
261 HANDLE
*handle_ptr
= result_ptr
;
262 *handle_ptr
= port
->hdl
;
264 int *fd_ptr
= result_ptr
;
271 enum sp_return
sp_copy_port(const struct sp_port
*port
, struct sp_port
**copy_ptr
)
273 TRACE("%p, %p", port
, copy_ptr
);
276 RETURN_ERROR(SP_ERR_ARG
, "Null result pointer");
281 RETURN_ERROR(SP_ERR_ARG
, "Null port");
284 RETURN_ERROR(SP_ERR_ARG
, "Null port name");
286 DEBUG("Copying port structure");
288 RETURN_VALUE("%p", sp_get_port_by_name(port
->name
, copy_ptr
));
291 void sp_free_port(struct sp_port
*port
)
300 DEBUG("Freeing port structure");
310 static struct sp_port
**list_append(struct sp_port
**list
, const char *portname
)
315 for (count
= 0; list
[count
]; count
++);
316 if (!(tmp
= realloc(list
, sizeof(struct sp_port
*) * (count
+ 2))))
319 if (sp_get_port_by_name(portname
, &list
[count
]) != SP_OK
)
321 list
[count
+ 1] = NULL
;
325 sp_free_port_list(list
);
329 enum sp_return
sp_list_ports(struct sp_port
***list_ptr
)
331 struct sp_port
**list
;
332 int ret
= SP_ERR_SUPP
;
334 TRACE("%p", list_ptr
);
337 RETURN_ERROR(SP_ERR_ARG
, "Null result pointer");
339 DEBUG("Enumerating ports");
341 if (!(list
= malloc(sizeof(struct sp_port
**))))
342 RETURN_ERROR(SP_ERR_MEM
, "Port list malloc failed");
349 DWORD max_value_len
, max_data_size
, max_data_len
;
350 DWORD value_len
, data_size
, data_len
;
351 DWORD type
, index
= 0;
357 DEBUG("Opening registry key");
358 if (RegOpenKeyEx(HKEY_LOCAL_MACHINE
, _T("HARDWARE\\DEVICEMAP\\SERIALCOMM"),
359 0, KEY_QUERY_VALUE
, &key
) != ERROR_SUCCESS
) {
360 SET_FAIL(ret
, "RegOpenKeyEx() failed");
363 DEBUG("Querying registry key value and data sizes");
364 if (RegQueryInfoKey(key
, NULL
, NULL
, NULL
, NULL
, NULL
, NULL
, NULL
,
365 &max_value_len
, &max_data_size
, NULL
, NULL
) != ERROR_SUCCESS
) {
366 SET_FAIL(ret
, "RegQueryInfoKey() failed");
369 max_data_len
= max_data_size
/ sizeof(TCHAR
);
370 if (!(value
= malloc((max_value_len
+ 1) * sizeof(TCHAR
)))) {
371 SET_ERROR(ret
, SP_ERR_MEM
, "registry value malloc failed");
374 if (!(data
= malloc((max_data_len
+ 1) * sizeof(TCHAR
)))) {
375 SET_ERROR(ret
, SP_ERR_MEM
, "registry data malloc failed");
378 DEBUG("Iterating over values");
380 value_len
= max_value_len
+ 1,
381 data_size
= max_data_size
,
382 RegEnumValue(key
, index
, value
, &value_len
,
383 NULL
, &type
, (LPBYTE
)data
, &data_size
) == ERROR_SUCCESS
)
385 data_len
= data_size
/ sizeof(TCHAR
);
386 data
[data_len
] = '\0';
388 name_len
= WideCharToMultiByte(CP_ACP
, 0, data
, -1, NULL
, 0, NULL
, NULL
)
390 name_len
= data_len
+ 1;
392 if (!(name
= malloc(name_len
))) {
393 SET_ERROR(ret
, SP_ERR_MEM
, "registry port name malloc failed");
397 WideCharToMultiByte(CP_ACP
, 0, data
, -1, name
, name_len
, NULL
, NULL
);
401 if (type
== REG_SZ
) {
402 DEBUG("Found port %s", name
);
403 if (!(list
= list_append(list
, name
))) {
404 SET_ERROR(ret
, SP_ERR_MEM
, "list append failed");
420 CFMutableDictionaryRef classes
;
429 DEBUG("Getting IOKit master port");
430 if (IOMasterPort(MACH_PORT_NULL
, &master
) != KERN_SUCCESS
) {
431 SET_FAIL(ret
, "IOMasterPort() failed");
435 DEBUG("Creating matching dictionary");
436 if (!(classes
= IOServiceMatching(kIOSerialBSDServiceValue
))) {
437 SET_FAIL(ret
, "IOServiceMatching() failed");
441 CFDictionarySetValue(classes
,
442 CFSTR(kIOSerialBSDTypeKey
), CFSTR(kIOSerialBSDAllTypes
));
444 DEBUG("Getting matching services");
445 if (IOServiceGetMatchingServices(master
, classes
, &iter
) != KERN_SUCCESS
) {
446 SET_FAIL(ret
, "IOServiceGetMatchingServices() failed");
450 if (!(path
= malloc(PATH_MAX
))) {
451 SET_ERROR(ret
, SP_ERR_MEM
, "device path malloc failed");
455 DEBUG("Iterating over results");
456 while ((port
= IOIteratorNext(iter
))) {
457 cf_path
= IORegistryEntryCreateCFProperty(port
,
458 CFSTR(kIOCalloutDeviceKey
), kCFAllocatorDefault
, 0);
460 result
= CFStringGetCString(cf_path
,
461 path
, PATH_MAX
, kCFStringEncodingASCII
);
464 DEBUG("Found port %s", path
);
465 if (!(list
= list_append(list
, path
))) {
466 SET_ERROR(ret
, SP_ERR_MEM
, "list append failed");
467 IOObjectRelease(port
);
472 IOObjectRelease(port
);
477 IOObjectRelease(iter
);
480 #if defined(__linux__) && defined(HAVE_LIBUDEV)
482 struct udev_enumerate
*ud_enumerate
;
483 struct udev_list_entry
*ud_list
;
484 struct udev_list_entry
*ud_entry
;
486 struct udev_device
*ud_dev
, *ud_parent
;
489 int fd
, ioctl_result
;
490 struct serial_struct serial_info
;
494 DEBUG("Enumerating tty devices");
496 ud_enumerate
= udev_enumerate_new(ud
);
497 udev_enumerate_add_match_subsystem(ud_enumerate
, "tty");
498 udev_enumerate_scan_devices(ud_enumerate
);
499 ud_list
= udev_enumerate_get_list_entry(ud_enumerate
);
500 DEBUG("Iterating over results");
501 udev_list_entry_foreach(ud_entry
, ud_list
) {
502 path
= udev_list_entry_get_name(ud_entry
);
503 DEBUG("Found device %s", path
);
504 ud_dev
= udev_device_new_from_syspath(ud
, path
);
505 /* If there is no parent device, this is a virtual tty. */
506 ud_parent
= udev_device_get_parent(ud_dev
);
507 if (ud_parent
== NULL
) {
508 DEBUG("No parent device, assuming virtual tty");
509 udev_device_unref(ud_dev
);
512 name
= udev_device_get_devnode(ud_dev
);
513 /* The serial8250 driver has a hardcoded number of ports.
514 * The only way to tell which actually exist on a given system
515 * is to try to open them and make an ioctl call. */
516 driver
= udev_device_get_driver(ud_parent
);
517 if (driver
&& !strcmp(driver
, "serial8250")) {
518 DEBUG("serial8250 device, attempting to open");
519 if ((fd
= open(name
, O_RDWR
| O_NONBLOCK
| O_NOCTTY
)) < 0) {
520 DEBUG("open failed, skipping");
523 ioctl_result
= ioctl(fd
, TIOCGSERIAL
, &serial_info
);
525 if (ioctl_result
!= 0) {
526 DEBUG("ioctl failed, skipping");
529 if (serial_info
.type
== PORT_UNKNOWN
) {
530 DEBUG("port type is unknown, skipping");
534 DEBUG("Found port %s", name
);
535 list
= list_append(list
, name
);
537 udev_device_unref(ud_dev
);
539 SET_ERROR(ret
, SP_ERR_MEM
, "list append failed");
544 udev_enumerate_unref(ud_enumerate
);
553 DEBUG_ERROR(SP_ERR_SUPP
, "Enumeration not supported on this platform");
556 sp_free_port_list(list
);
562 void sp_free_port_list(struct sp_port
**list
)
573 DEBUG("Freeing port list");
575 for (i
= 0; list
[i
]; i
++)
576 sp_free_port(list
[i
]);
582 #define CHECK_PORT() do { \
584 RETURN_ERROR(SP_ERR_ARG, "Null port"); \
585 if (port->name == NULL) \
586 RETURN_ERROR(SP_ERR_ARG, "Null port name"); \
589 #define CHECK_PORT_HANDLE() do { \
590 if (port->hdl == INVALID_HANDLE_VALUE) \
591 RETURN_ERROR(SP_ERR_ARG, "Invalid port handle"); \
594 #define CHECK_PORT_HANDLE() do { \
596 RETURN_ERROR(SP_ERR_ARG, "Invalid port fd"); \
599 #define CHECK_OPEN_PORT() do { \
601 CHECK_PORT_HANDLE(); \
604 enum sp_return
sp_open(struct sp_port
*port
, enum sp_mode flags
)
606 struct port_data data
;
607 struct sp_port_config config
;
610 TRACE("%p, 0x%x", port
, flags
);
614 if (flags
> (SP_MODE_READ
| SP_MODE_WRITE
))
615 RETURN_ERROR(SP_ERR_ARG
, "Invalid flags");
617 DEBUG("Opening port %s", port
->name
);
620 DWORD desired_access
= 0, flags_and_attributes
= 0, errors
;
621 char *escaped_port_name
;
624 /* Prefix port name with '\\.\' to work with ports above COM9. */
625 if (!(escaped_port_name
= malloc(strlen(port
->name
+ 5))))
626 RETURN_ERROR(SP_ERR_MEM
, "Escaped port name malloc failed");
627 sprintf(escaped_port_name
, "\\\\.\\%s", port
->name
);
629 /* Map 'flags' to the OS-specific settings. */
630 flags_and_attributes
= FILE_ATTRIBUTE_NORMAL
| FILE_FLAG_OVERLAPPED
;
631 if (flags
& SP_MODE_READ
)
632 desired_access
|= GENERIC_READ
;
633 if (flags
& SP_MODE_WRITE
)
634 desired_access
|= GENERIC_WRITE
;
636 port
->hdl
= CreateFile(escaped_port_name
, desired_access
, 0, 0,
637 OPEN_EXISTING
, flags_and_attributes
, 0);
639 free(escaped_port_name
);
641 if (port
->hdl
== INVALID_HANDLE_VALUE
)
642 RETURN_FAIL("port CreateFile() failed");
644 /* All timeouts initially disabled. */
645 port
->timeouts
.ReadIntervalTimeout
= 0;
646 port
->timeouts
.ReadTotalTimeoutMultiplier
= 0;
647 port
->timeouts
.ReadTotalTimeoutConstant
= 0;
648 port
->timeouts
.WriteTotalTimeoutMultiplier
= 0;
649 port
->timeouts
.WriteTotalTimeoutConstant
= 0;
651 if (SetCommTimeouts(port
->hdl
, &port
->timeouts
) == 0) {
653 RETURN_FAIL("SetCommTimeouts() failed");
656 /* Prepare OVERLAPPED structures. */
657 #define INIT_OVERLAPPED(ovl) do { \
658 memset(&port->ovl, 0, sizeof(port->ovl)); \
659 port->ovl.hEvent = INVALID_HANDLE_VALUE; \
660 if ((port->ovl.hEvent = CreateEvent(NULL, TRUE, TRUE, NULL)) \
661 == INVALID_HANDLE_VALUE) { \
663 RETURN_FAIL(#ovl "CreateEvent() failed"); \
667 INIT_OVERLAPPED(read_ovl
);
668 INIT_OVERLAPPED(write_ovl
);
669 INIT_OVERLAPPED(wait_ovl
);
671 /* Set event mask for RX and error events. */
672 if (SetCommMask(port
->hdl
, EV_RXCHAR
| EV_ERR
) == 0) {
674 RETURN_FAIL("SetCommMask() failed");
677 /* Start background operation for RX and error events. */
678 if (WaitCommEvent(port
->hdl
, &port
->events
, &port
->wait_ovl
) == 0) {
679 if (GetLastError() != ERROR_IO_PENDING
) {
681 RETURN_FAIL("WaitCommEvent() failed");
685 port
->writing
= FALSE
;
688 int flags_local
= O_NONBLOCK
| O_NOCTTY
;
690 /* Map 'flags' to the OS-specific settings. */
691 if (flags
& (SP_MODE_READ
| SP_MODE_WRITE
))
692 flags_local
|= O_RDWR
;
693 else if (flags
& SP_MODE_READ
)
694 flags_local
|= O_RDONLY
;
695 else if (flags
& SP_MODE_WRITE
)
696 flags_local
|= O_WRONLY
;
698 if ((port
->fd
= open(port
->name
, flags_local
)) < 0)
699 RETURN_FAIL("open() failed");
702 ret
= get_config(port
, &data
, &config
);
709 /* Set sane port settings. */
711 data
.dcb
.fBinary
= TRUE
;
712 data
.dcb
.fDsrSensitivity
= FALSE
;
713 data
.dcb
.fErrorChar
= FALSE
;
714 data
.dcb
.fNull
= FALSE
;
715 data
.dcb
.fAbortOnError
= TRUE
;
717 /* Turn off all fancy termios tricks, give us a raw channel. */
718 data
.term
.c_iflag
&= ~(IGNBRK
| BRKINT
| PARMRK
| ISTRIP
| INLCR
| IGNCR
| ICRNL
| IMAXBEL
);
720 data
.term
.c_iflag
&= ~IUCLC
;
722 data
.term
.c_oflag
&= ~(OPOST
| ONLCR
| OCRNL
| ONOCR
| ONLRET
);
724 data
.term
.c_oflag
&= ~OLCUC
;
727 data
.term
.c_oflag
&= ~NLDLY
;
730 data
.term
.c_oflag
&= ~CRDLY
;
733 data
.term
.c_oflag
&= ~TABDLY
;
736 data
.term
.c_oflag
&= ~BSDLY
;
739 data
.term
.c_oflag
&= ~VTDLY
;
742 data
.term
.c_oflag
&= ~FFDLY
;
745 data
.term
.c_oflag
&= ~OFILL
;
747 data
.term
.c_lflag
&= ~(ISIG
| ICANON
| ECHO
| IEXTEN
);
748 data
.term
.c_cc
[VMIN
] = 0;
749 data
.term
.c_cc
[VTIME
] = 0;
751 /* Ignore modem status lines; enable receiver; leave control lines alone on close. */
752 data
.term
.c_cflag
|= (CLOCAL
| CREAD
| HUPCL
);
756 if (ClearCommError(port
->hdl
, &errors
, &status
) == 0)
757 RETURN_FAIL("ClearCommError() failed");
760 ret
= set_config(port
, &data
, &config
);
770 enum sp_return
sp_close(struct sp_port
*port
)
776 DEBUG("Closing port %s", port
->name
);
779 /* Returns non-zero upon success, 0 upon failure. */
780 if (CloseHandle(port
->hdl
) == 0)
781 RETURN_FAIL("port CloseHandle() failed");
782 port
->hdl
= INVALID_HANDLE_VALUE
;
784 /* Close event handles for overlapped structures. */
785 #define CLOSE_OVERLAPPED(ovl) do { \
786 if (port->ovl.hEvent != INVALID_HANDLE_VALUE && \
787 CloseHandle(port->ovl.hEvent) == 0) \
788 RETURN_FAIL(# ovl "event CloseHandle() failed"); \
790 CLOSE_OVERLAPPED(read_ovl
);
791 CLOSE_OVERLAPPED(write_ovl
);
792 CLOSE_OVERLAPPED(wait_ovl
);
795 /* Returns 0 upon success, -1 upon failure. */
796 if (close(port
->fd
) == -1)
797 RETURN_FAIL("close() failed");
804 enum sp_return
sp_flush(struct sp_port
*port
, enum sp_buffer buffers
)
806 TRACE("%p, 0x%x", port
, buffers
);
810 if (buffers
> SP_BUF_BOTH
)
811 RETURN_ERROR(SP_ERR_ARG
, "Invalid buffer selection");
813 const char *buffer_names
[] = {"no", "input", "output", "both"};
815 DEBUG("Flushing %s buffers on port %s", buffer_names
[buffers
], port
->name
);
819 if (buffers
& SP_BUF_INPUT
)
820 flags
|= PURGE_RXCLEAR
;
821 if (buffers
& SP_BUF_OUTPUT
)
822 flags
|= PURGE_TXCLEAR
;
824 /* Returns non-zero upon success, 0 upon failure. */
825 if (PurgeComm(port
->hdl
, flags
) == 0)
826 RETURN_FAIL("PurgeComm() failed");
829 if (buffers
& SP_BUF_BOTH
)
831 else if (buffers
& SP_BUF_INPUT
)
833 else if (buffers
& SP_BUF_OUTPUT
)
836 /* Returns 0 upon success, -1 upon failure. */
837 if (tcflush(port
->fd
, flags
) < 0)
838 RETURN_FAIL("tcflush() failed");
843 enum sp_return
sp_drain(struct sp_port
*port
)
849 DEBUG("Draining port %s", port
->name
);
852 /* Returns non-zero upon success, 0 upon failure. */
853 if (FlushFileBuffers(port
->hdl
) == 0)
854 RETURN_FAIL("FlushFileBuffers() failed");
861 result
= ioctl(port
->fd
, TCSBRK
, &arg
);
863 result
= tcdrain(port
->fd
);
866 if (errno
== EINTR
) {
867 DEBUG("tcdrain() was interrupted");
870 RETURN_FAIL("tcdrain() failed");
879 enum sp_return
sp_blocking_write(struct sp_port
*port
, const void *buf
, size_t count
, unsigned int timeout
)
881 TRACE("%p, %p, %d, %d", port
, buf
, count
, timeout
);
886 RETURN_ERROR(SP_ERR_ARG
, "Null buffer");
889 DEBUG("Writing %d bytes to port %s, timeout %d ms", count
, port
->name
, timeout
);
891 DEBUG("Writing %d bytes to port %s, no timeout", count
, port
->name
);
894 RETURN_VALUE("0", 0);
897 DWORD bytes_written
= 0;
900 /* Wait for previous non-blocking write to complete, if any. */
902 DEBUG("Waiting for previous write to complete");
903 result
= GetOverlappedResult(port
->hdl
, &port
->write_ovl
, &bytes_written
, TRUE
);
906 RETURN_FAIL("Previous write failed to complete");
907 DEBUG("Previous write completed");
911 port
->timeouts
.WriteTotalTimeoutConstant
= timeout
;
912 if (SetCommTimeouts(port
->hdl
, &port
->timeouts
) == 0)
913 RETURN_FAIL("SetCommTimeouts() failed");
916 if (WriteFile(port
->hdl
, buf
, count
, NULL
, &port
->write_ovl
) == 0) {
917 if (GetLastError() == ERROR_IO_PENDING
) {
918 DEBUG("Waiting for write to complete");
919 GetOverlappedResult(port
->hdl
, &port
->write_ovl
, &bytes_written
, TRUE
);
920 DEBUG("Write completed, %d/%d bytes written", bytes_written
, count
);
921 RETURN_VALUE("%d", bytes_written
);
923 RETURN_FAIL("WriteFile() failed");
926 DEBUG("Write completed immediately");
927 RETURN_VALUE("%d", count
);
930 size_t bytes_written
= 0;
931 unsigned char *ptr
= (unsigned char *) buf
;
932 struct timeval start
, delta
, now
, end
= {0, 0};
937 /* Get time at start of operation. */
938 gettimeofday(&start
, NULL
);
939 /* Define duration of timeout. */
940 delta
.tv_sec
= timeout
/ 1000;
941 delta
.tv_usec
= (timeout
% 1000) * 1000;
942 /* Calculate time at which we should give up. */
943 timeradd(&start
, &delta
, &end
);
946 /* Loop until we have written the requested number of bytes. */
947 while (bytes_written
< count
)
949 /* Wait until space is available. */
951 FD_SET(port
->fd
, &fds
);
953 gettimeofday(&now
, NULL
);
954 if (timercmp(&now
, &end
, >)) {
955 DEBUG("write timed out");
956 RETURN_VALUE("%d", bytes_written
);
958 timersub(&end
, &now
, &delta
);
960 result
= select(port
->fd
+ 1, NULL
, &fds
, NULL
, timeout
? &delta
: NULL
);
962 if (errno
== EINTR
) {
963 DEBUG("select() call was interrupted, repeating");
966 RETURN_FAIL("select() failed");
968 } else if (result
== 0) {
969 DEBUG("write timed out");
970 RETURN_VALUE("%d", bytes_written
);
974 result
= write(port
->fd
, ptr
, count
- bytes_written
);
978 /* This shouldn't happen because we did a select() first, but handle anyway. */
981 /* This is an actual failure. */
982 RETURN_FAIL("write() failed");
985 bytes_written
+= result
;
989 RETURN_VALUE("%d", bytes_written
);
993 enum sp_return
sp_nonblocking_write(struct sp_port
*port
, const void *buf
, size_t count
)
995 TRACE("%p, %p, %d", port
, buf
, count
);
1000 RETURN_ERROR(SP_ERR_ARG
, "Null buffer");
1002 DEBUG("Writing up to %d bytes to port %s", count
, port
->name
);
1005 RETURN_VALUE("0", 0);
1009 BYTE
*ptr
= (BYTE
*) buf
;
1011 /* Check whether previous write is complete. */
1012 if (port
->writing
) {
1013 if (HasOverlappedIoCompleted(&port
->write_ovl
)) {
1014 DEBUG("Previous write completed");
1017 DEBUG("Previous write not complete");
1018 /* Can't take a new write until the previous one finishes. */
1019 RETURN_VALUE("0", 0);
1024 port
->timeouts
.WriteTotalTimeoutConstant
= 0;
1025 if (SetCommTimeouts(port
->hdl
, &port
->timeouts
) == 0)
1026 RETURN_FAIL("SetCommTimeouts() failed");
1028 /* Keep writing data until the OS has to actually start an async IO for it.
1029 * At that point we know the buffer is full. */
1030 while (written
< count
)
1032 /* Copy first byte of user buffer. */
1033 port
->pending_byte
= *ptr
++;
1035 /* Start asynchronous write. */
1036 if (WriteFile(port
->hdl
, &port
->pending_byte
, 1, NULL
, &port
->write_ovl
) == 0) {
1037 if (GetLastError() == ERROR_IO_PENDING
) {
1038 if (HasOverlappedIoCompleted(&port
->write_ovl
)) {
1039 DEBUG("Asynchronous write completed immediately");
1044 DEBUG("Asynchronous write running");
1046 RETURN_VALUE("%d", ++written
);
1049 /* Actual failure of some kind. */
1050 RETURN_FAIL("WriteFile() failed");
1053 DEBUG("Single byte written immediately");
1058 DEBUG("All bytes written immediately");
1060 RETURN_VALUE("%d", written
);
1062 /* Returns the number of bytes written, or -1 upon failure. */
1063 ssize_t written
= write(port
->fd
, buf
, count
);
1066 RETURN_FAIL("write() failed");
1068 RETURN_VALUE("%d", written
);
1072 enum sp_return
sp_blocking_read(struct sp_port
*port
, void *buf
, size_t count
, unsigned int timeout
)
1074 TRACE("%p, %p, %d, %d", port
, buf
, count
, timeout
);
1079 RETURN_ERROR(SP_ERR_ARG
, "Null buffer");
1082 DEBUG("Reading %d bytes from port %s, timeout %d ms", count
, port
->name
, timeout
);
1084 DEBUG("Reading %d bytes from port %s, no timeout", count
, port
->name
);
1087 RETURN_VALUE("0", 0);
1090 DWORD bytes_read
= 0;
1093 port
->timeouts
.ReadIntervalTimeout
= 0;
1094 port
->timeouts
.ReadTotalTimeoutConstant
= timeout
;
1095 if (SetCommTimeouts(port
->hdl
, &port
->timeouts
) == 0)
1096 RETURN_FAIL("SetCommTimeouts() failed");
1099 if (ReadFile(port
->hdl
, buf
, count
, NULL
, &port
->read_ovl
) == 0) {
1100 if (GetLastError() == ERROR_IO_PENDING
) {
1101 DEBUG("Waiting for read to complete");
1102 GetOverlappedResult(port
->hdl
, &port
->read_ovl
, &bytes_read
, TRUE
);
1103 DEBUG("Read completed, %d/%d bytes read", bytes_read
, count
);
1105 RETURN_FAIL("ReadFile() failed");
1108 DEBUG("Read completed immediately");
1112 /* Start background operation for subsequent events. */
1113 if (WaitCommEvent(port
->hdl
, &port
->events
, &port
->wait_ovl
) == 0) {
1114 if (GetLastError() != ERROR_IO_PENDING
)
1115 RETURN_FAIL("WaitCommEvent() failed");
1118 RETURN_VALUE("%d", bytes_read
);
1121 size_t bytes_read
= 0;
1122 unsigned char *ptr
= (unsigned char *) buf
;
1123 struct timeval start
, delta
, now
, end
= {0, 0};
1128 /* Get time at start of operation. */
1129 gettimeofday(&start
, NULL
);
1130 /* Define duration of timeout. */
1131 delta
.tv_sec
= timeout
/ 1000;
1132 delta
.tv_usec
= (timeout
% 1000) * 1000;
1133 /* Calculate time at which we should give up. */
1134 timeradd(&start
, &delta
, &end
);
1137 /* Loop until we have the requested number of bytes. */
1138 while (bytes_read
< count
)
1140 /* Wait until data is available. */
1142 FD_SET(port
->fd
, &fds
);
1144 gettimeofday(&now
, NULL
);
1145 if (timercmp(&now
, &end
, >))
1146 /* Timeout has expired. */
1147 RETURN_VALUE("%d", bytes_read
);
1148 timersub(&end
, &now
, &delta
);
1150 result
= select(port
->fd
+ 1, &fds
, NULL
, NULL
, timeout
? &delta
: NULL
);
1152 if (errno
== EINTR
) {
1153 DEBUG("select() call was interrupted, repeating");
1156 RETURN_FAIL("select() failed");
1158 } else if (result
== 0) {
1159 DEBUG("read timed out");
1160 RETURN_VALUE("%d", bytes_read
);
1164 result
= read(port
->fd
, ptr
, count
- bytes_read
);
1167 if (errno
== EAGAIN
)
1168 /* This shouldn't happen because we did a select() first, but handle anyway. */
1171 /* This is an actual failure. */
1172 RETURN_FAIL("read() failed");
1175 bytes_read
+= result
;
1179 RETURN_VALUE("%d", bytes_read
);
1183 enum sp_return
sp_nonblocking_read(struct sp_port
*port
, void *buf
, size_t count
)
1185 TRACE("%p, %p, %d", port
, buf
, count
);
1190 RETURN_ERROR(SP_ERR_ARG
, "Null buffer");
1192 DEBUG("Reading up to %d bytes from port %s", count
, port
->name
);
1198 port
->timeouts
.ReadIntervalTimeout
= MAXDWORD
;
1199 port
->timeouts
.ReadTotalTimeoutConstant
= 0;
1200 if (SetCommTimeouts(port
->hdl
, &port
->timeouts
) == 0)
1201 RETURN_FAIL("SetCommTimeouts() failed");
1204 if (ReadFile(port
->hdl
, buf
, count
, NULL
, &port
->read_ovl
) == 0)
1205 RETURN_FAIL("ReadFile() failed");
1207 /* Get number of bytes read. */
1208 if (GetOverlappedResult(port
->hdl
, &port
->read_ovl
, &bytes_read
, TRUE
) == 0)
1209 RETURN_FAIL("GetOverlappedResult() failed");
1211 if (bytes_read
> 0) {
1212 /* Start background operation for subsequent events. */
1213 if (WaitCommEvent(port
->hdl
, &port
->events
, &port
->wait_ovl
) == 0) {
1214 if (GetLastError() != ERROR_IO_PENDING
)
1215 RETURN_FAIL("WaitCommEvent() failed");
1219 RETURN_VALUE("%d", bytes_read
);
1223 /* Returns the number of bytes read, or -1 upon failure. */
1224 if ((bytes_read
= read(port
->fd
, buf
, count
)) < 0) {
1225 if (errno
== EAGAIN
)
1226 /* No bytes available. */
1229 /* This is an actual failure. */
1230 RETURN_FAIL("read() failed");
1232 RETURN_VALUE("%d", bytes_read
);
1236 enum sp_return
sp_input_waiting(struct sp_port
*port
)
1242 DEBUG("Checking input bytes waiting on port %s", port
->name
);
1248 if (ClearCommError(port
->hdl
, &errors
, &comstat
) == 0)
1249 RETURN_FAIL("ClearCommError() failed");
1250 RETURN_VALUE("%d", comstat
.cbInQue
);
1253 if (ioctl(port
->fd
, TIOCINQ
, &bytes_waiting
) < 0)
1254 RETURN_FAIL("TIOCINQ ioctl failed");
1255 RETURN_VALUE("%d", bytes_waiting
);
1259 enum sp_return
sp_output_waiting(struct sp_port
*port
)
1265 DEBUG("Checking output bytes waiting on port %s", port
->name
);
1271 if (ClearCommError(port
->hdl
, &errors
, &comstat
) == 0)
1272 RETURN_FAIL("ClearCommError() failed");
1273 RETURN_VALUE("%d", comstat
.cbOutQue
);
1276 if (ioctl(port
->fd
, TIOCOUTQ
, &bytes_waiting
) < 0)
1277 RETURN_FAIL("TIOCOUTQ ioctl failed");
1278 RETURN_VALUE("%d", bytes_waiting
);
1282 enum sp_return
sp_new_event_set(struct sp_event_set
**result_ptr
)
1284 struct sp_event_set
*result
;
1286 TRACE("%p", result_ptr
);
1289 RETURN_ERROR(SP_ERR_ARG
, "Null result");
1293 if (!(result
= malloc(sizeof(struct sp_event_set
))))
1294 RETURN_ERROR(SP_ERR_MEM
, "sp_event_set malloc() failed");
1296 memset(result
, 0, sizeof(struct sp_event_set
));
1298 *result_ptr
= result
;
1303 static enum sp_return
add_handle(struct sp_event_set
*event_set
,
1304 event_handle handle
, enum sp_event mask
)
1307 enum sp_event
*new_masks
;
1309 TRACE("%p, %d, %d", event_set
, handle
, mask
);
1311 if (!(new_handles
= realloc(event_set
->handles
,
1312 sizeof(event_handle
) * (event_set
->count
+ 1))))
1313 RETURN_ERROR(SP_ERR_MEM
, "handle array realloc() failed");
1315 if (!(new_masks
= realloc(event_set
->masks
,
1316 sizeof(enum sp_event
) * (event_set
->count
+ 1))))
1317 RETURN_ERROR(SP_ERR_MEM
, "mask array realloc() failed");
1319 event_set
->handles
= new_handles
;
1320 event_set
->masks
= new_masks
;
1322 ((event_handle
*) event_set
->handles
)[event_set
->count
] = handle
;
1323 event_set
->masks
[event_set
->count
] = mask
;
1330 enum sp_return
sp_add_port_events(struct sp_event_set
*event_set
,
1331 const struct sp_port
*port
, enum sp_event mask
)
1333 TRACE("%p, %p, %d", event_set
, port
, mask
);
1336 RETURN_ERROR(SP_ERR_ARG
, "Null event set");
1339 RETURN_ERROR(SP_ERR_ARG
, "Null port");
1341 if (mask
> (SP_EVENT_RX_READY
| SP_EVENT_TX_READY
| SP_EVENT_ERROR
))
1342 RETURN_ERROR(SP_ERR_ARG
, "Invalid event mask");
1348 enum sp_event handle_mask
;
1349 if ((handle_mask
= mask
& SP_EVENT_TX_READY
))
1350 TRY(add_handle(event_set
, port
->write_ovl
.hEvent
, handle_mask
));
1351 if ((handle_mask
= mask
& (SP_EVENT_RX_READY
| SP_EVENT_ERROR
)))
1352 TRY(add_handle(event_set
, port
->wait_ovl
.hEvent
, handle_mask
));
1354 TRY(add_handle(event_set
, port
->fd
, mask
));
1360 void sp_free_event_set(struct sp_event_set
*event_set
)
1362 TRACE("%p", event_set
);
1365 DEBUG("Null event set");
1369 DEBUG("Freeing event set");
1371 if (event_set
->handles
)
1372 free(event_set
->handles
);
1373 if (event_set
->masks
)
1374 free(event_set
->masks
);
1381 enum sp_return
sp_wait(struct sp_event_set
*event_set
, unsigned int timeout
)
1383 TRACE("%p, %d", event_set
, timeout
);
1386 RETURN_ERROR(SP_ERR_ARG
, "Null event set");
1389 if (WaitForMultipleObjects(event_set
->count
, event_set
->handles
, FALSE
,
1390 timeout
? timeout
: INFINITE
) == WAIT_FAILED
)
1391 RETURN_FAIL("WaitForMultipleObjects() failed");
1395 struct timeval start
, delta
, now
, end
= {0, 0};
1396 int result
, timeout_remaining
;
1397 struct pollfd
*pollfds
;
1400 if (!(pollfds
= malloc(sizeof(struct pollfd
) * event_set
->count
)))
1401 RETURN_ERROR(SP_ERR_MEM
, "pollfds malloc() failed");
1403 for (i
= 0; i
< event_set
->count
; i
++) {
1404 pollfds
[i
].fd
= ((int *) event_set
->handles
)[i
];
1405 pollfds
[i
].events
= 0;
1406 pollfds
[i
].revents
= 0;
1407 if (event_set
->masks
[i
] & SP_EVENT_RX_READY
)
1408 pollfds
[i
].events
|= POLLIN
;
1409 if (event_set
->masks
[i
] & SP_EVENT_TX_READY
)
1410 pollfds
[i
].events
|= POLLOUT
;
1411 if (event_set
->masks
[i
] & SP_EVENT_ERROR
)
1412 pollfds
[i
].events
|= POLLERR
;
1416 /* Get time at start of operation. */
1417 gettimeofday(&start
, NULL
);
1418 /* Define duration of timeout. */
1419 delta
.tv_sec
= timeout
/ 1000;
1420 delta
.tv_usec
= (timeout
% 1000) * 1000;
1421 /* Calculate time at which we should give up. */
1422 timeradd(&start
, &delta
, &end
);
1425 /* Loop until an event occurs. */
1429 gettimeofday(&now
, NULL
);
1430 if (timercmp(&now
, &end
, >)) {
1431 DEBUG("wait timed out");
1434 timersub(&end
, &now
, &delta
);
1435 timeout_remaining
= delta
.tv_sec
* 1000 + delta
.tv_usec
/ 1000;
1438 result
= poll(pollfds
, event_set
->count
, timeout
? timeout_remaining
: -1);
1441 if (errno
== EINTR
) {
1442 DEBUG("poll() call was interrupted, repeating");
1446 RETURN_FAIL("poll() failed");
1448 } else if (result
== 0) {
1449 DEBUG("poll() timed out");
1452 DEBUG("poll() completed");
1463 static enum sp_return
get_baudrate(int fd
, int *baudrate
)
1467 TRACE("%d, %p", fd
, baudrate
);
1469 DEBUG("Getting baud rate");
1471 if (!(data
= malloc(get_termios_size())))
1472 RETURN_ERROR(SP_ERR_MEM
, "termios malloc failed");
1474 if (ioctl(fd
, get_termios_get_ioctl(), data
) < 0) {
1476 RETURN_FAIL("getting termios failed");
1479 *baudrate
= get_termios_speed(data
);
1486 static enum sp_return
set_baudrate(int fd
, int baudrate
)
1490 TRACE("%d, %d", fd
, baudrate
);
1492 DEBUG("Getting baud rate");
1494 if (!(data
= malloc(get_termios_size())))
1495 RETURN_ERROR(SP_ERR_MEM
, "termios malloc failed");
1497 if (ioctl(fd
, get_termios_get_ioctl(), data
) < 0) {
1499 RETURN_FAIL("getting termios failed");
1502 DEBUG("Setting baud rate");
1504 set_termios_speed(data
, baudrate
);
1506 if (ioctl(fd
, get_termios_set_ioctl(), data
) < 0) {
1508 RETURN_FAIL("setting termios failed");
1517 static enum sp_return
get_flow(int fd
, int *flow
)
1521 TRACE("%d, %p", fd
, flow
);
1523 DEBUG("Getting advanced flow control");
1525 if (!(data
= malloc(get_termiox_size())))
1526 RETURN_ERROR(SP_ERR_MEM
, "termiox malloc failed");
1528 if (ioctl(fd
, TCGETX
, data
) < 0) {
1530 RETURN_FAIL("getting termiox failed");
1533 *flow
= get_termiox_flow(data
);
1540 static enum sp_return
set_flow(int fd
, int flow
)
1544 TRACE("%d, %d", fd
, flow
);
1546 DEBUG("Getting advanced flow control");
1548 if (!(data
= malloc(get_termiox_size())))
1549 RETURN_ERROR(SP_ERR_MEM
, "termiox malloc failed");
1551 if (ioctl(fd
, TCGETX
, data
) < 0) {
1553 RETURN_FAIL("getting termiox failed");
1556 DEBUG("Setting advanced flow control");
1558 set_termiox_flow(data
, flow
);
1560 if (ioctl(fd
, TCSETX
, data
) < 0) {
1562 RETURN_FAIL("setting termiox failed");
1569 #endif /* USE_TERMIOX */
1570 #endif /* __linux__ */
1572 static enum sp_return
get_config(struct sp_port
*port
, struct port_data
*data
,
1573 struct sp_port_config
*config
)
1577 TRACE("%p, %p, %p", port
, data
, config
);
1579 DEBUG("Getting configuration for port %s", port
->name
);
1582 if (!GetCommState(port
->hdl
, &data
->dcb
))
1583 RETURN_FAIL("GetCommState() failed");
1585 for (i
= 0; i
< NUM_STD_BAUDRATES
; i
++) {
1586 if (data
->dcb
.BaudRate
== std_baudrates
[i
].index
) {
1587 config
->baudrate
= std_baudrates
[i
].value
;
1592 if (i
== NUM_STD_BAUDRATES
)
1593 /* BaudRate field can be either an index or a custom baud rate. */
1594 config
->baudrate
= data
->dcb
.BaudRate
;
1596 config
->bits
= data
->dcb
.ByteSize
;
1598 if (data
->dcb
.fParity
)
1599 switch (data
->dcb
.Parity
) {
1601 config
->parity
= SP_PARITY_NONE
;
1604 config
->parity
= SP_PARITY_ODD
;
1607 config
->parity
= SP_PARITY_EVEN
;
1610 config
->parity
= SP_PARITY_MARK
;
1613 config
->parity
= SP_PARITY_SPACE
;
1616 config
->parity
= -1;
1619 config
->parity
= SP_PARITY_NONE
;
1621 switch (data
->dcb
.StopBits
) {
1623 config
->stopbits
= 1;
1626 config
->stopbits
= 2;
1629 config
->stopbits
= -1;
1632 switch (data
->dcb
.fRtsControl
) {
1633 case RTS_CONTROL_DISABLE
:
1634 config
->rts
= SP_RTS_OFF
;
1636 case RTS_CONTROL_ENABLE
:
1637 config
->rts
= SP_RTS_ON
;
1639 case RTS_CONTROL_HANDSHAKE
:
1640 config
->rts
= SP_RTS_FLOW_CONTROL
;
1646 config
->cts
= data
->dcb
.fOutxCtsFlow
? SP_CTS_FLOW_CONTROL
: SP_CTS_IGNORE
;
1648 switch (data
->dcb
.fDtrControl
) {
1649 case DTR_CONTROL_DISABLE
:
1650 config
->dtr
= SP_DTR_OFF
;
1652 case DTR_CONTROL_ENABLE
:
1653 config
->dtr
= SP_DTR_ON
;
1655 case DTR_CONTROL_HANDSHAKE
:
1656 config
->dtr
= SP_DTR_FLOW_CONTROL
;
1662 config
->dsr
= data
->dcb
.fOutxDsrFlow
? SP_DSR_FLOW_CONTROL
: SP_DSR_IGNORE
;
1664 if (data
->dcb
.fInX
) {
1665 if (data
->dcb
.fOutX
)
1666 config
->xon_xoff
= SP_XONXOFF_INOUT
;
1668 config
->xon_xoff
= SP_XONXOFF_IN
;
1670 if (data
->dcb
.fOutX
)
1671 config
->xon_xoff
= SP_XONXOFF_OUT
;
1673 config
->xon_xoff
= SP_XONXOFF_DISABLED
;
1678 if (tcgetattr(port
->fd
, &data
->term
) < 0)
1679 RETURN_FAIL("tcgetattr() failed");
1681 if (ioctl(port
->fd
, TIOCMGET
, &data
->controlbits
) < 0)
1682 RETURN_FAIL("TIOCMGET ioctl failed");
1685 int ret
= get_flow(port
->fd
, &data
->flow
);
1687 if (ret
== SP_ERR_FAIL
&& errno
== EINVAL
)
1688 data
->termiox_supported
= 0;
1690 RETURN_CODEVAL(ret
);
1692 data
->termiox_supported
= 1;
1694 data
->termiox_supported
= 0;
1697 for (i
= 0; i
< NUM_STD_BAUDRATES
; i
++) {
1698 if (cfgetispeed(&data
->term
) == std_baudrates
[i
].index
) {
1699 config
->baudrate
= std_baudrates
[i
].value
;
1704 if (i
== NUM_STD_BAUDRATES
) {
1706 config
->baudrate
= (int)data
->term
.c_ispeed
;
1707 #elif defined(__linux__)
1708 TRY(get_baudrate(port
->fd
, &config
->baudrate
));
1710 config
->baudrate
= -1;
1714 switch (data
->term
.c_cflag
& CSIZE
) {
1731 if (!(data
->term
.c_cflag
& PARENB
) && (data
->term
.c_iflag
& IGNPAR
))
1732 config
->parity
= SP_PARITY_NONE
;
1733 else if (!(data
->term
.c_cflag
& PARENB
) || (data
->term
.c_iflag
& IGNPAR
))
1734 config
->parity
= -1;
1736 else if (data
->term
.c_cflag
& CMSPAR
)
1737 config
->parity
= (data
->term
.c_cflag
& PARODD
) ? SP_PARITY_MARK
: SP_PARITY_SPACE
;
1740 config
->parity
= (data
->term
.c_cflag
& PARODD
) ? SP_PARITY_ODD
: SP_PARITY_EVEN
;
1742 config
->stopbits
= (data
->term
.c_cflag
& CSTOPB
) ? 2 : 1;
1744 if (data
->term
.c_cflag
& CRTSCTS
) {
1745 config
->rts
= SP_RTS_FLOW_CONTROL
;
1746 config
->cts
= SP_CTS_FLOW_CONTROL
;
1748 if (data
->termiox_supported
&& data
->flow
& RTS_FLOW
)
1749 config
->rts
= SP_RTS_FLOW_CONTROL
;
1751 config
->rts
= (data
->controlbits
& TIOCM_RTS
) ? SP_RTS_ON
: SP_RTS_OFF
;
1753 config
->cts
= (data
->termiox_supported
&& data
->flow
& CTS_FLOW
) ?
1754 SP_CTS_FLOW_CONTROL
: SP_CTS_IGNORE
;
1757 if (data
->termiox_supported
&& data
->flow
& DTR_FLOW
)
1758 config
->dtr
= SP_DTR_FLOW_CONTROL
;
1760 config
->dtr
= (data
->controlbits
& TIOCM_DTR
) ? SP_DTR_ON
: SP_DTR_OFF
;
1762 config
->dsr
= (data
->termiox_supported
&& data
->flow
& DSR_FLOW
) ?
1763 SP_DSR_FLOW_CONTROL
: SP_DSR_IGNORE
;
1765 if (data
->term
.c_iflag
& IXOFF
) {
1766 if (data
->term
.c_iflag
& IXON
)
1767 config
->xon_xoff
= SP_XONXOFF_INOUT
;
1769 config
->xon_xoff
= SP_XONXOFF_IN
;
1771 if (data
->term
.c_iflag
& IXON
)
1772 config
->xon_xoff
= SP_XONXOFF_OUT
;
1774 config
->xon_xoff
= SP_XONXOFF_DISABLED
;
1781 static enum sp_return
set_config(struct sp_port
*port
, struct port_data
*data
,
1782 const struct sp_port_config
*config
)
1786 BAUD_TYPE baud_nonstd
;
1791 int baud_nonstd
= 0;
1794 TRACE("%p, %p, %p", port
, data
, config
);
1796 DEBUG("Setting configuration for port %s", port
->name
);
1799 if (config
->baudrate
>= 0) {
1800 for (i
= 0; i
< NUM_STD_BAUDRATES
; i
++) {
1801 if (config
->baudrate
== std_baudrates
[i
].value
) {
1802 data
->dcb
.BaudRate
= std_baudrates
[i
].index
;
1807 if (i
== NUM_STD_BAUDRATES
)
1808 data
->dcb
.BaudRate
= config
->baudrate
;
1811 if (config
->bits
>= 0)
1812 data
->dcb
.ByteSize
= config
->bits
;
1814 if (config
->parity
>= 0) {
1815 switch (config
->parity
) {
1816 case SP_PARITY_NONE
:
1817 data
->dcb
.Parity
= NOPARITY
;
1820 data
->dcb
.Parity
= ODDPARITY
;
1822 case SP_PARITY_EVEN
:
1823 data
->dcb
.Parity
= EVENPARITY
;
1825 case SP_PARITY_MARK
:
1826 data
->dcb
.Parity
= MARKPARITY
;
1828 case SP_PARITY_SPACE
:
1829 data
->dcb
.Parity
= SPACEPARITY
;
1832 RETURN_ERROR(SP_ERR_ARG
, "Invalid parity setting");
1836 if (config
->stopbits
>= 0) {
1837 switch (config
->stopbits
) {
1838 /* Note: There's also ONE5STOPBITS == 1.5 (unneeded so far). */
1840 data
->dcb
.StopBits
= ONESTOPBIT
;
1843 data
->dcb
.StopBits
= TWOSTOPBITS
;
1846 RETURN_ERROR(SP_ERR_ARG
, "Invalid stop bit setting");
1850 if (config
->rts
>= 0) {
1851 switch (config
->rts
) {
1853 data
->dcb
.fRtsControl
= RTS_CONTROL_DISABLE
;
1856 data
->dcb
.fRtsControl
= RTS_CONTROL_ENABLE
;
1858 case SP_RTS_FLOW_CONTROL
:
1859 data
->dcb
.fRtsControl
= RTS_CONTROL_HANDSHAKE
;
1862 RETURN_ERROR(SP_ERR_ARG
, "Invalid RTS setting");
1866 if (config
->cts
>= 0) {
1867 switch (config
->cts
) {
1869 data
->dcb
.fOutxCtsFlow
= FALSE
;
1871 case SP_CTS_FLOW_CONTROL
:
1872 data
->dcb
.fOutxCtsFlow
= TRUE
;
1875 RETURN_ERROR(SP_ERR_ARG
, "Invalid CTS setting");
1879 if (config
->dtr
>= 0) {
1880 switch (config
->dtr
) {
1882 data
->dcb
.fDtrControl
= DTR_CONTROL_DISABLE
;
1885 data
->dcb
.fDtrControl
= DTR_CONTROL_ENABLE
;
1887 case SP_DTR_FLOW_CONTROL
:
1888 data
->dcb
.fDtrControl
= DTR_CONTROL_HANDSHAKE
;
1891 RETURN_ERROR(SP_ERR_ARG
, "Invalid DTR setting");
1895 if (config
->dsr
>= 0) {
1896 switch (config
->dsr
) {
1898 data
->dcb
.fOutxDsrFlow
= FALSE
;
1900 case SP_DSR_FLOW_CONTROL
:
1901 data
->dcb
.fOutxDsrFlow
= TRUE
;
1904 RETURN_ERROR(SP_ERR_ARG
, "Invalid DSR setting");
1908 if (config
->xon_xoff
>= 0) {
1909 switch (config
->xon_xoff
) {
1910 case SP_XONXOFF_DISABLED
:
1911 data
->dcb
.fInX
= FALSE
;
1912 data
->dcb
.fOutX
= FALSE
;
1915 data
->dcb
.fInX
= TRUE
;
1916 data
->dcb
.fOutX
= FALSE
;
1918 case SP_XONXOFF_OUT
:
1919 data
->dcb
.fInX
= FALSE
;
1920 data
->dcb
.fOutX
= TRUE
;
1922 case SP_XONXOFF_INOUT
:
1923 data
->dcb
.fInX
= TRUE
;
1924 data
->dcb
.fOutX
= TRUE
;
1927 RETURN_ERROR(SP_ERR_ARG
, "Invalid XON/XOFF setting");
1931 if (!SetCommState(port
->hdl
, &data
->dcb
))
1932 RETURN_FAIL("SetCommState() failed");
1938 if (config
->baudrate
>= 0) {
1939 for (i
= 0; i
< NUM_STD_BAUDRATES
; i
++) {
1940 if (config
->baudrate
== std_baudrates
[i
].value
) {
1941 if (cfsetospeed(&data
->term
, std_baudrates
[i
].index
) < 0)
1942 RETURN_FAIL("cfsetospeed() failed");
1944 if (cfsetispeed(&data
->term
, std_baudrates
[i
].index
) < 0)
1945 RETURN_FAIL("cfsetispeed() failed");
1950 /* Non-standard baud rate */
1951 if (i
== NUM_STD_BAUDRATES
) {
1953 /* Set "dummy" baud rate. */
1954 if (cfsetspeed(&data
->term
, B9600
) < 0)
1955 RETURN_FAIL("cfsetspeed() failed");
1956 baud_nonstd
= config
->baudrate
;
1957 #elif defined(__linux__)
1960 RETURN_ERROR(SP_ERR_SUPP
, "Non-standard baudrate not supported");
1965 if (config
->bits
>= 0) {
1966 data
->term
.c_cflag
&= ~CSIZE
;
1967 switch (config
->bits
) {
1969 data
->term
.c_cflag
|= CS8
;
1972 data
->term
.c_cflag
|= CS7
;
1975 data
->term
.c_cflag
|= CS6
;
1978 data
->term
.c_cflag
|= CS5
;
1981 RETURN_ERROR(SP_ERR_ARG
, "Invalid data bits setting");
1985 if (config
->parity
>= 0) {
1986 data
->term
.c_iflag
&= ~IGNPAR
;
1987 data
->term
.c_cflag
&= ~(PARENB
| PARODD
);
1989 data
->term
.c_cflag
&= ~CMSPAR
;
1991 switch (config
->parity
) {
1992 case SP_PARITY_NONE
:
1993 data
->term
.c_iflag
|= IGNPAR
;
1995 case SP_PARITY_EVEN
:
1996 data
->term
.c_cflag
|= PARENB
;
1999 data
->term
.c_cflag
|= PARENB
| PARODD
;
2002 case SP_PARITY_MARK
:
2003 data
->term
.c_cflag
|= PARENB
| PARODD
;
2004 data
->term
.c_cflag
|= CMSPAR
;
2006 case SP_PARITY_SPACE
:
2007 data
->term
.c_cflag
|= PARENB
;
2008 data
->term
.c_cflag
|= CMSPAR
;
2011 case SP_PARITY_MARK
:
2012 case SP_PARITY_SPACE
:
2013 RETURN_ERROR(SP_ERR_SUPP
, "Mark/space parity not supported");
2016 RETURN_ERROR(SP_ERR_ARG
, "Invalid parity setting");
2020 if (config
->stopbits
>= 0) {
2021 data
->term
.c_cflag
&= ~CSTOPB
;
2022 switch (config
->stopbits
) {
2024 data
->term
.c_cflag
&= ~CSTOPB
;
2027 data
->term
.c_cflag
|= CSTOPB
;
2030 RETURN_ERROR(SP_ERR_ARG
, "Invalid stop bits setting");
2034 if (config
->rts
>= 0 || config
->cts
>= 0) {
2035 if (data
->termiox_supported
) {
2036 data
->flow
&= ~(RTS_FLOW
| CTS_FLOW
);
2037 switch (config
->rts
) {
2040 controlbits
= TIOCM_RTS
;
2041 if (ioctl(port
->fd
, config
->rts
== SP_RTS_ON
? TIOCMBIS
: TIOCMBIC
, &controlbits
) < 0)
2042 RETURN_FAIL("Setting RTS signal level failed");
2044 case SP_RTS_FLOW_CONTROL
:
2045 data
->flow
|= RTS_FLOW
;
2050 if (config
->cts
== SP_CTS_FLOW_CONTROL
)
2051 data
->flow
|= CTS_FLOW
;
2053 if (data
->flow
& (RTS_FLOW
| CTS_FLOW
))
2054 data
->term
.c_iflag
|= CRTSCTS
;
2056 data
->term
.c_iflag
&= ~CRTSCTS
;
2058 /* Asymmetric use of RTS/CTS not supported. */
2059 if (data
->term
.c_iflag
& CRTSCTS
) {
2060 /* Flow control can only be disabled for both RTS & CTS together. */
2061 if (config
->rts
>= 0 && config
->rts
!= SP_RTS_FLOW_CONTROL
) {
2062 if (config
->cts
!= SP_CTS_IGNORE
)
2063 RETURN_ERROR(SP_ERR_SUPP
, "RTS & CTS flow control must be disabled together");
2065 if (config
->cts
>= 0 && config
->cts
!= SP_CTS_FLOW_CONTROL
) {
2066 if (config
->rts
<= 0 || config
->rts
== SP_RTS_FLOW_CONTROL
)
2067 RETURN_ERROR(SP_ERR_SUPP
, "RTS & CTS flow control must be disabled together");
2070 /* Flow control can only be enabled for both RTS & CTS together. */
2071 if (((config
->rts
== SP_RTS_FLOW_CONTROL
) && (config
->cts
!= SP_CTS_FLOW_CONTROL
)) ||
2072 ((config
->cts
== SP_CTS_FLOW_CONTROL
) && (config
->rts
!= SP_RTS_FLOW_CONTROL
)))
2073 RETURN_ERROR(SP_ERR_SUPP
, "RTS & CTS flow control must be enabled together");
2076 if (config
->rts
>= 0) {
2077 if (config
->rts
== SP_RTS_FLOW_CONTROL
) {
2078 data
->term
.c_iflag
|= CRTSCTS
;
2080 controlbits
= TIOCM_RTS
;
2081 if (ioctl(port
->fd
, config
->rts
== SP_RTS_ON
? TIOCMBIS
: TIOCMBIC
,
2083 RETURN_FAIL("Setting RTS signal level failed");
2089 if (config
->dtr
>= 0 || config
->dsr
>= 0) {
2090 if (data
->termiox_supported
) {
2091 data
->flow
&= ~(DTR_FLOW
| DSR_FLOW
);
2092 switch (config
->dtr
) {
2095 controlbits
= TIOCM_DTR
;
2096 if (ioctl(port
->fd
, config
->dtr
== SP_DTR_ON
? TIOCMBIS
: TIOCMBIC
, &controlbits
) < 0)
2097 RETURN_FAIL("Setting DTR signal level failed");
2099 case SP_DTR_FLOW_CONTROL
:
2100 data
->flow
|= DTR_FLOW
;
2105 if (config
->dsr
== SP_DSR_FLOW_CONTROL
)
2106 data
->flow
|= DSR_FLOW
;
2108 /* DTR/DSR flow control not supported. */
2109 if (config
->dtr
== SP_DTR_FLOW_CONTROL
|| config
->dsr
== SP_DSR_FLOW_CONTROL
)
2110 RETURN_ERROR(SP_ERR_SUPP
, "DTR/DSR flow control not supported");
2112 if (config
->dtr
>= 0) {
2113 controlbits
= TIOCM_DTR
;
2114 if (ioctl(port
->fd
, config
->dtr
== SP_DTR_ON
? TIOCMBIS
: TIOCMBIC
,
2116 RETURN_FAIL("Setting DTR signal level failed");
2121 if (config
->xon_xoff
>= 0) {
2122 data
->term
.c_iflag
&= ~(IXON
| IXOFF
| IXANY
);
2123 switch (config
->xon_xoff
) {
2124 case SP_XONXOFF_DISABLED
:
2127 data
->term
.c_iflag
|= IXOFF
;
2129 case SP_XONXOFF_OUT
:
2130 data
->term
.c_iflag
|= IXON
| IXANY
;
2132 case SP_XONXOFF_INOUT
:
2133 data
->term
.c_iflag
|= IXON
| IXOFF
| IXANY
;
2136 RETURN_ERROR(SP_ERR_ARG
, "Invalid XON/XOFF setting");
2140 if (tcsetattr(port
->fd
, TCSANOW
, &data
->term
) < 0)
2141 RETURN_FAIL("tcsetattr() failed");
2144 if (baud_nonstd
!= B0
) {
2145 if (ioctl(port
->fd
, IOSSIOSPEED
, &baud_nonstd
) == -1)
2146 RETURN_FAIL("IOSSIOSPEED ioctl failed");
2147 /* Set baud rates in data->term to correct, but incompatible
2148 * with tcsetattr() value, same as delivered by tcgetattr(). */
2149 if (cfsetspeed(&data
->term
, baud_nonstd
) < 0)
2150 RETURN_FAIL("cfsetspeed() failed");
2152 #elif defined(__linux__)
2154 TRY(set_baudrate(port
->fd
, config
->baudrate
));
2156 if (data
->termiox_supported
)
2157 TRY(set_flow(port
->fd
, data
->flow
));
2161 #endif /* !_WIN32 */
2166 enum sp_return
sp_new_config(struct sp_port_config
**config_ptr
)
2168 struct sp_port_config
*config
;
2170 TRACE("%p", config_ptr
);
2173 RETURN_ERROR(SP_ERR_ARG
, "Null result pointer");
2177 if (!(config
= malloc(sizeof(struct sp_port_config
))))
2178 RETURN_ERROR(SP_ERR_MEM
, "config malloc failed");
2180 config
->baudrate
= -1;
2182 config
->parity
= -1;
2183 config
->stopbits
= -1;
2189 *config_ptr
= config
;
2194 void sp_free_config(struct sp_port_config
*config
)
2196 TRACE("%p", config
);
2199 DEBUG("Null config");
2206 enum sp_return
sp_get_config(struct sp_port
*port
, struct sp_port_config
*config
)
2208 struct port_data data
;
2210 TRACE("%p, %p", port
, config
);
2215 RETURN_ERROR(SP_ERR_ARG
, "Null config");
2217 TRY(get_config(port
, &data
, config
));
2222 enum sp_return
sp_set_config(struct sp_port
*port
, const struct sp_port_config
*config
)
2224 struct port_data data
;
2225 struct sp_port_config prev_config
;
2227 TRACE("%p, %p", port
, config
);
2232 RETURN_ERROR(SP_ERR_ARG
, "Null config");
2234 TRY(get_config(port
, &data
, &prev_config
));
2235 TRY(set_config(port
, &data
, config
));
2240 #define CREATE_ACCESSORS(x, type) \
2241 enum sp_return sp_set_##x(struct sp_port *port, type x) { \
2242 struct port_data data; \
2243 struct sp_port_config config; \
2244 TRACE("%p, %d", port, x); \
2245 CHECK_OPEN_PORT(); \
2246 TRY(get_config(port, &data, &config)); \
2248 TRY(set_config(port, &data, &config)); \
2251 enum sp_return sp_get_config_##x(const struct sp_port_config *config, type *x) { \
2252 TRACE("%p, %p", config, x); \
2254 RETURN_ERROR(SP_ERR_ARG, "Null config"); \
2258 enum sp_return sp_set_config_##x(struct sp_port_config *config, type x) { \
2259 TRACE("%p, %d", config, x); \
2261 RETURN_ERROR(SP_ERR_ARG, "Null config"); \
2266 CREATE_ACCESSORS(baudrate
, int)
2267 CREATE_ACCESSORS(bits
, int)
2268 CREATE_ACCESSORS(parity
, enum sp_parity
)
2269 CREATE_ACCESSORS(stopbits
, int)
2270 CREATE_ACCESSORS(rts
, enum sp_rts
)
2271 CREATE_ACCESSORS(cts
, enum sp_cts
)
2272 CREATE_ACCESSORS(dtr
, enum sp_dtr
)
2273 CREATE_ACCESSORS(dsr
, enum sp_dsr
)
2274 CREATE_ACCESSORS(xon_xoff
, enum sp_xonxoff
)
2276 enum sp_return
sp_set_config_flowcontrol(struct sp_port_config
*config
, enum sp_flowcontrol flowcontrol
)
2279 RETURN_ERROR(SP_ERR_ARG
, "Null configuration");
2281 if (flowcontrol
> SP_FLOWCONTROL_DTRDSR
)
2282 RETURN_ERROR(SP_ERR_ARG
, "Invalid flow control setting");
2284 if (flowcontrol
== SP_FLOWCONTROL_XONXOFF
)
2285 config
->xon_xoff
= SP_XONXOFF_INOUT
;
2287 config
->xon_xoff
= SP_XONXOFF_DISABLED
;
2289 if (flowcontrol
== SP_FLOWCONTROL_RTSCTS
) {
2290 config
->rts
= SP_RTS_FLOW_CONTROL
;
2291 config
->cts
= SP_CTS_FLOW_CONTROL
;
2293 if (config
->rts
== SP_RTS_FLOW_CONTROL
)
2294 config
->rts
= SP_RTS_ON
;
2295 config
->cts
= SP_CTS_IGNORE
;
2298 if (flowcontrol
== SP_FLOWCONTROL_DTRDSR
) {
2299 config
->dtr
= SP_DTR_FLOW_CONTROL
;
2300 config
->dsr
= SP_DSR_FLOW_CONTROL
;
2302 if (config
->dtr
== SP_DTR_FLOW_CONTROL
)
2303 config
->dtr
= SP_DTR_ON
;
2304 config
->dsr
= SP_DSR_IGNORE
;
2310 enum sp_return
sp_set_flowcontrol(struct sp_port
*port
, enum sp_flowcontrol flowcontrol
)
2312 struct port_data data
;
2313 struct sp_port_config config
;
2315 TRACE("%p, %d", port
, flowcontrol
);
2319 TRY(get_config(port
, &data
, &config
));
2321 TRY(sp_set_config_flowcontrol(&config
, flowcontrol
));
2323 TRY(set_config(port
, &data
, &config
));
2328 enum sp_return
sp_get_signals(struct sp_port
*port
, enum sp_signal
*signals
)
2330 TRACE("%p, %p", port
, signals
);
2335 RETURN_ERROR(SP_ERR_ARG
, "Null result pointer");
2337 DEBUG("Getting control signals for port %s", port
->name
);
2342 if (GetCommModemStatus(port
->hdl
, &bits
) == 0)
2343 RETURN_FAIL("GetCommModemStatus() failed");
2344 if (bits
& MS_CTS_ON
)
2345 *signals
|= SP_SIG_CTS
;
2346 if (bits
& MS_DSR_ON
)
2347 *signals
|= SP_SIG_DSR
;
2348 if (bits
& MS_RLSD_ON
)
2349 *signals
|= SP_SIG_DCD
;
2350 if (bits
& MS_RING_ON
)
2351 *signals
|= SP_SIG_RI
;
2354 if (ioctl(port
->fd
, TIOCMGET
, &bits
) < 0)
2355 RETURN_FAIL("TIOCMGET ioctl failed");
2356 if (bits
& TIOCM_CTS
)
2357 *signals
|= SP_SIG_CTS
;
2358 if (bits
& TIOCM_DSR
)
2359 *signals
|= SP_SIG_DSR
;
2360 if (bits
& TIOCM_CAR
)
2361 *signals
|= SP_SIG_DCD
;
2362 if (bits
& TIOCM_RNG
)
2363 *signals
|= SP_SIG_RI
;
2368 enum sp_return
sp_start_break(struct sp_port
*port
)
2374 if (SetCommBreak(port
->hdl
) == 0)
2375 RETURN_FAIL("SetCommBreak() failed");
2377 if (ioctl(port
->fd
, TIOCSBRK
, 1) < 0)
2378 RETURN_FAIL("TIOCSBRK ioctl failed");
2384 enum sp_return
sp_end_break(struct sp_port
*port
)
2390 if (ClearCommBreak(port
->hdl
) == 0)
2391 RETURN_FAIL("ClearCommBreak() failed");
2393 if (ioctl(port
->fd
, TIOCCBRK
, 1) < 0)
2394 RETURN_FAIL("TIOCCBRK ioctl failed");
2400 int sp_last_error_code(void)
2404 RETURN_VALUE("%d", GetLastError());
2406 RETURN_VALUE("%d", errno
);
2410 char *sp_last_error_message(void)
2416 DWORD error
= GetLastError();
2419 FORMAT_MESSAGE_ALLOCATE_BUFFER
|
2420 FORMAT_MESSAGE_FROM_SYSTEM
|
2421 FORMAT_MESSAGE_IGNORE_INSERTS
,
2424 MAKELANGID(LANG_NEUTRAL
, SUBLANG_DEFAULT
),
2428 RETURN_VALUE("%s", message
);
2430 RETURN_VALUE("%s", strerror(errno
));
2434 void sp_free_error_message(char *message
)
2436 TRACE("%s", message
);
2447 void sp_set_debug_handler(void (*handler
)(const char *format
, ...))
2449 TRACE("%p", handler
);
2451 sp_debug_handler
= handler
;
2456 void sp_default_debug_handler(const char *format
, ...)
2459 va_start(args
, format
);
2460 if (getenv("LIBSERIALPORT_DEBUG")) {
2461 fputs("sp: ", stderr
);
2462 vfprintf(stderr
, format
, args
);