]> sigrok.org Git - sigrok-cli.git/blame - session.c
Fix more warnings when building without libsigrokdecode.
[sigrok-cli.git] / session.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
20fb52e0 20#include "sigrok-cli.h"
2be182e6
BV
21#include "config.h"
22#include <glib.h>
23#include <glib/gstdio.h>
55de58a2
UH
24#include <string.h>
25#include <stdlib.h>
2be182e6
BV
26
27static struct sr_output_format *output_format = NULL;
28static int default_output_format = FALSE;
29static char *output_format_param = NULL;
30static GByteArray *savebuf;
31static uint64_t limit_samples = 0;
32static uint64_t limit_frames = 0;
33
34extern gchar *opt_output_file;
35extern gchar *opt_output_format;
36extern gchar *opt_pds;
37extern gboolean opt_wait_trigger;
38extern gchar *opt_time;
39extern gchar *opt_samples;
40extern gchar *opt_frames;
41extern gchar *opt_continuous;
42extern gchar *opt_config;
43extern gchar *opt_triggers;
44#ifdef HAVE_SRD
45extern struct srd_session *srd_sess;
46#endif
47
48
49static GArray *get_enabled_logic_probes(const struct sr_dev_inst *sdi)
50{
51 struct sr_probe *probe;
52 GArray *probes;
53 GSList *l;
54
55 probes = g_array_new(FALSE, FALSE, sizeof(int));
56 for (l = sdi->probes; l; l = l->next) {
57 probe = l->data;
58 if (probe->type != SR_PROBE_LOGIC)
59 continue;
60 if (probe->enabled != TRUE)
61 continue;
62 g_array_append_val(probes, probe->index);
63 }
64
65 return probes;
66}
67
68static int set_limit_time(const struct sr_dev_inst *sdi)
69{
70 GVariant *gvar;
71 uint64_t time_msec;
72 uint64_t samplerate;
73
74 if (!(time_msec = sr_parse_timestring(opt_time))) {
75 g_critical("Invalid time '%s'", opt_time);
76 return SR_ERR;
77 }
78
79 if (sr_dev_has_option(sdi, SR_CONF_LIMIT_MSEC)) {
80 gvar = g_variant_new_uint64(time_msec);
81 if (sr_config_set(sdi, NULL, SR_CONF_LIMIT_MSEC, gvar) != SR_OK) {
82 g_critical("Failed to configure time limit.");
83 return SR_ERR;
84 }
85 } else if (sr_dev_has_option(sdi, SR_CONF_SAMPLERATE)) {
86 /* Convert to samples based on the samplerate. */
87 sr_config_get(sdi->driver, sdi, NULL, SR_CONF_SAMPLERATE, &gvar);
88 samplerate = g_variant_get_uint64(gvar);
89 g_variant_unref(gvar);
90 limit_samples = (samplerate) * time_msec / (uint64_t)1000;
91 if (limit_samples == 0) {
92 g_critical("Not enough time at this samplerate.");
93 return SR_ERR;
94 }
95 gvar = g_variant_new_uint64(limit_samples);
96 if (sr_config_set(sdi, NULL, SR_CONF_LIMIT_SAMPLES, gvar) != SR_OK) {
97 g_critical("Failed to configure time-based sample limit.");
98 return SR_ERR;
99 }
100 } else {
101 g_critical("This device does not support time limits.");
102 return SR_ERR;
103 }
104
105 return SR_OK;
106}
107
108int setup_output_format(void)
109{
110 GHashTable *fmtargs;
111 GHashTableIter iter;
112 gpointer key, value;
113 struct sr_output_format **outputs;
114 int i;
115 char *fmtspec;
116
117 if (opt_output_format && !strcmp(opt_output_format, "sigrok")) {
118 /* Doesn't really exist as an output module - this is
119 * the session save mode. */
120 g_free(opt_output_format);
121 opt_output_format = NULL;
122 }
123
124 if (!opt_output_format) {
125 opt_output_format = DEFAULT_OUTPUT_FORMAT;
126 /* we'll need to remember this so when saving to a file
127 * later, sigrok session format will be used.
128 */
129 default_output_format = TRUE;
130 }
131
132 fmtargs = parse_generic_arg(opt_output_format, TRUE);
133 fmtspec = g_hash_table_lookup(fmtargs, "sigrok_key");
134 if (!fmtspec) {
135 g_critical("Invalid output format.");
136 return 1;
137 }
138 outputs = sr_output_list();
139 for (i = 0; outputs[i]; i++) {
140 if (strcmp(outputs[i]->id, fmtspec))
141 continue;
142 g_hash_table_remove(fmtargs, "sigrok_key");
143 output_format = outputs[i];
144 g_hash_table_iter_init(&iter, fmtargs);
145 while (g_hash_table_iter_next(&iter, &key, &value)) {
146 /* only supporting one parameter per output module
147 * for now, and only its value */
148 output_format_param = g_strdup(value);
149 break;
150 }
151 break;
152 }
153 if (!output_format) {
154 g_critical("Invalid output format %s.", opt_output_format);
155 return 1;
156 }
157 g_hash_table_destroy(fmtargs);
158
159 return 0;
160}
161
162void datafeed_in(const struct sr_dev_inst *sdi,
163 const struct sr_datafeed_packet *packet, void *cb_data)
164{
165 const struct sr_datafeed_meta *meta;
166 const struct sr_datafeed_logic *logic;
167 const struct sr_datafeed_analog *analog;
168 struct sr_config *src;
169 static struct sr_output *o = NULL;
170 static GArray *logic_probelist = NULL;
171 static uint64_t received_samples = 0;
172 static int unitsize = 0;
173 static int triggered = 0;
174 static FILE *outfile = NULL;
175 GSList *l;
176 GString *out;
177 int sample_size, ret;
55de58a2
UH
178 uint64_t samplerate, output_len, filter_out_len;
179#ifdef HAVE_SRD
180 uint64_t end_sample;
181#endif
2be182e6
BV
182 uint8_t *output_buf, *filter_out;
183
184 (void) cb_data;
185
186 /* If the first packet to come in isn't a header, don't even try. */
187 if (packet->type != SR_DF_HEADER && o == NULL)
188 return;
189
190 sample_size = -1;
191 switch (packet->type) {
192 case SR_DF_HEADER:
193 g_debug("cli: Received SR_DF_HEADER");
194 /* Initialize the output module. */
195 if (!(o = g_try_malloc(sizeof(struct sr_output)))) {
196 g_critical("Output module malloc failed.");
197 exit(1);
198 }
199 o->format = output_format;
200 o->sdi = (struct sr_dev_inst *)sdi;
201 o->param = output_format_param;
202 if (o->format->init) {
203 if (o->format->init(o) != SR_OK) {
204 g_critical("Output format initialization failed.");
205 exit(1);
206 }
207 }
208
209 /* Prepare non-stdout output. */
210 outfile = stdout;
211 if (opt_output_file) {
212 if (default_output_format) {
213 /* output file is in session format, so we'll
214 * keep a copy of everything as it comes in
215 * and save from there after the session. */
216 outfile = NULL;
217 savebuf = g_byte_array_new();
218 } else {
219 /* saving to a file in whatever format was set
220 * with --format, so all we need is a filehandle */
221 outfile = g_fopen(opt_output_file, "wb");
222 }
223 }
224
225 /* Prepare for logic data. */
226 logic_probelist = get_enabled_logic_probes(sdi);
227 /* How many bytes we need to store the packed samples. */
228 unitsize = (logic_probelist->len + 7) / 8;
229
230#ifdef HAVE_SRD
231 GVariant *gvar;
232 if (opt_pds && logic_probelist->len) {
233 if (sr_config_get(sdi->driver, sdi, NULL, SR_CONF_SAMPLERATE,
234 &gvar) == SR_OK) {
235 samplerate = g_variant_get_uint64(gvar);
236 g_variant_unref(gvar);
237 if (srd_session_metadata_set(srd_sess, SRD_CONF_SAMPLERATE,
238 g_variant_new_uint64(samplerate)) != SRD_OK) {
239 g_critical("Failed to configure decode session.");
240 break;
241 }
242 }
243 if (srd_session_start(srd_sess) != SRD_OK) {
244 g_critical("Failed to start decode session.");
245 break;
246 }
247 }
248#endif
249 break;
250
251 case SR_DF_META:
252 g_debug("cli: received SR_DF_META");
253 meta = packet->payload;
254 for (l = meta->config; l; l = l->next) {
255 src = l->data;
256 switch (src->key) {
257 case SR_CONF_SAMPLERATE:
258 samplerate = g_variant_get_uint64(src->data);
259 g_debug("cli: got samplerate %"PRIu64" Hz", samplerate);
260#ifdef HAVE_SRD
261 if (opt_pds) {
262 if (srd_session_metadata_set(srd_sess, SRD_CONF_SAMPLERATE,
263 g_variant_new_uint64(samplerate)) != SRD_OK) {
264 g_critical("Failed to pass samplerate to decoder.");
265 }
266 }
267#endif
268 break;
269 case SR_CONF_SAMPLE_INTERVAL:
270 samplerate = g_variant_get_uint64(src->data);
271 g_debug("cli: got sample interval %"PRIu64" ms", samplerate);
272 break;
273 default:
274 /* Unknown metadata is not an error. */
275 break;
276 }
277 }
278 break;
279
280 case SR_DF_TRIGGER:
281 g_debug("cli: received SR_DF_TRIGGER");
282 if (o->format->event)
283 o->format->event(o, SR_DF_TRIGGER, &output_buf,
284 &output_len);
285 triggered = 1;
286 break;
287
288 case SR_DF_LOGIC:
289 logic = packet->payload;
290 g_message("cli: received SR_DF_LOGIC, %"PRIu64" bytes", logic->length);
291 sample_size = logic->unitsize;
292 if (logic->length == 0)
293 break;
294
295 /* Don't store any samples until triggered. */
296 if (opt_wait_trigger && !triggered)
297 break;
298
299 if (limit_samples && received_samples >= limit_samples)
300 break;
301
302 ret = sr_filter_probes(sample_size, unitsize, logic_probelist,
303 logic->data, logic->length,
304 &filter_out, &filter_out_len);
305 if (ret != SR_OK)
306 break;
307
308 /*
309 * What comes out of the filter is guaranteed to be packed into the
310 * minimum size needed to support the number of samples at this sample
311 * size. however, the driver may have submitted too much. Cut off
312 * the buffer of the last packet according to the sample limit.
313 */
314 if (limit_samples && (received_samples + logic->length / sample_size >
315 limit_samples * sample_size))
316 filter_out_len = limit_samples * sample_size - received_samples;
317
318 if (opt_output_file && default_output_format) {
319 /* Saving to a session file. */
320 g_byte_array_append(savebuf, filter_out, filter_out_len);
321 } else {
322 if (opt_pds) {
323#ifdef HAVE_SRD
324 end_sample = received_samples + filter_out_len / unitsize;
325 if (srd_session_send(srd_sess, received_samples, end_sample,
326 (uint8_t*)filter_out, filter_out_len) != SRD_OK)
327 sr_session_stop();
328#endif
329 } else {
330 output_len = 0;
331 if (o->format->data && packet->type == o->format->df_type)
332 o->format->data(o, filter_out, filter_out_len,
333 &output_buf, &output_len);
334 if (output_len) {
335 fwrite(output_buf, 1, output_len, outfile);
336 fflush(outfile);
337 g_free(output_buf);
338 }
339 }
340 }
341 g_free(filter_out);
342
343 received_samples += logic->length / sample_size;
344 break;
345
346 case SR_DF_ANALOG:
347 analog = packet->payload;
348 g_message("cli: received SR_DF_ANALOG, %d samples", analog->num_samples);
349 if (analog->num_samples == 0)
350 break;
351
352 if (limit_samples && received_samples >= limit_samples)
353 break;
354
355 if (o->format->data && packet->type == o->format->df_type) {
356 o->format->data(o, (const uint8_t *)analog->data,
357 analog->num_samples * sizeof(float),
358 &output_buf, &output_len);
359 if (output_buf) {
360 fwrite(output_buf, 1, output_len, outfile);
361 fflush(outfile);
362 g_free(output_buf);
363 }
364 }
365
366 received_samples += analog->num_samples;
367 break;
368
369 case SR_DF_FRAME_BEGIN:
370 g_debug("cli: received SR_DF_FRAME_BEGIN");
371 if (o->format->event) {
372 o->format->event(o, SR_DF_FRAME_BEGIN, &output_buf,
373 &output_len);
374 if (output_buf) {
375 fwrite(output_buf, 1, output_len, outfile);
376 fflush(outfile);
377 g_free(output_buf);
378 }
379 }
380 break;
381
382 case SR_DF_FRAME_END:
383 g_debug("cli: received SR_DF_FRAME_END");
384 if (o->format->event) {
385 o->format->event(o, SR_DF_FRAME_END, &output_buf,
386 &output_len);
387 if (output_buf) {
388 fwrite(output_buf, 1, output_len, outfile);
389 fflush(outfile);
390 g_free(output_buf);
391 }
392 }
393 break;
394
395 default:
396 break;
397 }
398
399 if (o && o->format->receive) {
400 if (o->format->receive(o, sdi, packet, &out) == SR_OK && out) {
401 fwrite(out->str, 1, out->len, outfile);
402 fflush(outfile);
403 g_string_free(out, TRUE);
404 }
405 }
406
407 /* SR_DF_END needs to be handled after the output module's receive()
408 * is called, so it can properly clean up that module etc. */
409 if (packet->type == SR_DF_END) {
410 g_debug("cli: Received SR_DF_END");
411
412 if (o->format->event) {
413 o->format->event(o, SR_DF_END, &output_buf, &output_len);
414 if (output_buf) {
415 if (outfile)
416 fwrite(output_buf, 1, output_len, outfile);
417 g_free(output_buf);
418 output_len = 0;
419 }
420 }
421
422 if (limit_samples && received_samples < limit_samples)
423 g_warning("Device only sent %" PRIu64 " samples.",
424 received_samples);
425
426 if (opt_continuous)
427 g_warning("Device stopped after %" PRIu64 " samples.",
428 received_samples);
429
430 g_array_free(logic_probelist, TRUE);
431
432 if (o->format->cleanup)
433 o->format->cleanup(o);
434 g_free(o);
435 o = NULL;
436
437 if (outfile && outfile != stdout)
438 fclose(outfile);
439
440 if (opt_output_file && default_output_format && savebuf->len) {
441 if (sr_session_save(opt_output_file, sdi, savebuf->data,
442 unitsize, savebuf->len / unitsize) != SR_OK)
443 g_critical("Failed to save session.");
30364883 444 g_byte_array_free(savebuf, TRUE);
2be182e6
BV
445 }
446 }
447
448}
449
ad54a1a6 450int opt_to_gvar(char *key, char *value, struct sr_config *src)
2be182e6
BV
451{
452 const struct sr_config_info *srci;
2be182e6
BV
453 double tmp_double;
454 uint64_t tmp_u64, p, q, low, high;
ad54a1a6 455 GVariant *rational[2], *range[2];
2be182e6 456 gboolean tmp_bool;
ad54a1a6 457 int ret;
2be182e6 458
ad54a1a6
BV
459 if (!(srci = sr_config_info_name_get(key))) {
460 g_critical("Unknown device option '%s'.", (char *) key);
461 return -1;
462 }
463 src->key = srci->key;
2be182e6 464
ad54a1a6
BV
465 if ((value == NULL) &&
466 (srci->datatype != SR_T_BOOL)) {
467 g_critical("Option '%s' needs a value.", (char *)key);
468 return -1;
469 }
470
471 ret = 0;
472 switch (srci->datatype) {
473 case SR_T_UINT64:
474 ret = sr_parse_sizestring(value, &tmp_u64);
475 if (ret != 0)
2be182e6 476 break;
ad54a1a6
BV
477 src->data = g_variant_new_uint64(tmp_u64);
478 break;
479 case SR_T_INT32:
480 ret = sr_parse_sizestring(value, &tmp_u64);
481 if (ret != 0)
2be182e6 482 break;
ad54a1a6
BV
483 src->data = g_variant_new_int32(tmp_u64);
484 break;
485 case SR_T_CHAR:
486 src->data = g_variant_new_string(value);
487 break;
488 case SR_T_BOOL:
489 if (!value)
490 tmp_bool = TRUE;
491 else
492 tmp_bool = sr_parse_boolstring(value);
493 src->data = g_variant_new_boolean(tmp_bool);
494 break;
495 case SR_T_FLOAT:
496 tmp_double = strtof(value, NULL);
497 src->data = g_variant_new_double(tmp_double);
498 break;
499 case SR_T_RATIONAL_PERIOD:
500 if ((ret = sr_parse_period(value, &p, &q)) != SR_OK)
2be182e6 501 break;
ad54a1a6
BV
502 rational[0] = g_variant_new_uint64(p);
503 rational[1] = g_variant_new_uint64(q);
504 src->data = g_variant_new_tuple(rational, 2);
505 break;
506 case SR_T_RATIONAL_VOLT:
507 if ((ret = sr_parse_voltage(value, &p, &q)) != SR_OK)
2be182e6 508 break;
ad54a1a6
BV
509 rational[0] = g_variant_new_uint64(p);
510 rational[1] = g_variant_new_uint64(q);
511 src->data = g_variant_new_tuple(rational, 2);
512 break;
513 case SR_T_UINT64_RANGE:
514 if (sscanf(value, "%"PRIu64"-%"PRIu64, &low, &high) != 2) {
515 ret = -1;
2be182e6 516 break;
ad54a1a6
BV
517 } else {
518 range[0] = g_variant_new_uint64(low);
519 range[1] = g_variant_new_uint64(high);
520 src->data = g_variant_new_tuple(range, 2);
2be182e6 521 }
ad54a1a6
BV
522 break;
523 default:
524 ret = -1;
525 }
526
527 return ret;
528}
529
530int set_dev_options(struct sr_dev_inst *sdi, GHashTable *args)
531{
532 struct sr_config src;
533 struct sr_probe_group *pg;
534 GHashTableIter iter;
535 gpointer key, value;
536 int ret;
537
538 g_hash_table_iter_init(&iter, args);
539 while (g_hash_table_iter_next(&iter, &key, &value)) {
540 if ((ret = opt_to_gvar(key, value, &src)) != 0)
541 return ret;
542 pg = select_probe_group(sdi);
543 ret = sr_config_set(sdi, pg, src.key, src.data);
2be182e6
BV
544 if (ret != SR_OK) {
545 g_critical("Failed to set device option '%s'.", (char *)key);
546 return ret;
547 }
548 }
549
550 return SR_OK;
551}
552
553void run_session(void)
554{
555 GSList *devices;
556 GHashTable *devargs;
557 GVariant *gvar;
558 struct sr_dev_inst *sdi;
02c65935 559 uint64_t min_samples, max_samples;
2be182e6
BV
560 int max_probes, i;
561 char **triggerlist;
562
563 devices = device_scan();
564 if (!devices) {
565 g_critical("No devices found.");
566 return;
567 }
568 if (g_slist_length(devices) > 1) {
569 g_critical("sigrok-cli only supports one device for capturing.");
570 return;
571 }
572 sdi = devices->data;
573
574 sr_session_new();
575 sr_session_datafeed_callback_add(datafeed_in, NULL);
576
577 if (sr_dev_open(sdi) != SR_OK) {
578 g_critical("Failed to open device.");
579 return;
580 }
581
582 if (sr_session_dev_add(sdi) != SR_OK) {
583 g_critical("Failed to add device to session.");
584 sr_session_destroy();
585 return;
586 }
587
588 if (opt_config) {
589 if ((devargs = parse_generic_arg(opt_config, FALSE))) {
590 if (set_dev_options(sdi, devargs) != SR_OK)
591 return;
592 g_hash_table_destroy(devargs);
593 }
594 }
595
596 if (select_probes(sdi) != SR_OK) {
597 g_critical("Failed to set probes.");
598 sr_session_destroy();
599 return;
600 }
601
602 if (opt_triggers) {
603 if (!(triggerlist = sr_parse_triggerstring(sdi, opt_triggers))) {
604 sr_session_destroy();
605 return;
606 }
607 max_probes = g_slist_length(sdi->probes);
608 for (i = 0; i < max_probes; i++) {
609 if (triggerlist[i]) {
610 sr_dev_trigger_set(sdi, i, triggerlist[i]);
611 g_free(triggerlist[i]);
612 }
613 }
614 g_free(triggerlist);
615 }
616
617 if (opt_continuous) {
618 if (!sr_dev_has_option(sdi, SR_CONF_CONTINUOUS)) {
619 g_critical("This device does not support continuous sampling.");
620 sr_session_destroy();
621 return;
622 }
623 }
624
625 if (opt_time) {
626 if (set_limit_time(sdi) != SR_OK) {
627 sr_session_destroy();
628 return;
629 }
630 }
631
632 if (opt_samples) {
633 if ((sr_parse_sizestring(opt_samples, &limit_samples) != SR_OK)) {
634 g_critical("Invalid sample limit '%s'.", opt_samples);
635 sr_session_destroy();
636 return;
637 }
02c65935
BV
638 if (sr_config_list(sdi->driver, sdi, NULL,
639 SR_CONF_LIMIT_SAMPLES, &gvar) == SR_OK) {
c7a5cb12
BV
640 /* The device has no compression, or compression is turned
641 * off, and publishes its sample memory size. */
02c65935 642 g_variant_get(gvar, "(tt)", &min_samples, &max_samples);
be781321 643 g_variant_unref(gvar);
02c65935
BV
644 if (limit_samples < min_samples) {
645 g_critical("The device stores at least %"PRIu64
646 " samples with the current settings.", min_samples);
647 }
c7a5cb12
BV
648 if (limit_samples > max_samples) {
649 g_critical("The device can store only %"PRIu64
650 " samples with the current settings.", max_samples);
651 }
652 }
2be182e6
BV
653 gvar = g_variant_new_uint64(limit_samples);
654 if (sr_config_set(sdi, NULL, SR_CONF_LIMIT_SAMPLES, gvar) != SR_OK) {
655 g_critical("Failed to configure sample limit.");
656 sr_session_destroy();
657 return;
658 }
659 }
660
661 if (opt_frames) {
662 if ((sr_parse_sizestring(opt_frames, &limit_frames) != SR_OK)) {
663 g_critical("Invalid sample limit '%s'.", opt_samples);
664 sr_session_destroy();
665 return;
666 }
667 gvar = g_variant_new_uint64(limit_frames);
668 if (sr_config_set(sdi, NULL, SR_CONF_LIMIT_FRAMES, gvar) != SR_OK) {
669 g_critical("Failed to configure frame limit.");
670 sr_session_destroy();
671 return;
672 }
673 }
674
675 if (sr_session_start() != SR_OK) {
676 g_critical("Failed to start session.");
677 sr_session_destroy();
678 return;
679 }
680
681 if (opt_continuous)
682 add_anykey();
683
684 sr_session_run();
685
686 if (opt_continuous)
687 clear_anykey();
688
689 sr_session_datafeed_callback_remove_all();
690 sr_session_destroy();
691 g_slist_free(devices);
692
693}
694