]> sigrok.org Git - libsigrok.git/blob - src/serial_libsp.c
hameg-hmo: Add SR_CONF_HIGH_RESOLUTION and SR_CONF_PEAK_DETECTION.
[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 /** @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