]> sigrok.org Git - libserialport.git/blame_incremental - serialport.c
Remove the udev dependency and parse the /sys hierarchy instead.
[libserialport.git] / serialport.c
... / ...
CommitLineData
1/*
2 * This file is part of the libserialport project.
3 *
4 * Copyright (C) 2010-2012 Bert Vermeulen <bert@biot.com>
5 * Copyright (C) 2010-2012 Uwe Hermann <uwe@hermann-uwe.de>
6 * Copyright (C) 2013 Martin Ling <martin-libserialport@earth.li>
7 * Copyright (C) 2013 Matthias Heidbrink <m-sigrok@heidbrink.biz>
8 *
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.
13 *
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.
18 *
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/>.
21 */
22
23#include <string.h>
24#include <sys/types.h>
25#include <sys/stat.h>
26#include <fcntl.h>
27#include <unistd.h>
28#include <stdlib.h>
29#include <errno.h>
30#include <stdio.h>
31#include <stdarg.h>
32#ifdef _WIN32
33#include <windows.h>
34#include <tchar.h>
35#else
36#include <limits.h>
37#include <termios.h>
38#include <sys/ioctl.h>
39#include <sys/time.h>
40#include <limits.h>
41#include <poll.h>
42#endif
43#ifdef __APPLE__
44#include <IOKit/IOKitLib.h>
45#include <IOKit/serial/IOSerialKeys.h>
46#include <IOKit/serial/ioss.h>
47#include <sys/syslimits.h>
48#endif
49#ifdef __linux__
50#include <dirent.h>
51#ifndef __ANDROID__
52#include "linux/serial.h"
53#endif
54#include "linux_termios.h"
55
56/* TCGETX/TCSETX is not available everywhere. */
57#if defined(TCGETX) && defined(TCSETX) && defined(HAVE_TERMIOX)
58#define USE_TERMIOX
59#endif
60#endif
61
62/* TIOCINQ/TIOCOUTQ is not available everywhere. */
63#if !defined(TIOCINQ) && defined(FIONREAD)
64#define TIOCINQ FIONREAD
65#endif
66#if !defined(TIOCOUTQ) && defined(FIONWRITE)
67#define TIOCOUTQ FIONWRITE
68#endif
69
70/* Non-standard baudrates are not available everywhere. */
71#if defined(HAVE_TERMIOS_SPEED) || defined(HAVE_TERMIOS2_SPEED)
72#define USE_TERMIOS_SPEED
73#endif
74
75#include "libserialport.h"
76
77struct sp_port {
78 char *name;
79#ifdef _WIN32
80 HANDLE hdl;
81 COMMTIMEOUTS timeouts;
82 OVERLAPPED write_ovl;
83 OVERLAPPED read_ovl;
84 OVERLAPPED wait_ovl;
85 DWORD events;
86 BYTE pending_byte;
87 BOOL writing;
88#else
89 int fd;
90#endif
91};
92
93struct sp_port_config {
94 int baudrate;
95 int bits;
96 enum sp_parity parity;
97 int stopbits;
98 enum sp_rts rts;
99 enum sp_cts cts;
100 enum sp_dtr dtr;
101 enum sp_dsr dsr;
102 enum sp_xonxoff xon_xoff;
103};
104
105struct port_data {
106#ifdef _WIN32
107 DCB dcb;
108#else
109 struct termios term;
110 int controlbits;
111 int termiox_supported;
112 int rts_flow;
113 int cts_flow;
114 int dtr_flow;
115 int dsr_flow;
116#endif
117};
118
119#ifdef _WIN32
120typedef HANDLE event_handle;
121#else
122typedef int event_handle;
123#endif
124
125/* Standard baud rates. */
126#ifdef _WIN32
127#define BAUD_TYPE DWORD
128#define BAUD(n) {CBR_##n, n}
129#else
130#define BAUD_TYPE speed_t
131#define BAUD(n) {B##n, n}
132#endif
133
134struct std_baudrate {
135 BAUD_TYPE index;
136 int value;
137};
138
139const struct std_baudrate std_baudrates[] = {
140#ifdef _WIN32
141 /*
142 * The baudrates 50/75/134/150/200/1800/230400/460800 do not seem to
143 * have documented CBR_* macros.
144 */
145 BAUD(110), BAUD(300), BAUD(600), BAUD(1200), BAUD(2400), BAUD(4800),
146 BAUD(9600), BAUD(14400), BAUD(19200), BAUD(38400), BAUD(57600),
147 BAUD(115200), BAUD(128000), BAUD(256000),
148#else
149 BAUD(50), BAUD(75), BAUD(110), BAUD(134), BAUD(150), BAUD(200),
150 BAUD(300), BAUD(600), BAUD(1200), BAUD(1800), BAUD(2400), BAUD(4800),
151 BAUD(9600), BAUD(19200), BAUD(38400), BAUD(57600), BAUD(115200),
152 BAUD(230400),
153#if !defined(__APPLE__) && !defined(__OpenBSD__)
154 BAUD(460800),
155#endif
156#endif
157};
158
159void (*sp_debug_handler)(const char *format, ...) = sp_default_debug_handler;
160
161#define ARRAY_SIZE(x) (sizeof(x) / sizeof(x[0]))
162#define NUM_STD_BAUDRATES ARRAY_SIZE(std_baudrates)
163
164/* Debug output macros. */
165#define DEBUG(fmt, ...) do { if (sp_debug_handler) sp_debug_handler(fmt ".\n", ##__VA_ARGS__); } while (0)
166#define DEBUG_ERROR(err, fmt, ...) DEBUG("%s returning " #err ": " fmt, __func__, ##__VA_ARGS__)
167#define DEBUG_FAIL(fmt, ...) do { \
168 char *errmsg = sp_last_error_message(); \
169 DEBUG("%s returning SP_ERR_FAIL: "fmt": %s", __func__,##__VA_ARGS__,errmsg); \
170 sp_free_error_message(errmsg); \
171} while (0);
172#define RETURN() do { DEBUG("%s returning", __func__); return; } while(0)
173#define RETURN_CODE(x) do { DEBUG("%s returning " #x, __func__); return x; } while (0)
174#define RETURN_CODEVAL(x) do { \
175 switch (x) { \
176 case SP_OK: RETURN_CODE(SP_OK); \
177 case SP_ERR_ARG: RETURN_CODE(SP_ERR_ARG); \
178 case SP_ERR_FAIL: RETURN_CODE(SP_ERR_FAIL); \
179 case SP_ERR_MEM: RETURN_CODE(SP_ERR_MEM); \
180 case SP_ERR_SUPP: RETURN_CODE(SP_ERR_SUPP); \
181 } \
182} while (0)
183#define RETURN_OK() RETURN_CODE(SP_OK);
184#define RETURN_ERROR(err, ...) do { DEBUG_ERROR(err, __VA_ARGS__); return err; } while (0)
185#define RETURN_FAIL(...) do { DEBUG_FAIL(__VA_ARGS__); return SP_ERR_FAIL; } while (0)
186#define RETURN_VALUE(fmt, x) do { \
187 typeof(x) _x = x; \
188 DEBUG("%s returning " fmt, __func__, _x); \
189 return _x; \
190} while (0)
191#define SET_ERROR(val, err, msg) do { DEBUG_ERROR(err, msg); val = err; } while (0)
192#define SET_FAIL(val, msg) do { DEBUG_FAIL(msg); val = SP_ERR_FAIL; } while (0)
193#define TRACE(fmt, ...) DEBUG("%s(" fmt ") called", __func__, ##__VA_ARGS__)
194
195#define TRY(x) do { int ret = x; if (ret != SP_OK) RETURN_CODEVAL(ret); } while (0)
196
197/* Helper functions. */
198static enum sp_return get_config(struct sp_port *port, struct port_data *data,
199 struct sp_port_config *config);
200static enum sp_return set_config(struct sp_port *port, struct port_data *data,
201 const struct sp_port_config *config);
202
203enum sp_return sp_get_port_by_name(const char *portname, struct sp_port **port_ptr)
204{
205 struct sp_port *port;
206 int len;
207
208 TRACE("%s, %p", portname, port_ptr);
209
210 if (!port_ptr)
211 RETURN_ERROR(SP_ERR_ARG, "Null result pointer");
212
213 *port_ptr = NULL;
214
215 if (!portname)
216 RETURN_ERROR(SP_ERR_ARG, "Null port name");
217
218 DEBUG("Building structure for port %s", portname);
219
220 if (!(port = malloc(sizeof(struct sp_port))))
221 RETURN_ERROR(SP_ERR_MEM, "Port structure malloc failed");
222
223 len = strlen(portname) + 1;
224
225 if (!(port->name = malloc(len))) {
226 free(port);
227 RETURN_ERROR(SP_ERR_MEM, "Port name malloc failed");
228 }
229
230 memcpy(port->name, portname, len);
231
232#ifdef _WIN32
233 port->hdl = INVALID_HANDLE_VALUE;
234#else
235 port->fd = -1;
236#endif
237
238 *port_ptr = port;
239
240 RETURN_OK();
241}
242
243char *sp_get_port_name(const struct sp_port *port)
244{
245 TRACE("%p", port);
246
247 if (!port)
248 return NULL;
249
250 RETURN_VALUE("%s", port->name);
251}
252
253enum sp_return sp_get_port_handle(const struct sp_port *port, void *result_ptr)
254{
255 TRACE("%p, %p", port, result_ptr);
256
257 if (!port)
258 RETURN_ERROR(SP_ERR_ARG, "Null port");
259
260#ifdef _WIN32
261 HANDLE *handle_ptr = result_ptr;
262 *handle_ptr = port->hdl;
263#else
264 int *fd_ptr = result_ptr;
265 *fd_ptr = port->fd;
266#endif
267
268 RETURN_OK();
269}
270
271enum sp_return sp_copy_port(const struct sp_port *port, struct sp_port **copy_ptr)
272{
273 TRACE("%p, %p", port, copy_ptr);
274
275 if (!copy_ptr)
276 RETURN_ERROR(SP_ERR_ARG, "Null result pointer");
277
278 *copy_ptr = NULL;
279
280 if (!port)
281 RETURN_ERROR(SP_ERR_ARG, "Null port");
282
283 if (!port->name)
284 RETURN_ERROR(SP_ERR_ARG, "Null port name");
285
286 DEBUG("Copying port structure");
287
288 RETURN_VALUE("%p", sp_get_port_by_name(port->name, copy_ptr));
289}
290
291void sp_free_port(struct sp_port *port)
292{
293 TRACE("%p", port);
294
295 if (!port) {
296 DEBUG("Null port");
297 RETURN();
298 }
299
300 DEBUG("Freeing port structure");
301
302 if (port->name)
303 free(port->name);
304
305 free(port);
306
307 RETURN();
308}
309
310static struct sp_port **list_append(struct sp_port **list, const char *portname)
311{
312 void *tmp;
313 unsigned int count;
314
315 for (count = 0; list[count]; count++);
316 if (!(tmp = realloc(list, sizeof(struct sp_port *) * (count + 2))))
317 goto fail;
318 list = tmp;
319 if (sp_get_port_by_name(portname, &list[count]) != SP_OK)
320 goto fail;
321 list[count + 1] = NULL;
322 return list;
323
324fail:
325 sp_free_port_list(list);
326 return NULL;
327}
328
329enum sp_return sp_list_ports(struct sp_port ***list_ptr)
330{
331 struct sp_port **list;
332 int ret = SP_ERR_SUPP;
333
334 TRACE("%p", list_ptr);
335
336 if (!list_ptr)
337 RETURN_ERROR(SP_ERR_ARG, "Null result pointer");
338
339 DEBUG("Enumerating ports");
340
341 if (!(list = malloc(sizeof(struct sp_port **))))
342 RETURN_ERROR(SP_ERR_MEM, "Port list malloc failed");
343
344 list[0] = NULL;
345
346#ifdef _WIN32
347 HKEY key;
348 TCHAR *value, *data;
349 DWORD max_value_len, max_data_size, max_data_len;
350 DWORD value_len, data_size, data_len;
351 DWORD type, index = 0;
352 char *name;
353 int name_len;
354
355 ret = SP_OK;
356
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");
361 goto out_done;
362 }
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");
367 goto out_close;
368 }
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");
372 goto out_close;
373 }
374 if (!(data = malloc((max_data_len + 1) * sizeof(TCHAR)))) {
375 SET_ERROR(ret, SP_ERR_MEM, "registry data malloc failed");
376 goto out_free_value;
377 }
378 DEBUG("Iterating over values");
379 while (
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)
384 {
385 data_len = data_size / sizeof(TCHAR);
386 data[data_len] = '\0';
387#ifdef UNICODE
388 name_len = WideCharToMultiByte(CP_ACP, 0, data, -1, NULL, 0, NULL, NULL);
389#else
390 name_len = data_len + 1;
391#endif
392 if (!(name = malloc(name_len))) {
393 SET_ERROR(ret, SP_ERR_MEM, "registry port name malloc failed");
394 goto out;
395 }
396#ifdef UNICODE
397 WideCharToMultiByte(CP_ACP, 0, data, -1, name, name_len, NULL, NULL);
398#else
399 strcpy(name, data);
400#endif
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");
405 goto out;
406 }
407 }
408 index++;
409 }
410out:
411 free(data);
412out_free_value:
413 free(value);
414out_close:
415 RegCloseKey(key);
416out_done:
417#endif
418#ifdef __APPLE__
419 CFMutableDictionaryRef classes;
420 io_iterator_t iter;
421 char path[PATH_MAX];
422 io_object_t port;
423 CFTypeRef cf_path;
424 Boolean result;
425
426 ret = SP_OK;
427
428 DEBUG("Creating matching dictionary");
429 if (!(classes = IOServiceMatching(kIOSerialBSDServiceValue))) {
430 SET_FAIL(ret, "IOServiceMatching() failed");
431 goto out_done;
432 }
433
434 DEBUG("Getting matching services");
435 if (IOServiceGetMatchingServices(kIOMasterPortDefault, classes,
436 &iter) != KERN_SUCCESS) {
437 SET_FAIL(ret, "IOServiceGetMatchingServices() failed");
438 goto out_done;
439 }
440
441 DEBUG("Iterating over results");
442 while ((port = IOIteratorNext(iter))) {
443 cf_path = IORegistryEntryCreateCFProperty(port,
444 CFSTR(kIOCalloutDeviceKey), kCFAllocatorDefault, 0);
445 if (cf_path) {
446 result = CFStringGetCString(cf_path, path, sizeof(path),
447 kCFStringEncodingASCII);
448 CFRelease(cf_path);
449 if (result) {
450 DEBUG("Found port %s", path);
451 if (!(list = list_append(list, path))) {
452 SET_ERROR(ret, SP_ERR_MEM, "list append failed");
453 IOObjectRelease(port);
454 goto out;
455 }
456 }
457 }
458 IOObjectRelease(port);
459 }
460out:
461 IOObjectRelease(iter);
462out_done:
463#endif
464#ifdef __linux__
465 char name[PATH_MAX], target[PATH_MAX];
466 struct dirent entry, *result;
467 struct serial_struct serial_info;
468 int len, fd, ioctl_result;
469 DIR *dir;
470
471 ret = SP_OK;
472
473 DEBUG("Enumerating tty devices");
474 if (!(dir = opendir("/sys/class/tty")))
475 RETURN_FAIL("could not open /sys/class/tty");
476
477 DEBUG("Iterating over results");
478 while (!readdir_r(dir, &entry, &result) && result) {
479 len = readlinkat(dirfd(dir), entry.d_name, target, sizeof(target));
480 if (len <= 0 || len >= (int) sizeof(target)-1)
481 continue;
482 target[len] = 0;
483 if (strstr(target, "virtual"))
484 continue;
485 snprintf(name, sizeof(name), "/dev/%s", entry.d_name);
486 DEBUG("Found device %s", name);
487 if (strstr(target, "serial8250")) {
488 /* The serial8250 driver has a hardcoded number of ports.
489 * The only way to tell which actually exist on a given system
490 * is to try to open them and make an ioctl call. */
491 DEBUG("serial8250 device, attempting to open");
492 if ((fd = open(name, O_RDWR | O_NONBLOCK | O_NOCTTY)) < 0) {
493 DEBUG("open failed, skipping");
494 continue;
495 }
496 ioctl_result = ioctl(fd, TIOCGSERIAL, &serial_info);
497 close(fd);
498 if (ioctl_result != 0) {
499 DEBUG("ioctl failed, skipping");
500 continue;
501 }
502 if (serial_info.type == PORT_UNKNOWN) {
503 DEBUG("port type is unknown, skipping");
504 continue;
505 }
506 }
507 DEBUG("Found port %s", name);
508 list = list_append(list, name);
509 if (!list) {
510 SET_ERROR(ret, SP_ERR_MEM, "list append failed");
511 break;
512 }
513 }
514 closedir(dir);
515#endif
516
517 switch (ret) {
518 case SP_OK:
519 *list_ptr = list;
520 RETURN_OK();
521 case SP_ERR_SUPP:
522 DEBUG_ERROR(SP_ERR_SUPP, "Enumeration not supported on this platform");
523 default:
524 if (list)
525 sp_free_port_list(list);
526 *list_ptr = NULL;
527 return ret;
528 }
529}
530
531void sp_free_port_list(struct sp_port **list)
532{
533 unsigned int i;
534
535 TRACE("%p", list);
536
537 if (!list) {
538 DEBUG("Null list");
539 RETURN();
540 }
541
542 DEBUG("Freeing port list");
543
544 for (i = 0; list[i]; i++)
545 sp_free_port(list[i]);
546 free(list);
547
548 RETURN();
549}
550
551#define CHECK_PORT() do { \
552 if (port == NULL) \
553 RETURN_ERROR(SP_ERR_ARG, "Null port"); \
554 if (port->name == NULL) \
555 RETURN_ERROR(SP_ERR_ARG, "Null port name"); \
556} while (0)
557#ifdef _WIN32
558#define CHECK_PORT_HANDLE() do { \
559 if (port->hdl == INVALID_HANDLE_VALUE) \
560 RETURN_ERROR(SP_ERR_ARG, "Invalid port handle"); \
561} while (0)
562#else
563#define CHECK_PORT_HANDLE() do { \
564 if (port->fd < 0) \
565 RETURN_ERROR(SP_ERR_ARG, "Invalid port fd"); \
566} while (0)
567#endif
568#define CHECK_OPEN_PORT() do { \
569 CHECK_PORT(); \
570 CHECK_PORT_HANDLE(); \
571} while (0)
572
573enum sp_return sp_open(struct sp_port *port, enum sp_mode flags)
574{
575 struct port_data data;
576 struct sp_port_config config;
577 enum sp_return ret;
578
579 TRACE("%p, 0x%x", port, flags);
580
581 CHECK_PORT();
582
583 if (flags > (SP_MODE_READ | SP_MODE_WRITE))
584 RETURN_ERROR(SP_ERR_ARG, "Invalid flags");
585
586 DEBUG("Opening port %s", port->name);
587
588#ifdef _WIN32
589 DWORD desired_access = 0, flags_and_attributes = 0, errors;
590 char *escaped_port_name;
591 COMSTAT status;
592
593 /* Prefix port name with '\\.\' to work with ports above COM9. */
594 if (!(escaped_port_name = malloc(strlen(port->name) + 5)))
595 RETURN_ERROR(SP_ERR_MEM, "Escaped port name malloc failed");
596 sprintf(escaped_port_name, "\\\\.\\%s", port->name);
597
598 /* Map 'flags' to the OS-specific settings. */
599 flags_and_attributes = FILE_ATTRIBUTE_NORMAL | FILE_FLAG_OVERLAPPED;
600 if (flags & SP_MODE_READ)
601 desired_access |= GENERIC_READ;
602 if (flags & SP_MODE_WRITE)
603 desired_access |= GENERIC_WRITE;
604
605 port->hdl = CreateFile(escaped_port_name, desired_access, 0, 0,
606 OPEN_EXISTING, flags_and_attributes, 0);
607
608 free(escaped_port_name);
609
610 if (port->hdl == INVALID_HANDLE_VALUE)
611 RETURN_FAIL("port CreateFile() failed");
612
613 /* All timeouts initially disabled. */
614 port->timeouts.ReadIntervalTimeout = 0;
615 port->timeouts.ReadTotalTimeoutMultiplier = 0;
616 port->timeouts.ReadTotalTimeoutConstant = 0;
617 port->timeouts.WriteTotalTimeoutMultiplier = 0;
618 port->timeouts.WriteTotalTimeoutConstant = 0;
619
620 if (SetCommTimeouts(port->hdl, &port->timeouts) == 0) {
621 sp_close(port);
622 RETURN_FAIL("SetCommTimeouts() failed");
623 }
624
625 /* Prepare OVERLAPPED structures. */
626#define INIT_OVERLAPPED(ovl) do { \
627 memset(&port->ovl, 0, sizeof(port->ovl)); \
628 port->ovl.hEvent = INVALID_HANDLE_VALUE; \
629 if ((port->ovl.hEvent = CreateEvent(NULL, TRUE, TRUE, NULL)) \
630 == INVALID_HANDLE_VALUE) { \
631 sp_close(port); \
632 RETURN_FAIL(#ovl "CreateEvent() failed"); \
633 } \
634} while (0)
635
636 INIT_OVERLAPPED(read_ovl);
637 INIT_OVERLAPPED(write_ovl);
638 INIT_OVERLAPPED(wait_ovl);
639
640 /* Set event mask for RX and error events. */
641 if (SetCommMask(port->hdl, EV_RXCHAR | EV_ERR) == 0) {
642 sp_close(port);
643 RETURN_FAIL("SetCommMask() failed");
644 }
645
646 /* Start background operation for RX and error events. */
647 if (WaitCommEvent(port->hdl, &port->events, &port->wait_ovl) == 0) {
648 if (GetLastError() != ERROR_IO_PENDING) {
649 sp_close(port);
650 RETURN_FAIL("WaitCommEvent() failed");
651 }
652 }
653
654 port->writing = FALSE;
655
656#else
657 int flags_local = O_NONBLOCK | O_NOCTTY;
658
659 /* Map 'flags' to the OS-specific settings. */
660 if (flags & (SP_MODE_READ | SP_MODE_WRITE))
661 flags_local |= O_RDWR;
662 else if (flags & SP_MODE_READ)
663 flags_local |= O_RDONLY;
664 else if (flags & SP_MODE_WRITE)
665 flags_local |= O_WRONLY;
666
667 if ((port->fd = open(port->name, flags_local)) < 0)
668 RETURN_FAIL("open() failed");
669#endif
670
671 ret = get_config(port, &data, &config);
672
673 if (ret < 0) {
674 sp_close(port);
675 RETURN_CODEVAL(ret);
676 }
677
678 /* Set sane port settings. */
679#ifdef _WIN32
680 data.dcb.fBinary = TRUE;
681 data.dcb.fDsrSensitivity = FALSE;
682 data.dcb.fErrorChar = FALSE;
683 data.dcb.fNull = FALSE;
684 data.dcb.fAbortOnError = TRUE;
685#else
686 /* Turn off all fancy termios tricks, give us a raw channel. */
687 data.term.c_iflag &= ~(IGNBRK | BRKINT | PARMRK | ISTRIP | INLCR | IGNCR | ICRNL | IMAXBEL);
688#ifdef IUCLC
689 data.term.c_iflag &= ~IUCLC;
690#endif
691 data.term.c_oflag &= ~(OPOST | ONLCR | OCRNL | ONOCR | ONLRET);
692#ifdef OLCUC
693 data.term.c_oflag &= ~OLCUC;
694#endif
695#ifdef NLDLY
696 data.term.c_oflag &= ~NLDLY;
697#endif
698#ifdef CRDLY
699 data.term.c_oflag &= ~CRDLY;
700#endif
701#ifdef TABDLY
702 data.term.c_oflag &= ~TABDLY;
703#endif
704#ifdef BSDLY
705 data.term.c_oflag &= ~BSDLY;
706#endif
707#ifdef VTDLY
708 data.term.c_oflag &= ~VTDLY;
709#endif
710#ifdef FFDLY
711 data.term.c_oflag &= ~FFDLY;
712#endif
713#ifdef OFILL
714 data.term.c_oflag &= ~OFILL;
715#endif
716 data.term.c_lflag &= ~(ISIG | ICANON | ECHO | IEXTEN);
717 data.term.c_cc[VMIN] = 0;
718 data.term.c_cc[VTIME] = 0;
719
720 /* Ignore modem status lines; enable receiver; leave control lines alone on close. */
721 data.term.c_cflag |= (CLOCAL | CREAD | HUPCL);
722#endif
723
724#ifdef _WIN32
725 if (ClearCommError(port->hdl, &errors, &status) == 0)
726 RETURN_FAIL("ClearCommError() failed");
727#endif
728
729 ret = set_config(port, &data, &config);
730
731 if (ret < 0) {
732 sp_close(port);
733 RETURN_CODEVAL(ret);
734 }
735
736 RETURN_OK();
737}
738
739enum sp_return sp_close(struct sp_port *port)
740{
741 TRACE("%p", port);
742
743 CHECK_OPEN_PORT();
744
745 DEBUG("Closing port %s", port->name);
746
747#ifdef _WIN32
748 /* Returns non-zero upon success, 0 upon failure. */
749 if (CloseHandle(port->hdl) == 0)
750 RETURN_FAIL("port CloseHandle() failed");
751 port->hdl = INVALID_HANDLE_VALUE;
752
753 /* Close event handles for overlapped structures. */
754#define CLOSE_OVERLAPPED(ovl) do { \
755 if (port->ovl.hEvent != INVALID_HANDLE_VALUE && \
756 CloseHandle(port->ovl.hEvent) == 0) \
757 RETURN_FAIL(# ovl "event CloseHandle() failed"); \
758} while (0)
759 CLOSE_OVERLAPPED(read_ovl);
760 CLOSE_OVERLAPPED(write_ovl);
761 CLOSE_OVERLAPPED(wait_ovl);
762
763#else
764 /* Returns 0 upon success, -1 upon failure. */
765 if (close(port->fd) == -1)
766 RETURN_FAIL("close() failed");
767 port->fd = -1;
768#endif
769
770 RETURN_OK();
771}
772
773enum sp_return sp_flush(struct sp_port *port, enum sp_buffer buffers)
774{
775 TRACE("%p, 0x%x", port, buffers);
776
777 CHECK_OPEN_PORT();
778
779 if (buffers > SP_BUF_BOTH)
780 RETURN_ERROR(SP_ERR_ARG, "Invalid buffer selection");
781
782 const char *buffer_names[] = {"no", "input", "output", "both"};
783
784 DEBUG("Flushing %s buffers on port %s", buffer_names[buffers], port->name);
785
786#ifdef _WIN32
787 DWORD flags = 0;
788 if (buffers & SP_BUF_INPUT)
789 flags |= PURGE_RXCLEAR;
790 if (buffers & SP_BUF_OUTPUT)
791 flags |= PURGE_TXCLEAR;
792
793 /* Returns non-zero upon success, 0 upon failure. */
794 if (PurgeComm(port->hdl, flags) == 0)
795 RETURN_FAIL("PurgeComm() failed");
796#else
797 int flags = 0;
798 if (buffers & SP_BUF_BOTH)
799 flags = TCIOFLUSH;
800 else if (buffers & SP_BUF_INPUT)
801 flags = TCIFLUSH;
802 else if (buffers & SP_BUF_OUTPUT)
803 flags = TCOFLUSH;
804
805 /* Returns 0 upon success, -1 upon failure. */
806 if (tcflush(port->fd, flags) < 0)
807 RETURN_FAIL("tcflush() failed");
808#endif
809 RETURN_OK();
810}
811
812enum sp_return sp_drain(struct sp_port *port)
813{
814 TRACE("%p", port);
815
816 CHECK_OPEN_PORT();
817
818 DEBUG("Draining port %s", port->name);
819
820#ifdef _WIN32
821 /* Returns non-zero upon success, 0 upon failure. */
822 if (FlushFileBuffers(port->hdl) == 0)
823 RETURN_FAIL("FlushFileBuffers() failed");
824 RETURN_OK();
825#else
826 int result;
827 while (1) {
828#ifdef __ANDROID__
829 int arg = 1;
830 result = ioctl(port->fd, TCSBRK, &arg);
831#else
832 result = tcdrain(port->fd);
833#endif
834 if (result < 0) {
835 if (errno == EINTR) {
836 DEBUG("tcdrain() was interrupted");
837 continue;
838 } else {
839 RETURN_FAIL("tcdrain() failed");
840 }
841 } else {
842 RETURN_OK();
843 }
844 }
845#endif
846}
847
848enum sp_return sp_blocking_write(struct sp_port *port, const void *buf, size_t count, unsigned int timeout)
849{
850 TRACE("%p, %p, %d, %d", port, buf, count, timeout);
851
852 CHECK_OPEN_PORT();
853
854 if (!buf)
855 RETURN_ERROR(SP_ERR_ARG, "Null buffer");
856
857 if (timeout)
858 DEBUG("Writing %d bytes to port %s, timeout %d ms", count, port->name, timeout);
859 else
860 DEBUG("Writing %d bytes to port %s, no timeout", count, port->name);
861
862 if (count == 0)
863 RETURN_VALUE("0", 0);
864
865#ifdef _WIN32
866 DWORD bytes_written = 0;
867 BOOL result;
868
869 /* Wait for previous non-blocking write to complete, if any. */
870 if (port->writing) {
871 DEBUG("Waiting for previous write to complete");
872 result = GetOverlappedResult(port->hdl, &port->write_ovl, &bytes_written, TRUE);
873 port->writing = 0;
874 if (!result)
875 RETURN_FAIL("Previous write failed to complete");
876 DEBUG("Previous write completed");
877 }
878
879 /* Set timeout. */
880 port->timeouts.WriteTotalTimeoutConstant = timeout;
881 if (SetCommTimeouts(port->hdl, &port->timeouts) == 0)
882 RETURN_FAIL("SetCommTimeouts() failed");
883
884 /* Start write. */
885 if (WriteFile(port->hdl, buf, count, NULL, &port->write_ovl) == 0) {
886 if (GetLastError() == ERROR_IO_PENDING) {
887 DEBUG("Waiting for write to complete");
888 GetOverlappedResult(port->hdl, &port->write_ovl, &bytes_written, TRUE);
889 DEBUG("Write completed, %d/%d bytes written", bytes_written, count);
890 RETURN_VALUE("%d", bytes_written);
891 } else {
892 RETURN_FAIL("WriteFile() failed");
893 }
894 } else {
895 DEBUG("Write completed immediately");
896 RETURN_VALUE("%d", count);
897 }
898#else
899 size_t bytes_written = 0;
900 unsigned char *ptr = (unsigned char *) buf;
901 struct timeval start, delta, now, end = {0, 0};
902 fd_set fds;
903 int result;
904
905 if (timeout) {
906 /* Get time at start of operation. */
907 gettimeofday(&start, NULL);
908 /* Define duration of timeout. */
909 delta.tv_sec = timeout / 1000;
910 delta.tv_usec = (timeout % 1000) * 1000;
911 /* Calculate time at which we should give up. */
912 timeradd(&start, &delta, &end);
913 }
914
915 /* Loop until we have written the requested number of bytes. */
916 while (bytes_written < count)
917 {
918 /* Wait until space is available. */
919 FD_ZERO(&fds);
920 FD_SET(port->fd, &fds);
921 if (timeout) {
922 gettimeofday(&now, NULL);
923 if (timercmp(&now, &end, >)) {
924 DEBUG("write timed out");
925 RETURN_VALUE("%d", bytes_written);
926 }
927 timersub(&end, &now, &delta);
928 }
929 result = select(port->fd + 1, NULL, &fds, NULL, timeout ? &delta : NULL);
930 if (result < 0) {
931 if (errno == EINTR) {
932 DEBUG("select() call was interrupted, repeating");
933 continue;
934 } else {
935 RETURN_FAIL("select() failed");
936 }
937 } else if (result == 0) {
938 DEBUG("write timed out");
939 RETURN_VALUE("%d", bytes_written);
940 }
941
942 /* Do write. */
943 result = write(port->fd, ptr, count - bytes_written);
944
945 if (result < 0) {
946 if (errno == EAGAIN)
947 /* This shouldn't happen because we did a select() first, but handle anyway. */
948 continue;
949 else
950 /* This is an actual failure. */
951 RETURN_FAIL("write() failed");
952 }
953
954 bytes_written += result;
955 ptr += result;
956 }
957
958 RETURN_VALUE("%d", bytes_written);
959#endif
960}
961
962enum sp_return sp_nonblocking_write(struct sp_port *port, const void *buf, size_t count)
963{
964 TRACE("%p, %p, %d", port, buf, count);
965
966 CHECK_OPEN_PORT();
967
968 if (!buf)
969 RETURN_ERROR(SP_ERR_ARG, "Null buffer");
970
971 DEBUG("Writing up to %d bytes to port %s", count, port->name);
972
973 if (count == 0)
974 RETURN_VALUE("0", 0);
975
976#ifdef _WIN32
977 DWORD written = 0;
978 BYTE *ptr = (BYTE *) buf;
979
980 /* Check whether previous write is complete. */
981 if (port->writing) {
982 if (HasOverlappedIoCompleted(&port->write_ovl)) {
983 DEBUG("Previous write completed");
984 port->writing = 0;
985 } else {
986 DEBUG("Previous write not complete");
987 /* Can't take a new write until the previous one finishes. */
988 RETURN_VALUE("0", 0);
989 }
990 }
991
992 /* Set timeout. */
993 port->timeouts.WriteTotalTimeoutConstant = 0;
994 if (SetCommTimeouts(port->hdl, &port->timeouts) == 0)
995 RETURN_FAIL("SetCommTimeouts() failed");
996
997 /* Keep writing data until the OS has to actually start an async IO for it.
998 * At that point we know the buffer is full. */
999 while (written < count)
1000 {
1001 /* Copy first byte of user buffer. */
1002 port->pending_byte = *ptr++;
1003
1004 /* Start asynchronous write. */
1005 if (WriteFile(port->hdl, &port->pending_byte, 1, NULL, &port->write_ovl) == 0) {
1006 if (GetLastError() == ERROR_IO_PENDING) {
1007 if (HasOverlappedIoCompleted(&port->write_ovl)) {
1008 DEBUG("Asynchronous write completed immediately");
1009 port->writing = 0;
1010 written++;
1011 continue;
1012 } else {
1013 DEBUG("Asynchronous write running");
1014 port->writing = 1;
1015 RETURN_VALUE("%d", ++written);
1016 }
1017 } else {
1018 /* Actual failure of some kind. */
1019 RETURN_FAIL("WriteFile() failed");
1020 }
1021 } else {
1022 DEBUG("Single byte written immediately");
1023 written++;
1024 }
1025 }
1026
1027 DEBUG("All bytes written immediately");
1028
1029 RETURN_VALUE("%d", written);
1030#else
1031 /* Returns the number of bytes written, or -1 upon failure. */
1032 ssize_t written = write(port->fd, buf, count);
1033
1034 if (written < 0)
1035 RETURN_FAIL("write() failed");
1036 else
1037 RETURN_VALUE("%d", written);
1038#endif
1039}
1040
1041enum sp_return sp_blocking_read(struct sp_port *port, void *buf, size_t count, unsigned int timeout)
1042{
1043 TRACE("%p, %p, %d, %d", port, buf, count, timeout);
1044
1045 CHECK_OPEN_PORT();
1046
1047 if (!buf)
1048 RETURN_ERROR(SP_ERR_ARG, "Null buffer");
1049
1050 if (timeout)
1051 DEBUG("Reading %d bytes from port %s, timeout %d ms", count, port->name, timeout);
1052 else
1053 DEBUG("Reading %d bytes from port %s, no timeout", count, port->name);
1054
1055 if (count == 0)
1056 RETURN_VALUE("0", 0);
1057
1058#ifdef _WIN32
1059 DWORD bytes_read = 0;
1060
1061 /* Set timeout. */
1062 port->timeouts.ReadIntervalTimeout = 0;
1063 port->timeouts.ReadTotalTimeoutConstant = timeout;
1064 if (SetCommTimeouts(port->hdl, &port->timeouts) == 0)
1065 RETURN_FAIL("SetCommTimeouts() failed");
1066
1067 /* Start read. */
1068 if (ReadFile(port->hdl, buf, count, NULL, &port->read_ovl) == 0) {
1069 if (GetLastError() == ERROR_IO_PENDING) {
1070 DEBUG("Waiting for read to complete");
1071 GetOverlappedResult(port->hdl, &port->read_ovl, &bytes_read, TRUE);
1072 DEBUG("Read completed, %d/%d bytes read", bytes_read, count);
1073 } else {
1074 RETURN_FAIL("ReadFile() failed");
1075 }
1076 } else {
1077 DEBUG("Read completed immediately");
1078 bytes_read = count;
1079 }
1080
1081 /* Start background operation for subsequent events. */
1082 if (WaitCommEvent(port->hdl, &port->events, &port->wait_ovl) == 0) {
1083 if (GetLastError() != ERROR_IO_PENDING)
1084 RETURN_FAIL("WaitCommEvent() failed");
1085 }
1086
1087 RETURN_VALUE("%d", bytes_read);
1088
1089#else
1090 size_t bytes_read = 0;
1091 unsigned char *ptr = (unsigned char *) buf;
1092 struct timeval start, delta, now, end = {0, 0};
1093 fd_set fds;
1094 int result;
1095
1096 if (timeout) {
1097 /* Get time at start of operation. */
1098 gettimeofday(&start, NULL);
1099 /* Define duration of timeout. */
1100 delta.tv_sec = timeout / 1000;
1101 delta.tv_usec = (timeout % 1000) * 1000;
1102 /* Calculate time at which we should give up. */
1103 timeradd(&start, &delta, &end);
1104 }
1105
1106 /* Loop until we have the requested number of bytes. */
1107 while (bytes_read < count)
1108 {
1109 /* Wait until data is available. */
1110 FD_ZERO(&fds);
1111 FD_SET(port->fd, &fds);
1112 if (timeout) {
1113 gettimeofday(&now, NULL);
1114 if (timercmp(&now, &end, >))
1115 /* Timeout has expired. */
1116 RETURN_VALUE("%d", bytes_read);
1117 timersub(&end, &now, &delta);
1118 }
1119 result = select(port->fd + 1, &fds, NULL, NULL, timeout ? &delta : NULL);
1120 if (result < 0) {
1121 if (errno == EINTR) {
1122 DEBUG("select() call was interrupted, repeating");
1123 continue;
1124 } else {
1125 RETURN_FAIL("select() failed");
1126 }
1127 } else if (result == 0) {
1128 DEBUG("read timed out");
1129 RETURN_VALUE("%d", bytes_read);
1130 }
1131
1132 /* Do read. */
1133 result = read(port->fd, ptr, count - bytes_read);
1134
1135 if (result < 0) {
1136 if (errno == EAGAIN)
1137 /* This shouldn't happen because we did a select() first, but handle anyway. */
1138 continue;
1139 else
1140 /* This is an actual failure. */
1141 RETURN_FAIL("read() failed");
1142 }
1143
1144 bytes_read += result;
1145 ptr += result;
1146 }
1147
1148 RETURN_VALUE("%d", bytes_read);
1149#endif
1150}
1151
1152enum sp_return sp_nonblocking_read(struct sp_port *port, void *buf, size_t count)
1153{
1154 TRACE("%p, %p, %d", port, buf, count);
1155
1156 CHECK_OPEN_PORT();
1157
1158 if (!buf)
1159 RETURN_ERROR(SP_ERR_ARG, "Null buffer");
1160
1161 DEBUG("Reading up to %d bytes from port %s", count, port->name);
1162
1163#ifdef _WIN32
1164 DWORD bytes_read;
1165
1166 /* Set timeout. */
1167 port->timeouts.ReadIntervalTimeout = MAXDWORD;
1168 port->timeouts.ReadTotalTimeoutConstant = 0;
1169 if (SetCommTimeouts(port->hdl, &port->timeouts) == 0)
1170 RETURN_FAIL("SetCommTimeouts() failed");
1171
1172 /* Do read. */
1173 if (ReadFile(port->hdl, buf, count, NULL, &port->read_ovl) == 0)
1174 RETURN_FAIL("ReadFile() failed");
1175
1176 /* Get number of bytes read. */
1177 if (GetOverlappedResult(port->hdl, &port->read_ovl, &bytes_read, TRUE) == 0)
1178 RETURN_FAIL("GetOverlappedResult() failed");
1179
1180 if (bytes_read > 0) {
1181 /* Start background operation for subsequent events. */
1182 if (WaitCommEvent(port->hdl, &port->events, &port->wait_ovl) == 0) {
1183 if (GetLastError() != ERROR_IO_PENDING)
1184 RETURN_FAIL("WaitCommEvent() failed");
1185 }
1186 }
1187
1188 RETURN_VALUE("%d", bytes_read);
1189#else
1190 ssize_t bytes_read;
1191
1192 /* Returns the number of bytes read, or -1 upon failure. */
1193 if ((bytes_read = read(port->fd, buf, count)) < 0) {
1194 if (errno == EAGAIN)
1195 /* No bytes available. */
1196 bytes_read = 0;
1197 else
1198 /* This is an actual failure. */
1199 RETURN_FAIL("read() failed");
1200 }
1201 RETURN_VALUE("%d", bytes_read);
1202#endif
1203}
1204
1205enum sp_return sp_input_waiting(struct sp_port *port)
1206{
1207 TRACE("%p", port);
1208
1209 CHECK_OPEN_PORT();
1210
1211 DEBUG("Checking input bytes waiting on port %s", port->name);
1212
1213#ifdef _WIN32
1214 DWORD errors;
1215 COMSTAT comstat;
1216
1217 if (ClearCommError(port->hdl, &errors, &comstat) == 0)
1218 RETURN_FAIL("ClearCommError() failed");
1219 RETURN_VALUE("%d", comstat.cbInQue);
1220#else
1221 int bytes_waiting;
1222 if (ioctl(port->fd, TIOCINQ, &bytes_waiting) < 0)
1223 RETURN_FAIL("TIOCINQ ioctl failed");
1224 RETURN_VALUE("%d", bytes_waiting);
1225#endif
1226}
1227
1228enum sp_return sp_output_waiting(struct sp_port *port)
1229{
1230 TRACE("%p", port);
1231
1232 CHECK_OPEN_PORT();
1233
1234 DEBUG("Checking output bytes waiting on port %s", port->name);
1235
1236#ifdef _WIN32
1237 DWORD errors;
1238 COMSTAT comstat;
1239
1240 if (ClearCommError(port->hdl, &errors, &comstat) == 0)
1241 RETURN_FAIL("ClearCommError() failed");
1242 RETURN_VALUE("%d", comstat.cbOutQue);
1243#else
1244 int bytes_waiting;
1245 if (ioctl(port->fd, TIOCOUTQ, &bytes_waiting) < 0)
1246 RETURN_FAIL("TIOCOUTQ ioctl failed");
1247 RETURN_VALUE("%d", bytes_waiting);
1248#endif
1249}
1250
1251enum sp_return sp_new_event_set(struct sp_event_set **result_ptr)
1252{
1253 struct sp_event_set *result;
1254
1255 TRACE("%p", result_ptr);
1256
1257 if (!result_ptr)
1258 RETURN_ERROR(SP_ERR_ARG, "Null result");
1259
1260 *result_ptr = NULL;
1261
1262 if (!(result = malloc(sizeof(struct sp_event_set))))
1263 RETURN_ERROR(SP_ERR_MEM, "sp_event_set malloc() failed");
1264
1265 memset(result, 0, sizeof(struct sp_event_set));
1266
1267 *result_ptr = result;
1268
1269 RETURN_OK();
1270}
1271
1272static enum sp_return add_handle(struct sp_event_set *event_set,
1273 event_handle handle, enum sp_event mask)
1274{
1275 void *new_handles;
1276 enum sp_event *new_masks;
1277
1278 TRACE("%p, %d, %d", event_set, handle, mask);
1279
1280 if (!(new_handles = realloc(event_set->handles,
1281 sizeof(event_handle) * (event_set->count + 1))))
1282 RETURN_ERROR(SP_ERR_MEM, "handle array realloc() failed");
1283
1284 if (!(new_masks = realloc(event_set->masks,
1285 sizeof(enum sp_event) * (event_set->count + 1))))
1286 RETURN_ERROR(SP_ERR_MEM, "mask array realloc() failed");
1287
1288 event_set->handles = new_handles;
1289 event_set->masks = new_masks;
1290
1291 ((event_handle *) event_set->handles)[event_set->count] = handle;
1292 event_set->masks[event_set->count] = mask;
1293
1294 event_set->count++;
1295
1296 RETURN_OK();
1297}
1298
1299enum sp_return sp_add_port_events(struct sp_event_set *event_set,
1300 const struct sp_port *port, enum sp_event mask)
1301{
1302 TRACE("%p, %p, %d", event_set, port, mask);
1303
1304 if (!event_set)
1305 RETURN_ERROR(SP_ERR_ARG, "Null event set");
1306
1307 if (!port)
1308 RETURN_ERROR(SP_ERR_ARG, "Null port");
1309
1310 if (mask > (SP_EVENT_RX_READY | SP_EVENT_TX_READY | SP_EVENT_ERROR))
1311 RETURN_ERROR(SP_ERR_ARG, "Invalid event mask");
1312
1313 if (!mask)
1314 RETURN_OK();
1315
1316#ifdef _WIN32
1317 enum sp_event handle_mask;
1318 if ((handle_mask = mask & SP_EVENT_TX_READY))
1319 TRY(add_handle(event_set, port->write_ovl.hEvent, handle_mask));
1320 if ((handle_mask = mask & (SP_EVENT_RX_READY | SP_EVENT_ERROR)))
1321 TRY(add_handle(event_set, port->wait_ovl.hEvent, handle_mask));
1322#else
1323 TRY(add_handle(event_set, port->fd, mask));
1324#endif
1325
1326 RETURN_OK();
1327}
1328
1329void sp_free_event_set(struct sp_event_set *event_set)
1330{
1331 TRACE("%p", event_set);
1332
1333 if (!event_set) {
1334 DEBUG("Null event set");
1335 RETURN();
1336 }
1337
1338 DEBUG("Freeing event set");
1339
1340 if (event_set->handles)
1341 free(event_set->handles);
1342 if (event_set->masks)
1343 free(event_set->masks);
1344
1345 free(event_set);
1346
1347 RETURN();
1348}
1349
1350enum sp_return sp_wait(struct sp_event_set *event_set, unsigned int timeout)
1351{
1352 TRACE("%p, %d", event_set, timeout);
1353
1354 if (!event_set)
1355 RETURN_ERROR(SP_ERR_ARG, "Null event set");
1356
1357#ifdef _WIN32
1358 if (WaitForMultipleObjects(event_set->count, event_set->handles, FALSE,
1359 timeout ? timeout : INFINITE) == WAIT_FAILED)
1360 RETURN_FAIL("WaitForMultipleObjects() failed");
1361
1362 RETURN_OK();
1363#else
1364 struct timeval start, delta, now, end = {0, 0};
1365 int result, timeout_remaining;
1366 struct pollfd *pollfds;
1367 unsigned int i;
1368
1369 if (!(pollfds = malloc(sizeof(struct pollfd) * event_set->count)))
1370 RETURN_ERROR(SP_ERR_MEM, "pollfds malloc() failed");
1371
1372 for (i = 0; i < event_set->count; i++) {
1373 pollfds[i].fd = ((int *) event_set->handles)[i];
1374 pollfds[i].events = 0;
1375 pollfds[i].revents = 0;
1376 if (event_set->masks[i] & SP_EVENT_RX_READY)
1377 pollfds[i].events |= POLLIN;
1378 if (event_set->masks[i] & SP_EVENT_TX_READY)
1379 pollfds[i].events |= POLLOUT;
1380 if (event_set->masks[i] & SP_EVENT_ERROR)
1381 pollfds[i].events |= POLLERR;
1382 }
1383
1384 if (timeout) {
1385 /* Get time at start of operation. */
1386 gettimeofday(&start, NULL);
1387 /* Define duration of timeout. */
1388 delta.tv_sec = timeout / 1000;
1389 delta.tv_usec = (timeout % 1000) * 1000;
1390 /* Calculate time at which we should give up. */
1391 timeradd(&start, &delta, &end);
1392 }
1393
1394 /* Loop until an event occurs. */
1395 while (1)
1396 {
1397 if (timeout) {
1398 gettimeofday(&now, NULL);
1399 if (timercmp(&now, &end, >)) {
1400 DEBUG("wait timed out");
1401 break;
1402 }
1403 timersub(&end, &now, &delta);
1404 timeout_remaining = delta.tv_sec * 1000 + delta.tv_usec / 1000;
1405 }
1406
1407 result = poll(pollfds, event_set->count, timeout ? timeout_remaining : -1);
1408
1409 if (result < 0) {
1410 if (errno == EINTR) {
1411 DEBUG("poll() call was interrupted, repeating");
1412 continue;
1413 } else {
1414 free(pollfds);
1415 RETURN_FAIL("poll() failed");
1416 }
1417 } else if (result == 0) {
1418 DEBUG("poll() timed out");
1419 break;
1420 } else {
1421 DEBUG("poll() completed");
1422 break;
1423 }
1424 }
1425
1426 free(pollfds);
1427 RETURN_OK();
1428#endif
1429}
1430
1431#ifdef USE_TERMIOS_SPEED
1432static enum sp_return get_baudrate(int fd, int *baudrate)
1433{
1434 void *data;
1435
1436 TRACE("%d, %p", fd, baudrate);
1437
1438 DEBUG("Getting baud rate");
1439
1440 if (!(data = malloc(get_termios_size())))
1441 RETURN_ERROR(SP_ERR_MEM, "termios malloc failed");
1442
1443 if (ioctl(fd, get_termios_get_ioctl(), data) < 0) {
1444 free(data);
1445 RETURN_FAIL("getting termios failed");
1446 }
1447
1448 *baudrate = get_termios_speed(data);
1449
1450 free(data);
1451
1452 RETURN_OK();
1453}
1454
1455static enum sp_return set_baudrate(int fd, int baudrate)
1456{
1457 void *data;
1458
1459 TRACE("%d, %d", fd, baudrate);
1460
1461 DEBUG("Getting baud rate");
1462
1463 if (!(data = malloc(get_termios_size())))
1464 RETURN_ERROR(SP_ERR_MEM, "termios malloc failed");
1465
1466 if (ioctl(fd, get_termios_get_ioctl(), data) < 0) {
1467 free(data);
1468 RETURN_FAIL("getting termios failed");
1469 }
1470
1471 DEBUG("Setting baud rate");
1472
1473 set_termios_speed(data, baudrate);
1474
1475 if (ioctl(fd, get_termios_set_ioctl(), data) < 0) {
1476 free(data);
1477 RETURN_FAIL("setting termios failed");
1478 }
1479
1480 free(data);
1481
1482 RETURN_OK();
1483}
1484#endif /* USE_TERMIOS_SPEED */
1485
1486#ifdef USE_TERMIOX
1487static enum sp_return get_flow(int fd, struct port_data *data)
1488{
1489 void *termx;
1490
1491 TRACE("%d, %p", fd, data);
1492
1493 DEBUG("Getting advanced flow control");
1494
1495 if (!(termx = malloc(get_termiox_size())))
1496 RETURN_ERROR(SP_ERR_MEM, "termiox malloc failed");
1497
1498 if (ioctl(fd, TCGETX, termx) < 0) {
1499 free(termx);
1500 RETURN_FAIL("getting termiox failed");
1501 }
1502
1503 get_termiox_flow(termx, &data->rts_flow, &data->cts_flow,
1504 &data->dtr_flow, &data->dsr_flow);
1505
1506 free(termx);
1507
1508 RETURN_OK();
1509}
1510
1511static enum sp_return set_flow(int fd, struct port_data *data)
1512{
1513 void *termx;
1514
1515 TRACE("%d, %p", fd, data);
1516
1517 DEBUG("Getting advanced flow control");
1518
1519 if (!(termx = malloc(get_termiox_size())))
1520 RETURN_ERROR(SP_ERR_MEM, "termiox malloc failed");
1521
1522 if (ioctl(fd, TCGETX, termx) < 0) {
1523 free(termx);
1524 RETURN_FAIL("getting termiox failed");
1525 }
1526
1527 DEBUG("Setting advanced flow control");
1528
1529 set_termiox_flow(termx, data->rts_flow, data->cts_flow,
1530 data->dtr_flow, data->dsr_flow);
1531
1532 if (ioctl(fd, TCSETX, termx) < 0) {
1533 free(termx);
1534 RETURN_FAIL("setting termiox failed");
1535 }
1536
1537 free(termx);
1538
1539 RETURN_OK();
1540}
1541#endif /* USE_TERMIOX */
1542
1543static enum sp_return get_config(struct sp_port *port, struct port_data *data,
1544 struct sp_port_config *config)
1545{
1546 unsigned int i;
1547
1548 TRACE("%p, %p, %p", port, data, config);
1549
1550 DEBUG("Getting configuration for port %s", port->name);
1551
1552#ifdef _WIN32
1553 if (!GetCommState(port->hdl, &data->dcb))
1554 RETURN_FAIL("GetCommState() failed");
1555
1556 for (i = 0; i < NUM_STD_BAUDRATES; i++) {
1557 if (data->dcb.BaudRate == std_baudrates[i].index) {
1558 config->baudrate = std_baudrates[i].value;
1559 break;
1560 }
1561 }
1562
1563 if (i == NUM_STD_BAUDRATES)
1564 /* BaudRate field can be either an index or a custom baud rate. */
1565 config->baudrate = data->dcb.BaudRate;
1566
1567 config->bits = data->dcb.ByteSize;
1568
1569 if (data->dcb.fParity)
1570 switch (data->dcb.Parity) {
1571 case NOPARITY:
1572 config->parity = SP_PARITY_NONE;
1573 break;
1574 case ODDPARITY:
1575 config->parity = SP_PARITY_ODD;
1576 break;
1577 case EVENPARITY:
1578 config->parity = SP_PARITY_EVEN;
1579 break;
1580 case MARKPARITY:
1581 config->parity = SP_PARITY_MARK;
1582 break;
1583 case SPACEPARITY:
1584 config->parity = SP_PARITY_SPACE;
1585 break;
1586 default:
1587 config->parity = -1;
1588 }
1589 else
1590 config->parity = SP_PARITY_NONE;
1591
1592 switch (data->dcb.StopBits) {
1593 case ONESTOPBIT:
1594 config->stopbits = 1;
1595 break;
1596 case TWOSTOPBITS:
1597 config->stopbits = 2;
1598 break;
1599 default:
1600 config->stopbits = -1;
1601 }
1602
1603 switch (data->dcb.fRtsControl) {
1604 case RTS_CONTROL_DISABLE:
1605 config->rts = SP_RTS_OFF;
1606 break;
1607 case RTS_CONTROL_ENABLE:
1608 config->rts = SP_RTS_ON;
1609 break;
1610 case RTS_CONTROL_HANDSHAKE:
1611 config->rts = SP_RTS_FLOW_CONTROL;
1612 break;
1613 default:
1614 config->rts = -1;
1615 }
1616
1617 config->cts = data->dcb.fOutxCtsFlow ? SP_CTS_FLOW_CONTROL : SP_CTS_IGNORE;
1618
1619 switch (data->dcb.fDtrControl) {
1620 case DTR_CONTROL_DISABLE:
1621 config->dtr = SP_DTR_OFF;
1622 break;
1623 case DTR_CONTROL_ENABLE:
1624 config->dtr = SP_DTR_ON;
1625 break;
1626 case DTR_CONTROL_HANDSHAKE:
1627 config->dtr = SP_DTR_FLOW_CONTROL;
1628 break;
1629 default:
1630 config->dtr = -1;
1631 }
1632
1633 config->dsr = data->dcb.fOutxDsrFlow ? SP_DSR_FLOW_CONTROL : SP_DSR_IGNORE;
1634
1635 if (data->dcb.fInX) {
1636 if (data->dcb.fOutX)
1637 config->xon_xoff = SP_XONXOFF_INOUT;
1638 else
1639 config->xon_xoff = SP_XONXOFF_IN;
1640 } else {
1641 if (data->dcb.fOutX)
1642 config->xon_xoff = SP_XONXOFF_OUT;
1643 else
1644 config->xon_xoff = SP_XONXOFF_DISABLED;
1645 }
1646
1647#else // !_WIN32
1648
1649 if (tcgetattr(port->fd, &data->term) < 0)
1650 RETURN_FAIL("tcgetattr() failed");
1651
1652 if (ioctl(port->fd, TIOCMGET, &data->controlbits) < 0)
1653 RETURN_FAIL("TIOCMGET ioctl failed");
1654
1655#ifdef USE_TERMIOX
1656 int ret = get_flow(port->fd, data);
1657
1658 if (ret == SP_ERR_FAIL && errno == EINVAL)
1659 data->termiox_supported = 0;
1660 else if (ret < 0)
1661 RETURN_CODEVAL(ret);
1662 else
1663 data->termiox_supported = 1;
1664#else
1665 data->termiox_supported = 0;
1666#endif
1667
1668 for (i = 0; i < NUM_STD_BAUDRATES; i++) {
1669 if (cfgetispeed(&data->term) == std_baudrates[i].index) {
1670 config->baudrate = std_baudrates[i].value;
1671 break;
1672 }
1673 }
1674
1675 if (i == NUM_STD_BAUDRATES) {
1676#ifdef __APPLE__
1677 config->baudrate = (int)data->term.c_ispeed;
1678#elif defined(USE_TERMIOS_SPEED)
1679 TRY(get_baudrate(port->fd, &config->baudrate));
1680#else
1681 config->baudrate = -1;
1682#endif
1683 }
1684
1685 switch (data->term.c_cflag & CSIZE) {
1686 case CS8:
1687 config->bits = 8;
1688 break;
1689 case CS7:
1690 config->bits = 7;
1691 break;
1692 case CS6:
1693 config->bits = 6;
1694 break;
1695 case CS5:
1696 config->bits = 5;
1697 break;
1698 default:
1699 config->bits = -1;
1700 }
1701
1702 if (!(data->term.c_cflag & PARENB) && (data->term.c_iflag & IGNPAR))
1703 config->parity = SP_PARITY_NONE;
1704 else if (!(data->term.c_cflag & PARENB) || (data->term.c_iflag & IGNPAR))
1705 config->parity = -1;
1706#ifdef CMSPAR
1707 else if (data->term.c_cflag & CMSPAR)
1708 config->parity = (data->term.c_cflag & PARODD) ? SP_PARITY_MARK : SP_PARITY_SPACE;
1709#endif
1710 else
1711 config->parity = (data->term.c_cflag & PARODD) ? SP_PARITY_ODD : SP_PARITY_EVEN;
1712
1713 config->stopbits = (data->term.c_cflag & CSTOPB) ? 2 : 1;
1714
1715 if (data->term.c_cflag & CRTSCTS) {
1716 config->rts = SP_RTS_FLOW_CONTROL;
1717 config->cts = SP_CTS_FLOW_CONTROL;
1718 } else {
1719 if (data->termiox_supported && data->rts_flow)
1720 config->rts = SP_RTS_FLOW_CONTROL;
1721 else
1722 config->rts = (data->controlbits & TIOCM_RTS) ? SP_RTS_ON : SP_RTS_OFF;
1723
1724 config->cts = (data->termiox_supported && data->cts_flow) ?
1725 SP_CTS_FLOW_CONTROL : SP_CTS_IGNORE;
1726 }
1727
1728 if (data->termiox_supported && data->dtr_flow)
1729 config->dtr = SP_DTR_FLOW_CONTROL;
1730 else
1731 config->dtr = (data->controlbits & TIOCM_DTR) ? SP_DTR_ON : SP_DTR_OFF;
1732
1733 config->dsr = (data->termiox_supported && data->dsr_flow) ?
1734 SP_DSR_FLOW_CONTROL : SP_DSR_IGNORE;
1735
1736 if (data->term.c_iflag & IXOFF) {
1737 if (data->term.c_iflag & IXON)
1738 config->xon_xoff = SP_XONXOFF_INOUT;
1739 else
1740 config->xon_xoff = SP_XONXOFF_IN;
1741 } else {
1742 if (data->term.c_iflag & IXON)
1743 config->xon_xoff = SP_XONXOFF_OUT;
1744 else
1745 config->xon_xoff = SP_XONXOFF_DISABLED;
1746 }
1747#endif
1748
1749 RETURN_OK();
1750}
1751
1752static enum sp_return set_config(struct sp_port *port, struct port_data *data,
1753 const struct sp_port_config *config)
1754{
1755 unsigned int i;
1756#ifdef __APPLE__
1757 BAUD_TYPE baud_nonstd;
1758
1759 baud_nonstd = B0;
1760#endif
1761#ifdef USE_TERMIOS_SPEED
1762 int baud_nonstd = 0;
1763#endif
1764
1765 TRACE("%p, %p, %p", port, data, config);
1766
1767 DEBUG("Setting configuration for port %s", port->name);
1768
1769#ifdef _WIN32
1770 if (config->baudrate >= 0) {
1771 for (i = 0; i < NUM_STD_BAUDRATES; i++) {
1772 if (config->baudrate == std_baudrates[i].value) {
1773 data->dcb.BaudRate = std_baudrates[i].index;
1774 break;
1775 }
1776 }
1777
1778 if (i == NUM_STD_BAUDRATES)
1779 data->dcb.BaudRate = config->baudrate;
1780 }
1781
1782 if (config->bits >= 0)
1783 data->dcb.ByteSize = config->bits;
1784
1785 if (config->parity >= 0) {
1786 switch (config->parity) {
1787 case SP_PARITY_NONE:
1788 data->dcb.Parity = NOPARITY;
1789 break;
1790 case SP_PARITY_ODD:
1791 data->dcb.Parity = ODDPARITY;
1792 break;
1793 case SP_PARITY_EVEN:
1794 data->dcb.Parity = EVENPARITY;
1795 break;
1796 case SP_PARITY_MARK:
1797 data->dcb.Parity = MARKPARITY;
1798 break;
1799 case SP_PARITY_SPACE:
1800 data->dcb.Parity = SPACEPARITY;
1801 break;
1802 default:
1803 RETURN_ERROR(SP_ERR_ARG, "Invalid parity setting");
1804 }
1805 }
1806
1807 if (config->stopbits >= 0) {
1808 switch (config->stopbits) {
1809 /* Note: There's also ONE5STOPBITS == 1.5 (unneeded so far). */
1810 case 1:
1811 data->dcb.StopBits = ONESTOPBIT;
1812 break;
1813 case 2:
1814 data->dcb.StopBits = TWOSTOPBITS;
1815 break;
1816 default:
1817 RETURN_ERROR(SP_ERR_ARG, "Invalid stop bit setting");
1818 }
1819 }
1820
1821 if (config->rts >= 0) {
1822 switch (config->rts) {
1823 case SP_RTS_OFF:
1824 data->dcb.fRtsControl = RTS_CONTROL_DISABLE;
1825 break;
1826 case SP_RTS_ON:
1827 data->dcb.fRtsControl = RTS_CONTROL_ENABLE;
1828 break;
1829 case SP_RTS_FLOW_CONTROL:
1830 data->dcb.fRtsControl = RTS_CONTROL_HANDSHAKE;
1831 break;
1832 default:
1833 RETURN_ERROR(SP_ERR_ARG, "Invalid RTS setting");
1834 }
1835 }
1836
1837 if (config->cts >= 0) {
1838 switch (config->cts) {
1839 case SP_CTS_IGNORE:
1840 data->dcb.fOutxCtsFlow = FALSE;
1841 break;
1842 case SP_CTS_FLOW_CONTROL:
1843 data->dcb.fOutxCtsFlow = TRUE;
1844 break;
1845 default:
1846 RETURN_ERROR(SP_ERR_ARG, "Invalid CTS setting");
1847 }
1848 }
1849
1850 if (config->dtr >= 0) {
1851 switch (config->dtr) {
1852 case SP_DTR_OFF:
1853 data->dcb.fDtrControl = DTR_CONTROL_DISABLE;
1854 break;
1855 case SP_DTR_ON:
1856 data->dcb.fDtrControl = DTR_CONTROL_ENABLE;
1857 break;
1858 case SP_DTR_FLOW_CONTROL:
1859 data->dcb.fDtrControl = DTR_CONTROL_HANDSHAKE;
1860 break;
1861 default:
1862 RETURN_ERROR(SP_ERR_ARG, "Invalid DTR setting");
1863 }
1864 }
1865
1866 if (config->dsr >= 0) {
1867 switch (config->dsr) {
1868 case SP_DSR_IGNORE:
1869 data->dcb.fOutxDsrFlow = FALSE;
1870 break;
1871 case SP_DSR_FLOW_CONTROL:
1872 data->dcb.fOutxDsrFlow = TRUE;
1873 break;
1874 default:
1875 RETURN_ERROR(SP_ERR_ARG, "Invalid DSR setting");
1876 }
1877 }
1878
1879 if (config->xon_xoff >= 0) {
1880 switch (config->xon_xoff) {
1881 case SP_XONXOFF_DISABLED:
1882 data->dcb.fInX = FALSE;
1883 data->dcb.fOutX = FALSE;
1884 break;
1885 case SP_XONXOFF_IN:
1886 data->dcb.fInX = TRUE;
1887 data->dcb.fOutX = FALSE;
1888 break;
1889 case SP_XONXOFF_OUT:
1890 data->dcb.fInX = FALSE;
1891 data->dcb.fOutX = TRUE;
1892 break;
1893 case SP_XONXOFF_INOUT:
1894 data->dcb.fInX = TRUE;
1895 data->dcb.fOutX = TRUE;
1896 break;
1897 default:
1898 RETURN_ERROR(SP_ERR_ARG, "Invalid XON/XOFF setting");
1899 }
1900 }
1901
1902 if (!SetCommState(port->hdl, &data->dcb))
1903 RETURN_FAIL("SetCommState() failed");
1904
1905#else /* !_WIN32 */
1906
1907 int controlbits;
1908
1909 if (config->baudrate >= 0) {
1910 for (i = 0; i < NUM_STD_BAUDRATES; i++) {
1911 if (config->baudrate == std_baudrates[i].value) {
1912 if (cfsetospeed(&data->term, std_baudrates[i].index) < 0)
1913 RETURN_FAIL("cfsetospeed() failed");
1914
1915 if (cfsetispeed(&data->term, std_baudrates[i].index) < 0)
1916 RETURN_FAIL("cfsetispeed() failed");
1917 break;
1918 }
1919 }
1920
1921 /* Non-standard baud rate */
1922 if (i == NUM_STD_BAUDRATES) {
1923#ifdef __APPLE__
1924 /* Set "dummy" baud rate. */
1925 if (cfsetspeed(&data->term, B9600) < 0)
1926 RETURN_FAIL("cfsetspeed() failed");
1927 baud_nonstd = config->baudrate;
1928#elif defined(USE_TERMIOS_SPEED)
1929 baud_nonstd = 1;
1930#else
1931 RETURN_ERROR(SP_ERR_SUPP, "Non-standard baudrate not supported");
1932#endif
1933 }
1934 }
1935
1936 if (config->bits >= 0) {
1937 data->term.c_cflag &= ~CSIZE;
1938 switch (config->bits) {
1939 case 8:
1940 data->term.c_cflag |= CS8;
1941 break;
1942 case 7:
1943 data->term.c_cflag |= CS7;
1944 break;
1945 case 6:
1946 data->term.c_cflag |= CS6;
1947 break;
1948 case 5:
1949 data->term.c_cflag |= CS5;
1950 break;
1951 default:
1952 RETURN_ERROR(SP_ERR_ARG, "Invalid data bits setting");
1953 }
1954 }
1955
1956 if (config->parity >= 0) {
1957 data->term.c_iflag &= ~IGNPAR;
1958 data->term.c_cflag &= ~(PARENB | PARODD);
1959#ifdef CMSPAR
1960 data->term.c_cflag &= ~CMSPAR;
1961#endif
1962 switch (config->parity) {
1963 case SP_PARITY_NONE:
1964 data->term.c_iflag |= IGNPAR;
1965 break;
1966 case SP_PARITY_EVEN:
1967 data->term.c_cflag |= PARENB;
1968 break;
1969 case SP_PARITY_ODD:
1970 data->term.c_cflag |= PARENB | PARODD;
1971 break;
1972#ifdef CMSPAR
1973 case SP_PARITY_MARK:
1974 data->term.c_cflag |= PARENB | PARODD;
1975 data->term.c_cflag |= CMSPAR;
1976 break;
1977 case SP_PARITY_SPACE:
1978 data->term.c_cflag |= PARENB;
1979 data->term.c_cflag |= CMSPAR;
1980 break;
1981#else
1982 case SP_PARITY_MARK:
1983 case SP_PARITY_SPACE:
1984 RETURN_ERROR(SP_ERR_SUPP, "Mark/space parity not supported");
1985#endif
1986 default:
1987 RETURN_ERROR(SP_ERR_ARG, "Invalid parity setting");
1988 }
1989 }
1990
1991 if (config->stopbits >= 0) {
1992 data->term.c_cflag &= ~CSTOPB;
1993 switch (config->stopbits) {
1994 case 1:
1995 data->term.c_cflag &= ~CSTOPB;
1996 break;
1997 case 2:
1998 data->term.c_cflag |= CSTOPB;
1999 break;
2000 default:
2001 RETURN_ERROR(SP_ERR_ARG, "Invalid stop bits setting");
2002 }
2003 }
2004
2005 if (config->rts >= 0 || config->cts >= 0) {
2006 if (data->termiox_supported) {
2007 data->rts_flow = data->cts_flow = 0;
2008 switch (config->rts) {
2009 case SP_RTS_OFF:
2010 case SP_RTS_ON:
2011 controlbits = TIOCM_RTS;
2012 if (ioctl(port->fd, config->rts == SP_RTS_ON ? TIOCMBIS : TIOCMBIC, &controlbits) < 0)
2013 RETURN_FAIL("Setting RTS signal level failed");
2014 break;
2015 case SP_RTS_FLOW_CONTROL:
2016 data->rts_flow = 1;
2017 break;
2018 default:
2019 break;
2020 }
2021 if (config->cts == SP_CTS_FLOW_CONTROL)
2022 data->cts_flow = 1;
2023
2024 if (data->rts_flow && data->cts_flow)
2025 data->term.c_iflag |= CRTSCTS;
2026 else
2027 data->term.c_iflag &= ~CRTSCTS;
2028 } else {
2029 /* Asymmetric use of RTS/CTS not supported. */
2030 if (data->term.c_iflag & CRTSCTS) {
2031 /* Flow control can only be disabled for both RTS & CTS together. */
2032 if (config->rts >= 0 && config->rts != SP_RTS_FLOW_CONTROL) {
2033 if (config->cts != SP_CTS_IGNORE)
2034 RETURN_ERROR(SP_ERR_SUPP, "RTS & CTS flow control must be disabled together");
2035 }
2036 if (config->cts >= 0 && config->cts != SP_CTS_FLOW_CONTROL) {
2037 if (config->rts <= 0 || config->rts == SP_RTS_FLOW_CONTROL)
2038 RETURN_ERROR(SP_ERR_SUPP, "RTS & CTS flow control must be disabled together");
2039 }
2040 } else {
2041 /* Flow control can only be enabled for both RTS & CTS together. */
2042 if (((config->rts == SP_RTS_FLOW_CONTROL) && (config->cts != SP_CTS_FLOW_CONTROL)) ||
2043 ((config->cts == SP_CTS_FLOW_CONTROL) && (config->rts != SP_RTS_FLOW_CONTROL)))
2044 RETURN_ERROR(SP_ERR_SUPP, "RTS & CTS flow control must be enabled together");
2045 }
2046
2047 if (config->rts >= 0) {
2048 if (config->rts == SP_RTS_FLOW_CONTROL) {
2049 data->term.c_iflag |= CRTSCTS;
2050 } else {
2051 controlbits = TIOCM_RTS;
2052 if (ioctl(port->fd, config->rts == SP_RTS_ON ? TIOCMBIS : TIOCMBIC,
2053 &controlbits) < 0)
2054 RETURN_FAIL("Setting RTS signal level failed");
2055 }
2056 }
2057 }
2058 }
2059
2060 if (config->dtr >= 0 || config->dsr >= 0) {
2061 if (data->termiox_supported) {
2062 data->dtr_flow = data->dsr_flow = 0;
2063 switch (config->dtr) {
2064 case SP_DTR_OFF:
2065 case SP_DTR_ON:
2066 controlbits = TIOCM_DTR;
2067 if (ioctl(port->fd, config->dtr == SP_DTR_ON ? TIOCMBIS : TIOCMBIC, &controlbits) < 0)
2068 RETURN_FAIL("Setting DTR signal level failed");
2069 break;
2070 case SP_DTR_FLOW_CONTROL:
2071 data->dtr_flow = 1;
2072 break;
2073 default:
2074 break;
2075 }
2076 if (config->dsr == SP_DSR_FLOW_CONTROL)
2077 data->dsr_flow = 1;
2078 } else {
2079 /* DTR/DSR flow control not supported. */
2080 if (config->dtr == SP_DTR_FLOW_CONTROL || config->dsr == SP_DSR_FLOW_CONTROL)
2081 RETURN_ERROR(SP_ERR_SUPP, "DTR/DSR flow control not supported");
2082
2083 if (config->dtr >= 0) {
2084 controlbits = TIOCM_DTR;
2085 if (ioctl(port->fd, config->dtr == SP_DTR_ON ? TIOCMBIS : TIOCMBIC,
2086 &controlbits) < 0)
2087 RETURN_FAIL("Setting DTR signal level failed");
2088 }
2089 }
2090 }
2091
2092 if (config->xon_xoff >= 0) {
2093 data->term.c_iflag &= ~(IXON | IXOFF | IXANY);
2094 switch (config->xon_xoff) {
2095 case SP_XONXOFF_DISABLED:
2096 break;
2097 case SP_XONXOFF_IN:
2098 data->term.c_iflag |= IXOFF;
2099 break;
2100 case SP_XONXOFF_OUT:
2101 data->term.c_iflag |= IXON | IXANY;
2102 break;
2103 case SP_XONXOFF_INOUT:
2104 data->term.c_iflag |= IXON | IXOFF | IXANY;
2105 break;
2106 default:
2107 RETURN_ERROR(SP_ERR_ARG, "Invalid XON/XOFF setting");
2108 }
2109 }
2110
2111 if (tcsetattr(port->fd, TCSANOW, &data->term) < 0)
2112 RETURN_FAIL("tcsetattr() failed");
2113
2114#ifdef __APPLE__
2115 if (baud_nonstd != B0) {
2116 if (ioctl(port->fd, IOSSIOSPEED, &baud_nonstd) == -1)
2117 RETURN_FAIL("IOSSIOSPEED ioctl failed");
2118 /* Set baud rates in data->term to correct, but incompatible
2119 * with tcsetattr() value, same as delivered by tcgetattr(). */
2120 if (cfsetspeed(&data->term, baud_nonstd) < 0)
2121 RETURN_FAIL("cfsetspeed() failed");
2122 }
2123#elif defined(__linux__)
2124#ifdef USE_TERMIOS_SPEED
2125 if (baud_nonstd)
2126 TRY(set_baudrate(port->fd, config->baudrate));
2127#endif
2128#ifdef USE_TERMIOX
2129 if (data->termiox_supported)
2130 TRY(set_flow(port->fd, data));
2131#endif
2132#endif
2133
2134#endif /* !_WIN32 */
2135
2136 RETURN_OK();
2137}
2138
2139enum sp_return sp_new_config(struct sp_port_config **config_ptr)
2140{
2141 struct sp_port_config *config;
2142
2143 TRACE("%p", config_ptr);
2144
2145 if (!config_ptr)
2146 RETURN_ERROR(SP_ERR_ARG, "Null result pointer");
2147
2148 *config_ptr = NULL;
2149
2150 if (!(config = malloc(sizeof(struct sp_port_config))))
2151 RETURN_ERROR(SP_ERR_MEM, "config malloc failed");
2152
2153 config->baudrate = -1;
2154 config->bits = -1;
2155 config->parity = -1;
2156 config->stopbits = -1;
2157 config->rts = -1;
2158 config->cts = -1;
2159 config->dtr = -1;
2160 config->dsr = -1;
2161
2162 *config_ptr = config;
2163
2164 RETURN_OK();
2165}
2166
2167void sp_free_config(struct sp_port_config *config)
2168{
2169 TRACE("%p", config);
2170
2171 if (!config)
2172 DEBUG("Null config");
2173 else
2174 free(config);
2175
2176 RETURN();
2177}
2178
2179enum sp_return sp_get_config(struct sp_port *port, struct sp_port_config *config)
2180{
2181 struct port_data data;
2182
2183 TRACE("%p, %p", port, config);
2184
2185 CHECK_OPEN_PORT();
2186
2187 if (!config)
2188 RETURN_ERROR(SP_ERR_ARG, "Null config");
2189
2190 TRY(get_config(port, &data, config));
2191
2192 RETURN_OK();
2193}
2194
2195enum sp_return sp_set_config(struct sp_port *port, const struct sp_port_config *config)
2196{
2197 struct port_data data;
2198 struct sp_port_config prev_config;
2199
2200 TRACE("%p, %p", port, config);
2201
2202 CHECK_OPEN_PORT();
2203
2204 if (!config)
2205 RETURN_ERROR(SP_ERR_ARG, "Null config");
2206
2207 TRY(get_config(port, &data, &prev_config));
2208 TRY(set_config(port, &data, config));
2209
2210 RETURN_OK();
2211}
2212
2213#define CREATE_ACCESSORS(x, type) \
2214enum sp_return sp_set_##x(struct sp_port *port, type x) { \
2215 struct port_data data; \
2216 struct sp_port_config config; \
2217 TRACE("%p, %d", port, x); \
2218 CHECK_OPEN_PORT(); \
2219 TRY(get_config(port, &data, &config)); \
2220 config.x = x; \
2221 TRY(set_config(port, &data, &config)); \
2222 RETURN_OK(); \
2223} \
2224enum sp_return sp_get_config_##x(const struct sp_port_config *config, type *x) { \
2225 TRACE("%p, %p", config, x); \
2226 if (!config) \
2227 RETURN_ERROR(SP_ERR_ARG, "Null config"); \
2228 *x = config->x; \
2229 RETURN_OK(); \
2230} \
2231enum sp_return sp_set_config_##x(struct sp_port_config *config, type x) { \
2232 TRACE("%p, %d", config, x); \
2233 if (!config) \
2234 RETURN_ERROR(SP_ERR_ARG, "Null config"); \
2235 config->x = x; \
2236 RETURN_OK(); \
2237}
2238
2239CREATE_ACCESSORS(baudrate, int)
2240CREATE_ACCESSORS(bits, int)
2241CREATE_ACCESSORS(parity, enum sp_parity)
2242CREATE_ACCESSORS(stopbits, int)
2243CREATE_ACCESSORS(rts, enum sp_rts)
2244CREATE_ACCESSORS(cts, enum sp_cts)
2245CREATE_ACCESSORS(dtr, enum sp_dtr)
2246CREATE_ACCESSORS(dsr, enum sp_dsr)
2247CREATE_ACCESSORS(xon_xoff, enum sp_xonxoff)
2248
2249enum sp_return sp_set_config_flowcontrol(struct sp_port_config *config, enum sp_flowcontrol flowcontrol)
2250{
2251 if (!config)
2252 RETURN_ERROR(SP_ERR_ARG, "Null configuration");
2253
2254 if (flowcontrol > SP_FLOWCONTROL_DTRDSR)
2255 RETURN_ERROR(SP_ERR_ARG, "Invalid flow control setting");
2256
2257 if (flowcontrol == SP_FLOWCONTROL_XONXOFF)
2258 config->xon_xoff = SP_XONXOFF_INOUT;
2259 else
2260 config->xon_xoff = SP_XONXOFF_DISABLED;
2261
2262 if (flowcontrol == SP_FLOWCONTROL_RTSCTS) {
2263 config->rts = SP_RTS_FLOW_CONTROL;
2264 config->cts = SP_CTS_FLOW_CONTROL;
2265 } else {
2266 if (config->rts == SP_RTS_FLOW_CONTROL)
2267 config->rts = SP_RTS_ON;
2268 config->cts = SP_CTS_IGNORE;
2269 }
2270
2271 if (flowcontrol == SP_FLOWCONTROL_DTRDSR) {
2272 config->dtr = SP_DTR_FLOW_CONTROL;
2273 config->dsr = SP_DSR_FLOW_CONTROL;
2274 } else {
2275 if (config->dtr == SP_DTR_FLOW_CONTROL)
2276 config->dtr = SP_DTR_ON;
2277 config->dsr = SP_DSR_IGNORE;
2278 }
2279
2280 RETURN_OK();
2281}
2282
2283enum sp_return sp_set_flowcontrol(struct sp_port *port, enum sp_flowcontrol flowcontrol)
2284{
2285 struct port_data data;
2286 struct sp_port_config config;
2287
2288 TRACE("%p, %d", port, flowcontrol);
2289
2290 CHECK_OPEN_PORT();
2291
2292 TRY(get_config(port, &data, &config));
2293
2294 TRY(sp_set_config_flowcontrol(&config, flowcontrol));
2295
2296 TRY(set_config(port, &data, &config));
2297
2298 RETURN_OK();
2299}
2300
2301enum sp_return sp_get_signals(struct sp_port *port, enum sp_signal *signals)
2302{
2303 TRACE("%p, %p", port, signals);
2304
2305 CHECK_OPEN_PORT();
2306
2307 if (!signals)
2308 RETURN_ERROR(SP_ERR_ARG, "Null result pointer");
2309
2310 DEBUG("Getting control signals for port %s", port->name);
2311
2312 *signals = 0;
2313#ifdef _WIN32
2314 DWORD bits;
2315 if (GetCommModemStatus(port->hdl, &bits) == 0)
2316 RETURN_FAIL("GetCommModemStatus() failed");
2317 if (bits & MS_CTS_ON)
2318 *signals |= SP_SIG_CTS;
2319 if (bits & MS_DSR_ON)
2320 *signals |= SP_SIG_DSR;
2321 if (bits & MS_RLSD_ON)
2322 *signals |= SP_SIG_DCD;
2323 if (bits & MS_RING_ON)
2324 *signals |= SP_SIG_RI;
2325#else
2326 int bits;
2327 if (ioctl(port->fd, TIOCMGET, &bits) < 0)
2328 RETURN_FAIL("TIOCMGET ioctl failed");
2329 if (bits & TIOCM_CTS)
2330 *signals |= SP_SIG_CTS;
2331 if (bits & TIOCM_DSR)
2332 *signals |= SP_SIG_DSR;
2333 if (bits & TIOCM_CAR)
2334 *signals |= SP_SIG_DCD;
2335 if (bits & TIOCM_RNG)
2336 *signals |= SP_SIG_RI;
2337#endif
2338 RETURN_OK();
2339}
2340
2341enum sp_return sp_start_break(struct sp_port *port)
2342{
2343 TRACE("%p", port);
2344
2345 CHECK_OPEN_PORT();
2346#ifdef _WIN32
2347 if (SetCommBreak(port->hdl) == 0)
2348 RETURN_FAIL("SetCommBreak() failed");
2349#else
2350 if (ioctl(port->fd, TIOCSBRK, 1) < 0)
2351 RETURN_FAIL("TIOCSBRK ioctl failed");
2352#endif
2353
2354 RETURN_OK();
2355}
2356
2357enum sp_return sp_end_break(struct sp_port *port)
2358{
2359 TRACE("%p", port);
2360
2361 CHECK_OPEN_PORT();
2362#ifdef _WIN32
2363 if (ClearCommBreak(port->hdl) == 0)
2364 RETURN_FAIL("ClearCommBreak() failed");
2365#else
2366 if (ioctl(port->fd, TIOCCBRK, 1) < 0)
2367 RETURN_FAIL("TIOCCBRK ioctl failed");
2368#endif
2369
2370 RETURN_OK();
2371}
2372
2373int sp_last_error_code(void)
2374{
2375 TRACE("");
2376#ifdef _WIN32
2377 RETURN_VALUE("%d", GetLastError());
2378#else
2379 RETURN_VALUE("%d", errno);
2380#endif
2381}
2382
2383char *sp_last_error_message(void)
2384{
2385 TRACE("");
2386
2387#ifdef _WIN32
2388 LPVOID message;
2389 DWORD error = GetLastError();
2390
2391 FormatMessage(
2392 FORMAT_MESSAGE_ALLOCATE_BUFFER |
2393 FORMAT_MESSAGE_FROM_SYSTEM |
2394 FORMAT_MESSAGE_IGNORE_INSERTS,
2395 NULL,
2396 error,
2397 MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
2398 (LPTSTR) &message,
2399 0, NULL );
2400
2401 RETURN_VALUE("%s", message);
2402#else
2403 RETURN_VALUE("%s", strerror(errno));
2404#endif
2405}
2406
2407void sp_free_error_message(char *message)
2408{
2409 TRACE("%s", message);
2410
2411#ifdef _WIN32
2412 LocalFree(message);
2413#else
2414 (void)message;
2415#endif
2416
2417 RETURN();
2418}
2419
2420void sp_set_debug_handler(void (*handler)(const char *format, ...))
2421{
2422 TRACE("%p", handler);
2423
2424 sp_debug_handler = handler;
2425
2426 RETURN();
2427}
2428
2429void sp_default_debug_handler(const char *format, ...)
2430{
2431 va_list args;
2432 va_start(args, format);
2433 if (getenv("LIBSERIALPORT_DEBUG")) {
2434 fputs("sp: ", stderr);
2435 vfprintf(stderr, format, args);
2436 }
2437 va_end(args);
2438}
2439
2440int sp_get_major_package_version(void)
2441{
2442 return SP_PACKAGE_VERSION_MAJOR;
2443}
2444
2445int sp_get_minor_package_version(void)
2446{
2447 return SP_PACKAGE_VERSION_MINOR;
2448}
2449
2450int sp_get_micro_package_version(void)
2451{
2452 return SP_PACKAGE_VERSION_MICRO;
2453}
2454
2455const char *sp_get_package_version_string(void)
2456{
2457 return SP_PACKAGE_VERSION_STRING;
2458}
2459
2460int sp_get_current_lib_version(void)
2461{
2462 return SP_LIB_VERSION_CURRENT;
2463}
2464
2465int sp_get_revision_lib_version(void)
2466{
2467 return SP_LIB_VERSION_REVISION;
2468}
2469
2470int sp_get_age_lib_version(void)
2471{
2472 return SP_LIB_VERSION_AGE;
2473}
2474
2475const char *sp_get_lib_version_string(void)
2476{
2477 return SP_LIB_VERSION_STRING;
2478}
2479
2480/** @} */