]> sigrok.org Git - libsigrok.git/blob - src/input/input.c
sr_dev_inst_free(): Allow NULL as argument.
[libsigrok.git] / src / input / input.c
1 /*
2  * This file is part of the libsigrok project.
3  *
4  * Copyright (C) 2014 Bert Vermeulen <bert@biot.com>
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 3 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 #include <config.h>
21 #include <string.h>
22 #include <errno.h>
23 #include <glib.h>
24 #include <glib/gstdio.h>
25 #include <libsigrok/libsigrok.h>
26 #include "libsigrok-internal.h"
27
28 /** @cond PRIVATE */
29 #define LOG_PREFIX "input"
30 /** @endcond */
31
32 /**
33  * @file
34  *
35  * Input module handling.
36  */
37
38 /**
39  * @defgroup grp_input Input modules
40  *
41  * Input file/data module handling.
42  *
43  * libsigrok can process acquisition data in several different ways.
44  * Aside from acquiring data from a hardware device, it can also take it
45  * from a file in various formats (binary, CSV, VCD, and so on).
46  *
47  * Like all libsigrok data handling, processing is done in a streaming
48  * manner: input should be supplied a chunk at a time. This way anything
49  * that processes data can do so in real time, without the user having
50  * to wait for the whole thing to be finished.
51  *
52  * Every input module is "pluggable", meaning it's handled as being separate
53  * from the main libsigrok, but linked in to it statically. To keep things
54  * modular and separate like this, functions within an input module should be
55  * declared static, with only the respective 'struct sr_input_module' being
56  * exported for use into the wider libsigrok namespace.
57  *
58  * @{
59  */
60
61 /** @cond PRIVATE */
62 extern SR_PRIV struct sr_input_module input_chronovu_la8;
63 extern SR_PRIV struct sr_input_module input_csv;
64 extern SR_PRIV struct sr_input_module input_binary;
65 extern SR_PRIV struct sr_input_module input_trace32_ad;
66 extern SR_PRIV struct sr_input_module input_vcd;
67 extern SR_PRIV struct sr_input_module input_wav;
68 extern SR_PRIV struct sr_input_module input_raw_analog;
69 /* @endcond */
70
71 static const struct sr_input_module *input_module_list[] = {
72         &input_binary,
73         &input_chronovu_la8,
74         &input_csv,
75         &input_trace32_ad,
76         &input_vcd,
77         &input_wav,
78         &input_raw_analog,
79         NULL,
80 };
81
82 /**
83  * Returns a NULL-terminated list of all available input modules.
84  *
85  * @since 0.4.0
86  */
87 SR_API const struct sr_input_module **sr_input_list(void)
88 {
89         return input_module_list;
90 }
91
92 /**
93  * Returns the specified input module's ID.
94  *
95  * @since 0.4.0
96  */
97 SR_API const char *sr_input_id_get(const struct sr_input_module *imod)
98 {
99         if (!imod) {
100                 sr_err("Invalid input module NULL!");
101                 return NULL;
102         }
103
104         return imod->id;
105 }
106
107 /**
108  * Returns the specified input module's name.
109  *
110  * @since 0.4.0
111  */
112 SR_API const char *sr_input_name_get(const struct sr_input_module *imod)
113 {
114         if (!imod) {
115                 sr_err("Invalid input module NULL!");
116                 return NULL;
117         }
118
119         return imod->name;
120 }
121
122 /**
123  * Returns the specified input module's description.
124  *
125  * @since 0.4.0
126  */
127 SR_API const char *sr_input_description_get(const struct sr_input_module *imod)
128 {
129         if (!imod) {
130                 sr_err("Invalid input module NULL!");
131                 return NULL;
132         }
133
134         return imod->desc;
135 }
136
137 /**
138  * Returns the specified input module's file extensions typical for the file
139  * format, as a NULL terminated array, or returns a NULL pointer if there is
140  * no preferred extension.
141  * @note these are a suggestions only.
142  *
143  * @since 0.4.0
144  */
145 SR_API const char *const *sr_input_extensions_get(
146                 const struct sr_input_module *imod)
147 {
148         if (!imod) {
149                 sr_err("Invalid input module NULL!");
150                 return NULL;
151         }
152
153         return imod->exts;
154 }
155
156 /**
157  * Return the input module with the specified ID, or NULL if no module
158  * with that id is found.
159  *
160  * @since 0.4.0
161  */
162 SR_API const struct sr_input_module *sr_input_find(char *id)
163 {
164         int i;
165
166         for (i = 0; input_module_list[i]; i++) {
167                 if (!strcmp(input_module_list[i]->id, id))
168                         return input_module_list[i];
169         }
170
171         return NULL;
172 }
173
174 /**
175  * Returns a NULL-terminated array of struct sr_option, or NULL if the
176  * module takes no options.
177  *
178  * Each call to this function must be followed by a call to
179  * sr_input_options_free().
180  *
181  * @since 0.4.0
182  */
183 SR_API const struct sr_option **sr_input_options_get(const struct sr_input_module *imod)
184 {
185         const struct sr_option *mod_opts, **opts;
186         int size, i;
187
188         if (!imod || !imod->options)
189                 return NULL;
190
191         mod_opts = imod->options();
192
193         for (size = 0; mod_opts[size].id; size++)
194                 ;
195         opts = g_malloc((size + 1) * sizeof(struct sr_option *));
196
197         for (i = 0; i < size; i++)
198                 opts[i] = &mod_opts[i];
199         opts[i] = NULL;
200
201         return opts;
202 }
203
204 /**
205  * After a call to sr_input_options_get(), this function cleans up all
206  * resources returned by that call.
207  *
208  * @since 0.4.0
209  */
210 SR_API void sr_input_options_free(const struct sr_option **options)
211 {
212         int i;
213
214         if (!options)
215                 return;
216
217         for (i = 0; options[i]; i++) {
218                 if (options[i]->def) {
219                         g_variant_unref(options[i]->def);
220                         ((struct sr_option *)options[i])->def = NULL;
221                 }
222
223                 if (options[i]->values) {
224                         g_slist_free_full(options[i]->values, (GDestroyNotify)g_variant_unref);
225                         ((struct sr_option *)options[i])->values = NULL;
226                 }
227         }
228         g_free(options);
229 }
230
231 /**
232  * Create a new input instance using the specified input module.
233  *
234  * This function is used when a client wants to use a specific input
235  * module to parse a stream. No effort is made to identify the format.
236  *
237  * @param imod The input module to use. Must not be NULL.
238  * @param options GHashTable consisting of keys corresponding with
239  * the module options @c id field. The values should be GVariant
240  * pointers with sunk references, of the same GVariantType as the option's
241  * default value.
242  *
243  * @since 0.4.0
244  */
245 SR_API struct sr_input *sr_input_new(const struct sr_input_module *imod,
246                 GHashTable *options)
247 {
248         struct sr_input *in;
249         const struct sr_option *mod_opts;
250         const GVariantType *gvt;
251         GHashTable *new_opts;
252         GHashTableIter iter;
253         gpointer key, value;
254         int i;
255
256         in = g_malloc0(sizeof(struct sr_input));
257         in->module = imod;
258
259         new_opts = g_hash_table_new_full(g_str_hash, g_str_equal, g_free,
260                         (GDestroyNotify)g_variant_unref);
261         if (imod->options) {
262                 mod_opts = imod->options();
263                 for (i = 0; mod_opts[i].id; i++) {
264                         if (options && g_hash_table_lookup_extended(options,
265                                         mod_opts[i].id, &key, &value)) {
266                                 /* Option not given: insert the default value. */
267                                 gvt = g_variant_get_type(mod_opts[i].def);
268                                 if (!g_variant_is_of_type(value, gvt)) {
269                                         sr_err("Invalid type for '%s' option.",
270                                                 (char *)key);
271                                         g_free(in);
272                                         return NULL;
273                                 }
274                                 g_hash_table_insert(new_opts, g_strdup(mod_opts[i].id),
275                                                 g_variant_ref(value));
276                         } else {
277                                 /* Pass option along. */
278                                 g_hash_table_insert(new_opts, g_strdup(mod_opts[i].id),
279                                                 g_variant_ref(mod_opts[i].def));
280                         }
281                 }
282
283                 /* Make sure no invalid options were given. */
284                 if (options) {
285                         g_hash_table_iter_init(&iter, options);
286                         while (g_hash_table_iter_next(&iter, &key, &value)) {
287                                 if (!g_hash_table_lookup(new_opts, key)) {
288                                         sr_err("Input module '%s' has no option '%s'",
289                                                 imod->id, (char *)key);
290                                         g_hash_table_destroy(new_opts);
291                                         g_free(in);
292                                         return NULL;
293                                 }
294                         }
295                 }
296         }
297
298         if (in->module->init && in->module->init(in, new_opts) != SR_OK) {
299                 g_free(in);
300                 in = NULL;
301         } else {
302                 in->buf = g_string_sized_new(128);
303         }
304
305         if (new_opts)
306                 g_hash_table_destroy(new_opts);
307
308         return in;
309 }
310
311 /* Returns TRUE if all required meta items are available. */
312 static gboolean check_required_metadata(const uint8_t *metadata, uint8_t *avail)
313 {
314         int m, a;
315         uint8_t reqd;
316
317         for (m = 0; metadata[m]; m++) {
318                 if (!(metadata[m] & SR_INPUT_META_REQUIRED))
319                         continue;
320                 reqd = metadata[m] & ~SR_INPUT_META_REQUIRED;
321                 for (a = 0; avail[a]; a++) {
322                         if (avail[a] == reqd)
323                                 break;
324                 }
325                 if (!avail[a])
326                         /* Found a required meta item that isn't available. */
327                         return FALSE;
328         }
329
330         return TRUE;
331 }
332
333 /**
334  * Try to find an input module that can parse the given buffer.
335  *
336  * The buffer must contain enough of the beginning of the file for
337  * the input modules to find a match. This is format-dependent, but
338  * 128 bytes is normally enough.
339  *
340  * If an input module is found, an instance is created into *in.
341  * Otherwise, *in contains NULL.
342  *
343  * If an instance is created, it has the given buffer used for scanning
344  * already submitted to it, to be processed before more data is sent.
345  * This allows a frontend to submit an initial chunk of a non-seekable
346  * stream, such as stdin, without having to keep it around and submit
347  * it again later.
348  *
349  */
350 SR_API int sr_input_scan_buffer(GString *buf, const struct sr_input **in)
351 {
352         const struct sr_input_module *imod;
353         GHashTable *meta;
354         unsigned int m, i;
355         int ret;
356         uint8_t mitem, avail_metadata[8];
357
358         /* No more metadata to be had from a buffer. */
359         avail_metadata[0] = SR_INPUT_META_HEADER;
360         avail_metadata[1] = 0;
361
362         *in = NULL;
363         ret = SR_ERR;
364         for (i = 0; input_module_list[i]; i++) {
365                 imod = input_module_list[i];
366                 if (!imod->metadata[0]) {
367                         /* Module has no metadata for matching so will take
368                          * any input. No point in letting it try to match. */
369                         continue;
370                 }
371                 if (!check_required_metadata(imod->metadata, avail_metadata))
372                         /* Cannot satisfy this module's requirements. */
373                         continue;
374
375                 meta = g_hash_table_new(NULL, NULL);
376                 for (m = 0; m < sizeof(imod->metadata); m++) {
377                         mitem = imod->metadata[m] & ~SR_INPUT_META_REQUIRED;
378                         if (mitem == SR_INPUT_META_HEADER)
379                                 g_hash_table_insert(meta, GINT_TO_POINTER(mitem), buf);
380                 }
381                 if (g_hash_table_size(meta) == 0) {
382                         /* No metadata for this module, so nothing to match. */
383                         g_hash_table_destroy(meta);
384                         continue;
385                 }
386                 sr_spew("Trying module %s.", imod->id);
387                 ret = imod->format_match(meta);
388                 g_hash_table_destroy(meta);
389                 if (ret == SR_ERR_DATA) {
390                         /* Module recognized this buffer, but cannot handle it. */
391                         break;
392                 } else if (ret == SR_ERR) {
393                         /* Module didn't recognize this buffer. */
394                         continue;
395                 } else if (ret != SR_OK) {
396                         /* Can be SR_ERR_NA. */
397                         return ret;
398                 }
399
400                 /* Found a matching module. */
401                 sr_spew("Module %s matched.", imod->id);
402                 *in = sr_input_new(imod, NULL);
403                 g_string_insert_len((*in)->buf, 0, buf->str, buf->len);
404                 break;
405         }
406
407         return ret;
408 }
409
410 /**
411  * Try to find an input module that can parse the given file.
412  *
413  * If an input module is found, an instance is created into *in.
414  * Otherwise, *in contains NULL.
415  *
416  */
417 SR_API int sr_input_scan_file(const char *filename, const struct sr_input **in)
418 {
419         int64_t filesize;
420         FILE *stream;
421         const struct sr_input_module *imod;
422         GHashTable *meta;
423         GString *header;
424         size_t count;
425         unsigned int midx, i;
426         int ret;
427         uint8_t avail_metadata[8];
428
429         *in = NULL;
430
431         if (!filename || !filename[0]) {
432                 sr_err("Invalid filename.");
433                 return SR_ERR_ARG;
434         }
435         stream = g_fopen(filename, "rb");
436         if (!stream) {
437                 sr_err("Failed to open %s: %s", filename, g_strerror(errno));
438                 return SR_ERR;
439         }
440         filesize = sr_file_get_size(stream);
441         if (filesize < 0) {
442                 sr_err("Failed to get size of %s: %s",
443                         filename, g_strerror(errno));
444                 fclose(stream);
445                 return SR_ERR;
446         }
447         /* This actually allocates 256 bytes to allow for NUL termination. */
448         header = g_string_sized_new(255);
449         count = fread(header->str, 1, header->allocated_len - 1, stream);
450
451         if (count != header->allocated_len - 1 && ferror(stream)) {
452                 sr_err("Failed to read %s: %s", filename, g_strerror(errno));
453                 fclose(stream);
454                 g_string_free(header, TRUE);
455                 return SR_ERR;
456         }
457         fclose(stream);
458         g_string_set_size(header, count);
459
460         meta = g_hash_table_new(NULL, NULL);
461         g_hash_table_insert(meta, GINT_TO_POINTER(SR_INPUT_META_FILENAME),
462                         (char *)filename);
463         g_hash_table_insert(meta, GINT_TO_POINTER(SR_INPUT_META_FILESIZE),
464                         GSIZE_TO_POINTER(MIN(filesize, G_MAXSSIZE)));
465         g_hash_table_insert(meta, GINT_TO_POINTER(SR_INPUT_META_HEADER),
466                         header);
467         midx = 0;
468         avail_metadata[midx++] = SR_INPUT_META_FILENAME;
469         avail_metadata[midx++] = SR_INPUT_META_FILESIZE;
470         avail_metadata[midx++] = SR_INPUT_META_HEADER;
471         avail_metadata[midx] = 0;
472         /* TODO: MIME type */
473
474         ret = SR_ERR;
475
476         for (i = 0; input_module_list[i]; i++) {
477                 imod = input_module_list[i];
478                 if (!imod->metadata[0]) {
479                         /* Module has no metadata for matching so will take
480                          * any input. No point in letting it try to match. */
481                         continue;
482                 }
483                 if (!check_required_metadata(imod->metadata, avail_metadata))
484                         /* Cannot satisfy this module's requirements. */
485                         continue;
486
487                 sr_dbg("Trying module %s.", imod->id);
488
489                 ret = imod->format_match(meta);
490                 if (ret == SR_ERR) {
491                         /* Module didn't recognize this buffer. */
492                         continue;
493                 } else if (ret != SR_OK) {
494                         /* Module recognized this buffer, but cannot handle it. */
495                         break;
496                 }
497                 /* Found a matching module. */
498                 sr_dbg("Module %s matched.", imod->id);
499
500                 *in = sr_input_new(imod, NULL);
501                 break;
502         }
503         g_hash_table_destroy(meta);
504         g_string_free(header, TRUE);
505
506         return ret;
507 }
508
509 /**
510  * Return the input instance's (virtual) device instance. This can be
511  * used to find out the number of channels and other information.
512  *
513  * If the device instance has not yet been fully populated by the input
514  * module, NULL is returned. This indicates the module needs more data
515  * to identify the number of channels and so on.
516  *
517  * @since 0.4.0
518  */
519 SR_API struct sr_dev_inst *sr_input_dev_inst_get(const struct sr_input *in)
520 {
521         if (in->sdi_ready)
522                 return in->sdi;
523         else
524                 return NULL;
525 }
526
527 /**
528  * Send data to the specified input instance.
529  *
530  * When an input module instance is created with sr_input_new(), this
531  * function is used to feed data to the instance.
532  *
533  * As enough data gets fed into this function to completely populate
534  * the device instance associated with this input instance, this is
535  * guaranteed to return the moment it's ready. This gives the caller
536  * the chance to examine the device instance, attach session callbacks
537  * and so on.
538  *
539  * @since 0.4.0
540  */
541 SR_API int sr_input_send(const struct sr_input *in, GString *buf)
542 {
543         sr_spew("Sending %" G_GSIZE_FORMAT " bytes to %s module.",
544                 buf->len, in->module->id);
545         return in->module->receive((struct sr_input *)in, buf);
546 }
547
548 /**
549  * Signal the input module no more data will come.
550  *
551  * This will cause the module to process any data it may have buffered.
552  * The SR_DF_END packet will also typically be sent at this time.
553  *
554  * @since 0.4.0
555  */
556 SR_API int sr_input_end(const struct sr_input *in)
557 {
558         sr_spew("Calling end() on %s module.", in->module->id);
559         return in->module->end((struct sr_input *)in);
560 }
561
562 /**
563  * Reset the input module's input handling structures.
564  *
565  * Causes the input module to reset its internal state so that we can re-send
566  * the input data from the beginning without having to re-create the entire
567  * input module.
568  *
569  * @since 0.5.0
570  */
571 SR_API int sr_input_reset(const struct sr_input *in)
572 {
573         if (!in->module->reset) {
574                 sr_spew("Tried to reset %s module but no reset handler found.",
575                         in->module->id);
576                 return SR_OK;
577         }
578
579         sr_spew("Resetting %s module.", in->module->id);
580         return in->module->reset((struct sr_input *)in);
581 }
582
583 /**
584  * Free the specified input instance and all associated resources.
585  *
586  * @since 0.4.0
587  */
588 SR_API void sr_input_free(const struct sr_input *in)
589 {
590         if (!in)
591                 return;
592
593         if (in->module->cleanup)
594                 in->module->cleanup((struct sr_input *)in);
595         sr_dev_inst_free(in->sdi);
596         if (in->buf->len > 64) {
597                 /* That seems more than just some sub-unitsize leftover... */
598                 sr_warn("Found %" G_GSIZE_FORMAT
599                         " unprocessed bytes at free time.", in->buf->len);
600         }
601         g_string_free(in->buf, TRUE);
602         g_free(in->priv);
603         g_free((gpointer)in);
604 }
605
606 /** @} */