]> sigrok.org Git - libserialport.git/blame_incremental - serialport.c
Make port structure opaque.
[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#include <stdio.h>
36#else
37#include <termios.h>
38#include <sys/ioctl.h>
39#endif
40#ifdef __APPLE__
41#include <IOKit/IOKitLib.h>
42#include <IOKit/serial/IOSerialKeys.h>
43#include <IOKit/serial/ioss.h>
44#include <sys/syslimits.h>
45#endif
46#ifdef __linux__
47#include "libudev.h"
48#include "linux/serial.h"
49#include "linux_termios.h"
50#if defined(TCGETX) && defined(TCSETX) && defined(HAVE_TERMIOX)
51#define USE_TERMIOX
52#endif
53#endif
54
55#ifndef _WIN32
56#include "linux_termios.h"
57#endif
58
59#include "libserialport.h"
60
61struct sp_port {
62 char *name;
63#ifdef _WIN32
64 HANDLE hdl;
65#else
66 int fd;
67#endif
68};
69
70struct port_data {
71#ifdef _WIN32
72 DCB dcb;
73#else
74 struct termios term;
75 int controlbits;
76 int termiox_supported;
77 int flow;
78#endif
79};
80
81/* Standard baud rates. */
82#ifdef _WIN32
83#define BAUD_TYPE DWORD
84#define BAUD(n) {CBR_##n, n}
85#else
86#define BAUD_TYPE speed_t
87#define BAUD(n) {B##n, n}
88#endif
89
90struct std_baudrate {
91 BAUD_TYPE index;
92 int value;
93};
94
95const struct std_baudrate std_baudrates[] = {
96#ifdef _WIN32
97 /*
98 * The baudrates 50/75/134/150/200/1800/230400/460800 do not seem to
99 * have documented CBR_* macros.
100 */
101 BAUD(110), BAUD(300), BAUD(600), BAUD(1200), BAUD(2400), BAUD(4800),
102 BAUD(9600), BAUD(14400), BAUD(19200), BAUD(38400), BAUD(57600),
103 BAUD(115200), BAUD(128000), BAUD(256000),
104#else
105 BAUD(50), BAUD(75), BAUD(110), BAUD(134), BAUD(150), BAUD(200),
106 BAUD(300), BAUD(600), BAUD(1200), BAUD(1800), BAUD(2400), BAUD(4800),
107 BAUD(9600), BAUD(19200), BAUD(38400), BAUD(57600), BAUD(115200),
108 BAUD(230400),
109#if !defined(__APPLE__) && !defined(__OpenBSD__)
110 BAUD(460800),
111#endif
112#endif
113};
114
115void (*sp_debug_handler)(const char *format, ...) = sp_default_debug_handler;
116
117#define ARRAY_SIZE(x) (sizeof(x) / sizeof(x[0]))
118#define NUM_STD_BAUDRATES ARRAY_SIZE(std_baudrates)
119
120/* Debug output macros. */
121#define DEBUG(fmt, ...) do { if (sp_debug_handler) sp_debug_handler(fmt ".\n", ##__VA_ARGS__); } while (0)
122#define DEBUG_ERROR(err, msg) DEBUG("%s returning " #err ": " msg, __func__)
123#define DEBUG_FAIL(msg) do { \
124 char *errmsg = sp_last_error_message(); \
125 DEBUG("%s returning SP_ERR_FAIL: " msg ": %s", __func__, errmsg); \
126 sp_free_error_message(errmsg); \
127} while (0);
128#define RETURN() do { DEBUG("%s returning", __func__); return; } while(0)
129#define RETURN_CODE(x) do { DEBUG("%s returning " #x, __func__); return x; } while (0)
130#define RETURN_CODEVAL(x) do { \
131 switch (x) { \
132 case SP_OK: RETURN_CODE(SP_OK); \
133 case SP_ERR_ARG: RETURN_CODE(SP_ERR_ARG); \
134 case SP_ERR_FAIL: RETURN_CODE(SP_ERR_FAIL); \
135 case SP_ERR_MEM: RETURN_CODE(SP_ERR_MEM); \
136 case SP_ERR_SUPP: RETURN_CODE(SP_ERR_SUPP); \
137 } \
138} while (0)
139#define RETURN_OK() RETURN_CODE(SP_OK);
140#define RETURN_ERROR(err, msg) do { DEBUG_ERROR(err, msg); return err; } while (0)
141#define RETURN_FAIL(msg) do { DEBUG_FAIL(msg); return SP_ERR_FAIL; } while (0)
142#define RETURN_VALUE(fmt, x) do { DEBUG("%s returning " fmt, __func__, x); return x; } while (0)
143#define SET_ERROR(val, err, msg) do { DEBUG_ERROR(err, msg); val = err; } while (0)
144#define SET_FAIL(val, msg) do { DEBUG_FAIL(msg); val = err; } while (0)
145#define TRACE(fmt, ...) DEBUG("%s(" fmt ") called", __func__, ##__VA_ARGS__)
146
147#define TRY(x) do { int ret = x; if (ret != SP_OK) RETURN_CODEVAL(ret); } while (0)
148
149/* Helper functions. */
150static struct sp_port **list_append(struct sp_port **list, const char *portname);
151static enum sp_return get_config(struct sp_port *port, struct port_data *data,
152 struct sp_port_config *config);
153static enum sp_return set_config(struct sp_port *port, struct port_data *data,
154 const struct sp_port_config *config);
155
156enum sp_return sp_get_port_by_name(const char *portname, struct sp_port **port_ptr)
157{
158 struct sp_port *port;
159 int len;
160
161 TRACE("%s, %p", portname, port_ptr);
162
163 if (!port_ptr)
164 RETURN_ERROR(SP_ERR_ARG, "Null result pointer");
165
166 *port_ptr = NULL;
167
168 if (!portname)
169 RETURN_ERROR(SP_ERR_ARG, "Null port name");
170
171 DEBUG("Building structure for port %s", portname);
172
173 if (!(port = malloc(sizeof(struct sp_port))))
174 RETURN_ERROR(SP_ERR_MEM, "Port structure malloc failed");
175
176 len = strlen(portname) + 1;
177
178 if (!(port->name = malloc(len))) {
179 free(port);
180 RETURN_ERROR(SP_ERR_MEM, "Port name malloc failed");
181 }
182
183 memcpy(port->name, portname, len);
184
185#ifdef _WIN32
186 port->hdl = INVALID_HANDLE_VALUE;
187#else
188 port->fd = -1;
189#endif
190
191 *port_ptr = port;
192
193 RETURN_OK();
194}
195
196char *sp_get_port_name(const struct sp_port *port)
197{
198 TRACE("%p", port);
199
200 if (!port)
201 return NULL;
202
203 RETURN_VALUE("%s", port->name);
204}
205
206enum sp_return sp_copy_port(const struct sp_port *port, struct sp_port **copy_ptr)
207{
208 TRACE("%p, %p", port, copy_ptr);
209
210 if (!copy_ptr)
211 RETURN_ERROR(SP_ERR_ARG, "Null result pointer");
212
213 *copy_ptr = NULL;
214
215 if (!port)
216 RETURN_ERROR(SP_ERR_ARG, "Null port");
217
218 if (!port->name)
219 RETURN_ERROR(SP_ERR_ARG, "Null port name");
220
221 DEBUG("Copying port structure");
222
223 RETURN_VALUE("%p", sp_get_port_by_name(port->name, copy_ptr));
224}
225
226void sp_free_port(struct sp_port *port)
227{
228 TRACE("%p", port);
229
230 if (!port)
231 {
232 DEBUG("Null port");
233 RETURN();
234 }
235
236 DEBUG("Freeing port structure");
237
238 if (port->name)
239 free(port->name);
240
241 free(port);
242
243 RETURN();
244}
245
246static struct sp_port **list_append(struct sp_port **list, const char *portname)
247{
248 void *tmp;
249 unsigned int count;
250
251 for (count = 0; list[count]; count++);
252 if (!(tmp = realloc(list, sizeof(struct sp_port *) * (count + 2))))
253 goto fail;
254 list = tmp;
255 if (sp_get_port_by_name(portname, &list[count]) != SP_OK)
256 goto fail;
257 list[count + 1] = NULL;
258 return list;
259
260fail:
261 sp_free_port_list(list);
262 return NULL;
263}
264
265enum sp_return sp_list_ports(struct sp_port ***list_ptr)
266{
267 struct sp_port **list;
268 int ret = SP_ERR_SUPP;
269
270 TRACE("%p", list_ptr);
271
272 if (!list_ptr)
273 RETURN_ERROR(SP_ERR_ARG, "Null result pointer");
274
275 DEBUG("Enumerating ports");
276
277 if (!(list = malloc(sizeof(struct sp_port **))))
278 RETURN_ERROR(SP_ERR_MEM, "Port list malloc failed");
279
280 list[0] = NULL;
281
282#ifdef _WIN32
283 HKEY key;
284 TCHAR *value, *data;
285 DWORD max_value_len, max_data_size, max_data_len;
286 DWORD value_len, data_size, data_len;
287 DWORD type, index = 0;
288 char *name;
289 int name_len;
290
291 ret = SP_OK;
292
293 DEBUG("Opening registry key");
294 if (RegOpenKeyEx(HKEY_LOCAL_MACHINE, _T("HARDWARE\\DEVICEMAP\\SERIALCOMM"),
295 0, KEY_QUERY_VALUE, &key) != ERROR_SUCCESS) {
296 SET_FAIL(ret, "RegOpenKeyEx() failed");
297 goto out_done;
298 }
299 DEBUG("Querying registry key value and data sizes");
300 if (RegQueryInfoKey(key, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
301 &max_value_len, &max_data_size, NULL, NULL) != ERROR_SUCCESS) {
302 SET_FAIL(ret, "RegQueryInfoKey() failed");
303 goto out_close;
304 }
305 max_data_len = max_data_size / sizeof(TCHAR);
306 if (!(value = malloc((max_value_len + 1) * sizeof(TCHAR)))) {
307 SET_ERROR(ret, SP_ERR_MEM, "registry value malloc failed");
308 goto out_close;
309 }
310 if (!(data = malloc((max_data_len + 1) * sizeof(TCHAR)))) {
311 SET_ERROR(ret, SP_ERR_MEM, "registry data malloc failed");
312 goto out_free_value;
313 }
314 DEBUG("Iterating over values");
315 while (
316 value_len = max_value_len + 1,
317 data_size = max_data_size,
318 RegEnumValue(key, index, value, &value_len,
319 NULL, &type, (LPBYTE)data, &data_size) == ERROR_SUCCESS)
320 {
321 data_len = data_size / sizeof(TCHAR);
322 data[data_len] = '\0';
323#ifdef UNICODE
324 name_len = WideCharToMultiByte(CP_ACP, 0, data, -1, NULL, 0, NULL, NULL)
325#else
326 name_len = data_len + 1;
327#endif
328 if (!(name = malloc(name_len))) {
329 SET_ERROR(ret, SP_ERR_MEM, "registry port name malloc failed");
330 goto out;
331 }
332#ifdef UNICODE
333 WideCharToMultiByte(CP_ACP, 0, data, -1, name, name_len, NULL, NULL);
334#else
335 strcpy(name, data);
336#endif
337 if (type == REG_SZ) {
338 DEBUG("Found port %s", name);
339 if (!(list = list_append(list, name))) {
340 SET_ERROR(ret, SP_ERR_MEM, "list append failed");
341 goto out;
342 }
343 }
344 index++;
345 }
346out:
347 free(data);
348out_free_value:
349 free(value);
350out_close:
351 RegCloseKey(key);
352out_done:
353#endif
354#ifdef __APPLE__
355 mach_port_t master;
356 CFMutableDictionaryRef classes;
357 io_iterator_t iter;
358 char *path;
359 io_object_t port;
360 CFTypeRef cf_path;
361 Boolean result;
362
363 ret = SP_OK;
364
365 DEBUG("Getting IOKit master port");
366 if (IOMasterPort(MACH_PORT_NULL, &master) != KERN_SUCCESS) {
367 SET_FAIL(ret, "IOMasterPort() failed");
368 goto out_done;
369 }
370
371 DEBUG("Creating matching dictionary");
372 if (!(classes = IOServiceMatching(kIOSerialBSDServiceValue))) {
373 SET_FAIL(ret, "IOServiceMatching() failed");
374 goto out_done;
375 }
376
377 CFDictionarySetValue(classes,
378 CFSTR(kIOSerialBSDTypeKey), CFSTR(kIOSerialBSDAllTypes));
379
380 DEBUG("Getting matching services");
381 if (IOServiceGetMatchingServices(master, classes, &iter) != KERN_SUCCESS) {
382 SET_FAIL(ret, "IOServiceGetMatchingServices() failed");
383 goto out_done;
384 }
385
386 if (!(path = malloc(PATH_MAX))) {
387 SET_ERROR(ret, SP_ERR_MEM, "device path malloc failed");
388 goto out_release;
389 }
390
391 DEBUG("Iterating over results");
392 while ((port = IOIteratorNext(iter))) {
393 cf_path = IORegistryEntryCreateCFProperty(port,
394 CFSTR(kIOCalloutDeviceKey), kCFAllocatorDefault, 0);
395 if (cf_path) {
396 result = CFStringGetCString(cf_path,
397 path, PATH_MAX, kCFStringEncodingASCII);
398 CFRelease(cf_path);
399 if (result) {
400 DEBUG("Found port %s", path);
401 if (!(list = list_append(list, path))) {
402 SET_ERROR(ret, SP_ERR_MEM, "list append failed");
403 IOObjectRelease(port);
404 goto out;
405 }
406 }
407 }
408 IOObjectRelease(port);
409 }
410out:
411 free(path);
412out_release:
413 IOObjectRelease(iter);
414out_done:
415#endif
416#ifdef __linux__
417 struct udev *ud;
418 struct udev_enumerate *ud_enumerate;
419 struct udev_list_entry *ud_list;
420 struct udev_list_entry *ud_entry;
421 const char *path;
422 struct udev_device *ud_dev, *ud_parent;
423 const char *name;
424 const char *driver;
425 int fd, ioctl_result;
426 struct serial_struct serial_info;
427
428 ret = SP_OK;
429
430 DEBUG("Enumerating tty devices");
431 ud = udev_new();
432 ud_enumerate = udev_enumerate_new(ud);
433 udev_enumerate_add_match_subsystem(ud_enumerate, "tty");
434 udev_enumerate_scan_devices(ud_enumerate);
435 ud_list = udev_enumerate_get_list_entry(ud_enumerate);
436 DEBUG("Iterating over results");
437 udev_list_entry_foreach(ud_entry, ud_list) {
438 path = udev_list_entry_get_name(ud_entry);
439 DEBUG("Found device %s", path);
440 ud_dev = udev_device_new_from_syspath(ud, path);
441 /* If there is no parent device, this is a virtual tty. */
442 ud_parent = udev_device_get_parent(ud_dev);
443 if (ud_parent == NULL) {
444 DEBUG("No parent device, assuming virtual tty");
445 udev_device_unref(ud_dev);
446 continue;
447 }
448 name = udev_device_get_devnode(ud_dev);
449 /* The serial8250 driver has a hardcoded number of ports.
450 * The only way to tell which actually exist on a given system
451 * is to try to open them and make an ioctl call. */
452 driver = udev_device_get_driver(ud_parent);
453 if (driver && !strcmp(driver, "serial8250")) {
454 DEBUG("serial8250 device, attempting to open");
455 if ((fd = open(name, O_RDWR | O_NONBLOCK | O_NOCTTY)) < 0) {
456 DEBUG("open failed, skipping");
457 goto skip;
458 }
459 ioctl_result = ioctl(fd, TIOCGSERIAL, &serial_info);
460 close(fd);
461 if (ioctl_result != 0) {
462 DEBUG("ioctl failed, skipping");
463 goto skip;
464 }
465 if (serial_info.type == PORT_UNKNOWN) {
466 DEBUG("port type is unknown, skipping");
467 goto skip;
468 }
469 }
470 DEBUG("Found port %s", name);
471 list = list_append(list, name);
472skip:
473 udev_device_unref(ud_dev);
474 if (!list) {
475 SET_ERROR(ret, SP_ERR_MEM, "list append failed");
476 goto out;
477 }
478 }
479out:
480 udev_enumerate_unref(ud_enumerate);
481 udev_unref(ud);
482#endif
483
484 switch (ret) {
485 case SP_OK:
486 *list_ptr = list;
487 RETURN_OK();
488 case SP_ERR_SUPP:
489 DEBUG_ERROR(SP_ERR_SUPP, "Enumeration not supported on this platform.");
490 default:
491 if (list)
492 sp_free_port_list(list);
493 *list_ptr = NULL;
494 return ret;
495 }
496}
497
498void sp_free_port_list(struct sp_port **list)
499{
500 unsigned int i;
501
502 TRACE("%p", list);
503
504 if (!list) {
505 DEBUG("Null list");
506 RETURN();
507 }
508
509 DEBUG("Freeing port list");
510
511 for (i = 0; list[i]; i++)
512 sp_free_port(list[i]);
513 free(list);
514
515 RETURN();
516}
517
518#define CHECK_PORT() do { \
519 if (port == NULL) \
520 RETURN_ERROR(SP_ERR_ARG, "Null port"); \
521 if (port->name == NULL) \
522 RETURN_ERROR(SP_ERR_ARG, "Null port name"); \
523} while (0)
524#ifdef _WIN32
525#define CHECK_PORT_HANDLE() do { \
526 if (port->hdl == INVALID_HANDLE_VALUE) \
527 RETURN_ERROR(SP_ERR_ARG, "Invalid port handle"); \
528} while (0)
529#else
530#define CHECK_PORT_HANDLE() do { \
531 if (port->fd < 0) \
532 RETURN_ERROR(SP_ERR_ARG, "Invalid port fd"); \
533} while (0)
534#endif
535#define CHECK_OPEN_PORT() do { \
536 CHECK_PORT(); \
537 CHECK_PORT_HANDLE(); \
538} while (0)
539
540enum sp_return sp_open(struct sp_port *port, enum sp_mode flags)
541{
542 TRACE("%p, %x", port, flags);
543
544 CHECK_PORT();
545
546 if (flags > (SP_MODE_READ | SP_MODE_WRITE | SP_MODE_NONBLOCK))
547 RETURN_ERROR(SP_ERR_ARG, "Invalid flags");
548
549 DEBUG("Opening port %s", port->name);
550
551#ifdef _WIN32
552 DWORD desired_access = 0, flags_and_attributes = 0;
553 char *escaped_port_name;
554
555 /* Prefix port name with '\\.\' to work with ports above COM9. */
556 if (!(escaped_port_name = malloc(strlen(port->name + 5))))
557 RETURN_ERROR(SP_ERR_MEM, "Escaped port name malloc failed");
558 sprintf(escaped_port_name, "\\\\.\\%s", port->name);
559
560 /* Map 'flags' to the OS-specific settings. */
561 flags_and_attributes = FILE_ATTRIBUTE_NORMAL;
562 if (flags & SP_MODE_READ)
563 desired_access |= GENERIC_READ;
564 if (flags & SP_MODE_WRITE)
565 desired_access |= GENERIC_WRITE;
566 if (flags & SP_MODE_NONBLOCK)
567 flags_and_attributes |= FILE_FLAG_OVERLAPPED;
568
569 port->hdl = CreateFile(escaped_port_name, desired_access, 0, 0,
570 OPEN_EXISTING, flags_and_attributes, 0);
571
572 free(escaped_port_name);
573
574 if (port->hdl == INVALID_HANDLE_VALUE)
575 RETURN_FAIL("CreateFile() failed");
576#else
577 int flags_local = 0;
578 struct port_data data;
579 struct sp_port_config config;
580 int ret;
581
582 /* Map 'flags' to the OS-specific settings. */
583 if (flags & (SP_MODE_READ | SP_MODE_WRITE))
584 flags_local |= O_RDWR;
585 else if (flags & SP_MODE_READ)
586 flags_local |= O_RDONLY;
587 else if (flags & SP_MODE_WRITE)
588 flags_local |= O_WRONLY;
589 if (flags & SP_MODE_NONBLOCK)
590 flags_local |= O_NONBLOCK;
591
592 if ((port->fd = open(port->name, flags_local)) < 0)
593 RETURN_FAIL("open() failed");
594
595 ret = get_config(port, &data, &config);
596
597 if (ret < 0) {
598 sp_close(port);
599 RETURN_CODEVAL(ret);
600 }
601
602 /* Turn off all serial port cooking. */
603 data.term.c_iflag &= ~(ISTRIP | INLCR | ICRNL);
604 data.term.c_oflag &= ~(ONLCR | OCRNL | ONOCR);
605#if !defined(__FreeBSD__) && !defined(__OpenBSD__) && !defined(__NetBSD__)
606 data.term.c_oflag &= ~OFILL;
607#endif
608 /* Disable canonical mode, and don't echo input characters. */
609 data.term.c_lflag &= ~(ICANON | ECHO);
610
611 /* Ignore modem status lines; enable receiver */
612 data.term.c_cflag |= (CLOCAL | CREAD);
613
614 ret = set_config(port, &data, &config);
615
616 if (ret < 0) {
617 sp_close(port);
618 RETURN_CODEVAL(ret);
619 }
620#endif
621
622 RETURN_OK();
623}
624
625enum sp_return sp_close(struct sp_port *port)
626{
627 TRACE("%p", port);
628
629 CHECK_OPEN_PORT();
630
631 DEBUG("Closing port %s", port->name);
632
633#ifdef _WIN32
634 /* Returns non-zero upon success, 0 upon failure. */
635 if (CloseHandle(port->hdl) == 0)
636 RETURN_FAIL("CloseHandle() failed");
637 port->hdl = INVALID_HANDLE_VALUE;
638#else
639 /* Returns 0 upon success, -1 upon failure. */
640 if (close(port->fd) == -1)
641 RETURN_FAIL("close() failed");
642 port->fd = -1;
643#endif
644
645 RETURN_OK();
646}
647
648enum sp_return sp_flush(struct sp_port *port, enum sp_buffer buffers)
649{
650 TRACE("%p, %x", port, buffers);
651
652 CHECK_OPEN_PORT();
653
654 if (buffers > SP_BUF_BOTH)
655 RETURN_ERROR(SP_ERR_ARG, "Invalid buffer selection");
656
657 const char *buffer_names[] = {"input", "output", "both"};
658
659 DEBUG("Flushing %s buffers on port %s", buffer_names[buffers], port->name);
660
661#ifdef _WIN32
662 DWORD flags = 0;
663 if (buffers & SP_BUF_INPUT)
664 flags |= PURGE_RXCLEAR;
665 if (buffers & SP_BUF_OUTPUT)
666 flags |= PURGE_TXCLEAR;
667
668 /* Returns non-zero upon success, 0 upon failure. */
669 if (PurgeComm(port->hdl, flags) == 0)
670 RETURN_FAIL("PurgeComm() failed");
671#else
672 int flags = 0;
673 if (buffers & SP_BUF_BOTH)
674 flags = TCIOFLUSH;
675 else if (buffers & SP_BUF_INPUT)
676 flags = TCIFLUSH;
677 else if (buffers & SP_BUF_OUTPUT)
678 flags = TCOFLUSH;
679
680 /* Returns 0 upon success, -1 upon failure. */
681 if (tcflush(port->fd, flags) < 0)
682 RETURN_FAIL("tcflush() failed");
683#endif
684 RETURN_OK();
685}
686
687enum sp_return sp_drain(struct sp_port *port)
688{
689 TRACE("%p", port);
690
691 CHECK_OPEN_PORT();
692
693 DEBUG("Draining port %s", port->name);
694
695#ifdef _WIN32
696 /* Returns non-zero upon success, 0 upon failure. */
697 if (FlushFileBuffers(port->hdl) == 0)
698 RETURN_FAIL("FlushFileBuffers() failed");
699#else
700 /* Returns 0 upon success, -1 upon failure. */
701 if (tcdrain(port->fd) < 0)
702 RETURN_FAIL("tcdrain() failed");
703#endif
704
705 RETURN_OK();
706}
707
708enum sp_return sp_write(struct sp_port *port, const void *buf, size_t count)
709{
710 TRACE("%p, %p, %d", port, buf, count);
711
712 CHECK_OPEN_PORT();
713
714 if (!buf)
715 RETURN_ERROR(SP_ERR_ARG, "Null buffer");
716
717 DEBUG("Writing up to %d bytes to port %s", count, port->name);
718
719#ifdef _WIN32
720 DWORD written = 0;
721
722 /* Returns non-zero upon success, 0 upon failure. */
723 if (WriteFile(port->hdl, buf, count, &written, NULL) == 0)
724 RETURN_FAIL("WriteFile() failed");
725 RETURN_VALUE("%d", written);
726#else
727 /* Returns the number of bytes written, or -1 upon failure. */
728 ssize_t written = write(port->fd, buf, count);
729
730 if (written < 0)
731 RETURN_FAIL("write() failed");
732 else
733 RETURN_VALUE("%d", written);
734#endif
735}
736
737enum sp_return sp_read(struct sp_port *port, void *buf, size_t count)
738{
739 TRACE("%p, %p, %d", port, buf, count);
740
741 CHECK_OPEN_PORT();
742
743 if (!buf)
744 RETURN_ERROR(SP_ERR_ARG, "Null buffer");
745
746 DEBUG("Reading up to %d bytes from port %s", count, port->name);
747
748#ifdef _WIN32
749 DWORD bytes_read = 0;
750
751 /* Returns non-zero upon success, 0 upon failure. */
752 if (ReadFile(port->hdl, buf, count, &bytes_read, NULL) == 0)
753 RETURN_FAIL("ReadFile() failed");
754 RETURN_VALUE("%d", bytes_read);
755#else
756 ssize_t bytes_read;
757
758 /* Returns the number of bytes read, or -1 upon failure. */
759 if ((bytes_read = read(port->fd, buf, count)) < 0)
760 RETURN_FAIL("read() failed");
761 RETURN_VALUE("%d", bytes_read);
762#endif
763}
764
765#ifdef __linux__
766static enum sp_return get_baudrate(int fd, int *baudrate)
767{
768 void *data;
769
770 TRACE("%d, %p", fd, baudrate);
771
772 DEBUG("Getting baud rate");
773
774 if (!(data = malloc(get_termios_size())))
775 RETURN_ERROR(SP_ERR_MEM, "termios malloc failed");
776
777 if (ioctl(fd, get_termios_get_ioctl(), data) < 0) {
778 free(data);
779 RETURN_FAIL("getting termios failed");
780 }
781
782 *baudrate = get_termios_speed(data);
783
784 free(data);
785
786 RETURN_OK();
787}
788
789static enum sp_return set_baudrate(int fd, int baudrate)
790{
791 void *data;
792
793 TRACE("%d, %d", fd, baudrate);
794
795 DEBUG("Getting baud rate");
796
797 if (!(data = malloc(get_termios_size())))
798 RETURN_ERROR(SP_ERR_MEM, "termios malloc failed");
799
800 if (ioctl(fd, get_termios_get_ioctl(), data) < 0) {
801 free(data);
802 RETURN_FAIL("getting termios failed");
803 }
804
805 DEBUG("Setting baud rate");
806
807 set_termios_speed(data, baudrate);
808
809 if (ioctl(fd, get_termios_set_ioctl(), data) < 0) {
810 free(data);
811 RETURN_FAIL("setting termios failed");
812 }
813
814 free(data);
815
816 RETURN_OK();
817}
818
819#ifdef USE_TERMIOX
820static enum sp_return get_flow(int fd, int *flow)
821{
822 void *data;
823
824 TRACE("%d, %p", fd, flow);
825
826 DEBUG("Getting advanced flow control");
827
828 if (!(data = malloc(get_termiox_size())))
829 RETURN_ERROR(SP_ERR_MEM, "termiox malloc failed");
830
831 if (ioctl(fd, TCGETX, data) < 0) {
832 free(data);
833 RETURN_FAIL("getting termiox failed");
834 }
835
836 *flow = get_termiox_flow(data);
837
838 free(data);
839
840 RETURN_OK();
841}
842
843static enum sp_return set_flow(int fd, int flow)
844{
845 void *data;
846
847 TRACE("%d, %d", fd, flow);
848
849 DEBUG("Getting advanced flow control");
850
851 if (!(data = malloc(get_termiox_size())))
852 RETURN_ERROR(SP_ERR_MEM, "termiox malloc failed");
853
854 if (ioctl(fd, TCGETX, data) < 0) {
855 free(data);
856 RETURN_FAIL("getting termiox failed");
857 }
858
859 DEBUG("Setting advanced flow control");
860
861 set_termiox_flow(data, flow);
862
863 if (ioctl(fd, TCSETX, data) < 0) {
864 free(data);
865 RETURN_FAIL("setting termiox failed");
866 }
867
868 free(data);
869
870 RETURN_OK();
871}
872#endif /* USE_TERMIOX */
873#endif /* __linux__ */
874
875static enum sp_return get_config(struct sp_port *port, struct port_data *data,
876 struct sp_port_config *config)
877{
878 unsigned int i;
879
880 TRACE("%p, %p, %p", port, data, config);
881
882 DEBUG("Getting configuration for port %s", port->name);
883
884#ifdef _WIN32
885 if (!GetCommState(port->hdl, &data->dcb))
886 RETURN_FAIL("GetCommState() failed");
887
888 for (i = 0; i < NUM_STD_BAUDRATES; i++) {
889 if (data->dcb.BaudRate == std_baudrates[i].index) {
890 config->baudrate = std_baudrates[i].value;
891 break;
892 }
893 }
894
895 if (i == NUM_STD_BAUDRATES)
896 /* BaudRate field can be either an index or a custom baud rate. */
897 config->baudrate = data->dcb.BaudRate;
898
899 config->bits = data->dcb.ByteSize;
900
901 if (data->dcb.fParity)
902 switch (data->dcb.Parity) {
903 case NOPARITY:
904 config->parity = SP_PARITY_NONE;
905 break;
906 case EVENPARITY:
907 config->parity = SP_PARITY_EVEN;
908 break;
909 case ODDPARITY:
910 config->parity = SP_PARITY_ODD;
911 break;
912 default:
913 config->parity = -1;
914 }
915 else
916 config->parity = SP_PARITY_NONE;
917
918 switch (data->dcb.StopBits) {
919 case ONESTOPBIT:
920 config->stopbits = 1;
921 break;
922 case TWOSTOPBITS:
923 config->stopbits = 2;
924 break;
925 default:
926 config->stopbits = -1;
927 }
928
929 switch (data->dcb.fRtsControl) {
930 case RTS_CONTROL_DISABLE:
931 config->rts = SP_RTS_OFF;
932 break;
933 case RTS_CONTROL_ENABLE:
934 config->rts = SP_RTS_ON;
935 break;
936 case RTS_CONTROL_HANDSHAKE:
937 config->rts = SP_RTS_FLOW_CONTROL;
938 break;
939 default:
940 config->rts = -1;
941 }
942
943 config->cts = data->dcb.fOutxCtsFlow ? SP_CTS_FLOW_CONTROL : SP_CTS_IGNORE;
944
945 switch (data->dcb.fDtrControl) {
946 case DTR_CONTROL_DISABLE:
947 config->dtr = SP_DTR_OFF;
948 break;
949 case DTR_CONTROL_ENABLE:
950 config->dtr = SP_DTR_ON;
951 break;
952 case DTR_CONTROL_HANDSHAKE:
953 config->dtr = SP_DTR_FLOW_CONTROL;
954 break;
955 default:
956 config->dtr = -1;
957 }
958
959 config->dsr = data->dcb.fOutxDsrFlow ? SP_DSR_FLOW_CONTROL : SP_DSR_IGNORE;
960
961 if (data->dcb.fInX) {
962 if (data->dcb.fOutX)
963 config->xon_xoff = SP_XONXOFF_INOUT;
964 else
965 config->xon_xoff = SP_XONXOFF_IN;
966 } else {
967 if (data->dcb.fOutX)
968 config->xon_xoff = SP_XONXOFF_OUT;
969 else
970 config->xon_xoff = SP_XONXOFF_DISABLED;
971 }
972
973#else // !_WIN32
974
975 if (tcgetattr(port->fd, &data->term) < 0)
976 RETURN_FAIL("tcgetattr() failed");
977
978 if (ioctl(port->fd, TIOCMGET, &data->controlbits) < 0)
979 RETURN_FAIL("TIOCMGET ioctl failed");
980
981#ifdef USE_TERMIOX
982 int ret = get_flow(port->fd, &data->flow);
983
984 if (ret == SP_ERR_FAIL && errno == EINVAL)
985 data->termiox_supported = 0;
986 else if (ret < 0)
987 RETURN_CODEVAL(ret);
988 else
989 data->termiox_supported = 1;
990#else
991 data->termiox_supported = 0;
992#endif
993
994 for (i = 0; i < NUM_STD_BAUDRATES; i++) {
995 if (cfgetispeed(&data->term) == std_baudrates[i].index) {
996 config->baudrate = std_baudrates[i].value;
997 break;
998 }
999 }
1000
1001 if (i == NUM_STD_BAUDRATES) {
1002#ifdef __APPLE__
1003 config->baudrate = (int)data->term.c_ispeed;
1004#elif defined(__linux__)
1005 TRY(get_baudrate(port->fd, &config->baudrate));
1006#else
1007 config->baudrate = -1;
1008#endif
1009 }
1010
1011 switch (data->term.c_cflag & CSIZE) {
1012 case CS8:
1013 config->bits = 8;
1014 break;
1015 case CS7:
1016 config->bits = 7;
1017 break;
1018 case CS6:
1019 config->bits = 6;
1020 break;
1021 case CS5:
1022 config->bits = 5;
1023 break;
1024 default:
1025 config->bits = -1;
1026 }
1027
1028 if (!(data->term.c_cflag & PARENB) && (data->term.c_iflag & IGNPAR))
1029 config->parity = SP_PARITY_NONE;
1030 else if (!(data->term.c_cflag & PARENB) || (data->term.c_iflag & IGNPAR))
1031 config->parity = -1;
1032 else
1033 config->parity = (data->term.c_cflag & PARODD) ? SP_PARITY_ODD : SP_PARITY_EVEN;
1034
1035 config->stopbits = (data->term.c_cflag & CSTOPB) ? 2 : 1;
1036
1037 if (data->term.c_cflag & CRTSCTS) {
1038 config->rts = SP_RTS_FLOW_CONTROL;
1039 config->cts = SP_CTS_FLOW_CONTROL;
1040 } else {
1041 if (data->termiox_supported && data->flow & RTS_FLOW)
1042 config->rts = SP_RTS_FLOW_CONTROL;
1043 else
1044 config->rts = (data->controlbits & TIOCM_RTS) ? SP_RTS_ON : SP_RTS_OFF;
1045
1046 config->cts = (data->termiox_supported && data->flow & CTS_FLOW) ?
1047 SP_CTS_FLOW_CONTROL : SP_CTS_IGNORE;
1048 }
1049
1050 if (data->termiox_supported && data->flow & DTR_FLOW)
1051 config->dtr = SP_DTR_FLOW_CONTROL;
1052 else
1053 config->dtr = (data->controlbits & TIOCM_DTR) ? SP_DTR_ON : SP_DTR_OFF;
1054
1055 config->dsr = (data->termiox_supported && data->flow & DSR_FLOW) ?
1056 SP_DSR_FLOW_CONTROL : SP_DSR_IGNORE;
1057
1058 if (data->term.c_iflag & IXOFF) {
1059 if (data->term.c_iflag & IXON)
1060 config->xon_xoff = SP_XONXOFF_INOUT;
1061 else
1062 config->xon_xoff = SP_XONXOFF_IN;
1063 } else {
1064 if (data->term.c_iflag & IXON)
1065 config->xon_xoff = SP_XONXOFF_OUT;
1066 else
1067 config->xon_xoff = SP_XONXOFF_DISABLED;
1068 }
1069#endif
1070
1071 RETURN_OK();
1072}
1073
1074static enum sp_return set_config(struct sp_port *port, struct port_data *data,
1075 const struct sp_port_config *config)
1076{
1077 unsigned int i;
1078#ifdef __APPLE__
1079 BAUD_TYPE baud_nonstd;
1080
1081 baud_nonstd = B0;
1082#endif
1083#ifdef __linux__
1084 int baud_nonstd = 0;
1085#endif
1086
1087 TRACE("%p, %p, %p", port, data, config);
1088
1089 DEBUG("Setting configuration for port %s", port->name);
1090
1091#ifdef _WIN32
1092 if (config->baudrate >= 0) {
1093 for (i = 0; i < NUM_STD_BAUDRATES; i++) {
1094 if (config->baudrate == std_baudrates[i].value) {
1095 data->dcb.BaudRate = std_baudrates[i].index;
1096 break;
1097 }
1098 }
1099
1100 if (i == NUM_STD_BAUDRATES)
1101 data->dcb.BaudRate = config->baudrate;
1102 }
1103
1104 if (config->bits >= 0)
1105 data->dcb.ByteSize = config->bits;
1106
1107 if (config->parity >= 0) {
1108 switch (config->parity) {
1109 /* Note: There's also SPACEPARITY, MARKPARITY (unneeded so far). */
1110 case SP_PARITY_NONE:
1111 data->dcb.Parity = NOPARITY;
1112 break;
1113 case SP_PARITY_EVEN:
1114 data->dcb.Parity = EVENPARITY;
1115 break;
1116 case SP_PARITY_ODD:
1117 data->dcb.Parity = ODDPARITY;
1118 break;
1119 default:
1120 RETURN_ERROR(SP_ERR_ARG, "Invalid parity setting");
1121 }
1122 }
1123
1124 if (config->stopbits >= 0) {
1125 switch (config->stopbits) {
1126 /* Note: There's also ONE5STOPBITS == 1.5 (unneeded so far). */
1127 case 1:
1128 data->dcb.StopBits = ONESTOPBIT;
1129 break;
1130 case 2:
1131 data->dcb.StopBits = TWOSTOPBITS;
1132 break;
1133 default:
1134 RETURN_ERROR(SP_ERR_ARG, "Invalid stop bit setting");
1135 }
1136 }
1137
1138 if (config->rts >= 0) {
1139 switch (config->rts) {
1140 case SP_RTS_OFF:
1141 data->dcb.fRtsControl = RTS_CONTROL_DISABLE;
1142 break;
1143 case SP_RTS_ON:
1144 data->dcb.fRtsControl = RTS_CONTROL_ENABLE;
1145 break;
1146 case SP_RTS_FLOW_CONTROL:
1147 data->dcb.fRtsControl = RTS_CONTROL_HANDSHAKE;
1148 break;
1149 default:
1150 RETURN_ERROR(SP_ERR_ARG, "Invalid RTS setting");
1151 }
1152 }
1153
1154 if (config->cts >= 0) {
1155 switch (config->cts) {
1156 case SP_CTS_IGNORE:
1157 data->dcb.fOutxCtsFlow = FALSE;
1158 break;
1159 case SP_CTS_FLOW_CONTROL:
1160 data->dcb.fOutxCtsFlow = TRUE;
1161 break;
1162 default:
1163 RETURN_ERROR(SP_ERR_ARG, "Invalid CTS setting");
1164 }
1165 }
1166
1167 if (config->dtr >= 0) {
1168 switch (config->dtr) {
1169 case SP_DTR_OFF:
1170 data->dcb.fDtrControl = DTR_CONTROL_DISABLE;
1171 break;
1172 case SP_DTR_ON:
1173 data->dcb.fDtrControl = DTR_CONTROL_ENABLE;
1174 break;
1175 case SP_DTR_FLOW_CONTROL:
1176 data->dcb.fDtrControl = DTR_CONTROL_HANDSHAKE;
1177 break;
1178 default:
1179 RETURN_ERROR(SP_ERR_ARG, "Invalid DTR setting");
1180 }
1181 }
1182
1183 if (config->dsr >= 0) {
1184 switch (config->dsr) {
1185 case SP_DSR_IGNORE:
1186 data->dcb.fOutxDsrFlow = FALSE;
1187 break;
1188 case SP_DSR_FLOW_CONTROL:
1189 data->dcb.fOutxDsrFlow = TRUE;
1190 break;
1191 default:
1192 RETURN_ERROR(SP_ERR_ARG, "Invalid DSR setting");
1193 }
1194 }
1195
1196 if (config->xon_xoff >= 0) {
1197 switch (config->xon_xoff) {
1198 case SP_XONXOFF_DISABLED:
1199 data->dcb.fInX = FALSE;
1200 data->dcb.fOutX = FALSE;
1201 break;
1202 case SP_XONXOFF_IN:
1203 data->dcb.fInX = TRUE;
1204 data->dcb.fOutX = FALSE;
1205 break;
1206 case SP_XONXOFF_OUT:
1207 data->dcb.fInX = FALSE;
1208 data->dcb.fOutX = TRUE;
1209 break;
1210 case SP_XONXOFF_INOUT:
1211 data->dcb.fInX = TRUE;
1212 data->dcb.fOutX = TRUE;
1213 break;
1214 default:
1215 RETURN_ERROR(SP_ERR_ARG, "Invalid XON/XOFF setting");
1216 }
1217 }
1218
1219 if (!SetCommState(port->hdl, &data->dcb))
1220 RETURN_FAIL("SetCommState() failed");
1221
1222#else /* !_WIN32 */
1223
1224 int controlbits;
1225
1226 if (config->baudrate >= 0) {
1227 for (i = 0; i < NUM_STD_BAUDRATES; i++) {
1228 if (config->baudrate == std_baudrates[i].value) {
1229 if (cfsetospeed(&data->term, std_baudrates[i].index) < 0)
1230 RETURN_FAIL("cfsetospeed() failed");
1231
1232 if (cfsetispeed(&data->term, std_baudrates[i].index) < 0)
1233 RETURN_FAIL("cfsetispeed() failed");
1234 break;
1235 }
1236 }
1237
1238 /* Non-standard baud rate */
1239 if (i == NUM_STD_BAUDRATES) {
1240#ifdef __APPLE__
1241 /* Set "dummy" baud rate. */
1242 if (cfsetspeed(&data->term, B9600) < 0)
1243 RETURN_FAIL("cfsetspeed() failed");
1244 baud_nonstd = config->baudrate;
1245#elif defined(__linux__)
1246 baud_nonstd = 1;
1247#else
1248 RETURN_ERROR(SP_ERR_SUPP, "Non-standard baudrate not supported");
1249#endif
1250 }
1251 }
1252
1253 if (config->bits >= 0) {
1254 data->term.c_cflag &= ~CSIZE;
1255 switch (config->bits) {
1256 case 8:
1257 data->term.c_cflag |= CS8;
1258 break;
1259 case 7:
1260 data->term.c_cflag |= CS7;
1261 break;
1262 case 6:
1263 data->term.c_cflag |= CS6;
1264 break;
1265 case 5:
1266 data->term.c_cflag |= CS5;
1267 break;
1268 default:
1269 RETURN_ERROR(SP_ERR_ARG, "Invalid data bits setting");
1270 }
1271 }
1272
1273 if (config->parity >= 0) {
1274 data->term.c_iflag &= ~IGNPAR;
1275 data->term.c_cflag &= ~(PARENB | PARODD);
1276 switch (config->parity) {
1277 case SP_PARITY_NONE:
1278 data->term.c_iflag |= IGNPAR;
1279 break;
1280 case SP_PARITY_EVEN:
1281 data->term.c_cflag |= PARENB;
1282 break;
1283 case SP_PARITY_ODD:
1284 data->term.c_cflag |= PARENB | PARODD;
1285 break;
1286 default:
1287 RETURN_ERROR(SP_ERR_ARG, "Invalid parity setting");
1288 }
1289 }
1290
1291 if (config->stopbits >= 0) {
1292 data->term.c_cflag &= ~CSTOPB;
1293 switch (config->stopbits) {
1294 case 1:
1295 data->term.c_cflag &= ~CSTOPB;
1296 break;
1297 case 2:
1298 data->term.c_cflag |= CSTOPB;
1299 break;
1300 default:
1301 RETURN_ERROR(SP_ERR_ARG, "Invalid stop bits setting");
1302 }
1303 }
1304
1305 if (config->rts >= 0 || config->cts >= 0) {
1306 if (data->termiox_supported) {
1307 data->flow &= ~(RTS_FLOW | CTS_FLOW);
1308 switch (config->rts) {
1309 case SP_RTS_OFF:
1310 case SP_RTS_ON:
1311 controlbits = TIOCM_RTS;
1312 if (ioctl(port->fd, config->rts == SP_RTS_ON ? TIOCMBIS : TIOCMBIC, &controlbits) < 0)
1313 RETURN_FAIL("Setting RTS signal level failed");
1314 break;
1315 case SP_RTS_FLOW_CONTROL:
1316 data->flow |= RTS_FLOW;
1317 break;
1318 default:
1319 break;
1320 }
1321 if (config->cts == SP_CTS_FLOW_CONTROL)
1322 data->flow |= CTS_FLOW;
1323
1324 if (data->flow & (RTS_FLOW | CTS_FLOW))
1325 data->term.c_iflag |= CRTSCTS;
1326 else
1327 data->term.c_iflag &= ~CRTSCTS;
1328 } else {
1329 /* Asymmetric use of RTS/CTS not supported. */
1330 if (data->term.c_iflag & CRTSCTS) {
1331 /* Flow control can only be disabled for both RTS & CTS together. */
1332 if (config->rts >= 0 && config->rts != SP_RTS_FLOW_CONTROL) {
1333 if (config->cts != SP_CTS_IGNORE)
1334 RETURN_ERROR(SP_ERR_SUPP, "RTS & CTS flow control must be disabled together");
1335 }
1336 if (config->cts >= 0 && config->cts != SP_CTS_FLOW_CONTROL) {
1337 if (config->rts <= 0 || config->rts == SP_RTS_FLOW_CONTROL)
1338 RETURN_ERROR(SP_ERR_SUPP, "RTS & CTS flow control must be disabled together");
1339 }
1340 } else {
1341 /* Flow control can only be enabled for both RTS & CTS together. */
1342 if (((config->rts == SP_RTS_FLOW_CONTROL) && (config->cts != SP_CTS_FLOW_CONTROL)) ||
1343 ((config->cts == SP_CTS_FLOW_CONTROL) && (config->rts != SP_RTS_FLOW_CONTROL)))
1344 RETURN_ERROR(SP_ERR_SUPP, "RTS & CTS flow control must be enabled together");
1345 }
1346
1347 if (config->rts >= 0) {
1348 if (config->rts == SP_RTS_FLOW_CONTROL) {
1349 data->term.c_iflag |= CRTSCTS;
1350 } else {
1351 controlbits = TIOCM_RTS;
1352 if (ioctl(port->fd, config->rts == SP_RTS_ON ? TIOCMBIS : TIOCMBIC,
1353 &controlbits) < 0)
1354 RETURN_FAIL("Setting RTS signal level failed");
1355 }
1356 }
1357 }
1358 }
1359
1360 if (config->dtr >= 0 || config->dsr >= 0) {
1361 if (data->termiox_supported) {
1362 data->flow &= ~(DTR_FLOW | DSR_FLOW);
1363 switch (config->dtr) {
1364 case SP_DTR_OFF:
1365 case SP_DTR_ON:
1366 controlbits = TIOCM_DTR;
1367 if (ioctl(port->fd, config->dtr == SP_DTR_ON ? TIOCMBIS : TIOCMBIC, &controlbits) < 0)
1368 RETURN_FAIL("Setting DTR signal level failed");
1369 break;
1370 case SP_DTR_FLOW_CONTROL:
1371 data->flow |= DTR_FLOW;
1372 break;
1373 default:
1374 break;
1375 }
1376 if (config->dsr == SP_DSR_FLOW_CONTROL)
1377 data->flow |= DSR_FLOW;
1378 } else {
1379 /* DTR/DSR flow control not supported. */
1380 if (config->dtr == SP_DTR_FLOW_CONTROL || config->dsr == SP_DSR_FLOW_CONTROL)
1381 RETURN_ERROR(SP_ERR_SUPP, "DTR/DSR flow control not supported");
1382
1383 if (config->dtr >= 0) {
1384 controlbits = TIOCM_DTR;
1385 if (ioctl(port->fd, config->dtr == SP_DTR_ON ? TIOCMBIS : TIOCMBIC,
1386 &controlbits) < 0)
1387 RETURN_FAIL("Setting DTR signal level failed");
1388 }
1389 }
1390 }
1391
1392 if (config->xon_xoff >= 0) {
1393 data->term.c_iflag &= ~(IXON | IXOFF | IXANY);
1394 switch (config->xon_xoff) {
1395 case SP_XONXOFF_DISABLED:
1396 break;
1397 case SP_XONXOFF_IN:
1398 data->term.c_iflag |= IXOFF;
1399 break;
1400 case SP_XONXOFF_OUT:
1401 data->term.c_iflag |= IXON | IXANY;
1402 break;
1403 case SP_XONXOFF_INOUT:
1404 data->term.c_iflag |= IXON | IXOFF | IXANY;
1405 break;
1406 default:
1407 RETURN_ERROR(SP_ERR_ARG, "Invalid XON/XOFF setting");
1408 }
1409 }
1410
1411 if (tcsetattr(port->fd, TCSADRAIN, &data->term) < 0)
1412 RETURN_FAIL("tcsetattr() failed");
1413
1414#ifdef __APPLE__
1415 if (baud_nonstd != B0) {
1416 if (ioctl(port->fd, IOSSIOSPEED, &baud_nonstd) == -1)
1417 RETURN_FAIL("IOSSIOSPEED ioctl failed");
1418 /* Set baud rates in data->term to correct, but incompatible
1419 * with tcsetattr() value, same as delivered by tcgetattr(). */
1420 if (cfsetspeed(&data->term, baud_nonstd) < 0)
1421 RETURN_FAIL("cfsetspeed() failed");
1422 }
1423#elif defined(__linux__)
1424 if (baud_nonstd)
1425 TRY(set_baudrate(port->fd, config->baudrate));
1426#ifdef USE_TERMIOX
1427 if (data->termiox_supported)
1428 TRY(set_flow(port->fd, data->flow));
1429#endif
1430#endif
1431
1432#endif /* !_WIN32 */
1433
1434 RETURN_OK();
1435}
1436
1437enum sp_return sp_get_config(struct sp_port *port, struct sp_port_config *config)
1438{
1439 struct port_data data;
1440
1441 TRACE("%p, %p", port, config);
1442
1443 CHECK_OPEN_PORT();
1444
1445 if (!config)
1446 RETURN_ERROR(SP_ERR_ARG, "Null result pointer");
1447
1448 TRY(get_config(port, &data, config));
1449
1450 RETURN_OK();
1451}
1452
1453enum sp_return sp_set_config(struct sp_port *port, const struct sp_port_config *config)
1454{
1455 struct port_data data;
1456 struct sp_port_config prev_config;
1457
1458 TRACE("%p, %p", port, config);
1459
1460 CHECK_OPEN_PORT();
1461
1462 if (!config)
1463 RETURN_ERROR(SP_ERR_ARG, "Null config");
1464
1465 TRY(get_config(port, &data, &prev_config));
1466 TRY(set_config(port, &data, config));
1467
1468 RETURN_OK();
1469}
1470
1471#define CREATE_SETTER(x, type) int sp_set_##x(struct sp_port *port, type x) { \
1472 struct port_data data; \
1473 struct sp_port_config config; \
1474 TRACE("%p, %d", port, x); \
1475 CHECK_OPEN_PORT(); \
1476 TRY(get_config(port, &data, &config)); \
1477 config.x = x; \
1478 TRY(set_config(port, &data, &config)); \
1479 RETURN_OK(); \
1480}
1481
1482CREATE_SETTER(baudrate, int)
1483CREATE_SETTER(bits, int)
1484CREATE_SETTER(parity, enum sp_parity)
1485CREATE_SETTER(stopbits, int)
1486CREATE_SETTER(rts, enum sp_rts)
1487CREATE_SETTER(cts, enum sp_cts)
1488CREATE_SETTER(dtr, enum sp_dtr)
1489CREATE_SETTER(dsr, enum sp_dsr)
1490CREATE_SETTER(xon_xoff, enum sp_xonxoff)
1491
1492enum sp_return sp_set_flowcontrol(struct sp_port *port, enum sp_flowcontrol flowcontrol)
1493{
1494 struct port_data data;
1495 struct sp_port_config config;
1496
1497 TRACE("%p, %d", port, flowcontrol);
1498
1499 CHECK_OPEN_PORT();
1500
1501 if (flowcontrol > SP_FLOWCONTROL_DTRDSR)
1502 RETURN_ERROR(SP_ERR_ARG, "Invalid flow control setting");
1503
1504 TRY(get_config(port, &data, &config));
1505
1506 if (flowcontrol == SP_FLOWCONTROL_XONXOFF)
1507 config.xon_xoff = SP_XONXOFF_INOUT;
1508 else
1509 config.xon_xoff = SP_XONXOFF_DISABLED;
1510
1511 if (flowcontrol == SP_FLOWCONTROL_RTSCTS) {
1512 config.rts = SP_RTS_FLOW_CONTROL;
1513 config.cts = SP_CTS_FLOW_CONTROL;
1514 } else {
1515 if (config.rts == SP_RTS_FLOW_CONTROL)
1516 config.rts = SP_RTS_ON;
1517 config.cts = SP_CTS_IGNORE;
1518 }
1519
1520 if (flowcontrol == SP_FLOWCONTROL_DTRDSR) {
1521 config.dtr = SP_DTR_FLOW_CONTROL;
1522 config.dsr = SP_DSR_FLOW_CONTROL;
1523 } else {
1524 if (config.dtr == SP_DTR_FLOW_CONTROL)
1525 config.dtr = SP_DTR_ON;
1526 config.dsr = SP_DSR_IGNORE;
1527 }
1528
1529 TRY(set_config(port, &data, &config));
1530
1531 RETURN_OK();
1532}
1533
1534enum sp_return sp_get_signals(struct sp_port *port, enum sp_signal *signals)
1535{
1536 TRACE("%p, %p", port, signals);
1537
1538 CHECK_OPEN_PORT();
1539
1540 if (!signals)
1541 RETURN_ERROR(SP_ERR_ARG, "Null result pointer");
1542
1543 DEBUG("Getting control signals for port %s", port->name);
1544
1545 *signals = 0;
1546#ifdef _WIN32
1547 DWORD bits;
1548 if (GetCommModemStatus(port->hdl, &bits) == 0)
1549 RETURN_FAIL("GetCommModemStatus() failed");
1550 if (bits & MS_CTS_ON)
1551 *signals |= SP_SIG_CTS;
1552 if (bits & MS_DSR_ON)
1553 *signals |= SP_SIG_DSR;
1554 if (bits & MS_RLSD_ON)
1555 *signals |= SP_SIG_DCD;
1556 if (bits & MS_RING_ON)
1557 *signals |= SP_SIG_RI;
1558#else
1559 int bits;
1560 if (ioctl(port->fd, TIOCMGET, &bits) < 0)
1561 RETURN_FAIL("TIOCMGET ioctl failed");
1562 if (bits & TIOCM_CTS)
1563 *signals |= SP_SIG_CTS;
1564 if (bits & TIOCM_DSR)
1565 *signals |= SP_SIG_DSR;
1566 if (bits & TIOCM_CAR)
1567 *signals |= SP_SIG_DCD;
1568 if (bits & TIOCM_RNG)
1569 *signals |= SP_SIG_RI;
1570#endif
1571 RETURN_OK();
1572}
1573
1574enum sp_return sp_start_break(struct sp_port *port)
1575{
1576 TRACE("%p", port);
1577
1578 CHECK_OPEN_PORT();
1579#ifdef _WIN32
1580 if (SetCommBreak(port->hdl) == 0)
1581 RETURN_FAIL("SetCommBreak() failed");
1582#else
1583 if (ioctl(port->fd, TIOCSBRK, 1) < 0)
1584 RETURN_FAIL("TIOCSBRK ioctl failed");
1585#endif
1586
1587 RETURN_OK();
1588}
1589
1590enum sp_return sp_end_break(struct sp_port *port)
1591{
1592 TRACE("%p", port);
1593
1594 CHECK_OPEN_PORT();
1595#ifdef _WIN32
1596 if (ClearCommBreak(port->hdl) == 0)
1597 RETURN_FAIL("ClearCommBreak() failed");
1598#else
1599 if (ioctl(port->fd, TIOCCBRK, 1) < 0)
1600 RETURN_FAIL("TIOCCBRK ioctl failed");
1601#endif
1602
1603 RETURN_OK();
1604}
1605
1606int sp_last_error_code(void)
1607{
1608 TRACE("");
1609#ifdef _WIN32
1610 RETURN_VALUE("%d", GetLastError());
1611#else
1612 RETURN_VALUE("%d", errno);
1613#endif
1614}
1615
1616char *sp_last_error_message(void)
1617{
1618 TRACE("");
1619
1620#ifdef _WIN32
1621 LPVOID message;
1622 DWORD error = GetLastError();
1623
1624 FormatMessage(
1625 FORMAT_MESSAGE_ALLOCATE_BUFFER |
1626 FORMAT_MESSAGE_FROM_SYSTEM |
1627 FORMAT_MESSAGE_IGNORE_INSERTS,
1628 NULL,
1629 error,
1630 MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
1631 (LPTSTR) &message,
1632 0, NULL );
1633
1634 RETURN_VALUE("%s", message);
1635#else
1636 RETURN_VALUE("%s", strerror(errno));
1637#endif
1638}
1639
1640void sp_free_error_message(char *message)
1641{
1642 TRACE("%s", message);
1643
1644#ifdef _WIN32
1645 LocalFree(message);
1646#else
1647 (void)message;
1648#endif
1649
1650 RETURN();
1651}
1652
1653void sp_set_debug_handler(void (*handler)(const char *format, ...))
1654{
1655 TRACE("%p", handler);
1656
1657 sp_debug_handler = handler;
1658
1659 RETURN();
1660}
1661
1662void sp_default_debug_handler(const char *format, ...)
1663{
1664 va_list args;
1665 va_start(args, format);
1666 if (getenv("LIBSERIALPORT_DEBUG")) {
1667 fputs("libserialport: ", stderr);
1668 vfprintf(stderr, format, args);
1669 }
1670 va_end(args);
1671}