void datafeed_in(const struct sr_dev_inst *sdi, const struct sr_datafeed_packet *packet, void *cb_data) { const struct sr_datafeed_meta *meta; const struct sr_datafeed_logic *logic; const struct sr_datafeed_analog *analog; struct sr_config *src; struct sr_channel *ch; static struct sr_output *o = NULL; static uint64_t rcvd_samples_logic = 0; static uint64_t rcvd_samples_analog = 0; static uint64_t samplerate = 0; static int triggered = 0; static FILE *outfile = NULL; GSList *l; GString *out; GVariant *gvar; uint64_t end_sample; uint64_t input_len; int i; char **channels; (void) cb_data; /* If the first packet to come in isn't a header, don't even try. */ if (packet->type != SR_DF_HEADER && o == NULL) return; switch (packet->type) { case SR_DF_HEADER: g_debug("cli: Received SR_DF_HEADER."); o = setup_output_format(sdi); /* Prepare non-stdout output. */ outfile = stdout; if (opt_output_file) { if (default_output_format) { outfile = NULL; } else { /* saving to a file in whatever format was set * with --format, so all we need is a filehandle */ outfile = g_fopen(opt_output_file, "wb"); } } rcvd_samples_logic = rcvd_samples_analog = 0; if (sr_config_get(sdi->driver, sdi, NULL, SR_CONF_SAMPLERATE, &gvar) == SR_OK) { samplerate = g_variant_get_uint64(gvar); g_variant_unref(gvar); } #ifdef HAVE_SRD if (opt_pds) { if (samplerate) { if (srd_session_metadata_set(srd_sess, SRD_CONF_SAMPLERATE, g_variant_new_uint64(samplerate)) != SRD_OK) { g_critical("Failed to configure decode session."); break; } } if (srd_session_start(srd_sess) != SRD_OK) { g_critical("Failed to start decode session."); break; } } #endif break; case SR_DF_META: g_debug("cli: Received SR_DF_META."); meta = packet->payload; for (l = meta->config; l; l = l->next) { src = l->data; switch (src->key) { case SR_CONF_SAMPLERATE: samplerate = g_variant_get_uint64(src->data); g_debug("cli: Got samplerate %"PRIu64" Hz.", samplerate); #ifdef HAVE_SRD if (opt_pds) { if (srd_session_metadata_set(srd_sess, SRD_CONF_SAMPLERATE, g_variant_new_uint64(samplerate)) != SRD_OK) { g_critical("Failed to pass samplerate to decoder."); } } #endif break; case SR_CONF_SAMPLE_INTERVAL: samplerate = g_variant_get_uint64(src->data); g_debug("cli: Got sample interval %"PRIu64" ms.", samplerate); break; default: /* Unknown metadata is not an error. */ break; } } break; case SR_DF_TRIGGER: g_debug("cli: Received SR_DF_TRIGGER."); triggered = 1; break; case SR_DF_LOGIC: logic = packet->payload; g_message("cli: Received SR_DF_LOGIC (%"PRIu64" bytes, unitsize = %d).", logic->length, logic->unitsize); if (logic->length == 0) break; /* Don't store any samples until triggered. */ if (opt_wait_trigger && !triggered) break; if (limit_samples && rcvd_samples_logic >= limit_samples) break; end_sample = rcvd_samples_logic + logic->length / logic->unitsize; /* Cut off last packet according to the sample limit. */ if (limit_samples && end_sample > limit_samples) end_sample = limit_samples; input_len = (end_sample - rcvd_samples_logic) * logic->unitsize; if (opt_output_file && default_output_format) { /* Saving to a session file. */ if (rcvd_samples_logic == 0) { /* First packet with logic data, init session file. */ channels = g_malloc(sizeof(char *) * g_slist_length(sdi->channels)); for (i = 0, l = sdi->channels; l; l = l->next) { ch = l->data; if (ch->enabled && ch->type == SR_CHANNEL_LOGIC) channels[i++] = ch->name; } channels[i] = NULL; sr_session_save_init(opt_output_file, samplerate, channels); g_free(channels); } save_chunk_logic(logic->data, input_len, logic->unitsize); } else { if (opt_pds) { #ifdef HAVE_SRD if (srd_session_send(srd_sess, rcvd_samples_logic, end_sample, logic->data, input_len) != SRD_OK) sr_session_stop(); #endif } } rcvd_samples_logic = end_sample; break; case SR_DF_ANALOG: analog = packet->payload; g_message("cli: Received SR_DF_ANALOG (%d samples).", analog->num_samples); if (analog->num_samples == 0) break; if (limit_samples && rcvd_samples_analog >= limit_samples) break; rcvd_samples_analog += analog->num_samples; break; case SR_DF_FRAME_BEGIN: g_debug("cli: Received SR_DF_FRAME_BEGIN."); break; case SR_DF_FRAME_END: g_debug("cli: Received SR_DF_FRAME_END."); break; default: break; } if (o && outfile && !opt_pds) { if (sr_output_send(o, packet, &out) == SR_OK && out) { fwrite(out->str, 1, out->len, outfile); fflush(outfile); g_string_free(out, TRUE); } } /* SR_DF_END needs to be handled after the output module's receive() * is called, so it can properly clean up that module. */ if (packet->type == SR_DF_END) { g_debug("cli: Received SR_DF_END."); if (o) sr_output_free(o); o = NULL; if (outfile && outfile != stdout) fclose(outfile); if (opt_output_file && default_output_format) /* Flush whatever is left out to the session file. */ save_chunk_logic(NULL, 0, 0); if (limit_samples) { if (rcvd_samples_logic > 0 && rcvd_samples_logic < limit_samples) g_warning("Device only sent %" PRIu64 " samples.", rcvd_samples_logic); else if (rcvd_samples_analog > 0 && rcvd_samples_analog < limit_samples) g_warning("Device only sent %" PRIu64 " samples.", rcvd_samples_analog); } } }
int main(int argc, char **argv) { GOptionContext *context; GError *error; g_log_set_default_handler(logger, NULL); error = NULL; context = g_option_context_new(NULL); g_option_context_add_main_entries(context, optargs, NULL); if (!g_option_context_parse(context, &argc, &argv, &error)) { g_critical("%s", error->message); return 1; } /* Set the loglevel (amount of messages to output) for libsigrok. */ if (sr_log_loglevel_set(opt_loglevel) != SR_OK) return 1; /* Set the loglevel (amount of messages to output) for libsigrokdecode. */ if (srd_log_loglevel_set(opt_loglevel) != SRD_OK) return 1; if (sr_init() != SR_OK) return 1; if (opt_pds) { if (srd_init(NULL) != SRD_OK) return 1; if (register_pds(NULL, opt_pds) != 0) return 1; if (srd_pd_output_callback_add(SRD_OUTPUT_ANN, show_pd_annotations, NULL) != SRD_OK) return 1; if (setup_pd_stack() != 0) return 1; if (setup_pd_annotations() != 0) return 1; } if (setup_output_format() != 0) return 1; if (opt_version) show_version(); else if (opt_list_devs) show_dev_list(); else if (opt_input_file) load_input_file(); else if (opt_samples || opt_time || opt_frames || opt_continuous) run_session(); else if (opt_dev) show_dev_detail(); else if (opt_pds) show_pd_detail(); else printf("%s", g_option_context_get_help(context, TRUE, NULL)); if (opt_pds) srd_exit(); g_option_context_free(context); sr_exit(); return 0; }