]> sigrok.org Git - sigrok-cli.git/blob - session.c
man: Update uart decode example syntax
[sigrok-cli.git] / session.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 "sigrok-cli.h"
21 #include "config.h"
22 #include <glib.h>
23 #include <glib/gstdio.h>
24 #include <string.h>
25 #include <stdlib.h>
26
27 static struct sr_output_format *output_format = NULL;
28 static int default_output_format = FALSE;
29 static char *output_format_param = NULL;
30 static GByteArray *savebuf;
31 static uint64_t limit_samples = 0;
32 static uint64_t limit_frames = 0;
33
34 extern gchar *opt_output_file;
35 extern gchar *opt_output_format;
36 extern gchar *opt_pds;
37 extern gboolean opt_wait_trigger;
38 extern gchar *opt_time;
39 extern gchar *opt_samples;
40 extern gchar *opt_frames;
41 extern gchar *opt_continuous;
42 extern gchar *opt_config;
43 extern gchar *opt_triggers;
44 #ifdef HAVE_SRD
45 extern struct srd_session *srd_sess;
46 #endif
47
48
49 static 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
68 static 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
108 int 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
162 void 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;
178         uint64_t samplerate, output_len, filter_out_len;
179 #ifdef HAVE_SRD
180         uint64_t end_sample;
181 #endif
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.");
444                         g_byte_array_free(savebuf, TRUE);
445                 }
446         }
447
448 }
449
450 int opt_to_gvar(char *key, char *value, struct sr_config *src)
451 {
452         const struct sr_config_info *srci;
453         double tmp_double;
454         uint64_t tmp_u64, p, q, low, high;
455         GVariant *rational[2], *range[2];
456         gboolean tmp_bool;
457         int ret;
458
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;
464
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)
476                         break;
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)
482                         break;
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)
501                         break;
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)
508                         break;
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;
516                         break;
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);
521                 }
522                 break;
523         default:
524                 ret = -1;
525         }
526
527         return ret;
528 }
529
530 int 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);
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
553 void run_session(void)
554 {
555         GSList *devices;
556         GHashTable *devargs;
557         GVariant *gvar;
558         struct sr_dev_inst *sdi;
559         uint64_t min_samples, max_samples;
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                 }
638                 if (sr_config_list(sdi->driver, sdi, NULL,
639                                 SR_CONF_LIMIT_SAMPLES, &gvar) == SR_OK) {
640                         /* The device has no compression, or compression is turned
641                          * off, and publishes its sample memory size. */
642                         g_variant_get(gvar, "(tt)", &min_samples, &max_samples);
643                         g_variant_unref(gvar);
644                         if (limit_samples < min_samples) {
645                                 g_critical("The device stores at least %"PRIu64
646                                                 " samples with the current settings.", min_samples);
647                         }
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                 }
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