]> sigrok.org Git - libsigrok.git/blob - src/std.c
std: Add and use std_dev_clear() where possible.
[libsigrok.git] / src / std.c
1 /*
2  * This file is part of the libsigrok project.
3  *
4  * Copyright (C) 2013 Uwe Hermann <uwe@hermann-uwe.de>
5  *
6  * This program is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation; either version 2 of the License, or
9  * (at your option) any later version.
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program; if not, see <http://www.gnu.org/licenses/>.
18  */
19
20 /**
21  * @file
22  *
23  * Standard API helper functions.
24  *
25  * @internal
26  */
27
28 #include <config.h>
29 #include <glib.h>
30 #include <libsigrok/libsigrok.h>
31 #include "libsigrok-internal.h"
32 #include "scpi.h"
33
34 #define LOG_PREFIX "std"
35
36 /**
37  * Standard driver init() callback API helper.
38  *
39  * This function can be used to simplify most driver's init() API callback.
40  *
41  * Create a new 'struct drv_context' (drvc), assign sr_ctx to it, and
42  * then assign 'drvc' to the 'struct sr_dev_driver' (di) that is passed.
43  *
44  * @param[in] di The driver instance to use. Must not be NULL.
45  * @param[in] sr_ctx The libsigrok context to assign. May be NULL.
46  *
47  * @retval SR_OK Success.
48  * @retval SR_ERR_ARG Invalid argument.
49  */
50 SR_PRIV int std_init(struct sr_dev_driver *di, struct sr_context *sr_ctx)
51 {
52         struct drv_context *drvc;
53
54         if (!di) {
55                 sr_err("%s: Invalid argument.", __func__);
56                 return SR_ERR_ARG;
57         }
58
59         drvc = g_malloc0(sizeof(struct drv_context));
60         drvc->sr_ctx = sr_ctx;
61         drvc->instances = NULL;
62         di->context = drvc;
63
64         return SR_OK;
65 }
66
67 /**
68  * Standard driver cleanup() callback API helper.
69  *
70  * This function can be used to simplify most driver's cleanup() API callback.
71  *
72  * Free all device instances by calling sr_dev_clear() and then release any
73  * resources allocated by std_init().
74  *
75  * @param[in] di The driver instance to use. Must not be NULL.
76  *
77  * @retval SR_OK Success.
78  * @retval SR_ERR_ARG Invalid argument.
79  * @retval other Other error.
80  */
81 SR_PRIV int std_cleanup(const struct sr_dev_driver *di)
82 {
83         int ret;
84
85         if (!di) {
86                 sr_err("%s: Invalid argument.", __func__);
87                 return SR_ERR_ARG;
88         }
89
90         ret = sr_dev_clear(di);
91         g_free(di->context);
92
93         return ret;
94 }
95
96 /**
97  * Dummmy driver dev_open() callback API helper.
98  *
99  * @param[in] sdi The device instance to use. May be NULL (unused).
100  *
101  * @retval SR_OK Success.
102  */
103 SR_PRIV int std_dummy_dev_open(struct sr_dev_inst *sdi)
104 {
105         (void)sdi;
106
107         return SR_OK;
108 }
109
110 /**
111  * Dummmy driver dev_close() callback API helper.
112  *
113  * @param[in] sdi The device instance to use. May be NULL (unused).
114  *
115  * @retval SR_OK Success.
116  */
117 SR_PRIV int std_dummy_dev_close(struct sr_dev_inst *sdi)
118 {
119         (void)sdi;
120
121         return SR_OK;
122 }
123
124 /**
125  * Dummmy driver dev_acquisition_start() callback API helper.
126  *
127  * @param[in] sdi The device instance to use. May be NULL (unused).
128  *
129  * @retval SR_OK Success.
130  */
131 SR_PRIV int std_dummy_dev_acquisition_start(const struct sr_dev_inst *sdi)
132 {
133         (void)sdi;
134
135         return SR_OK;
136 }
137
138 /**
139  * Dummmy driver dev_acquisition_stop() callback API helper.
140  *
141  * @param[in] sdi The device instance to use. May be NULL (unused).
142  *
143  * @retval SR_OK Success.
144  */
145 SR_PRIV int std_dummy_dev_acquisition_stop(struct sr_dev_inst *sdi)
146 {
147         (void)sdi;
148
149         return SR_OK;
150 }
151
152 /**
153  * Standard API helper for sending an SR_DF_HEADER packet.
154  *
155  * This function can be used to simplify most drivers'
156  * dev_acquisition_start() API callback.
157  *
158  * @param[in] sdi The device instance to use. Must not be NULL.
159  *
160  * @retval SR_OK Success.
161  * @retval SR_ERR_ARG Invalid argument.
162  * @retval other Other error.
163  */
164 SR_PRIV int std_session_send_df_header(const struct sr_dev_inst *sdi)
165 {
166         const char *prefix;
167         int ret;
168         struct sr_datafeed_packet packet;
169         struct sr_datafeed_header header;
170
171         if (!sdi) {
172                 sr_err("%s: Invalid argument.", __func__);
173                 return SR_ERR_ARG;
174         }
175
176         prefix = (sdi->driver) ? sdi->driver->name : "unknown";
177
178         /* Send header packet to the session bus. */
179         sr_dbg("%s: Sending SR_DF_HEADER packet.", prefix);
180         packet.type = SR_DF_HEADER;
181         packet.payload = (uint8_t *)&header;
182         header.feed_version = 1;
183         gettimeofday(&header.starttime, NULL);
184
185         if ((ret = sr_session_send(sdi, &packet)) < 0) {
186                 sr_err("%s: Failed to send SR_DF_HEADER packet: %d.", prefix, ret);
187                 return ret;
188         }
189
190         return SR_OK;
191 }
192
193 /**
194  * Standard API helper for sending an SR_DF_END packet.
195  *
196  * This function can be used to simplify most drivers'
197  * dev_acquisition_stop() API callback.
198  *
199  * @param[in] sdi The device instance to use. Must not be NULL.
200  *
201  * @retval SR_OK Success.
202  * @retval SR_ERR_ARG Invalid argument.
203  * @retval other Other error.
204  */
205 SR_PRIV int std_session_send_df_end(const struct sr_dev_inst *sdi)
206 {
207         const char *prefix;
208         int ret;
209         struct sr_datafeed_packet packet;
210
211         if (!sdi) {
212                 sr_err("%s: Invalid argument.", __func__);
213                 return SR_ERR_ARG;
214         }
215
216         prefix = (sdi->driver) ? sdi->driver->name : "unknown";
217
218         sr_dbg("%s: Sending SR_DF_END packet.", prefix);
219
220         packet.type = SR_DF_END;
221         packet.payload = NULL;
222
223         if ((ret = sr_session_send(sdi, &packet)) < 0) {
224                 sr_err("%s: Failed to send SR_DF_END packet: %d.", prefix, ret);
225                 return ret;
226         }
227
228         return SR_OK;
229 }
230
231 #ifdef HAVE_LIBSERIALPORT
232
233 /**
234  * Standard serial driver dev_open() callback API helper.
235  *
236  * This function can be used to implement the dev_open() driver API
237  * callback in drivers that use a serial port. The port is opened
238  * with the SERIAL_RDWR flag.
239  *
240  * @param[in] sdi The device instance to use. Must not be NULL.
241  *
242  * @retval SR_OK Success.
243  * @retval SR_ERR_ARG Invalid argument.
244  * @retval other Serial port open failed.
245  */
246 SR_PRIV int std_serial_dev_open(struct sr_dev_inst *sdi)
247 {
248         struct sr_serial_dev_inst *serial;
249
250         if (!sdi) {
251                 sr_err("%s: Invalid argument.", __func__);
252                 return SR_ERR_ARG;
253         }
254
255         serial = sdi->conn;
256
257         return serial_open(serial, SERIAL_RDWR);
258 }
259
260 /**
261  * Standard serial driver dev_close() callback API helper.
262  *
263  * This function can be used to implement the dev_close() driver API
264  * callback in drivers that use a serial port.
265  *
266  * @param[in] sdi The device instance to use. Must not be NULL.
267  *
268  * @retval SR_OK Success.
269  * @retval SR_ERR_ARG Invalid argument.
270  * @retval other Serial port close failed.
271  */
272 SR_PRIV int std_serial_dev_close(struct sr_dev_inst *sdi)
273 {
274         struct sr_serial_dev_inst *serial;
275
276         if (!sdi) {
277                 sr_err("%s: Invalid argument.", __func__);
278                 return SR_ERR_ARG;
279         }
280
281         serial = sdi->conn;
282
283         return serial_close(serial);
284 }
285
286 /**
287  * Standard serial driver dev_acquisition_stop() callback API helper.
288  *
289  * This function can be used to simplify most (serial port based) drivers'
290  * dev_acquisition_stop() API callback.
291  *
292  * @param[in] sdi The device instance for which acquisition should stop.
293  *                Must not be NULL.
294  *
295  * @retval SR_OK Success.
296  * @retval SR_ERR_ARG Invalid argument.
297  * @retval other Other error.
298  */
299 SR_PRIV int std_serial_dev_acquisition_stop(struct sr_dev_inst *sdi)
300 {
301         struct sr_serial_dev_inst *serial;
302         const char *prefix;
303         int ret;
304
305         if (!sdi) {
306                 sr_err("%s: Invalid argument.", __func__);
307                 return SR_ERR_ARG;
308         }
309
310         serial = sdi->conn;
311         prefix = sdi->driver->name;
312
313         if ((ret = serial_source_remove(sdi->session, serial)) < 0) {
314                 sr_err("%s: Failed to remove source: %d.", prefix, ret);
315                 return ret;
316         }
317
318         if ((ret = sr_dev_close(sdi)) < 0) {
319                 sr_err("%s: Failed to close device: %d.", prefix, ret);
320                 return ret;
321         }
322
323         return std_session_send_df_end(sdi);
324 }
325
326 #endif
327
328 /**
329  * Standard driver dev_clear() callback API helper.
330  *
331  * Clear driver, this means, close all instances.
332  *
333  * This function can be used to implement the dev_clear() driver API
334  * callback. dev_close() is called before every sr_dev_inst is cleared.
335  *
336  * The only limitation is driver-specific device contexts (sdi->priv).
337  * These are freed, but any dynamic allocation within structs stored
338  * there cannot be freed.
339  *
340  * @param[in] driver The driver which will have its instances released.
341  *                   Must not be NULL.
342  * @param[in] clear_private If not NULL, this points to a function called
343  *            with sdi->priv as argument. The function can then clear
344  *            any device instance-specific resources kept there.
345  *            It must also clear the struct pointed to by sdi->priv.
346  *
347  * @retval SR_OK Success.
348  * @retval SR_ERR_ARG Invalid argument.
349  * @retval SR_ERR_BUG Implementation bug.
350  * @retval other Other error.
351  */
352 SR_PRIV int std_dev_clear_with_callback(const struct sr_dev_driver *driver,
353                 std_dev_clear_callback clear_private)
354 {
355         struct drv_context *drvc;
356         struct sr_dev_inst *sdi;
357         GSList *l;
358         int ret;
359
360         if (!driver) {
361                 sr_err("%s: Invalid argument.", __func__);
362                 return SR_ERR_ARG;
363         }
364
365         drvc = driver->context; /* Caller checked for context != NULL. */
366
367         ret = SR_OK;
368         for (l = drvc->instances; l; l = l->next) {
369                 if (!(sdi = l->data)) {
370                         sr_err("%s: Invalid device instance.", __func__);
371                         ret = SR_ERR_BUG;
372                         continue;
373                 }
374                 if (driver->dev_close)
375                         driver->dev_close(sdi);
376
377                 if (sdi->conn) {
378 #ifdef HAVE_LIBSERIALPORT
379                         if (sdi->inst_type == SR_INST_SERIAL)
380                                 sr_serial_dev_inst_free(sdi->conn);
381 #endif
382 #ifdef HAVE_LIBUSB_1_0
383                         if (sdi->inst_type == SR_INST_USB)
384                                 sr_usb_dev_inst_free(sdi->conn);
385 #endif
386                         if (sdi->inst_type == SR_INST_SCPI)
387                                 sr_scpi_free(sdi->conn);
388                         if (sdi->inst_type == SR_INST_MODBUS)
389                                 sr_modbus_free(sdi->conn);
390                 }
391                 if (clear_private)
392                         /* The helper function is responsible for freeing
393                          * its own sdi->priv! */
394                         clear_private(sdi->priv);
395                 else
396                         g_free(sdi->priv);
397
398                 sr_dev_inst_free(sdi);
399         }
400
401         g_slist_free(drvc->instances);
402         drvc->instances = NULL;
403
404         return ret;
405 }
406
407 SR_PRIV int std_dev_clear(const struct sr_dev_driver *driver)
408 {
409         return std_dev_clear_with_callback(driver, NULL);
410 }
411
412 /**
413  * Standard driver dev_list() callback API helper.
414  *
415  * This function can be used as the dev_list() callback by most drivers.
416  *
417  * Return the devices contained in the driver context instances list.
418  *
419  * @param[in] di The driver instance to use. Must not be NULL.
420  *
421  * @retval NULL Error, or the list is empty.
422  * @retval other The list of device instances of this driver.
423  */
424 SR_PRIV GSList *std_dev_list(const struct sr_dev_driver *di)
425 {
426         struct drv_context *drvc;
427
428         if (!di) {
429                 sr_err("%s: Invalid argument.", __func__);
430                 return NULL;
431         }
432
433         drvc = di->context;
434
435         return drvc->instances;
436 }
437
438 /**
439  * Standard driver scan() callback API helper.
440  *
441  * This function can be used to perform common tasks required by a driver's
442  * scan() callback. It will initialize the driver for each device on the list
443  * and add the devices on the list to the driver's device instance list.
444  * Usually it should be used as the last step in the scan() callback, right
445  * before returning.
446  *
447  * Note: This function can only be used if std_init() has been called
448  * previously by the driver.
449  *
450  * Example:
451  * @code{c}
452  * static GSList *scan(struct sr_dev_driver *di, GSList *options)
453  * {
454  *     struct GSList *device;
455  *     struct sr_dev_inst *sdi;
456  *
457  *     sdi = g_new0(sr_dev_inst, 1);
458  *     sdi->vendor = ...;
459  *     ...
460  *     devices = g_slist_append(devices, sdi);
461  *     ...
462  *     return std_scan_complete(di, devices);
463  * }
464  * @endcode
465  *
466  * @param[in] di The driver instance to use. Must not be NULL.
467  * @param[in] devices List of newly discovered devices (struct sr_dev_inst).
468  *                    May be NULL.
469  *
470  * @return The @p devices list.
471  */
472 SR_PRIV GSList *std_scan_complete(struct sr_dev_driver *di, GSList *devices)
473 {
474         struct drv_context *drvc;
475         GSList *l;
476
477         if (!di) {
478                 sr_err("Invalid driver instance (di), cannot complete scan.");
479                 return NULL;
480         }
481
482         drvc = di->context;
483
484         for (l = devices; l; l = l->next) {
485                 struct sr_dev_inst *sdi = l->data;
486                 if (!sdi) {
487                         sr_err("Invalid device instance, cannot complete scan.");
488                         return NULL;
489                 }
490                 sdi->driver = di;
491         }
492
493         drvc->instances = g_slist_concat(drvc->instances, g_slist_copy(devices));
494
495         return devices;
496 }