]> sigrok.org Git - libsigrok.git/blob - src/serial_libsp.c
bfdc3202261c8adfb198fff28a8c80a29ccf07fe
[libsigrok.git] / src / serial_libsp.c
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 #define LOG_PREFIX "serial-libsp"
35
36 /**
37  * @file
38  *
39  * Serial port handling, wraps the external libserialport dependency.
40  */
41
42 #ifdef HAVE_LIBSERIALPORT
43
44 /**
45  * @defgroup grp_serial_libsp Serial port handling, libserialport group
46  *
47  * Serial port handling functions, based on libserialport.
48  *
49  * @{
50  */
51
52 static int sr_ser_libsp_open(struct sr_serial_dev_inst *serial, int flags)
53 {
54         int ret;
55         char *error;
56         int sp_flags;
57
58         sp_get_port_by_name(serial->port, &serial->sp_data);
59
60         sp_flags = 0;
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;
65
66         ret = sp_open(serial->sp_data, sp_flags);
67
68         switch (ret) {
69         case SP_ERR_ARG:
70                 sr_err("Attempt to open serial port with invalid parameters.");
71                 return SR_ERR_ARG;
72         case SP_ERR_FAIL:
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);
77                 return SR_ERR;
78         }
79
80         return SR_OK;
81 }
82
83 static int sr_ser_libsp_close(struct sr_serial_dev_inst *serial)
84 {
85         int ret;
86         char *error;
87
88         if (!serial->sp_data) {
89                 sr_dbg("Cannot close unopened serial port %s.", serial->port);
90                 return SR_ERR;
91         }
92
93         ret = sp_close(serial->sp_data);
94
95         switch (ret) {
96         case SP_ERR_ARG:
97                 sr_err("Attempt to close an invalid serial port.");
98                 return SR_ERR_ARG;
99         case SP_ERR_FAIL:
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);
104                 return SR_ERR;
105         }
106
107         sp_free_port(serial->sp_data);
108         serial->sp_data = NULL;
109
110         return SR_OK;
111 }
112
113 static int sr_ser_libsp_flush(struct sr_serial_dev_inst *serial)
114 {
115         int ret;
116         char *error;
117
118         if (!serial->sp_data) {
119                 sr_dbg("Cannot flush unopened serial port %s.", serial->port);
120                 return SR_ERR;
121         }
122
123         ret = sp_flush(serial->sp_data, SP_BUF_BOTH);
124
125         switch (ret) {
126         case SP_ERR_ARG:
127                 sr_err("Attempt to flush an invalid serial port.");
128                 return SR_ERR_ARG;
129         case SP_ERR_FAIL:
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);
134                 return SR_ERR;
135         }
136
137         return SR_OK;
138 }
139
140 static int sr_ser_libsp_drain(struct sr_serial_dev_inst *serial)
141 {
142         int ret;
143         char *error;
144
145         if (!serial->sp_data) {
146                 sr_dbg("Cannot drain unopened serial port %s.", serial->port);
147                 return SR_ERR;
148         }
149
150         ret = sp_drain(serial->sp_data);
151
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);
157                 return SR_ERR;
158         }
159
160         return SR_OK;
161 }
162
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)
166 {
167         ssize_t ret;
168         char *error;
169
170         if (!serial->sp_data) {
171                 sr_dbg("Cannot use unopened serial port %s.", serial->port);
172                 return SR_ERR;
173         }
174
175         if (nonblocking)
176                 ret = sp_nonblocking_write(serial->sp_data, buf, count);
177         else
178                 ret = sp_blocking_write(serial->sp_data, buf, count, timeout_ms);
179
180         switch (ret) {
181         case SP_ERR_ARG:
182                 sr_err("Attempted serial port write with invalid arguments.");
183                 return SR_ERR_ARG;
184         case SP_ERR_FAIL:
185                 error = sp_last_error_message();
186                 sr_err("Write error (%d): %s.", sp_last_error_code(), error);
187                 sp_free_error_message(error);
188                 return SR_ERR;
189         }
190
191         return ret;
192 }
193
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)
197 {
198         ssize_t ret;
199         char *error;
200
201         if (!serial->sp_data) {
202                 sr_dbg("Cannot use unopened serial port %s.", serial->port);
203                 return SR_ERR;
204         }
205
206         if (nonblocking)
207                 ret = sp_nonblocking_read(serial->sp_data, buf, count);
208         else
209                 ret = sp_blocking_read(serial->sp_data, buf, count, timeout_ms);
210
211         switch (ret) {
212         case SP_ERR_ARG:
213                 sr_err("Attempted serial port read with invalid arguments.");
214                 return SR_ERR_ARG;
215         case SP_ERR_FAIL:
216                 error = sp_last_error_message();
217                 sr_err("Read error (%d): %s.", sp_last_error_code(), error);
218                 sp_free_error_message(error);
219                 return SR_ERR;
220         }
221
222         return ret;
223 }
224
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)
228 {
229         int ret;
230         char *error;
231         struct sp_port_config *config;
232         int cts, xonoff;
233
234         if (!serial->sp_data) {
235                 sr_dbg("Cannot configure unopened serial port %s.", serial->port);
236                 return SR_ERR;
237         }
238
239         sp_new_config(&config);
240         sp_set_config_baudrate(config, baudrate);
241         sp_set_config_bits(config, bits);
242         switch (parity) {
243         case 0:
244                 sp_set_config_parity(config, SP_PARITY_NONE);
245                 break;
246         case 1:
247                 sp_set_config_parity(config, SP_PARITY_EVEN);
248                 break;
249         case 2:
250                 sp_set_config_parity(config, SP_PARITY_ODD);
251                 break;
252         default:
253                 return SR_ERR_ARG;
254         }
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);
264
265         ret = sp_set_config(serial->sp_data, config);
266         sp_free_config(config);
267
268         switch (ret) {
269         case SP_ERR_ARG:
270                 sr_err("Invalid arguments for setting serial port parameters.");
271                 return SR_ERR_ARG;
272         case SP_ERR_FAIL:
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);
277                 return SR_ERR;
278         }
279
280         return SR_OK;
281 }
282
283 static int sr_ser_libsp_set_handshake(struct sr_serial_dev_inst *serial,
284         int rts, int dtr)
285 {
286         int ret;
287
288         if (!serial->sp_data) {
289                 sr_dbg("Cannot configure unopened serial port %s.", serial->port);
290                 return SR_ERR;
291         }
292
293         if (rts >= 0) {
294                 ret = sp_set_rts(serial->sp_data, rts ? SP_RTS_ON : SP_RTS_OFF);
295                 if (ret != SP_OK)
296                         return SR_ERR;
297         }
298         if (dtr >= 0) {
299                 ret = sp_set_dtr(serial->sp_data, dtr ? SP_DTR_ON : SP_DTR_OFF);
300                 if (ret != SP_OK)
301                         return SR_ERR;
302         }
303
304         return SR_OK;
305 }
306
307 #ifdef G_OS_WIN32
308 typedef HANDLE event_handle;
309 #else
310 typedef int event_handle;
311 #endif
312
313 static int sr_ser_libsp_source_add_int(struct sr_serial_dev_inst *serial,
314         int events,
315         void **keyptr, gintptr *fdptr, unsigned int *pollevtptr)
316 {
317         struct sp_event_set *event_set;
318         gintptr poll_fd;
319         unsigned int poll_events;
320         enum sp_event mask;
321
322         if ((events & (G_IO_IN | G_IO_ERR)) && (events & G_IO_OUT)) {
323                 sr_err("Cannot poll input/error and output simultaneously.");
324                 return SR_ERR_ARG;
325         }
326         if (!serial->sp_data) {
327                 sr_err("Invalid serial port.");
328                 return SR_ERR_ARG;
329         }
330
331         if (sp_new_event_set(&event_set) != SP_OK)
332                 return SR_ERR;
333
334         mask = 0;
335         if (events & G_IO_IN)
336                 mask |= SP_EVENT_RX_READY;
337         if (events & G_IO_OUT)
338                 mask |= SP_EVENT_TX_READY;
339         if (events & G_IO_ERR)
340                 mask |= SP_EVENT_ERROR;
341
342         if (sp_add_port_events(event_set, serial->sp_data, mask) != SP_OK) {
343                 sp_free_event_set(event_set);
344                 return SR_ERR;
345         }
346         if (event_set->count != 1) {
347                 sr_err("Unexpected number (%u) of event handles to poll.",
348                         event_set->count);
349                 sp_free_event_set(event_set);
350                 return SR_ERR;
351         }
352
353         poll_fd = (gintptr) ((event_handle *)event_set->handles)[0];
354         mask = event_set->masks[0];
355
356         sp_free_event_set(event_set);
357
358         poll_events = 0;
359         if (mask & SP_EVENT_RX_READY)
360                 poll_events |= G_IO_IN;
361         if (mask & SP_EVENT_TX_READY)
362                 poll_events |= G_IO_OUT;
363         if (mask & SP_EVENT_ERROR)
364                 poll_events |= G_IO_ERR;
365
366         /*
367          * Using serial->sp_data as the key for the event source is not quite
368          * proper, as it makes it impossible to create another event source
369          * for the same serial port. However, these fixed keys will soon be
370          * removed from the API anyway, so this is OK for now.
371          */
372         *keyptr = serial->sp_data;
373         *fdptr = poll_fd;
374         *pollevtptr = poll_events;
375
376         return SR_OK;
377 }
378
379 static int sr_ser_libsp_source_add(struct sr_session *session,
380         struct sr_serial_dev_inst *serial, int events, int timeout,
381         sr_receive_data_callback cb, void *cb_data)
382 {
383         int ret;
384         void *key;
385         gintptr poll_fd;
386         unsigned int poll_events;
387
388         ret = sr_ser_libsp_source_add_int(serial, events,
389                 &key, &poll_fd, &poll_events);
390         if (ret != SR_OK)
391                 return ret;
392
393         return sr_session_fd_source_add(session,
394                 key, poll_fd, poll_events,
395                 timeout, cb, cb_data);
396 }
397
398 static int sr_ser_libsp_source_remove(struct sr_session *session,
399         struct sr_serial_dev_inst *serial)
400 {
401         void *key;
402
403         key = serial->sp_data;
404         return sr_session_source_remove_internal(session, key);
405 }
406
407 static GSList *sr_ser_libsp_list(GSList *list, sr_ser_list_append_t append)
408 {
409         struct sp_port **ports;
410         size_t i;
411         const char *name;
412         const char *desc;
413
414         if (sp_list_ports(&ports) != SP_OK)
415                 return list;
416
417         for (i = 0; ports[i]; i++) {
418                 name = sp_get_port_name(ports[i]);
419                 desc = sp_get_port_description(ports[i]);
420                 list = append(list, name, desc);
421         }
422
423         sp_free_port_list(ports);
424
425         return list;
426 }
427
428 static GSList *sr_ser_libsp_find_usb(GSList *list, sr_ser_find_append_t append,
429         uint16_t vendor_id, uint16_t product_id)
430 {
431         struct sp_port **ports;
432         int i, vid, pid;
433
434         if (sp_list_ports(&ports) != SP_OK)
435                 return list;
436
437         for (i = 0; ports[i]; i++) {
438                 if (sp_get_port_transport(ports[i]) != SP_TRANSPORT_USB)
439                         continue;
440                 if (sp_get_port_usb_vid_pid(ports[i], &vid, &pid) != SP_OK)
441                         continue;
442                 if (vendor_id && vid != vendor_id)
443                         continue;
444                 if (product_id && pid != product_id)
445                         continue;
446                 list = append(list, sp_get_port_name(ports[i]));
447         }
448
449         sp_free_port_list(ports);
450
451         return list;
452 }
453
454 static int sr_ser_libsp_get_frame_format(struct sr_serial_dev_inst *serial,
455         int *baud, int *bits)
456 {
457         struct sp_port_config *config;
458         int ret, tmp;
459         enum sp_parity parity;
460
461         if (sp_new_config(&config) < 0)
462                 return SR_ERR_MALLOC;
463         *baud = *bits = 0;
464         ret = SR_OK;
465         do {
466                 if (sp_get_config(serial->sp_data, config) < 0) {
467                         ret = SR_ERR_NA;
468                         break;
469                 }
470
471                 if (sp_get_config_baudrate(config, &tmp) < 0) {
472                         ret = SR_ERR_NA;
473                         break;
474                 }
475                 *baud = tmp;
476
477                 *bits += 1;     /* Start bit. */
478                 if (sp_get_config_bits(config, &tmp) < 0) {
479                         ret = SR_ERR_NA;
480                         break;
481                 }
482                 *bits += tmp;
483                 if (sp_get_config_parity(config, &parity) < 0) {
484                         ret = SR_ERR_NA;
485                         break;
486                 }
487                 *bits += (parity != SP_PARITY_NONE) ? 1 : 0;
488                 if (sp_get_config_stopbits(config, &tmp) < 0) {
489                         ret = SR_ERR_NA;
490                         break;
491                 }
492                 *bits += tmp;
493         } while (FALSE);
494         sp_free_config(config);
495
496         return ret;
497 }
498
499 static size_t sr_ser_libsp_get_rx_avail(struct sr_serial_dev_inst *serial)
500 {
501         int rc;
502
503         if (!serial)
504                 return 0;
505
506         rc = sp_input_waiting(serial->sp_data);
507         if (rc < 0)
508                 return 0;
509
510         return rc;
511 }
512
513 static struct ser_lib_functions serlib_sp = {
514         .open = sr_ser_libsp_open,
515         .close = sr_ser_libsp_close,
516         .flush = sr_ser_libsp_flush,
517         .drain = sr_ser_libsp_drain,
518         .write = sr_ser_libsp_write,
519         .read = sr_ser_libsp_read,
520         .set_params = sr_ser_libsp_set_params,
521         .set_handshake = sr_ser_libsp_set_handshake,
522         .setup_source_add = sr_ser_libsp_source_add,
523         .setup_source_remove = sr_ser_libsp_source_remove,
524         .list = sr_ser_libsp_list,
525         .find_usb = sr_ser_libsp_find_usb,
526         .get_frame_format = sr_ser_libsp_get_frame_format,
527         .get_rx_avail = sr_ser_libsp_get_rx_avail,
528 };
529 SR_PRIV struct ser_lib_functions *ser_lib_funcs_libsp = &serlib_sp;
530
531 #else
532
533 SR_PRIV struct ser_lib_functions *ser_lib_funcs_libsp = NULL;
534
535 #endif