2 * This file is part of the libsigrok project.
4 * Copyright (C) 2010-2012 Bert Vermeulen <bert@biot.com>
5 * Copyright (C) 2010-2012 Uwe Hermann <uwe@hermann-uwe.de>
6 * Copyright (C) 2012 Alexandru Gagniuc <mr.nuke.me@gmail.com>
7 * Copyright (C) 2014 Uffe Jakobsen <uffe@uffe.org>
9 * This program is free software: you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License as published by
11 * the Free Software Foundation, either version 3 of the License, or
12 * (at your option) any later version.
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU General Public License for more details.
19 * You should have received a copy of the GNU General Public License
20 * along with this program. If not, see <http://www.gnu.org/licenses/>.
25 #include <libsigrok/libsigrok.h>
26 #include "libsigrok-internal.h"
27 #ifdef HAVE_LIBSERIALPORT
28 #include <libserialport.h>
31 #include <windows.h> /* for HANDLE */
34 #define LOG_PREFIX "serial-libsp"
39 * Serial port handling, wraps the external libserialport dependency.
42 #ifdef HAVE_LIBSERIALPORT
45 * @defgroup grp_serial_libsp Serial port handling, libserialport group
47 * Serial port handling functions, based on libserialport.
52 static int sr_ser_libsp_open(struct sr_serial_dev_inst *serial, int flags)
58 sp_get_port_by_name(serial->port, &serial->sp_data);
61 if (flags & SERIAL_RDWR)
62 sp_flags = (SP_MODE_READ | SP_MODE_WRITE);
63 else if (flags & SERIAL_RDONLY)
64 sp_flags = SP_MODE_READ;
66 ret = sp_open(serial->sp_data, sp_flags);
70 sr_err("Attempt to open serial port with invalid parameters.");
73 error = sp_last_error_message();
74 sr_err("Error opening port (%d): %s.",
75 sp_last_error_code(), error);
76 sp_free_error_message(error);
83 static int sr_ser_libsp_close(struct sr_serial_dev_inst *serial)
88 if (!serial->sp_data) {
89 sr_dbg("Cannot close unopened serial port %s.", serial->port);
93 ret = sp_close(serial->sp_data);
97 sr_err("Attempt to close an invalid serial port.");
100 error = sp_last_error_message();
101 sr_err("Error closing port (%d): %s.",
102 sp_last_error_code(), error);
103 sp_free_error_message(error);
107 sp_free_port(serial->sp_data);
108 serial->sp_data = NULL;
113 static int sr_ser_libsp_flush(struct sr_serial_dev_inst *serial)
118 if (!serial->sp_data) {
119 sr_dbg("Cannot flush unopened serial port %s.", serial->port);
123 ret = sp_flush(serial->sp_data, SP_BUF_BOTH);
127 sr_err("Attempt to flush an invalid serial port.");
130 error = sp_last_error_message();
131 sr_err("Error flushing port (%d): %s.",
132 sp_last_error_code(), error);
133 sp_free_error_message(error);
140 static int sr_ser_libsp_drain(struct sr_serial_dev_inst *serial)
145 if (!serial->sp_data) {
146 sr_dbg("Cannot drain unopened serial port %s.", serial->port);
150 ret = sp_drain(serial->sp_data);
152 if (ret == SP_ERR_FAIL) {
153 error = sp_last_error_message();
154 sr_err("Error draining port (%d): %s.",
155 sp_last_error_code(), error);
156 sp_free_error_message(error);
163 static int sr_ser_libsp_write(struct sr_serial_dev_inst *serial,
164 const void *buf, size_t count,
165 int nonblocking, unsigned int timeout_ms)
170 if (!serial->sp_data) {
171 sr_dbg("Cannot use unopened serial port %s.", serial->port);
176 ret = sp_nonblocking_write(serial->sp_data, buf, count);
178 ret = sp_blocking_write(serial->sp_data, buf, count, timeout_ms);
182 sr_err("Attempted serial port write with invalid arguments.");
185 error = sp_last_error_message();
186 sr_err("Write error (%d): %s.", sp_last_error_code(), error);
187 sp_free_error_message(error);
194 static int sr_ser_libsp_read(struct sr_serial_dev_inst *serial,
195 void *buf, size_t count,
196 int nonblocking, unsigned int timeout_ms)
201 if (!serial->sp_data) {
202 sr_dbg("Cannot use unopened serial port %s.", serial->port);
207 ret = sp_nonblocking_read(serial->sp_data, buf, count);
209 ret = sp_blocking_read(serial->sp_data, buf, count, timeout_ms);
213 sr_err("Attempted serial port read with invalid arguments.");
216 error = sp_last_error_message();
217 sr_err("Read error (%d): %s.", sp_last_error_code(), error);
218 sp_free_error_message(error);
225 static int sr_ser_libsp_set_params(struct sr_serial_dev_inst *serial,
226 int baudrate, int bits, int parity, int stopbits,
227 int flowcontrol, int rts, int dtr)
231 struct sp_port_config *config;
234 if (!serial->sp_data) {
235 sr_dbg("Cannot configure unopened serial port %s.", serial->port);
239 sp_new_config(&config);
240 sp_set_config_baudrate(config, baudrate);
241 sp_set_config_bits(config, bits);
244 sp_set_config_parity(config, SP_PARITY_NONE);
247 sp_set_config_parity(config, SP_PARITY_EVEN);
250 sp_set_config_parity(config, SP_PARITY_ODD);
255 sp_set_config_stopbits(config, stopbits);
256 rts = flowcontrol == 1 ? SP_RTS_FLOW_CONTROL : rts;
257 sp_set_config_rts(config, rts);
258 cts = flowcontrol == 1 ? SP_CTS_FLOW_CONTROL : SP_CTS_IGNORE;
259 sp_set_config_cts(config, cts);
260 sp_set_config_dtr(config, dtr);
261 sp_set_config_dsr(config, SP_DSR_IGNORE);
262 xonoff = flowcontrol == 2 ? SP_XONXOFF_INOUT : SP_XONXOFF_DISABLED;
263 sp_set_config_xon_xoff(config, xonoff);
265 ret = sp_set_config(serial->sp_data, config);
266 sp_free_config(config);
270 sr_err("Invalid arguments for setting serial port parameters.");
273 error = sp_last_error_message();
274 sr_err("Error setting serial port parameters (%d): %s.",
275 sp_last_error_code(), error);
276 sp_free_error_message(error);
284 typedef HANDLE event_handle;
286 typedef int event_handle;
289 static int sr_ser_libsp_source_add_int(struct sr_serial_dev_inst *serial,
291 void **keyptr, gintptr *fdptr, unsigned int *pollevtptr)
293 struct sp_event_set *event_set;
295 unsigned int poll_events;
298 if ((events & (G_IO_IN | G_IO_ERR)) && (events & G_IO_OUT)) {
299 sr_err("Cannot poll input/error and output simultaneously.");
302 if (!serial->sp_data) {
303 sr_err("Invalid serial port.");
307 if (sp_new_event_set(&event_set) != SP_OK)
311 if (events & G_IO_IN)
312 mask |= SP_EVENT_RX_READY;
313 if (events & G_IO_OUT)
314 mask |= SP_EVENT_TX_READY;
315 if (events & G_IO_ERR)
316 mask |= SP_EVENT_ERROR;
318 if (sp_add_port_events(event_set, serial->sp_data, mask) != SP_OK) {
319 sp_free_event_set(event_set);
322 if (event_set->count != 1) {
323 sr_err("Unexpected number (%u) of event handles to poll.",
325 sp_free_event_set(event_set);
329 poll_fd = (gintptr) ((event_handle *)event_set->handles)[0];
330 mask = event_set->masks[0];
332 sp_free_event_set(event_set);
335 if (mask & SP_EVENT_RX_READY)
336 poll_events |= G_IO_IN;
337 if (mask & SP_EVENT_TX_READY)
338 poll_events |= G_IO_OUT;
339 if (mask & SP_EVENT_ERROR)
340 poll_events |= G_IO_ERR;
343 * Using serial->sp_data as the key for the event source is not quite
344 * proper, as it makes it impossible to create another event source
345 * for the same serial port. However, these fixed keys will soon be
346 * removed from the API anyway, so this is OK for now.
348 *keyptr = serial->sp_data;
350 *pollevtptr = poll_events;
355 static int sr_ser_libsp_source_add(struct sr_session *session,
356 struct sr_serial_dev_inst *serial, int events, int timeout,
357 sr_receive_data_callback cb, void *cb_data)
362 unsigned int poll_events;
364 ret = sr_ser_libsp_source_add_int(serial, events,
365 &key, &poll_fd, &poll_events);
369 return sr_session_fd_source_add(session,
370 key, poll_fd, poll_events,
371 timeout, cb, cb_data);
374 static int sr_ser_libsp_source_remove(struct sr_session *session,
375 struct sr_serial_dev_inst *serial)
379 key = serial->sp_data;
380 return sr_session_source_remove_internal(session, key);
383 static GSList *sr_ser_libsp_list(GSList *list, sr_ser_list_append_t append)
385 struct sp_port **ports;
390 if (sp_list_ports(&ports) != SP_OK)
393 for (i = 0; ports[i]; i++) {
394 name = sp_get_port_name(ports[i]);
395 desc = sp_get_port_description(ports[i]);
396 list = append(list, name, desc);
399 sp_free_port_list(ports);
404 static GSList *sr_ser_libsp_find_usb(GSList *list, sr_ser_find_append_t append,
405 uint16_t vendor_id, uint16_t product_id)
407 struct sp_port **ports;
410 if (sp_list_ports(&ports) != SP_OK)
413 for (i = 0; ports[i]; i++) {
414 if (sp_get_port_transport(ports[i]) != SP_TRANSPORT_USB)
416 if (sp_get_port_usb_vid_pid(ports[i], &vid, &pid) != SP_OK)
418 if (vendor_id && vid != vendor_id)
420 if (product_id && pid != product_id)
422 list = append(list, sp_get_port_name(ports[i]));
425 sp_free_port_list(ports);
430 static int sr_ser_libsp_get_frame_format(struct sr_serial_dev_inst *serial,
431 int *baud, int *bits)
433 struct sp_port_config *config;
435 enum sp_parity parity;
437 if (sp_new_config(&config) < 0)
438 return SR_ERR_MALLOC;
442 if (sp_get_config(serial->sp_data, config) < 0) {
447 if (sp_get_config_baudrate(config, &tmp) < 0) {
453 *bits += 1; /* Start bit. */
454 if (sp_get_config_bits(config, &tmp) < 0) {
459 if (sp_get_config_parity(config, &parity) < 0) {
463 *bits += (parity != SP_PARITY_NONE) ? 1 : 0;
464 if (sp_get_config_stopbits(config, &tmp) < 0) {
470 sp_free_config(config);
475 static size_t sr_ser_libsp_get_rx_avail(struct sr_serial_dev_inst *serial)
482 rc = sp_input_waiting(serial->sp_data);
489 static struct ser_lib_functions serlib_sp = {
490 .open = sr_ser_libsp_open,
491 .close = sr_ser_libsp_close,
492 .flush = sr_ser_libsp_flush,
493 .drain = sr_ser_libsp_drain,
494 .write = sr_ser_libsp_write,
495 .read = sr_ser_libsp_read,
496 .set_params = sr_ser_libsp_set_params,
497 .setup_source_add = sr_ser_libsp_source_add,
498 .setup_source_remove = sr_ser_libsp_source_remove,
499 .list = sr_ser_libsp_list,
500 .find_usb = sr_ser_libsp_find_usb,
501 .get_frame_format = sr_ser_libsp_get_frame_format,
502 .get_rx_avail = sr_ser_libsp_get_rx_avail,
504 SR_PRIV struct ser_lib_functions *ser_lib_funcs_libsp = &serlib_sp;
508 SR_PRIV struct ser_lib_functions *ser_lib_funcs_libsp = NULL;