]> sigrok.org Git - sigrok-cli.git/blame - decode.c
Refactor main source into separate files
[sigrok-cli.git] / decode.c
CommitLineData
2be182e6
BV
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
29static GHashTable *pd_ann_visible = NULL;
30static GHashTable *pd_meta_visible = NULL;
31static GHashTable *pd_binary_visible = NULL;
32
33extern struct srd_session *srd_sess;
34extern gint opt_loglevel;
35extern gchar *opt_pds;
36extern gchar *opt_pd_stack;
37extern gchar *opt_pd_annotations;
38extern gchar *opt_pd_meta;
39extern gchar *opt_pd_binary;
40
41
42static 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
86static 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 */
129int 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
210int 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
269int 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
317int 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
338int 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
387void 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
419void 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
438void 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