libsigrok  0.5.2
sigrok hardware access and backend library
serial_libsp.c
Go to the documentation of this file.
1 /*
2  * This file is part of the libsigrok 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) 2012 Alexandru Gagniuc <mr.nuke.me@gmail.com>
7  * Copyright (C) 2014 Uffe Jakobsen <uffe@uffe.org>
8  *
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.
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 General Public License
20  * along with this program. If not, see <http://www.gnu.org/licenses/>.
21  */
22 
23 #include <config.h>
24 #include <glib.h>
25 #include <libsigrok/libsigrok.h>
26 #include "libsigrok-internal.h"
27 #ifdef HAVE_LIBSERIALPORT
28 #include <libserialport.h>
29 #endif
30 #ifdef G_OS_WIN32
31 #include <windows.h> /* for HANDLE */
32 #endif
33 
34 /** @cond PRIVATE */
35 #define LOG_PREFIX "serial-libsp"
36 /** @endcond */
37 
38 /**
39  * @file
40  *
41  * Serial port handling, wraps the external libserialport dependency.
42  */
43 
44 #ifdef HAVE_LIBSERIALPORT
45 
46 /**
47  * @defgroup grp_serial_libsp Serial port handling, libserialport group
48  *
49  * Serial port handling functions, based on libserialport.
50  *
51  * @{
52  */
53 
54 static int sr_ser_libsp_open(struct sr_serial_dev_inst *serial, int flags)
55 {
56  int ret;
57  char *error;
58  int sp_flags;
59 
60  sp_get_port_by_name(serial->port, &serial->sp_data);
61 
62  sp_flags = 0;
63  if (flags & SERIAL_RDWR)
64  sp_flags = (SP_MODE_READ | SP_MODE_WRITE);
65  else if (flags & SERIAL_RDONLY)
66  sp_flags = SP_MODE_READ;
67 
68  ret = sp_open(serial->sp_data, sp_flags);
69 
70  switch (ret) {
71  case SP_ERR_ARG:
72  sr_err("Attempt to open serial port with invalid parameters.");
73  return SR_ERR_ARG;
74  case SP_ERR_FAIL:
75  error = sp_last_error_message();
76  sr_err("Error opening port (%d): %s.",
77  sp_last_error_code(), error);
78  sp_free_error_message(error);
79  return SR_ERR;
80  }
81 
82  return SR_OK;
83 }
84 
85 static int sr_ser_libsp_close(struct sr_serial_dev_inst *serial)
86 {
87  int ret;
88  char *error;
89 
90  if (!serial->sp_data) {
91  sr_dbg("Cannot close unopened serial port %s.", serial->port);
92  return SR_ERR;
93  }
94 
95  ret = sp_close(serial->sp_data);
96 
97  switch (ret) {
98  case SP_ERR_ARG:
99  sr_err("Attempt to close an invalid serial port.");
100  return SR_ERR_ARG;
101  case SP_ERR_FAIL:
102  error = sp_last_error_message();
103  sr_err("Error closing port (%d): %s.",
104  sp_last_error_code(), error);
105  sp_free_error_message(error);
106  return SR_ERR;
107  }
108 
109  sp_free_port(serial->sp_data);
110  serial->sp_data = NULL;
111 
112  return SR_OK;
113 }
114 
115 static int sr_ser_libsp_flush(struct sr_serial_dev_inst *serial)
116 {
117  int ret;
118  char *error;
119 
120  if (!serial->sp_data) {
121  sr_dbg("Cannot flush unopened serial port %s.", serial->port);
122  return SR_ERR;
123  }
124 
125  ret = sp_flush(serial->sp_data, SP_BUF_BOTH);
126 
127  switch (ret) {
128  case SP_ERR_ARG:
129  sr_err("Attempt to flush an invalid serial port.");
130  return SR_ERR_ARG;
131  case SP_ERR_FAIL:
132  error = sp_last_error_message();
133  sr_err("Error flushing port (%d): %s.",
134  sp_last_error_code(), error);
135  sp_free_error_message(error);
136  return SR_ERR;
137  }
138 
139  return SR_OK;
140 }
141 
142 static int sr_ser_libsp_drain(struct sr_serial_dev_inst *serial)
143 {
144  int ret;
145  char *error;
146 
147  if (!serial->sp_data) {
148  sr_dbg("Cannot drain unopened serial port %s.", serial->port);
149  return SR_ERR;
150  }
151 
152  ret = sp_drain(serial->sp_data);
153 
154  if (ret == SP_ERR_FAIL) {
155  error = sp_last_error_message();
156  sr_err("Error draining port (%d): %s.",
157  sp_last_error_code(), error);
158  sp_free_error_message(error);
159  return SR_ERR;
160  }
161 
162  return SR_OK;
163 }
164 
165 static int sr_ser_libsp_write(struct sr_serial_dev_inst *serial,
166  const void *buf, size_t count,
167  int nonblocking, unsigned int timeout_ms)
168 {
169  ssize_t ret;
170  char *error;
171 
172  if (!serial->sp_data) {
173  sr_dbg("Cannot use unopened serial port %s.", serial->port);
174  return SR_ERR;
175  }
176 
177  if (nonblocking)
178  ret = sp_nonblocking_write(serial->sp_data, buf, count);
179  else
180  ret = sp_blocking_write(serial->sp_data, buf, count, timeout_ms);
181 
182  switch (ret) {
183  case SP_ERR_ARG:
184  sr_err("Attempted serial port write with invalid arguments.");
185  return SR_ERR_ARG;
186  case SP_ERR_FAIL:
187  error = sp_last_error_message();
188  sr_err("Write error (%d): %s.", sp_last_error_code(), error);
189  sp_free_error_message(error);
190  return SR_ERR;
191  }
192 
193  return ret;
194 }
195 
196 static int sr_ser_libsp_read(struct sr_serial_dev_inst *serial,
197  void *buf, size_t count,
198  int nonblocking, unsigned int timeout_ms)
199 {
200  ssize_t ret;
201  char *error;
202 
203  if (!serial->sp_data) {
204  sr_dbg("Cannot use unopened serial port %s.", serial->port);
205  return SR_ERR;
206  }
207 
208  if (nonblocking)
209  ret = sp_nonblocking_read(serial->sp_data, buf, count);
210  else
211  ret = sp_blocking_read(serial->sp_data, buf, count, timeout_ms);
212 
213  switch (ret) {
214  case SP_ERR_ARG:
215  sr_err("Attempted serial port read with invalid arguments.");
216  return SR_ERR_ARG;
217  case SP_ERR_FAIL:
218  error = sp_last_error_message();
219  sr_err("Read error (%d): %s.", sp_last_error_code(), error);
220  sp_free_error_message(error);
221  return SR_ERR;
222  }
223 
224  return ret;
225 }
226 
227 static int sr_ser_libsp_set_params(struct sr_serial_dev_inst *serial,
228  int baudrate, int bits, int parity, int stopbits,
229  int flowcontrol, int rts, int dtr)
230 {
231  int ret;
232  char *error;
233  struct sp_port_config *config;
234  int cts, xonoff;
235 
236  if (!serial->sp_data) {
237  sr_dbg("Cannot configure unopened serial port %s.", serial->port);
238  return SR_ERR;
239  }
240 
241  sp_new_config(&config);
242  sp_set_config_baudrate(config, baudrate);
243  sp_set_config_bits(config, bits);
244  switch (parity) {
245  case 0:
246  sp_set_config_parity(config, SP_PARITY_NONE);
247  break;
248  case 1:
249  sp_set_config_parity(config, SP_PARITY_EVEN);
250  break;
251  case 2:
252  sp_set_config_parity(config, SP_PARITY_ODD);
253  break;
254  default:
255  return SR_ERR_ARG;
256  }
257  sp_set_config_stopbits(config, stopbits);
258  rts = flowcontrol == 1 ? SP_RTS_FLOW_CONTROL : rts;
259  sp_set_config_rts(config, rts);
260  cts = flowcontrol == 1 ? SP_CTS_FLOW_CONTROL : SP_CTS_IGNORE;
261  sp_set_config_cts(config, cts);
262  sp_set_config_dtr(config, dtr);
263  sp_set_config_dsr(config, SP_DSR_IGNORE);
264  xonoff = flowcontrol == 2 ? SP_XONXOFF_INOUT : SP_XONXOFF_DISABLED;
265  sp_set_config_xon_xoff(config, xonoff);
266 
267  ret = sp_set_config(serial->sp_data, config);
268  sp_free_config(config);
269 
270  switch (ret) {
271  case SP_ERR_ARG:
272  sr_err("Invalid arguments for setting serial port parameters.");
273  return SR_ERR_ARG;
274  case SP_ERR_FAIL:
275  error = sp_last_error_message();
276  sr_err("Error setting serial port parameters (%d): %s.",
277  sp_last_error_code(), error);
278  sp_free_error_message(error);
279  return SR_ERR;
280  }
281 
282  return SR_OK;
283 }
284 
285 /** @cond PRIVATE */
286 #ifdef G_OS_WIN32
287 typedef HANDLE event_handle;
288 #else
289 typedef int event_handle;
290 #endif
291 /** @endcond */
292 
293 static int sr_ser_libsp_source_add_int(struct sr_serial_dev_inst *serial,
294  int events,
295  void **keyptr, gintptr *fdptr, unsigned int *pollevtptr)
296 {
297  struct sp_event_set *event_set;
298  gintptr poll_fd;
299  unsigned int poll_events;
300  enum sp_event mask;
301 
302  if ((events & (G_IO_IN | G_IO_ERR)) && (events & G_IO_OUT)) {
303  sr_err("Cannot poll input/error and output simultaneously.");
304  return SR_ERR_ARG;
305  }
306  if (!serial->sp_data) {
307  sr_err("Invalid serial port.");
308  return SR_ERR_ARG;
309  }
310 
311  if (sp_new_event_set(&event_set) != SP_OK)
312  return SR_ERR;
313 
314  mask = 0;
315  if (events & G_IO_IN)
316  mask |= SP_EVENT_RX_READY;
317  if (events & G_IO_OUT)
318  mask |= SP_EVENT_TX_READY;
319  if (events & G_IO_ERR)
320  mask |= SP_EVENT_ERROR;
321 
322  if (sp_add_port_events(event_set, serial->sp_data, mask) != SP_OK) {
323  sp_free_event_set(event_set);
324  return SR_ERR;
325  }
326  if (event_set->count != 1) {
327  sr_err("Unexpected number (%u) of event handles to poll.",
328  event_set->count);
329  sp_free_event_set(event_set);
330  return SR_ERR;
331  }
332 
333  poll_fd = (gintptr) ((event_handle *)event_set->handles)[0];
334  mask = event_set->masks[0];
335 
336  sp_free_event_set(event_set);
337 
338  poll_events = 0;
339  if (mask & SP_EVENT_RX_READY)
340  poll_events |= G_IO_IN;
341  if (mask & SP_EVENT_TX_READY)
342  poll_events |= G_IO_OUT;
343  if (mask & SP_EVENT_ERROR)
344  poll_events |= G_IO_ERR;
345 
346  /*
347  * Using serial->sp_data as the key for the event source is not quite
348  * proper, as it makes it impossible to create another event source
349  * for the same serial port. However, these fixed keys will soon be
350  * removed from the API anyway, so this is OK for now.
351  */
352  *keyptr = serial->sp_data;
353  *fdptr = poll_fd;
354  *pollevtptr = poll_events;
355 
356  return SR_OK;
357 }
358 
359 static int sr_ser_libsp_source_add(struct sr_session *session,
360  struct sr_serial_dev_inst *serial, int events, int timeout,
361  sr_receive_data_callback cb, void *cb_data)
362 {
363  int ret;
364  void *key;
365  gintptr poll_fd;
366  unsigned int poll_events;
367 
368  ret = sr_ser_libsp_source_add_int(serial, events,
369  &key, &poll_fd, &poll_events);
370  if (ret != SR_OK)
371  return ret;
372 
373  return sr_session_fd_source_add(session,
374  key, poll_fd, poll_events,
375  timeout, cb, cb_data);
376 }
377 
378 static int sr_ser_libsp_source_remove(struct sr_session *session,
379  struct sr_serial_dev_inst *serial)
380 {
381  void *key;
382 
383  key = serial->sp_data;
384  return sr_session_source_remove_internal(session, key);
385 }
386 
387 static GSList *sr_ser_libsp_list(GSList *list, sr_ser_list_append_t append)
388 {
389  struct sp_port **ports;
390  size_t i;
391  const char *name;
392  const char *desc;
393 
394  if (sp_list_ports(&ports) != SP_OK)
395  return list;
396 
397  for (i = 0; ports[i]; i++) {
398  name = sp_get_port_name(ports[i]);
399  desc = sp_get_port_description(ports[i]);
400  list = append(list, name, desc);
401  }
402 
403  sp_free_port_list(ports);
404 
405  return list;
406 }
407 
408 static GSList *sr_ser_libsp_find_usb(GSList *list, sr_ser_find_append_t append,
409  uint16_t vendor_id, uint16_t product_id)
410 {
411  struct sp_port **ports;
412  int i, vid, pid;
413 
414  if (sp_list_ports(&ports) != SP_OK)
415  return list;
416 
417  for (i = 0; ports[i]; i++) {
418  if (sp_get_port_transport(ports[i]) != SP_TRANSPORT_USB)
419  continue;
420  if (sp_get_port_usb_vid_pid(ports[i], &vid, &pid) != SP_OK)
421  continue;
422  if (vendor_id && vid != vendor_id)
423  continue;
424  if (product_id && pid != product_id)
425  continue;
426  list = append(list, sp_get_port_name(ports[i]));
427  }
428 
429  sp_free_port_list(ports);
430 
431  return list;
432 }
433 
434 static int sr_ser_libsp_get_frame_format(struct sr_serial_dev_inst *serial,
435  int *baud, int *bits)
436 {
437  struct sp_port_config *config;
438  int ret, tmp;
439  enum sp_parity parity;
440 
441  if (sp_new_config(&config) < 0)
442  return SR_ERR_MALLOC;
443  *baud = *bits = 0;
444  ret = SR_OK;
445  do {
446  if (sp_get_config(serial->sp_data, config) < 0) {
447  ret = SR_ERR_NA;
448  break;
449  }
450 
451  if (sp_get_config_baudrate(config, &tmp) < 0) {
452  ret = SR_ERR_NA;
453  break;
454  }
455  *baud = tmp;
456 
457  *bits += 1; /* Start bit. */
458  if (sp_get_config_bits(config, &tmp) < 0) {
459  ret = SR_ERR_NA;
460  break;
461  }
462  *bits += tmp;
463  if (sp_get_config_parity(config, &parity) < 0) {
464  ret = SR_ERR_NA;
465  break;
466  }
467  *bits += (parity != SP_PARITY_NONE) ? 1 : 0;
468  if (sp_get_config_stopbits(config, &tmp) < 0) {
469  ret = SR_ERR_NA;
470  break;
471  }
472  *bits += tmp;
473  } while (FALSE);
474  sp_free_config(config);
475 
476  return ret;
477 }
478 
479 static size_t sr_ser_libsp_get_rx_avail(struct sr_serial_dev_inst *serial)
480 {
481  int rc;
482 
483  if (!serial)
484  return 0;
485 
486  rc = sp_input_waiting(serial->sp_data);
487  if (rc < 0)
488  return 0;
489 
490  return rc;
491 }
492 
493 static struct ser_lib_functions serlib_sp = {
494  .open = sr_ser_libsp_open,
495  .close = sr_ser_libsp_close,
496  .flush = sr_ser_libsp_flush,
497  .drain = sr_ser_libsp_drain,
498  .write = sr_ser_libsp_write,
499  .read = sr_ser_libsp_read,
500  .set_params = sr_ser_libsp_set_params,
501  .setup_source_add = sr_ser_libsp_source_add,
502  .setup_source_remove = sr_ser_libsp_source_remove,
503  .list = sr_ser_libsp_list,
504  .find_usb = sr_ser_libsp_find_usb,
505  .get_frame_format = sr_ser_libsp_get_frame_format,
506  .get_rx_avail = sr_ser_libsp_get_rx_avail,
507 };
508 SR_PRIV struct ser_lib_functions *ser_lib_funcs_libsp = &serlib_sp;
509 
510 #else
511 
512 SR_PRIV struct ser_lib_functions *ser_lib_funcs_libsp = NULL;
513 
514 #endif
Generic/unspecified error.
Definition: libsigrok.h:68
No error.
Definition: libsigrok.h:67
The public libsigrok header file to be used by frontends.
int(* sr_receive_data_callback)(int fd, int revents, void *cb_data)
Type definition for callback function for data reception.
Definition: libsigrok.h:134
Not applicable.
Definition: libsigrok.h:73
Malloc/calloc/realloc error.
Definition: libsigrok.h:69
#define SR_PRIV
Definition: libsigrok.h:128
Function argument error.
Definition: libsigrok.h:70
SR_PRIV struct ser_lib_functions * ser_lib_funcs_libsp
Definition: serial_libsp.c:512
Opaque structure representing a libsigrok session.
Definition: libsigrok.h:456