]> sigrok.org Git - sigrok-cli.git/blob - decode.c
Refactor main source into separate files
[sigrok-cli.git] / decode.c
1 /*
2  * This file is part of the sigrok-cli project.
3  *
4  * Copyright (C) 2013 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 <glib.h>
22 #include <libsigrok/libsigrok.h>
23 #ifdef HAVE_SRD
24 #include <libsigrokdecode/libsigrokdecode.h> /* First, so we avoid a _POSIX_C_SOURCE warning. */
25 #endif
26 #include "sigrok-cli.h"
27
28 #ifdef HAVE_SRD
29 static GHashTable *pd_ann_visible = NULL;
30 static GHashTable *pd_meta_visible = NULL;
31 static GHashTable *pd_binary_visible = NULL;
32
33 extern struct srd_session *srd_sess;
34 extern gint opt_loglevel;
35 extern gchar *opt_pds;
36 extern gchar *opt_pd_stack;
37 extern gchar *opt_pd_annotations;
38 extern gchar *opt_pd_meta;
39 extern gchar *opt_pd_binary;
40
41
42 static int opts_to_gvar(struct srd_decoder *dec, GHashTable *hash,
43                 GHashTable **options)
44 {
45         struct srd_decoder_option *o;
46         GSList *optl;
47         GVariant *gvar;
48         gint64 val_int;
49         int ret;
50         char *val_str, *conv;
51
52         ret = TRUE;
53         *options = g_hash_table_new_full(g_str_hash, g_str_equal, g_free,
54                         (GDestroyNotify)g_variant_unref);
55
56         for (optl = dec->options; optl; optl = optl->next) {
57                 o = optl->data;
58                 if (!(val_str = g_hash_table_lookup(hash, o->id)))
59                         /* Not specified. */
60                         continue;
61                 if (g_variant_is_of_type(o->def, G_VARIANT_TYPE_STRING)) {
62                         gvar = g_variant_new_string(val_str);
63                 } else if (g_variant_is_of_type(o->def, G_VARIANT_TYPE_INT64)) {
64                         val_int = strtoll(val_str, &conv, 0);
65                         if (!conv || conv == val_str) {
66                                 g_critical("Protocol decoder '%s' option '%s' "
67                                                 "requires a number.", dec->name, o->id);
68                                 ret = FALSE;
69                                 break;
70                         }
71                         gvar = g_variant_new_int64(val_int);
72                 } else {
73                         g_critical("Unsupported type for option '%s' (%s)",
74                                         o->id, g_variant_get_type_string(o->def));
75                         ret = FALSE;
76                         break;
77                 }
78                 g_variant_ref_sink(gvar);
79                 g_hash_table_insert(*options, g_strdup(o->id), gvar);
80                 g_hash_table_remove(hash, o->id);
81         }
82
83         return ret;
84 }
85
86 static int probes_to_gvar(struct srd_decoder *dec, GHashTable *hash,
87                 GHashTable **probes)
88 {
89         struct srd_probe *p;
90         GSList *all_probes, *l;
91         GVariant *gvar;
92         gint32 val_int;
93         int ret;
94         char *val_str, *conv;
95
96         ret = TRUE;
97         *probes = g_hash_table_new_full(g_str_hash, g_str_equal, g_free,
98                         (GDestroyNotify)g_variant_unref);
99
100         all_probes = g_slist_copy(dec->probes);
101         all_probes = g_slist_concat(all_probes, g_slist_copy(dec->opt_probes));
102         for (l = all_probes; l; l = l->next) {
103                 p = l->data;
104                 if (!(val_str = g_hash_table_lookup(hash, p->id)))
105                         /* Not specified. */
106                         continue;
107                 val_int = strtoll(val_str, &conv, 10);
108                 if (!conv || conv == val_str) {
109                         g_critical("Protocol decoder '%s' probes '%s' "
110                                         "is not a number.", dec->name, p->id);
111                         ret = FALSE;
112                         break;
113                 }
114                 gvar = g_variant_new_int32(val_int);
115                 g_variant_ref_sink(gvar);
116                 g_hash_table_insert(*probes, g_strdup(p->id), gvar);
117                 g_hash_table_remove(hash, p->id);
118         }
119         g_slist_free(all_probes);
120
121         return ret;
122 }
123
124 /* Register the given PDs for this session.
125  * Accepts a string of the form: "spi:sck=3:sdata=4,spi:sck=3:sdata=5"
126  * That will instantiate two SPI decoders on the clock but different data
127  * lines.
128  */
129 int register_pds(const char *pdstring)
130 {
131         struct srd_decoder *dec;
132         GHashTable *pd_opthash, *options, *probes;
133         GList *leftover, *l;
134         struct srd_decoder_inst *di;
135         int ret;
136         char **pdtokens, **pdtok, *pd_name;
137
138         pd_ann_visible = g_hash_table_new_full(g_str_hash, g_int_equal,
139                         g_free, NULL);
140         ret = 0;
141         pd_name = NULL;
142         pd_opthash = options = probes = NULL;
143         pdtokens = g_strsplit(pdstring, ",", 0);
144         for (pdtok = pdtokens; *pdtok; pdtok++) {
145                 if (!(pd_opthash = parse_generic_arg(*pdtok, TRUE))) {
146                         g_critical("Invalid protocol decoder option '%s'.", *pdtok);
147                         break;
148                 }
149
150                 pd_name = g_strdup(g_hash_table_lookup(pd_opthash, "sigrok_key"));
151                 g_hash_table_remove(pd_opthash, "sigrok_key");
152                 if (srd_decoder_load(pd_name) != SRD_OK) {
153                         g_critical("Failed to load protocol decoder %s.", pd_name);
154                         ret = 1;
155                         break;
156                 }
157                 dec = srd_decoder_get_by_id(pd_name);
158
159                 /* Convert decoder option and probe values to GVariant. */
160                 if (!opts_to_gvar(dec, pd_opthash, &options)) {
161                         ret = 1;
162                         break;
163                 }
164                 if (!probes_to_gvar(dec, pd_opthash, &probes)) {
165                         ret = 1;
166                         break;
167                 }
168                 if (g_hash_table_size(pd_opthash) > 0) {
169                         leftover = g_hash_table_get_keys(pd_opthash);
170                         for (l = leftover; l; l = l->next)
171                                 g_critical("Unknown option or probe '%s'", (char *)l->data);
172                         g_list_free(leftover);
173                         break;
174                 }
175
176                 if (!(di = srd_inst_new(srd_sess, pd_name, options))) {
177                         g_critical("Failed to instantiate protocol decoder %s.", pd_name);
178                         ret = 1;
179                         break;
180                 }
181
182                 /* If no annotation list was specified, add them all in now.
183                  * This will be pared down later to leave only the last PD
184                  * in the stack.
185                  */
186                 if (!opt_pd_annotations)
187                         g_hash_table_insert(pd_ann_visible,
188                                             g_strdup(di->inst_id), GINT_TO_POINTER(-1));
189
190                 /* Remap the probes if needed. */
191                 if (srd_inst_probe_set_all(di, probes) != SRD_OK) {
192                         ret = 1;
193                         break;
194                 }
195         }
196
197         g_strfreev(pdtokens);
198         if (pd_opthash)
199                 g_hash_table_destroy(pd_opthash);
200         if (options)
201                 g_hash_table_destroy(options);
202         if (probes)
203                 g_hash_table_destroy(probes);
204         if (pd_name)
205                 g_free(pd_name);
206
207         return ret;
208 }
209
210 int setup_pd_stack(void)
211 {
212         struct srd_decoder_inst *di_from, *di_to;
213         int ret, i;
214         char **pds, **ids;
215
216         /* Set up the protocol decoder stack. */
217         pds = g_strsplit(opt_pds, ",", 0);
218         if (g_strv_length(pds) > 1) {
219                 if (opt_pd_stack) {
220                         /* A stack setup was specified, use that. */
221                         g_strfreev(pds);
222                         pds = g_strsplit(opt_pd_stack, ",", 0);
223                         if (g_strv_length(pds) < 2) {
224                                 g_strfreev(pds);
225                                 g_critical("Specify at least two protocol decoders to stack.");
226                                 return 1;
227                         }
228                 }
229
230                 /* First PD goes at the bottom of the stack. */
231                 ids = g_strsplit(pds[0], ":", 0);
232                 if (!(di_from = srd_inst_find_by_id(srd_sess, ids[0]))) {
233                         g_strfreev(ids);
234                         g_critical("Cannot stack protocol decoder '%s': "
235                                         "instance not found.", pds[0]);
236                         return 1;
237                 }
238                 g_strfreev(ids);
239
240                 /* Every subsequent PD goes on top. */
241                 for (i = 1; pds[i]; i++) {
242                         ids = g_strsplit(pds[i], ":", 0);
243                         if (!(di_to = srd_inst_find_by_id(srd_sess, ids[0]))) {
244                                 g_strfreev(ids);
245                                 g_critical("Cannot stack protocol decoder '%s': "
246                                                 "instance not found.", pds[i]);
247                                 return 1;
248                         }
249                         g_strfreev(ids);
250                         if ((ret = srd_inst_stack(srd_sess, di_from, di_to)) != SRD_OK)
251                                 return 1;
252
253                         /* Don't show annotation from this PD. Only the last PD in
254                          * the stack will be left on the annotation list (unless
255                          * the annotation list was specifically provided).
256                          */
257                         if (!opt_pd_annotations)
258                                 g_hash_table_remove(pd_ann_visible,
259                                                     di_from->inst_id);
260
261                         di_from = di_to;
262                 }
263         }
264         g_strfreev(pds);
265
266         return 0;
267 }
268
269 int setup_pd_annotations(void)
270 {
271         GSList *l;
272         struct srd_decoder *dec;
273         int ann_class;
274         char **pds, **pdtok, **keyval, **ann_descr;
275
276         /* Set up custom list of PDs and annotations to show. */
277         pds = g_strsplit(opt_pd_annotations, ",", 0);
278         for (pdtok = pds; *pdtok && **pdtok; pdtok++) {
279                 keyval = g_strsplit(*pdtok, "=", 0);
280                 if (!(dec = srd_decoder_get_by_id(keyval[0]))) {
281                         g_critical("Protocol decoder '%s' not found.", keyval[0]);
282                         return 1;
283                 }
284                 if (!dec->annotations) {
285                         g_critical("Protocol decoder '%s' has no annotations.", keyval[0]);
286                         return 1;
287                 }
288                 ann_class = 0;
289                 if (g_strv_length(keyval) == 2) {
290                         for (l = dec->annotations; l; l = l->next, ann_class++) {
291                                 ann_descr = l->data;
292                                 if (!canon_cmp(ann_descr[0], keyval[1]))
293                                         /* Found it. */
294                                         break;
295                         }
296                         if (!l) {
297                                 g_critical("Annotation '%s' not found "
298                                                 "for protocol decoder '%s'.", keyval[1], keyval[0]);
299                                 return 1;
300                         }
301                         g_debug("cli: Showing protocol decoder %s annotation "
302                                         "class %d (%s).", keyval[0], ann_class, ann_descr[0]);
303                 } else {
304                         /* No class specified: show all of them. */
305                         ann_class = -1;
306                         g_debug("cli: Showing all annotation classes for protocol "
307                                         "decoder %s.", keyval[0]);
308                 }
309                 g_hash_table_insert(pd_ann_visible, g_strdup(keyval[0]), GINT_TO_POINTER(ann_class));
310                 g_strfreev(keyval);
311         }
312         g_strfreev(pds);
313
314         return 0;
315 }
316
317 int setup_pd_meta(void)
318 {
319         struct srd_decoder *dec;
320         char **pds, **pdtok;
321
322         pd_meta_visible = g_hash_table_new_full(g_str_hash, g_int_equal,
323                         g_free, NULL);
324         pds = g_strsplit(opt_pd_meta, ",", 0);
325         for (pdtok = pds; *pdtok && **pdtok; pdtok++) {
326                 if (!(dec = srd_decoder_get_by_id(*pdtok))) {
327                         g_critical("Protocol decoder '%s' not found.", *pdtok);
328                         return 1;
329                 }
330                 g_debug("cli: Showing protocol decoder meta output from '%s'.", *pdtok);
331                 g_hash_table_insert(pd_meta_visible, g_strdup(*pdtok), NULL);
332         }
333         g_strfreev(pds);
334
335         return 0;
336 }
337
338 int setup_pd_binary(void)
339 {
340         GSList *l;
341         struct srd_decoder *dec;
342         int bin_class;
343         char **pds, **pdtok, **keyval, *bin_name;
344
345         pd_binary_visible = g_hash_table_new_full(g_str_hash, g_int_equal,
346                         g_free, NULL);
347         pds = g_strsplit(opt_pd_binary, ",", 0);
348         for (pdtok = pds; *pdtok && **pdtok; pdtok++) {
349                 keyval = g_strsplit(*pdtok, "=", 0);
350                 if (!(dec = srd_decoder_get_by_id(keyval[0]))) {
351                         g_critical("Protocol decoder '%s' not found.", keyval[0]);
352                         return 1;
353                 }
354                 if (!dec->binary) {
355                         g_critical("Protocol decoder '%s' has no binary output.", keyval[0]);
356                         return 1;
357                 }
358                 bin_class = 0;
359                 if (g_strv_length(keyval) == 2) {
360                         for (l = dec->binary; l; l = l->next, bin_class++) {
361                                 bin_name = l->data;
362                                 if (!canon_cmp(bin_name, keyval[1]))
363                                         /* Found it. */
364                                         break;
365                         }
366                         if (!l) {
367                                 g_critical("binary output '%s' not found "
368                                                 "for protocol decoder '%s'.", keyval[1], keyval[0]);
369                                 return 1;
370                         }
371                         g_debug("cli: Showing protocol decoder %s binary class "
372                                         "%d (%s).", keyval[0], bin_class, bin_name);
373                 } else {
374                         /* No class specified: output all of them. */
375                         bin_class = -1;
376                         g_debug("cli: Showing all binary classes for protocol "
377                                         "decoder %s.", keyval[0]);
378                 }
379                 g_hash_table_insert(pd_binary_visible, g_strdup(keyval[0]), GINT_TO_POINTER(bin_class));
380                 g_strfreev(keyval);
381         }
382         g_strfreev(pds);
383
384         return 0;
385 }
386
387 void show_pd_annotations(struct srd_proto_data *pdata, void *cb_data)
388 {
389         struct srd_proto_data_annotation *pda;
390         gpointer ann_format;
391         int format;
392
393         /* 'cb_data' is not used in this specific callback. */
394         (void)cb_data;
395
396         if (!pd_ann_visible)
397                 return;
398
399         if (!g_hash_table_lookup_extended(pd_ann_visible, pdata->pdo->di->inst_id,
400                         NULL, &ann_format))
401                 /* Not in the list of PDs whose annotations we're showing. */
402                 return;
403
404         format = GPOINTER_TO_INT(ann_format);
405         pda = pdata->data;
406         if (format != -1 && pda->ann_format != format)
407                 /* We don't want this particular format from the PD. */
408                 return;
409
410         if (opt_loglevel > SR_LOG_WARN)
411                 printf("%"PRIu64"-%"PRIu64" ", pdata->start_sample, pdata->end_sample);
412         printf("%s: ", pdata->pdo->proto_id);
413         /* Show only the longest annotation. */
414         printf("\"%s\" ", pda->ann_text[0]);
415         printf("\n");
416         fflush(stdout);
417 }
418
419 void show_pd_meta(struct srd_proto_data *pdata, void *cb_data)
420 {
421
422         /* 'cb_data' is not used in this specific callback. */
423         (void)cb_data;
424
425         if (!g_hash_table_lookup_extended(pd_meta_visible,
426                         pdata->pdo->di->decoder->id, NULL, NULL))
427                 /* Not in the list of PDs whose meta output we're showing. */
428                 return;
429
430         if (opt_loglevel > SR_LOG_WARN)
431                 printf("%"PRIu64"-%"PRIu64" ", pdata->start_sample, pdata->end_sample);
432         printf("%s: ", pdata->pdo->proto_id);
433         printf("%s: %s", pdata->pdo->meta_name, g_variant_print(pdata->data, FALSE));
434         printf("\n");
435         fflush(stdout);
436 }
437
438 void show_pd_binary(struct srd_proto_data *pdata, void *cb_data)
439 {
440         struct srd_proto_data_binary *pdb;
441         gpointer classp;
442         int class;
443
444         /* 'cb_data' is not used in this specific callback. */
445         (void)cb_data;
446
447         if (!g_hash_table_lookup_extended(pd_binary_visible,
448                         pdata->pdo->di->decoder->id, NULL, (void **)&classp))
449                 /* Not in the list of PDs whose meta output we're showing. */
450                 return;
451
452         class = GPOINTER_TO_INT(classp);
453         pdb = pdata->data;
454         if (class != -1 && class != pdb->bin_class)
455                 /* Not showing this binary class. */
456                 return;
457
458         /* Just send the binary output to stdout, no embellishments. */
459         fwrite(pdb->data, pdb->size, 1, stdout);
460         fflush(stdout);
461 }
462 #endif
463