decode: Defer probe setup until after the input probes are known
authorDaniel Elstner <daniel.kitta@gmail.com>
Fri, 21 Feb 2014 19:10:09 +0000 (20:10 +0100)
committerDaniel Elstner <daniel.kitta@gmail.com>
Fri, 21 Feb 2014 19:59:14 +0000 (20:59 +0100)
decode.c
main.c
parsers.c
sigrok-cli.h

index 0b7d9ee49e200cf6b8fa4010f9f869cdbe209772..63679d4be5028f30b72d2aa9326a1b1e2ed5a77e 100644 (file)
--- a/decode.c
+++ b/decode.c
@@ -25,6 +25,7 @@
 static GHashTable *pd_ann_visible = NULL;
 static GHashTable *pd_meta_visible = NULL;
 static GHashTable *pd_binary_visible = NULL;
+static GHashTable *pd_probe_maps = NULL;
 
 extern struct srd_session *srd_sess;
 extern gint opt_loglevel;
@@ -74,42 +75,38 @@ static int opts_to_gvar(struct srd_decoder *dec, GHashTable *hash,
        return ret;
 }
 
-static int probes_to_gvar(struct srd_decoder *dec, GHashTable *hash,
-               GHashTable **probes)
+static int move_hash_element(GHashTable *src, GHashTable *dest, void *key)
 {
+       void *orig_key, *value;
+
+       if (!g_hash_table_lookup_extended(src, key, &orig_key, &value))
+               /* Not specified. */
+               return FALSE;
+       g_hash_table_steal(src, orig_key);
+       g_hash_table_insert(dest, orig_key, value);
+
+       return TRUE;
+}
+
+static GHashTable *extract_probe_map(struct srd_decoder *dec, GHashTable *hash)
+{
+       GHashTable *probe_map;
        struct srd_probe *p;
-       GSList *all_probes, *l;
-       GVariant *gvar;
-       gint32 val_int;
-       int ret;
-       char *val_str, *conv;
+       GSList *l;
 
-       ret = TRUE;
-       *probes = g_hash_table_new_full(g_str_hash, g_str_equal, g_free,
-                       (GDestroyNotify)g_variant_unref);
+       probe_map = g_hash_table_new_full(g_str_hash, g_str_equal,
+                                         g_free, g_free);
 
-       all_probes = g_slist_copy(dec->probes);
-       all_probes = g_slist_concat(all_probes, g_slist_copy(dec->opt_probes));
-       for (l = all_probes; l; l = l->next) {
+       for (l = dec->probes; l; l = l->next) {
                p = l->data;
-               if (!(val_str = g_hash_table_lookup(hash, p->id)))
-                       /* Not specified. */
-                       continue;
-               val_int = strtoll(val_str, &conv, 10);
-               if (!conv || conv == val_str) {
-                       g_critical("Protocol decoder '%s' probes '%s' "
-                                       "is not a number.", dec->name, p->id);
-                       ret = FALSE;
-                       break;
-               }
-               gvar = g_variant_new_int32(val_int);
-               g_variant_ref_sink(gvar);
-               g_hash_table_insert(*probes, g_strdup(p->id), gvar);
-               g_hash_table_remove(hash, p->id);
+               move_hash_element(hash, probe_map, p->id);
+       }
+       for (l = dec->opt_probes; l; l = l->next) {
+               p = l->data;
+               move_hash_element(hash, probe_map, p->id);
        }
-       g_slist_free(all_probes);
 
-       return ret;
+       return probe_map;
 }
 
 /* Register the given PDs for this session.
@@ -126,8 +123,10 @@ int register_pds(const char *opt_pds, char *opt_pd_annotations)
        int ret;
        char **pdtokens, **pdtok, *pd_name;
 
-       pd_ann_visible = g_hash_table_new_full(g_str_hash, g_int_equal,
-                       g_free, NULL);
+       pd_ann_visible = g_hash_table_new_full(g_str_hash, g_str_equal,
+                                              g_free, NULL);
+       pd_probe_maps = g_hash_table_new_full(g_str_hash, g_str_equal, g_free,
+                                       (GDestroyNotify)g_hash_table_destroy);
        ret = 0;
        pd_name = NULL;
        pd_opthash = options = probes = NULL;
@@ -152,10 +151,8 @@ int register_pds(const char *opt_pds, char *opt_pd_annotations)
                        ret = 1;
                        break;
                }
-               if (!probes_to_gvar(dec, pd_opthash, &probes)) {
-                       ret = 1;
-                       break;
-               }
+               probes = extract_probe_map(dec, pd_opthash);
+
                if (g_hash_table_size(pd_opthash) > 0) {
                        leftover = g_hash_table_get_keys(pd_opthash);
                        for (l = leftover; l; l = l->next)
@@ -170,6 +167,10 @@ int register_pds(const char *opt_pds, char *opt_pd_annotations)
                        break;
                }
 
+               /* Save the probe setup for later. */
+               g_hash_table_insert(pd_probe_maps, g_strdup(di->inst_id), probes);
+               probes = NULL;
+
                /* If no annotation list was specified, add them all in now.
                 * This will be pared down later to leave only the last PD
                 * in the stack.
@@ -177,12 +178,6 @@ int register_pds(const char *opt_pds, char *opt_pd_annotations)
                if (!opt_pd_annotations)
                        g_hash_table_insert(pd_ann_visible,
                                            g_strdup(di->inst_id), GINT_TO_POINTER(-1));
-
-               /* Remap the probes if needed. */
-               if (srd_inst_probe_set_all(di, probes, (g_hash_table_size(probes) + 7) / 8) != SRD_OK) {
-                       ret = 1;
-                       break;
-               }
        }
 
        g_strfreev(pdtokens);
