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>
44 #include <IOKit/IOKitLib.h>
45 #include <IOKit/serial/IOSerialKeys.h>
46 #include <IOKit/serial/ioss.h>
47 #include <sys/syslimits.h>
51 #include "linux/serial.h"
52 #include "linux_termios.h"
54 /* TCGETX/TCSETX is not available everywhere. */
55 #if defined(TCGETX) && defined(TCSETX) && defined(HAVE_TERMIOX)
60 /* TIOCINQ/TIOCOUTQ is not available everywhere. */
61 #if !defined(TIOCINQ) && defined(FIONREAD)
62 #define TIOCINQ FIONREAD
64 #if !defined(TIOCOUTQ) && defined(FIONWRITE)
65 #define TIOCOUTQ FIONWRITE
69 #include "linux_termios.h"
72 #include "libserialport.h"
78 COMMTIMEOUTS timeouts
;
88 struct sp_port_config
{
91 enum sp_parity parity
;
97 enum sp_xonxoff xon_xoff
;
106 int termiox_supported
;
111 /* Standard baud rates. */
113 #define BAUD_TYPE DWORD
114 #define BAUD(n) {CBR_##n, n}
116 #define BAUD_TYPE speed_t
117 #define BAUD(n) {B##n, n}
120 struct std_baudrate
{
125 const struct std_baudrate std_baudrates
[] = {
128 * The baudrates 50/75/134/150/200/1800/230400/460800 do not seem to
129 * have documented CBR_* macros.
131 BAUD(110), BAUD(300), BAUD(600), BAUD(1200), BAUD(2400), BAUD(4800),
132 BAUD(9600), BAUD(14400), BAUD(19200), BAUD(38400), BAUD(57600),
133 BAUD(115200), BAUD(128000), BAUD(256000),
135 BAUD(50), BAUD(75), BAUD(110), BAUD(134), BAUD(150), BAUD(200),
136 BAUD(300), BAUD(600), BAUD(1200), BAUD(1800), BAUD(2400), BAUD(4800),
137 BAUD(9600), BAUD(19200), BAUD(38400), BAUD(57600), BAUD(115200),
139 #if !defined(__APPLE__) && !defined(__OpenBSD__)
145 void (*sp_debug_handler
)(const char *format
, ...) = sp_default_debug_handler
;
147 #define ARRAY_SIZE(x) (sizeof(x) / sizeof(x[0]))
148 #define NUM_STD_BAUDRATES ARRAY_SIZE(std_baudrates)
150 /* Debug output macros. */
151 #define DEBUG(fmt, ...) do { if (sp_debug_handler) sp_debug_handler(fmt ".\n", ##__VA_ARGS__); } while (0)
152 #define DEBUG_ERROR(err, msg) DEBUG("%s returning " #err ": " msg, __func__)
153 #define DEBUG_FAIL(msg) do { \
154 char *errmsg = sp_last_error_message(); \
155 DEBUG("%s returning SP_ERR_FAIL: " msg ": %s", __func__, errmsg); \
156 sp_free_error_message(errmsg); \
158 #define RETURN() do { DEBUG("%s returning", __func__); return; } while(0)
159 #define RETURN_CODE(x) do { DEBUG("%s returning " #x, __func__); return x; } while (0)
160 #define RETURN_CODEVAL(x) do { \
162 case SP_OK: RETURN_CODE(SP_OK); \
163 case SP_ERR_ARG: RETURN_CODE(SP_ERR_ARG); \
164 case SP_ERR_FAIL: RETURN_CODE(SP_ERR_FAIL); \
165 case SP_ERR_MEM: RETURN_CODE(SP_ERR_MEM); \
166 case SP_ERR_SUPP: RETURN_CODE(SP_ERR_SUPP); \
169 #define RETURN_OK() RETURN_CODE(SP_OK);
170 #define RETURN_ERROR(err, msg) do { DEBUG_ERROR(err, msg); return err; } while (0)
171 #define RETURN_FAIL(msg) do { DEBUG_FAIL(msg); return SP_ERR_FAIL; } while (0)
172 #define RETURN_VALUE(fmt, x) do { DEBUG("%s returning " fmt, __func__, x); return x; } while (0)
173 #define SET_ERROR(val, err, msg) do { DEBUG_ERROR(err, msg); val = err; } while (0)
174 #define SET_FAIL(val, msg) do { DEBUG_FAIL(msg); val = SP_ERR_FAIL; } while (0)
175 #define TRACE(fmt, ...) DEBUG("%s(" fmt ") called", __func__, ##__VA_ARGS__)
177 #define TRY(x) do { int ret = x; if (ret != SP_OK) RETURN_CODEVAL(ret); } while (0)
179 /* Helper functions. */
180 static struct sp_port
**list_append(struct sp_port
**list
, const char *portname
);
181 static enum sp_return
get_config(struct sp_port
*port
, struct port_data
*data
,
182 struct sp_port_config
*config
);
183 static enum sp_return
set_config(struct sp_port
*port
, struct port_data
*data
,
184 const struct sp_port_config
*config
);
186 enum sp_return
sp_get_port_by_name(const char *portname
, struct sp_port
**port_ptr
)
188 struct sp_port
*port
;
191 TRACE("%s, %p", portname
, port_ptr
);
194 RETURN_ERROR(SP_ERR_ARG
, "Null result pointer");
199 RETURN_ERROR(SP_ERR_ARG
, "Null port name");
201 DEBUG("Building structure for port %s", portname
);
203 if (!(port
= malloc(sizeof(struct sp_port
))))
204 RETURN_ERROR(SP_ERR_MEM
, "Port structure malloc failed");
206 len
= strlen(portname
) + 1;
208 if (!(port
->name
= malloc(len
))) {
210 RETURN_ERROR(SP_ERR_MEM
, "Port name malloc failed");
213 memcpy(port
->name
, portname
, len
);
216 port
->hdl
= INVALID_HANDLE_VALUE
;
226 char *sp_get_port_name(const struct sp_port
*port
)
233 RETURN_VALUE("%s", port
->name
);
236 enum sp_return
sp_get_port_handle(const struct sp_port
*port
, void *result_ptr
)
238 TRACE("%p, %p", port
, result_ptr
);
241 RETURN_ERROR(SP_ERR_ARG
, "Null port");
244 HANDLE
*handle_ptr
= result_ptr
;
245 *handle_ptr
= port
->hdl
;
247 int *fd_ptr
= result_ptr
;
254 enum sp_return
sp_copy_port(const struct sp_port
*port
, struct sp_port
**copy_ptr
)
256 TRACE("%p, %p", port
, copy_ptr
);
259 RETURN_ERROR(SP_ERR_ARG
, "Null result pointer");
264 RETURN_ERROR(SP_ERR_ARG
, "Null port");
267 RETURN_ERROR(SP_ERR_ARG
, "Null port name");
269 DEBUG("Copying port structure");
271 RETURN_VALUE("%p", sp_get_port_by_name(port
->name
, copy_ptr
));
274 void sp_free_port(struct sp_port
*port
)
283 DEBUG("Freeing port structure");
293 static struct sp_port
**list_append(struct sp_port
**list
, const char *portname
)
298 for (count
= 0; list
[count
]; count
++);
299 if (!(tmp
= realloc(list
, sizeof(struct sp_port
*) * (count
+ 2))))
302 if (sp_get_port_by_name(portname
, &list
[count
]) != SP_OK
)
304 list
[count
+ 1] = NULL
;
308 sp_free_port_list(list
);
312 enum sp_return
sp_list_ports(struct sp_port
***list_ptr
)
314 struct sp_port
**list
;
315 int ret
= SP_ERR_SUPP
;
317 TRACE("%p", list_ptr
);
320 RETURN_ERROR(SP_ERR_ARG
, "Null result pointer");
322 DEBUG("Enumerating ports");
324 if (!(list
= malloc(sizeof(struct sp_port
**))))
325 RETURN_ERROR(SP_ERR_MEM
, "Port list malloc failed");
332 DWORD max_value_len
, max_data_size
, max_data_len
;
333 DWORD value_len
, data_size
, data_len
;
334 DWORD type
, index
= 0;
340 DEBUG("Opening registry key");
341 if (RegOpenKeyEx(HKEY_LOCAL_MACHINE
, _T("HARDWARE\\DEVICEMAP\\SERIALCOMM"),
342 0, KEY_QUERY_VALUE
, &key
) != ERROR_SUCCESS
) {
343 SET_FAIL(ret
, "RegOpenKeyEx() failed");
346 DEBUG("Querying registry key value and data sizes");
347 if (RegQueryInfoKey(key
, NULL
, NULL
, NULL
, NULL
, NULL
, NULL
, NULL
,
348 &max_value_len
, &max_data_size
, NULL
, NULL
) != ERROR_SUCCESS
) {
349 SET_FAIL(ret
, "RegQueryInfoKey() failed");
352 max_data_len
= max_data_size
/ sizeof(TCHAR
);
353 if (!(value
= malloc((max_value_len
+ 1) * sizeof(TCHAR
)))) {
354 SET_ERROR(ret
, SP_ERR_MEM
, "registry value malloc failed");
357 if (!(data
= malloc((max_data_len
+ 1) * sizeof(TCHAR
)))) {
358 SET_ERROR(ret
, SP_ERR_MEM
, "registry data malloc failed");
361 DEBUG("Iterating over values");
363 value_len
= max_value_len
+ 1,
364 data_size
= max_data_size
,
365 RegEnumValue(key
, index
, value
, &value_len
,
366 NULL
, &type
, (LPBYTE
)data
, &data_size
) == ERROR_SUCCESS
)
368 data_len
= data_size
/ sizeof(TCHAR
);
369 data
[data_len
] = '\0';
371 name_len
= WideCharToMultiByte(CP_ACP
, 0, data
, -1, NULL
, 0, NULL
, NULL
)
373 name_len
= data_len
+ 1;
375 if (!(name
= malloc(name_len
))) {
376 SET_ERROR(ret
, SP_ERR_MEM
, "registry port name malloc failed");
380 WideCharToMultiByte(CP_ACP
, 0, data
, -1, name
, name_len
, NULL
, NULL
);
384 if (type
== REG_SZ
) {
385 DEBUG("Found port %s", name
);
386 if (!(list
= list_append(list
, name
))) {
387 SET_ERROR(ret
, SP_ERR_MEM
, "list append failed");
403 CFMutableDictionaryRef classes
;
412 DEBUG("Getting IOKit master port");
413 if (IOMasterPort(MACH_PORT_NULL
, &master
) != KERN_SUCCESS
) {
414 SET_FAIL(ret
, "IOMasterPort() failed");
418 DEBUG("Creating matching dictionary");
419 if (!(classes
= IOServiceMatching(kIOSerialBSDServiceValue
))) {
420 SET_FAIL(ret
, "IOServiceMatching() failed");
424 CFDictionarySetValue(classes
,
425 CFSTR(kIOSerialBSDTypeKey
), CFSTR(kIOSerialBSDAllTypes
));
427 DEBUG("Getting matching services");
428 if (IOServiceGetMatchingServices(master
, classes
, &iter
) != KERN_SUCCESS
) {
429 SET_FAIL(ret
, "IOServiceGetMatchingServices() failed");
433 if (!(path
= malloc(PATH_MAX
))) {
434 SET_ERROR(ret
, SP_ERR_MEM
, "device path malloc failed");
438 DEBUG("Iterating over results");
439 while ((port
= IOIteratorNext(iter
))) {
440 cf_path
= IORegistryEntryCreateCFProperty(port
,
441 CFSTR(kIOCalloutDeviceKey
), kCFAllocatorDefault
, 0);
443 result
= CFStringGetCString(cf_path
,
444 path
, PATH_MAX
, kCFStringEncodingASCII
);
447 DEBUG("Found port %s", path
);
448 if (!(list
= list_append(list
, path
))) {
449 SET_ERROR(ret
, SP_ERR_MEM
, "list append failed");
450 IOObjectRelease(port
);
455 IOObjectRelease(port
);
460 IOObjectRelease(iter
);
465 struct udev_enumerate
*ud_enumerate
;
466 struct udev_list_entry
*ud_list
;
467 struct udev_list_entry
*ud_entry
;
469 struct udev_device
*ud_dev
, *ud_parent
;
472 int fd
, ioctl_result
;
473 struct serial_struct serial_info
;
477 DEBUG("Enumerating tty devices");
479 ud_enumerate
= udev_enumerate_new(ud
);
480 udev_enumerate_add_match_subsystem(ud_enumerate
, "tty");
481 udev_enumerate_scan_devices(ud_enumerate
);
482 ud_list
= udev_enumerate_get_list_entry(ud_enumerate
);
483 DEBUG("Iterating over results");
484 udev_list_entry_foreach(ud_entry
, ud_list
) {
485 path
= udev_list_entry_get_name(ud_entry
);
486 DEBUG("Found device %s", path
);
487 ud_dev
= udev_device_new_from_syspath(ud
, path
);
488 /* If there is no parent device, this is a virtual tty. */
489 ud_parent
= udev_device_get_parent(ud_dev
);
490 if (ud_parent
== NULL
) {
491 DEBUG("No parent device, assuming virtual tty");
492 udev_device_unref(ud_dev
);
495 name
= udev_device_get_devnode(ud_dev
);
496 /* The serial8250 driver has a hardcoded number of ports.
497 * The only way to tell which actually exist on a given system
498 * is to try to open them and make an ioctl call. */
499 driver
= udev_device_get_driver(ud_parent
);
500 if (driver
&& !strcmp(driver
, "serial8250")) {
501 DEBUG("serial8250 device, attempting to open");
502 if ((fd
= open(name
, O_RDWR
| O_NONBLOCK
| O_NOCTTY
)) < 0) {
503 DEBUG("open failed, skipping");
506 ioctl_result
= ioctl(fd
, TIOCGSERIAL
, &serial_info
);
508 if (ioctl_result
!= 0) {
509 DEBUG("ioctl failed, skipping");
512 if (serial_info
.type
== PORT_UNKNOWN
) {
513 DEBUG("port type is unknown, skipping");
517 DEBUG("Found port %s", name
);
518 list
= list_append(list
, name
);
520 udev_device_unref(ud_dev
);
522 SET_ERROR(ret
, SP_ERR_MEM
, "list append failed");
527 udev_enumerate_unref(ud_enumerate
);
536 DEBUG_ERROR(SP_ERR_SUPP
, "Enumeration not supported on this platform.");
539 sp_free_port_list(list
);
545 void sp_free_port_list(struct sp_port
**list
)
556 DEBUG("Freeing port list");
558 for (i
= 0; list
[i
]; i
++)
559 sp_free_port(list
[i
]);
565 #define CHECK_PORT() do { \
567 RETURN_ERROR(SP_ERR_ARG, "Null port"); \
568 if (port->name == NULL) \
569 RETURN_ERROR(SP_ERR_ARG, "Null port name"); \
572 #define CHECK_PORT_HANDLE() do { \
573 if (port->hdl == INVALID_HANDLE_VALUE) \
574 RETURN_ERROR(SP_ERR_ARG, "Invalid port handle"); \
577 #define CHECK_PORT_HANDLE() do { \
579 RETURN_ERROR(SP_ERR_ARG, "Invalid port fd"); \
582 #define CHECK_OPEN_PORT() do { \
584 CHECK_PORT_HANDLE(); \
587 enum sp_return
sp_open(struct sp_port
*port
, enum sp_mode flags
)
589 struct port_data data
;
590 struct sp_port_config config
;
593 TRACE("%p, 0x%x", port
, flags
);
597 if (flags
> (SP_MODE_READ
| SP_MODE_WRITE
))
598 RETURN_ERROR(SP_ERR_ARG
, "Invalid flags");
600 DEBUG("Opening port %s", port
->name
);
603 DWORD desired_access
= 0, flags_and_attributes
= 0;
604 char *escaped_port_name
;
606 /* Prefix port name with '\\.\' to work with ports above COM9. */
607 if (!(escaped_port_name
= malloc(strlen(port
->name
+ 5))))
608 RETURN_ERROR(SP_ERR_MEM
, "Escaped port name malloc failed");
609 sprintf(escaped_port_name
, "\\\\.\\%s", port
->name
);
611 /* Map 'flags' to the OS-specific settings. */
612 flags_and_attributes
= FILE_ATTRIBUTE_NORMAL
| FILE_FLAG_OVERLAPPED
;
613 if (flags
& SP_MODE_READ
)
614 desired_access
|= GENERIC_READ
;
615 if (flags
& SP_MODE_WRITE
)
616 desired_access
|= GENERIC_WRITE
;
618 port
->hdl
= CreateFile(escaped_port_name
, desired_access
, 0, 0,
619 OPEN_EXISTING
, flags_and_attributes
, 0);
621 free(escaped_port_name
);
623 if (port
->hdl
== INVALID_HANDLE_VALUE
)
624 RETURN_FAIL("port CreateFile() failed");
626 /* All timeouts initially disabled. */
627 port
->timeouts
.ReadIntervalTimeout
= 0;
628 port
->timeouts
.ReadTotalTimeoutMultiplier
= 0;
629 port
->timeouts
.ReadTotalTimeoutConstant
= 0;
630 port
->timeouts
.WriteTotalTimeoutMultiplier
= 0;
631 port
->timeouts
.WriteTotalTimeoutConstant
= 0;
633 if (SetCommTimeouts(port
->hdl
, &port
->timeouts
) == 0) {
635 RETURN_FAIL("SetCommTimeouts() failed");
638 /* Prepare OVERLAPPED structures. */
639 memset(&port
->read_ovl
, 0, sizeof(port
->read_ovl
));
640 memset(&port
->write_ovl
, 0, sizeof(port
->write_ovl
));
641 port
->read_ovl
.hEvent
= INVALID_HANDLE_VALUE
;
642 port
->write_ovl
.hEvent
= INVALID_HANDLE_VALUE
;
643 if ((port
->read_ovl
.hEvent
= CreateEvent(NULL
, TRUE
, FALSE
, NULL
)) == INVALID_HANDLE_VALUE
) {
645 RETURN_FAIL("read event CreateEvent() failed");
647 if ((port
->write_ovl
.hEvent
= CreateEvent(NULL
, TRUE
, FALSE
, NULL
)) == INVALID_HANDLE_VALUE
) {
649 RETURN_FAIL("write event CreateEvent() failed");
652 port
->writing
= FALSE
;
655 int flags_local
= O_NONBLOCK
| O_NOCTTY
;
657 /* Map 'flags' to the OS-specific settings. */
658 if (flags
& (SP_MODE_READ
| SP_MODE_WRITE
))
659 flags_local
|= O_RDWR
;
660 else if (flags
& SP_MODE_READ
)
661 flags_local
|= O_RDONLY
;
662 else if (flags
& SP_MODE_WRITE
)
663 flags_local
|= O_WRONLY
;
665 if ((port
->fd
= open(port
->name
, flags_local
)) < 0)
666 RETURN_FAIL("open() failed");
669 ret
= get_config(port
, &data
, &config
);
676 /* Set sane port settings. */
678 data
.dcb
.fBinary
= TRUE
;
679 data
.dcb
.fDsrSensitivity
= FALSE
;
680 data
.dcb
.fErrorChar
= FALSE
;
681 data
.dcb
.fNull
= FALSE
;
682 data
.dcb
.fAbortOnError
= TRUE
;
684 /* Turn off all fancy termios tricks, give us a raw channel. */
685 data
.term
.c_iflag
&= ~(IGNBRK
| BRKINT
| PARMRK
| ISTRIP
| INLCR
| IGNCR
| ICRNL
| IMAXBEL
);
687 data
.term
.c_iflag
&= ~IUCLC
;
689 data
.term
.c_oflag
&= ~(OPOST
| ONLCR
| OCRNL
| ONOCR
| ONLRET
);
691 data
.term
.c_oflag
&= ~OLCUC
;
694 data
.term
.c_oflag
&= ~NLDLY
;
697 data
.term
.c_oflag
&= ~CRDLY
;
700 data
.term
.c_oflag
&= ~TABDLY
;
703 data
.term
.c_oflag
&= ~BSDLY
;
706 data
.term
.c_oflag
&= ~VTDLY
;
709 data
.term
.c_oflag
&= ~FFDLY
;
712 data
.term
.c_oflag
&= ~OFILL
;
714 data
.term
.c_lflag
&= ~(ISIG
| ICANON
| ECHO
| IEXTEN
);
715 data
.term
.c_cc
[VMIN
] = 0;
716 data
.term
.c_cc
[VTIME
] = 0;
718 /* Ignore modem status lines; enable receiver; leave control lines alone on close. */
719 data
.term
.c_cflag
|= (CLOCAL
| CREAD
| HUPCL
);
722 ret
= set_config(port
, &data
, &config
);
732 enum sp_return
sp_close(struct sp_port
*port
)
738 DEBUG("Closing port %s", port
->name
);
741 /* Returns non-zero upon success, 0 upon failure. */
742 if (CloseHandle(port
->hdl
) == 0)
743 RETURN_FAIL("port CloseHandle() failed");
744 port
->hdl
= INVALID_HANDLE_VALUE
;
745 /* Close event handle created for overlapped reads. */
746 if (port
->read_ovl
.hEvent
!= INVALID_HANDLE_VALUE
&& CloseHandle(port
->read_ovl
.hEvent
) == 0)
747 RETURN_FAIL("read event CloseHandle() failed");
748 /* Close event handle created for overlapped writes. */
749 if (port
->write_ovl
.hEvent
!= INVALID_HANDLE_VALUE
&& CloseHandle(port
->write_ovl
.hEvent
) == 0)
750 RETURN_FAIL("write event CloseHandle() failed");
752 /* Returns 0 upon success, -1 upon failure. */
753 if (close(port
->fd
) == -1)
754 RETURN_FAIL("close() failed");
761 enum sp_return
sp_flush(struct sp_port
*port
, enum sp_buffer buffers
)
763 TRACE("%p, 0x%x", port
, buffers
);
767 if (buffers
> SP_BUF_BOTH
)
768 RETURN_ERROR(SP_ERR_ARG
, "Invalid buffer selection");
770 const char *buffer_names
[] = {"no", "input", "output", "both"};
772 DEBUG("Flushing %s buffers on port %s", buffer_names
[buffers
], port
->name
);
776 if (buffers
& SP_BUF_INPUT
)
777 flags
|= PURGE_RXCLEAR
;
778 if (buffers
& SP_BUF_OUTPUT
)
779 flags
|= PURGE_TXCLEAR
;
781 /* Returns non-zero upon success, 0 upon failure. */
782 if (PurgeComm(port
->hdl
, flags
) == 0)
783 RETURN_FAIL("PurgeComm() failed");
786 if (buffers
& SP_BUF_BOTH
)
788 else if (buffers
& SP_BUF_INPUT
)
790 else if (buffers
& SP_BUF_OUTPUT
)
793 /* Returns 0 upon success, -1 upon failure. */
794 if (tcflush(port
->fd
, flags
) < 0)
795 RETURN_FAIL("tcflush() failed");
800 enum sp_return
sp_drain(struct sp_port
*port
)
806 DEBUG("Draining port %s", port
->name
);
809 /* Returns non-zero upon success, 0 upon failure. */
810 if (FlushFileBuffers(port
->hdl
) == 0)
811 RETURN_FAIL("FlushFileBuffers() failed");
816 result
= tcdrain(port
->fd
);
818 if (errno
== EINTR
) {
819 DEBUG("tcdrain() was interrupted");
822 RETURN_FAIL("tcdrain() failed");
831 enum sp_return
sp_blocking_write(struct sp_port
*port
, const void *buf
, size_t count
, unsigned int timeout
)
833 TRACE("%p, %p, %d, %d", port
, buf
, count
, timeout
);
838 RETURN_ERROR(SP_ERR_ARG
, "Null buffer");
841 DEBUG("Writing %d bytes to port %s, timeout %d ms", count
, port
->name
, timeout
);
843 DEBUG("Writing %d bytes to port %s, no timeout", count
, port
->name
);
846 RETURN_VALUE("0", 0);
849 DWORD bytes_written
= 0;
852 /* Wait for previous non-blocking write to complete, if any. */
854 DEBUG("Waiting for previous write to complete");
855 result
= GetOverlappedResult(port
->hdl
, &port
->write_ovl
, &bytes_written
, TRUE
);
858 RETURN_FAIL("Previous write failed to complete");
859 DEBUG("Previous write completed");
863 port
->timeouts
.WriteTotalTimeoutConstant
= timeout
;
864 if (SetCommTimeouts(port
->hdl
, &port
->timeouts
) == 0)
865 RETURN_FAIL("SetCommTimeouts() failed");
868 if (WriteFile(port
->hdl
, buf
, count
, NULL
, &port
->write_ovl
) == 0) {
869 if (GetLastError() == ERROR_IO_PENDING
) {
870 DEBUG("Waiting for write to complete");
871 GetOverlappedResult(port
->hdl
, &port
->write_ovl
, &bytes_written
, TRUE
);
872 DEBUG("Write completed, %d/%d bytes written", bytes_written
, count
);
873 RETURN_VALUE("%d", bytes_written
);
875 RETURN_FAIL("WriteFile() failed");
878 DEBUG("Write completed immediately");
879 RETURN_VALUE("%d", count
);
882 size_t bytes_written
= 0;
883 unsigned char *ptr
= (unsigned char *) buf
;
884 struct timeval start
, delta
, now
, end
= {0, 0};
889 /* Get time at start of operation. */
890 gettimeofday(&start
, NULL
);
891 /* Define duration of timeout. */
892 delta
.tv_sec
= timeout
/ 1000;
893 delta
.tv_usec
= (timeout
% 1000) * 1000;
894 /* Calculate time at which we should give up. */
895 timeradd(&start
, &delta
, &end
);
898 /* Loop until we have written the requested number of bytes. */
899 while (bytes_written
< count
)
901 /* Wait until space is available. */
903 FD_SET(port
->fd
, &fds
);
905 gettimeofday(&now
, NULL
);
906 if (timercmp(&now
, &end
, >)) {
907 DEBUG("write timed out");
908 RETURN_VALUE("%d", bytes_written
);
910 timersub(&end
, &now
, &delta
);
912 result
= select(port
->fd
+ 1, NULL
, &fds
, NULL
, timeout
? &delta
: NULL
);
914 if (errno
== EINTR
) {
915 DEBUG("select() call was interrupted, repeating");
918 RETURN_FAIL("select() failed");
920 } else if (result
== 0) {
921 DEBUG("write timed out");
922 RETURN_VALUE("%d", bytes_written
);
926 result
= write(port
->fd
, ptr
, count
- bytes_written
);
930 /* This shouldn't happen because we did a select() first, but handle anyway. */
933 /* This is an actual failure. */
934 RETURN_FAIL("write() failed");
937 bytes_written
+= result
;
941 RETURN_VALUE("%d", bytes_written
);
945 enum sp_return
sp_nonblocking_write(struct sp_port
*port
, const void *buf
, size_t count
)
947 TRACE("%p, %p, %d", port
, buf
, count
);
952 RETURN_ERROR(SP_ERR_ARG
, "Null buffer");
954 DEBUG("Writing up to %d bytes to port %s", count
, port
->name
);
957 RETURN_VALUE("0", 0);
961 BYTE
*ptr
= (BYTE
*) buf
;
963 /* Check whether previous write is complete. */
965 if (HasOverlappedIoCompleted(&port
->write_ovl
)) {
966 DEBUG("Previous write completed");
969 DEBUG("Previous write not complete");
970 /* Can't take a new write until the previous one finishes. */
971 RETURN_VALUE("0", 0);
976 port
->timeouts
.WriteTotalTimeoutConstant
= 0;
977 if (SetCommTimeouts(port
->hdl
, &port
->timeouts
) == 0)
978 RETURN_FAIL("SetCommTimeouts() failed");
980 /* Keep writing data until the OS has to actually start an async IO for it.
981 * At that point we know the buffer is full. */
982 while (written
< count
)
984 /* Copy first byte of user buffer. */
985 port
->pending_byte
= *ptr
++;
987 /* Start asynchronous write. */
988 if (WriteFile(port
->hdl
, &port
->pending_byte
, 1, NULL
, &port
->write_ovl
) == 0) {
989 if (GetLastError() == ERROR_IO_PENDING
) {
990 DEBUG("Asynchronous write started");
992 RETURN_VALUE("%d", ++written
);
994 /* Actual failure of some kind. */
995 RETURN_FAIL("WriteFile() failed");
998 DEBUG("Single byte written immediately.");
1003 DEBUG("All bytes written immediately.");
1005 RETURN_VALUE("%d", written
);
1007 /* Returns the number of bytes written, or -1 upon failure. */
1008 ssize_t written
= write(port
->fd
, buf
, count
);
1011 RETURN_FAIL("write() failed");
1013 RETURN_VALUE("%d", written
);
1017 enum sp_return
sp_blocking_read(struct sp_port
*port
, void *buf
, size_t count
, unsigned int timeout
)
1019 TRACE("%p, %p, %d, %d", port
, buf
, count
, timeout
);
1024 RETURN_ERROR(SP_ERR_ARG
, "Null buffer");
1027 DEBUG("Reading %d bytes from port %s, timeout %d ms", count
, port
->name
, timeout
);
1029 DEBUG("Reading %d bytes from port %s, no timeout", count
, port
->name
);
1032 RETURN_VALUE("0", 0);
1035 DWORD bytes_read
= 0;
1038 port
->timeouts
.ReadIntervalTimeout
= 0;
1039 port
->timeouts
.ReadTotalTimeoutConstant
= timeout
;
1040 if (SetCommTimeouts(port
->hdl
, &port
->timeouts
) == 0)
1041 RETURN_FAIL("SetCommTimeouts() failed");
1044 if (ReadFile(port
->hdl
, buf
, count
, NULL
, &port
->read_ovl
) == 0) {
1045 if (GetLastError() == ERROR_IO_PENDING
) {
1046 DEBUG("Waiting for read to complete");
1047 GetOverlappedResult(port
->hdl
, &port
->read_ovl
, &bytes_read
, TRUE
);
1048 DEBUG("Read completed, %d/%d bytes read", bytes_read
, count
);
1049 RETURN_VALUE("%d", bytes_read
);
1051 RETURN_FAIL("ReadFile() failed");
1054 DEBUG("Read completed immediately");
1055 RETURN_VALUE("%d", count
);
1058 size_t bytes_read
= 0;
1059 unsigned char *ptr
= (unsigned char *) buf
;
1060 struct timeval start
, delta
, now
, end
= {0, 0};
1065 /* Get time at start of operation. */
1066 gettimeofday(&start
, NULL
);
1067 /* Define duration of timeout. */
1068 delta
.tv_sec
= timeout
/ 1000;
1069 delta
.tv_usec
= (timeout
% 1000) * 1000;
1070 /* Calculate time at which we should give up. */
1071 timeradd(&start
, &delta
, &end
);
1074 /* Loop until we have the requested number of bytes. */
1075 while (bytes_read
< count
)
1077 /* Wait until data is available. */
1079 FD_SET(port
->fd
, &fds
);
1081 gettimeofday(&now
, NULL
);
1082 if (timercmp(&now
, &end
, >))
1083 /* Timeout has expired. */
1084 RETURN_VALUE("%d", bytes_read
);
1085 timersub(&end
, &now
, &delta
);
1087 result
= select(port
->fd
+ 1, &fds
, NULL
, NULL
, timeout
? &delta
: NULL
);
1089 if (errno
== EINTR
) {
1090 DEBUG("select() call was interrupted, repeating");
1093 RETURN_FAIL("select() failed");
1095 } else if (result
== 0) {
1096 DEBUG("read timed out");
1097 RETURN_VALUE("%d", bytes_read
);
1101 result
= read(port
->fd
, ptr
, count
- bytes_read
);
1104 if (errno
== EAGAIN
)
1105 /* This shouldn't happen because we did a select() first, but handle anyway. */
1108 /* This is an actual failure. */
1109 RETURN_FAIL("read() failed");
1112 bytes_read
+= result
;
1116 RETURN_VALUE("%d", bytes_read
);
1120 enum sp_return
sp_nonblocking_read(struct sp_port
*port
, void *buf
, size_t count
)
1122 TRACE("%p, %p, %d", port
, buf
, count
);
1127 RETURN_ERROR(SP_ERR_ARG
, "Null buffer");
1129 DEBUG("Reading up to %d bytes from port %s", count
, port
->name
);
1135 port
->timeouts
.ReadIntervalTimeout
= MAXDWORD
;
1136 port
->timeouts
.ReadTotalTimeoutConstant
= 0;
1137 if (SetCommTimeouts(port
->hdl
, &port
->timeouts
) == 0)
1138 RETURN_FAIL("SetCommTimeouts() failed");
1141 if (ReadFile(port
->hdl
, buf
, count
, NULL
, &port
->read_ovl
) == 0)
1142 RETURN_FAIL("ReadFile() failed");
1144 /* Get number of bytes read. */
1145 GetOverlappedResult(port
->hdl
, &port
->read_ovl
, &bytes_read
, TRUE
);
1147 RETURN_VALUE("%d", bytes_read
);
1151 /* Returns the number of bytes read, or -1 upon failure. */
1152 if ((bytes_read
= read(port
->fd
, buf
, count
)) < 0) {
1153 if (errno
== EAGAIN
)
1154 /* No bytes available. */
1157 /* This is an actual failure. */
1158 RETURN_FAIL("read() failed");
1160 RETURN_VALUE("%d", bytes_read
);
1164 enum sp_return
sp_input_waiting(struct sp_port
*port
)
1170 DEBUG("Checking input bytes waiting on port %s", port
->name
);
1176 if (ClearCommError(port
->hdl
, &errors
, &comstat
) == 0)
1177 RETURN_FAIL("ClearComError() failed");
1178 RETURN_VALUE("%d", comstat
.cbInQue
);
1181 if (ioctl(port
->fd
, TIOCINQ
, &bytes_waiting
) < 0)
1182 RETURN_FAIL("TIOCINQ ioctl failed");
1183 RETURN_VALUE("%d", bytes_waiting
);
1187 enum sp_return
sp_output_waiting(struct sp_port
*port
)
1193 DEBUG("Checking output bytes waiting on port %s", port
->name
);
1199 if (ClearCommError(port
->hdl
, &errors
, &comstat
) == 0)
1200 RETURN_FAIL("ClearComError() failed");
1201 RETURN_VALUE("%d", comstat
.cbOutQue
);
1204 if (ioctl(port
->fd
, TIOCOUTQ
, &bytes_waiting
) < 0)
1205 RETURN_FAIL("TIOCOUTQ ioctl failed");
1206 RETURN_VALUE("%d", bytes_waiting
);
1211 static enum sp_return
get_baudrate(int fd
, int *baudrate
)
1215 TRACE("%d, %p", fd
, baudrate
);
1217 DEBUG("Getting baud rate");
1219 if (!(data
= malloc(get_termios_size())))
1220 RETURN_ERROR(SP_ERR_MEM
, "termios malloc failed");
1222 if (ioctl(fd
, get_termios_get_ioctl(), data
) < 0) {
1224 RETURN_FAIL("getting termios failed");
1227 *baudrate
= get_termios_speed(data
);
1234 static enum sp_return
set_baudrate(int fd
, int baudrate
)
1238 TRACE("%d, %d", fd
, baudrate
);
1240 DEBUG("Getting baud rate");
1242 if (!(data
= malloc(get_termios_size())))
1243 RETURN_ERROR(SP_ERR_MEM
, "termios malloc failed");
1245 if (ioctl(fd
, get_termios_get_ioctl(), data
) < 0) {
1247 RETURN_FAIL("getting termios failed");
1250 DEBUG("Setting baud rate");
1252 set_termios_speed(data
, baudrate
);
1254 if (ioctl(fd
, get_termios_set_ioctl(), data
) < 0) {
1256 RETURN_FAIL("setting termios failed");
1265 static enum sp_return
get_flow(int fd
, int *flow
)
1269 TRACE("%d, %p", fd
, flow
);
1271 DEBUG("Getting advanced flow control");
1273 if (!(data
= malloc(get_termiox_size())))
1274 RETURN_ERROR(SP_ERR_MEM
, "termiox malloc failed");
1276 if (ioctl(fd
, TCGETX
, data
) < 0) {
1278 RETURN_FAIL("getting termiox failed");
1281 *flow
= get_termiox_flow(data
);
1288 static enum sp_return
set_flow(int fd
, int flow
)
1292 TRACE("%d, %d", fd
, flow
);
1294 DEBUG("Getting advanced flow control");
1296 if (!(data
= malloc(get_termiox_size())))
1297 RETURN_ERROR(SP_ERR_MEM
, "termiox malloc failed");
1299 if (ioctl(fd
, TCGETX
, data
) < 0) {
1301 RETURN_FAIL("getting termiox failed");
1304 DEBUG("Setting advanced flow control");
1306 set_termiox_flow(data
, flow
);
1308 if (ioctl(fd
, TCSETX
, data
) < 0) {
1310 RETURN_FAIL("setting termiox failed");
1317 #endif /* USE_TERMIOX */
1318 #endif /* __linux__ */
1320 static enum sp_return
get_config(struct sp_port
*port
, struct port_data
*data
,
1321 struct sp_port_config
*config
)
1325 TRACE("%p, %p, %p", port
, data
, config
);
1327 DEBUG("Getting configuration for port %s", port
->name
);
1330 if (!GetCommState(port
->hdl
, &data
->dcb
))
1331 RETURN_FAIL("GetCommState() failed");
1333 for (i
= 0; i
< NUM_STD_BAUDRATES
; i
++) {
1334 if (data
->dcb
.BaudRate
== std_baudrates
[i
].index
) {
1335 config
->baudrate
= std_baudrates
[i
].value
;
1340 if (i
== NUM_STD_BAUDRATES
)
1341 /* BaudRate field can be either an index or a custom baud rate. */
1342 config
->baudrate
= data
->dcb
.BaudRate
;
1344 config
->bits
= data
->dcb
.ByteSize
;
1346 if (data
->dcb
.fParity
)
1347 switch (data
->dcb
.Parity
) {
1349 config
->parity
= SP_PARITY_NONE
;
1352 config
->parity
= SP_PARITY_ODD
;
1355 config
->parity
= SP_PARITY_EVEN
;
1358 config
->parity
= SP_PARITY_MARK
;
1361 config
->parity
= SP_PARITY_SPACE
;
1364 config
->parity
= -1;
1367 config
->parity
= SP_PARITY_NONE
;
1369 switch (data
->dcb
.StopBits
) {
1371 config
->stopbits
= 1;
1374 config
->stopbits
= 2;
1377 config
->stopbits
= -1;
1380 switch (data
->dcb
.fRtsControl
) {
1381 case RTS_CONTROL_DISABLE
:
1382 config
->rts
= SP_RTS_OFF
;
1384 case RTS_CONTROL_ENABLE
:
1385 config
->rts
= SP_RTS_ON
;
1387 case RTS_CONTROL_HANDSHAKE
:
1388 config
->rts
= SP_RTS_FLOW_CONTROL
;
1394 config
->cts
= data
->dcb
.fOutxCtsFlow
? SP_CTS_FLOW_CONTROL
: SP_CTS_IGNORE
;
1396 switch (data
->dcb
.fDtrControl
) {
1397 case DTR_CONTROL_DISABLE
:
1398 config
->dtr
= SP_DTR_OFF
;
1400 case DTR_CONTROL_ENABLE
:
1401 config
->dtr
= SP_DTR_ON
;
1403 case DTR_CONTROL_HANDSHAKE
:
1404 config
->dtr
= SP_DTR_FLOW_CONTROL
;
1410 config
->dsr
= data
->dcb
.fOutxDsrFlow
? SP_DSR_FLOW_CONTROL
: SP_DSR_IGNORE
;
1412 if (data
->dcb
.fInX
) {
1413 if (data
->dcb
.fOutX
)
1414 config
->xon_xoff
= SP_XONXOFF_INOUT
;
1416 config
->xon_xoff
= SP_XONXOFF_IN
;
1418 if (data
->dcb
.fOutX
)
1419 config
->xon_xoff
= SP_XONXOFF_OUT
;
1421 config
->xon_xoff
= SP_XONXOFF_DISABLED
;
1426 if (tcgetattr(port
->fd
, &data
->term
) < 0)
1427 RETURN_FAIL("tcgetattr() failed");
1429 if (ioctl(port
->fd
, TIOCMGET
, &data
->controlbits
) < 0)
1430 RETURN_FAIL("TIOCMGET ioctl failed");
1433 int ret
= get_flow(port
->fd
, &data
->flow
);
1435 if (ret
== SP_ERR_FAIL
&& errno
== EINVAL
)
1436 data
->termiox_supported
= 0;
1438 RETURN_CODEVAL(ret
);
1440 data
->termiox_supported
= 1;
1442 data
->termiox_supported
= 0;
1445 for (i
= 0; i
< NUM_STD_BAUDRATES
; i
++) {
1446 if (cfgetispeed(&data
->term
) == std_baudrates
[i
].index
) {
1447 config
->baudrate
= std_baudrates
[i
].value
;
1452 if (i
== NUM_STD_BAUDRATES
) {
1454 config
->baudrate
= (int)data
->term
.c_ispeed
;
1455 #elif defined(__linux__)
1456 TRY(get_baudrate(port
->fd
, &config
->baudrate
));
1458 config
->baudrate
= -1;
1462 switch (data
->term
.c_cflag
& CSIZE
) {
1479 if (!(data
->term
.c_cflag
& PARENB
) && (data
->term
.c_iflag
& IGNPAR
))
1480 config
->parity
= SP_PARITY_NONE
;
1481 else if (!(data
->term
.c_cflag
& PARENB
) || (data
->term
.c_iflag
& IGNPAR
))
1482 config
->parity
= -1;
1484 else if (data
->term
.c_cflag
& CMSPAR
)
1485 config
->parity
= (data
->term
.c_cflag
& PARODD
) ? SP_PARITY_MARK
: SP_PARITY_SPACE
;
1488 config
->parity
= (data
->term
.c_cflag
& PARODD
) ? SP_PARITY_ODD
: SP_PARITY_EVEN
;
1490 config
->stopbits
= (data
->term
.c_cflag
& CSTOPB
) ? 2 : 1;
1492 if (data
->term
.c_cflag
& CRTSCTS
) {
1493 config
->rts
= SP_RTS_FLOW_CONTROL
;
1494 config
->cts
= SP_CTS_FLOW_CONTROL
;
1496 if (data
->termiox_supported
&& data
->flow
& RTS_FLOW
)
1497 config
->rts
= SP_RTS_FLOW_CONTROL
;
1499 config
->rts
= (data
->controlbits
& TIOCM_RTS
) ? SP_RTS_ON
: SP_RTS_OFF
;
1501 config
->cts
= (data
->termiox_supported
&& data
->flow
& CTS_FLOW
) ?
1502 SP_CTS_FLOW_CONTROL
: SP_CTS_IGNORE
;
1505 if (data
->termiox_supported
&& data
->flow
& DTR_FLOW
)
1506 config
->dtr
= SP_DTR_FLOW_CONTROL
;
1508 config
->dtr
= (data
->controlbits
& TIOCM_DTR
) ? SP_DTR_ON
: SP_DTR_OFF
;
1510 config
->dsr
= (data
->termiox_supported
&& data
->flow
& DSR_FLOW
) ?
1511 SP_DSR_FLOW_CONTROL
: SP_DSR_IGNORE
;
1513 if (data
->term
.c_iflag
& IXOFF
) {
1514 if (data
->term
.c_iflag
& IXON
)
1515 config
->xon_xoff
= SP_XONXOFF_INOUT
;
1517 config
->xon_xoff
= SP_XONXOFF_IN
;
1519 if (data
->term
.c_iflag
& IXON
)
1520 config
->xon_xoff
= SP_XONXOFF_OUT
;
1522 config
->xon_xoff
= SP_XONXOFF_DISABLED
;
1529 static enum sp_return
set_config(struct sp_port
*port
, struct port_data
*data
,
1530 const struct sp_port_config
*config
)
1534 BAUD_TYPE baud_nonstd
;
1539 int baud_nonstd
= 0;
1542 TRACE("%p, %p, %p", port
, data
, config
);
1544 DEBUG("Setting configuration for port %s", port
->name
);
1547 if (config
->baudrate
>= 0) {
1548 for (i
= 0; i
< NUM_STD_BAUDRATES
; i
++) {
1549 if (config
->baudrate
== std_baudrates
[i
].value
) {
1550 data
->dcb
.BaudRate
= std_baudrates
[i
].index
;
1555 if (i
== NUM_STD_BAUDRATES
)
1556 data
->dcb
.BaudRate
= config
->baudrate
;
1559 if (config
->bits
>= 0)
1560 data
->dcb
.ByteSize
= config
->bits
;
1562 if (config
->parity
>= 0) {
1563 switch (config
->parity
) {
1564 /* Note: There's also SPACEPARITY, MARKPARITY (unneeded so far). */
1565 case SP_PARITY_NONE
:
1566 data
->dcb
.Parity
= NOPARITY
;
1569 data
->dcb
.Parity
= ODDPARITY
;
1571 case SP_PARITY_EVEN
:
1572 data
->dcb
.Parity
= EVENPARITY
;
1574 case SP_PARITY_MARK
:
1575 data
->dcb
.Parity
= MARKPARITY
;
1577 case SP_PARITY_SPACE
:
1578 data
->dcb
.Parity
= SPACEPARITY
;
1581 RETURN_ERROR(SP_ERR_ARG
, "Invalid parity setting");
1585 if (config
->stopbits
>= 0) {
1586 switch (config
->stopbits
) {
1587 /* Note: There's also ONE5STOPBITS == 1.5 (unneeded so far). */
1589 data
->dcb
.StopBits
= ONESTOPBIT
;
1592 data
->dcb
.StopBits
= TWOSTOPBITS
;
1595 RETURN_ERROR(SP_ERR_ARG
, "Invalid stop bit setting");
1599 if (config
->rts
>= 0) {
1600 switch (config
->rts
) {
1602 data
->dcb
.fRtsControl
= RTS_CONTROL_DISABLE
;
1605 data
->dcb
.fRtsControl
= RTS_CONTROL_ENABLE
;
1607 case SP_RTS_FLOW_CONTROL
:
1608 data
->dcb
.fRtsControl
= RTS_CONTROL_HANDSHAKE
;
1611 RETURN_ERROR(SP_ERR_ARG
, "Invalid RTS setting");
1615 if (config
->cts
>= 0) {
1616 switch (config
->cts
) {
1618 data
->dcb
.fOutxCtsFlow
= FALSE
;
1620 case SP_CTS_FLOW_CONTROL
:
1621 data
->dcb
.fOutxCtsFlow
= TRUE
;
1624 RETURN_ERROR(SP_ERR_ARG
, "Invalid CTS setting");
1628 if (config
->dtr
>= 0) {
1629 switch (config
->dtr
) {
1631 data
->dcb
.fDtrControl
= DTR_CONTROL_DISABLE
;
1634 data
->dcb
.fDtrControl
= DTR_CONTROL_ENABLE
;
1636 case SP_DTR_FLOW_CONTROL
:
1637 data
->dcb
.fDtrControl
= DTR_CONTROL_HANDSHAKE
;
1640 RETURN_ERROR(SP_ERR_ARG
, "Invalid DTR setting");
1644 if (config
->dsr
>= 0) {
1645 switch (config
->dsr
) {
1647 data
->dcb
.fOutxDsrFlow
= FALSE
;
1649 case SP_DSR_FLOW_CONTROL
:
1650 data
->dcb
.fOutxDsrFlow
= TRUE
;
1653 RETURN_ERROR(SP_ERR_ARG
, "Invalid DSR setting");
1657 if (config
->xon_xoff
>= 0) {
1658 switch (config
->xon_xoff
) {
1659 case SP_XONXOFF_DISABLED
:
1660 data
->dcb
.fInX
= FALSE
;
1661 data
->dcb
.fOutX
= FALSE
;
1664 data
->dcb
.fInX
= TRUE
;
1665 data
->dcb
.fOutX
= FALSE
;
1667 case SP_XONXOFF_OUT
:
1668 data
->dcb
.fInX
= FALSE
;
1669 data
->dcb
.fOutX
= TRUE
;
1671 case SP_XONXOFF_INOUT
:
1672 data
->dcb
.fInX
= TRUE
;
1673 data
->dcb
.fOutX
= TRUE
;
1676 RETURN_ERROR(SP_ERR_ARG
, "Invalid XON/XOFF setting");
1680 if (!SetCommState(port
->hdl
, &data
->dcb
))
1681 RETURN_FAIL("SetCommState() failed");
1687 if (config
->baudrate
>= 0) {
1688 for (i
= 0; i
< NUM_STD_BAUDRATES
; i
++) {
1689 if (config
->baudrate
== std_baudrates
[i
].value
) {
1690 if (cfsetospeed(&data
->term
, std_baudrates
[i
].index
) < 0)
1691 RETURN_FAIL("cfsetospeed() failed");
1693 if (cfsetispeed(&data
->term
, std_baudrates
[i
].index
) < 0)
1694 RETURN_FAIL("cfsetispeed() failed");
1699 /* Non-standard baud rate */
1700 if (i
== NUM_STD_BAUDRATES
) {
1702 /* Set "dummy" baud rate. */
1703 if (cfsetspeed(&data
->term
, B9600
) < 0)
1704 RETURN_FAIL("cfsetspeed() failed");
1705 baud_nonstd
= config
->baudrate
;
1706 #elif defined(__linux__)
1709 RETURN_ERROR(SP_ERR_SUPP
, "Non-standard baudrate not supported");
1714 if (config
->bits
>= 0) {
1715 data
->term
.c_cflag
&= ~CSIZE
;
1716 switch (config
->bits
) {
1718 data
->term
.c_cflag
|= CS8
;
1721 data
->term
.c_cflag
|= CS7
;
1724 data
->term
.c_cflag
|= CS6
;
1727 data
->term
.c_cflag
|= CS5
;
1730 RETURN_ERROR(SP_ERR_ARG
, "Invalid data bits setting");
1734 if (config
->parity
>= 0) {
1735 data
->term
.c_iflag
&= ~IGNPAR
;
1736 data
->term
.c_cflag
&= ~(PARENB
| PARODD
);
1738 data
->term
.c_cflag
&= ~CMSPAR
;
1740 switch (config
->parity
) {
1741 case SP_PARITY_NONE
:
1742 data
->term
.c_iflag
|= IGNPAR
;
1744 case SP_PARITY_EVEN
:
1745 data
->term
.c_cflag
|= PARENB
;
1748 data
->term
.c_cflag
|= PARENB
| PARODD
;
1751 case SP_PARITY_MARK
:
1752 data
->term
.c_cflag
|= PARENB
| PARODD
;
1753 data
->term
.c_cflag
|= CMSPAR
;
1755 case SP_PARITY_SPACE
:
1756 data
->term
.c_cflag
|= PARENB
;
1757 data
->term
.c_cflag
|= CMSPAR
;
1760 case SP_PARITY_MARK
:
1761 case SP_PARITY_SPACE
:
1762 RETURN_ERROR(SP_ERR_SUPP
, "Mark/space parity not supported");
1765 RETURN_ERROR(SP_ERR_ARG
, "Invalid parity setting");
1769 if (config
->stopbits
>= 0) {
1770 data
->term
.c_cflag
&= ~CSTOPB
;
1771 switch (config
->stopbits
) {
1773 data
->term
.c_cflag
&= ~CSTOPB
;
1776 data
->term
.c_cflag
|= CSTOPB
;
1779 RETURN_ERROR(SP_ERR_ARG
, "Invalid stop bits setting");
1783 if (config
->rts
>= 0 || config
->cts
>= 0) {
1784 if (data
->termiox_supported
) {
1785 data
->flow
&= ~(RTS_FLOW
| CTS_FLOW
);
1786 switch (config
->rts
) {
1789 controlbits
= TIOCM_RTS
;
1790 if (ioctl(port
->fd
, config
->rts
== SP_RTS_ON
? TIOCMBIS
: TIOCMBIC
, &controlbits
) < 0)
1791 RETURN_FAIL("Setting RTS signal level failed");
1793 case SP_RTS_FLOW_CONTROL
:
1794 data
->flow
|= RTS_FLOW
;
1799 if (config
->cts
== SP_CTS_FLOW_CONTROL
)
1800 data
->flow
|= CTS_FLOW
;
1802 if (data
->flow
& (RTS_FLOW
| CTS_FLOW
))
1803 data
->term
.c_iflag
|= CRTSCTS
;
1805 data
->term
.c_iflag
&= ~CRTSCTS
;
1807 /* Asymmetric use of RTS/CTS not supported. */
1808 if (data
->term
.c_iflag
& CRTSCTS
) {
1809 /* Flow control can only be disabled for both RTS & CTS together. */
1810 if (config
->rts
>= 0 && config
->rts
!= SP_RTS_FLOW_CONTROL
) {
1811 if (config
->cts
!= SP_CTS_IGNORE
)
1812 RETURN_ERROR(SP_ERR_SUPP
, "RTS & CTS flow control must be disabled together");
1814 if (config
->cts
>= 0 && config
->cts
!= SP_CTS_FLOW_CONTROL
) {
1815 if (config
->rts
<= 0 || config
->rts
== SP_RTS_FLOW_CONTROL
)
1816 RETURN_ERROR(SP_ERR_SUPP
, "RTS & CTS flow control must be disabled together");
1819 /* Flow control can only be enabled for both RTS & CTS together. */
1820 if (((config
->rts
== SP_RTS_FLOW_CONTROL
) && (config
->cts
!= SP_CTS_FLOW_CONTROL
)) ||
1821 ((config
->cts
== SP_CTS_FLOW_CONTROL
) && (config
->rts
!= SP_RTS_FLOW_CONTROL
)))
1822 RETURN_ERROR(SP_ERR_SUPP
, "RTS & CTS flow control must be enabled together");
1825 if (config
->rts
>= 0) {
1826 if (config
->rts
== SP_RTS_FLOW_CONTROL
) {
1827 data
->term
.c_iflag
|= CRTSCTS
;
1829 controlbits
= TIOCM_RTS
;
1830 if (ioctl(port
->fd
, config
->rts
== SP_RTS_ON
? TIOCMBIS
: TIOCMBIC
,
1832 RETURN_FAIL("Setting RTS signal level failed");
1838 if (config
->dtr
>= 0 || config
->dsr
>= 0) {
1839 if (data
->termiox_supported
) {
1840 data
->flow
&= ~(DTR_FLOW
| DSR_FLOW
);
1841 switch (config
->dtr
) {
1844 controlbits
= TIOCM_DTR
;
1845 if (ioctl(port
->fd
, config
->dtr
== SP_DTR_ON
? TIOCMBIS
: TIOCMBIC
, &controlbits
) < 0)
1846 RETURN_FAIL("Setting DTR signal level failed");
1848 case SP_DTR_FLOW_CONTROL
:
1849 data
->flow
|= DTR_FLOW
;
1854 if (config
->dsr
== SP_DSR_FLOW_CONTROL
)
1855 data
->flow
|= DSR_FLOW
;
1857 /* DTR/DSR flow control not supported. */
1858 if (config
->dtr
== SP_DTR_FLOW_CONTROL
|| config
->dsr
== SP_DSR_FLOW_CONTROL
)
1859 RETURN_ERROR(SP_ERR_SUPP
, "DTR/DSR flow control not supported");
1861 if (config
->dtr
>= 0) {
1862 controlbits
= TIOCM_DTR
;
1863 if (ioctl(port
->fd
, config
->dtr
== SP_DTR_ON
? TIOCMBIS
: TIOCMBIC
,
1865 RETURN_FAIL("Setting DTR signal level failed");
1870 if (config
->xon_xoff
>= 0) {
1871 data
->term
.c_iflag
&= ~(IXON
| IXOFF
| IXANY
);
1872 switch (config
->xon_xoff
) {
1873 case SP_XONXOFF_DISABLED
:
1876 data
->term
.c_iflag
|= IXOFF
;
1878 case SP_XONXOFF_OUT
:
1879 data
->term
.c_iflag
|= IXON
| IXANY
;
1881 case SP_XONXOFF_INOUT
:
1882 data
->term
.c_iflag
|= IXON
| IXOFF
| IXANY
;
1885 RETURN_ERROR(SP_ERR_ARG
, "Invalid XON/XOFF setting");
1889 if (tcsetattr(port
->fd
, TCSANOW
, &data
->term
) < 0)
1890 RETURN_FAIL("tcsetattr() failed");
1893 if (baud_nonstd
!= B0
) {
1894 if (ioctl(port
->fd
, IOSSIOSPEED
, &baud_nonstd
) == -1)
1895 RETURN_FAIL("IOSSIOSPEED ioctl failed");
1896 /* Set baud rates in data->term to correct, but incompatible
1897 * with tcsetattr() value, same as delivered by tcgetattr(). */
1898 if (cfsetspeed(&data
->term
, baud_nonstd
) < 0)
1899 RETURN_FAIL("cfsetspeed() failed");
1901 #elif defined(__linux__)
1903 TRY(set_baudrate(port
->fd
, config
->baudrate
));
1905 if (data
->termiox_supported
)
1906 TRY(set_flow(port
->fd
, data
->flow
));
1910 #endif /* !_WIN32 */
1915 enum sp_return
sp_new_config(struct sp_port_config
**config_ptr
)
1917 struct sp_port_config
*config
;
1919 TRACE("%p", config_ptr
);
1922 RETURN_ERROR(SP_ERR_ARG
, "Null result pointer");
1926 if (!(config
= malloc(sizeof(struct sp_port_config
))))
1927 RETURN_ERROR(SP_ERR_MEM
, "config malloc failed");
1929 config
->baudrate
= -1;
1931 config
->parity
= -1;
1932 config
->stopbits
= -1;
1938 *config_ptr
= config
;
1943 void sp_free_config(struct sp_port_config
*config
)
1945 TRACE("%p", config
);
1948 DEBUG("Null config");
1955 enum sp_return
sp_get_config(struct sp_port
*port
, struct sp_port_config
*config
)
1957 struct port_data data
;
1959 TRACE("%p, %p", port
, config
);
1964 RETURN_ERROR(SP_ERR_ARG
, "Null config");
1966 TRY(get_config(port
, &data
, config
));
1971 enum sp_return
sp_set_config(struct sp_port
*port
, const struct sp_port_config
*config
)
1973 struct port_data data
;
1974 struct sp_port_config prev_config
;
1976 TRACE("%p, %p", port
, config
);
1981 RETURN_ERROR(SP_ERR_ARG
, "Null config");
1983 TRY(get_config(port
, &data
, &prev_config
));
1984 TRY(set_config(port
, &data
, config
));
1989 #define CREATE_ACCESSORS(x, type) \
1990 enum sp_return sp_set_##x(struct sp_port *port, type x) { \
1991 struct port_data data; \
1992 struct sp_port_config config; \
1993 TRACE("%p, %d", port, x); \
1994 CHECK_OPEN_PORT(); \
1995 TRY(get_config(port, &data, &config)); \
1997 TRY(set_config(port, &data, &config)); \
2000 enum sp_return sp_get_config_##x(const struct sp_port_config *config, type *x) { \
2001 TRACE("%p, %p", config, x); \
2003 RETURN_ERROR(SP_ERR_ARG, "Null config"); \
2007 enum sp_return sp_set_config_##x(struct sp_port_config *config, type x) { \
2008 TRACE("%p, %d", config, x); \
2010 RETURN_ERROR(SP_ERR_ARG, "Null config"); \
2015 CREATE_ACCESSORS(baudrate
, int)
2016 CREATE_ACCESSORS(bits
, int)
2017 CREATE_ACCESSORS(parity
, enum sp_parity
)
2018 CREATE_ACCESSORS(stopbits
, int)
2019 CREATE_ACCESSORS(rts
, enum sp_rts
)
2020 CREATE_ACCESSORS(cts
, enum sp_cts
)
2021 CREATE_ACCESSORS(dtr
, enum sp_dtr
)
2022 CREATE_ACCESSORS(dsr
, enum sp_dsr
)
2023 CREATE_ACCESSORS(xon_xoff
, enum sp_xonxoff
)
2025 enum sp_return
sp_set_config_flowcontrol(struct sp_port_config
*config
, enum sp_flowcontrol flowcontrol
)
2028 RETURN_ERROR(SP_ERR_ARG
, "Null configuration");
2030 if (flowcontrol
> SP_FLOWCONTROL_DTRDSR
)
2031 RETURN_ERROR(SP_ERR_ARG
, "Invalid flow control setting");
2033 if (flowcontrol
== SP_FLOWCONTROL_XONXOFF
)
2034 config
->xon_xoff
= SP_XONXOFF_INOUT
;
2036 config
->xon_xoff
= SP_XONXOFF_DISABLED
;
2038 if (flowcontrol
== SP_FLOWCONTROL_RTSCTS
) {
2039 config
->rts
= SP_RTS_FLOW_CONTROL
;
2040 config
->cts
= SP_CTS_FLOW_CONTROL
;
2042 if (config
->rts
== SP_RTS_FLOW_CONTROL
)
2043 config
->rts
= SP_RTS_ON
;
2044 config
->cts
= SP_CTS_IGNORE
;
2047 if (flowcontrol
== SP_FLOWCONTROL_DTRDSR
) {
2048 config
->dtr
= SP_DTR_FLOW_CONTROL
;
2049 config
->dsr
= SP_DSR_FLOW_CONTROL
;
2051 if (config
->dtr
== SP_DTR_FLOW_CONTROL
)
2052 config
->dtr
= SP_DTR_ON
;
2053 config
->dsr
= SP_DSR_IGNORE
;
2059 enum sp_return
sp_set_flowcontrol(struct sp_port
*port
, enum sp_flowcontrol flowcontrol
)
2061 struct port_data data
;
2062 struct sp_port_config config
;
2064 TRACE("%p, %d", port
, flowcontrol
);
2068 TRY(get_config(port
, &data
, &config
));
2070 TRY(sp_set_config_flowcontrol(&config
, flowcontrol
));
2072 TRY(set_config(port
, &data
, &config
));
2077 enum sp_return
sp_get_signals(struct sp_port
*port
, enum sp_signal
*signals
)
2079 TRACE("%p, %p", port
, signals
);
2084 RETURN_ERROR(SP_ERR_ARG
, "Null result pointer");
2086 DEBUG("Getting control signals for port %s", port
->name
);
2091 if (GetCommModemStatus(port
->hdl
, &bits
) == 0)
2092 RETURN_FAIL("GetCommModemStatus() failed");
2093 if (bits
& MS_CTS_ON
)
2094 *signals
|= SP_SIG_CTS
;
2095 if (bits
& MS_DSR_ON
)
2096 *signals
|= SP_SIG_DSR
;
2097 if (bits
& MS_RLSD_ON
)
2098 *signals
|= SP_SIG_DCD
;
2099 if (bits
& MS_RING_ON
)
2100 *signals
|= SP_SIG_RI
;
2103 if (ioctl(port
->fd
, TIOCMGET
, &bits
) < 0)
2104 RETURN_FAIL("TIOCMGET ioctl failed");
2105 if (bits
& TIOCM_CTS
)
2106 *signals
|= SP_SIG_CTS
;
2107 if (bits
& TIOCM_DSR
)
2108 *signals
|= SP_SIG_DSR
;
2109 if (bits
& TIOCM_CAR
)
2110 *signals
|= SP_SIG_DCD
;
2111 if (bits
& TIOCM_RNG
)
2112 *signals
|= SP_SIG_RI
;
2117 enum sp_return
sp_start_break(struct sp_port
*port
)
2123 if (SetCommBreak(port
->hdl
) == 0)
2124 RETURN_FAIL("SetCommBreak() failed");
2126 if (ioctl(port
->fd
, TIOCSBRK
, 1) < 0)
2127 RETURN_FAIL("TIOCSBRK ioctl failed");
2133 enum sp_return
sp_end_break(struct sp_port
*port
)
2139 if (ClearCommBreak(port
->hdl
) == 0)
2140 RETURN_FAIL("ClearCommBreak() failed");
2142 if (ioctl(port
->fd
, TIOCCBRK
, 1) < 0)
2143 RETURN_FAIL("TIOCCBRK ioctl failed");
2149 int sp_last_error_code(void)
2153 RETURN_VALUE("%d", GetLastError());
2155 RETURN_VALUE("%d", errno
);
2159 char *sp_last_error_message(void)
2165 DWORD error
= GetLastError();
2168 FORMAT_MESSAGE_ALLOCATE_BUFFER
|
2169 FORMAT_MESSAGE_FROM_SYSTEM
|
2170 FORMAT_MESSAGE_IGNORE_INSERTS
,
2173 MAKELANGID(LANG_NEUTRAL
, SUBLANG_DEFAULT
),
2177 RETURN_VALUE("%s", message
);
2179 RETURN_VALUE("%s", strerror(errno
));
2183 void sp_free_error_message(char *message
)
2185 TRACE("%s", message
);
2196 void sp_set_debug_handler(void (*handler
)(const char *format
, ...))
2198 TRACE("%p", handler
);
2200 sp_debug_handler
= handler
;
2205 void sp_default_debug_handler(const char *format
, ...)
2208 va_start(args
, format
);
2209 if (getenv("LIBSERIALPORT_DEBUG")) {
2210 fputs("sp: ", stderr
);
2211 vfprintf(stderr
, format
, args
);