@@ -198,6 +193,66 @@ int register_pds(const char *opt_pds, char *opt_pd_annotations)
        return ret;
 }
 
+static void map_pd_inst_probes(void *key, void *value, void *user_data)
+{
+       GHashTable *probe_map;
+       GHashTable *probe_indices;
+       GSList *probe_list;
+       struct srd_decoder_inst *di;
+       GVariant *var;
+       void *probe_id;
+       void *probe_target;
+       struct sr_probe *probe;
+       GHashTableIter iter;
+       int num_probes;
+
+       probe_map = value;
+       probe_list = user_data;
+
+       di = srd_inst_find_by_id(srd_sess, key);
+       if (!di) {
+               g_critical("Protocol decoder instance \"%s\" not found.",
+                          (char *)key);
+               return;
+       }
+       probe_indices = g_hash_table_new_full(g_str_hash, g_str_equal, g_free,
+                                             (GDestroyNotify)g_variant_unref);
+
+       g_hash_table_iter_init(&iter, probe_map);
+       while (g_hash_table_iter_next(&iter, &probe_id, &probe_target)) {
+               probe = find_probe(probe_list, probe_target);
+               if (!probe) {
+                       g_printerr("cli: No probe with name \"%s\" found.\n",
+                                  (char *)probe_target);
+                       continue;
+               }
+               if (probe->enabled)
+                       g_printerr("cli: Mapping probe \"%s\" to \"%s\" "
+                                  "(index %d).\n", (char *)probe_id,
+                                  (char *)probe_target, probe->index);
+               else
+                       g_printerr("cli: Target probe \"%s\" not enabled.\n",
+                                  (char *)probe_target);
+
+               var = g_variant_new_int32(probe->index);
+               g_variant_ref_sink(var);
+               g_hash_table_insert(probe_indices, g_strdup(probe_id), var);
+       }
+
+       num_probes = g_slist_length(probe_list);
+       srd_inst_probe_set_all(di, probe_indices, (num_probes + 7) / 8);
+}
+
+void map_pd_probes(struct sr_dev_inst *sdi)
+{
+       if (pd_probe_maps) {
+               g_hash_table_foreach(pd_probe_maps, &map_pd_inst_probes,
+                                    sdi->probes);
+               g_hash_table_destroy(pd_probe_maps);
+               pd_probe_maps = NULL;
+       }
+}
+
 int setup_pd_stack(char *opt_pds, char *opt_pd_stack, char *opt_pd_annotations)
 {
        struct srd_decoder_inst *di_from, *di_to;
diff --git a/main.c b/main.c
index 5dcee2cd25d680709ae5506ee66efa6dadefe75f..271d28a99271f6c61f77570e897fe45aee32b1d4 100644 (file)
--- a/main.c
+++ b/main.c
@@ -134,21 +134,22 @@ int select_probes(struct sr_dev_inst *sdi)
        struct sr_probe *probe;
        GSList *selected_probes, *l;
 
-       if (!opt_probes)
-               return SR_OK;
-
-       if (!(selected_probes = parse_probestring(sdi, opt_probes)))
-               return SR_ERR;
-
-       for (l = sdi->probes; l; l = l->next) {
-               probe = l->data;
-               if (g_slist_find(selected_probes, probe))
-                       probe->enabled = TRUE;
-               else
-                       probe->enabled = FALSE;
+       if (opt_probes) {
+               if (!(selected_probes = parse_probestring(sdi, opt_probes)))
+                       return SR_ERR;
+
+               for (l = sdi->probes; l; l = l->next) {
+                       probe = l->data;
+                       if (g_slist_find(selected_probes, probe))
+                               probe->enabled = TRUE;
+                       else
+                               probe->enabled = FALSE;
+               }
+               g_slist_free(selected_probes);
        }
-       g_slist_free(selected_probes);
-
+#ifdef HAVE_SRD
+       map_pd_probes(sdi);
+#endif
        return SR_OK;
 }
 
index 43b61b698cef21912f44707cdcf1c49fb65aa1f1..d575dce076c83660a0107d53884b4cade36b8b80 100644 (file)
--- a/parsers.c
+++ b/parsers.c
@@ -24,7 +24,7 @@
 #include <string.h>
 #include <glib.h>
 
-static struct sr_probe *find_probe(GSList *probelist, const char *probename)
+struct sr_probe *find_probe(GSList *probelist, const char *probename)
 {
        struct sr_probe *probe;
        GSList *l;
index 4d2f0f2ffba3fde4bb5c61475bb2ee5b646f369f..6d635117f4eeee81ba085986ec0e99faece54b0a 100644 (file)
@@ -63,9 +63,11 @@ int setup_pd_binary(char *opt_pd_binary);
 void show_pd_annotations(struct srd_proto_data *pdata, void *cb_data);
 void show_pd_meta(struct srd_proto_data *pdata, void *cb_data);
 void show_pd_binary(struct srd_proto_data *pdata, void *cb_data);
+void map_pd_probes(struct sr_dev_inst *sdi);
 #endif
 
 /* parsers.c */
+struct sr_probe *find_probe(GSList *probelist, const char *probename);
 GSList *parse_probestring(struct sr_dev_inst *sdi, const char *probestring);
 GHashTable *parse_generic_arg(const char *arg, gboolean sep_first);
 int canon_cmp(const char *str1, const char *str2);