]> sigrok.org Git - libsigrokdecode.git/commitdiff
srd: support for mapping probes
authorBert Vermeulen <redacted>
Fri, 20 Jan 2012 21:25:42 +0000 (22:25 +0100)
committerBert Vermeulen <redacted>
Sat, 21 Jan 2012 14:06:21 +0000 (15:06 +0100)
controller.c
decoder.c
sigrokdecode.h
type_logic.c

index fa67004b22caf0b35e3014ea22d52eeac3c51101..3292603b1df909f0fb250f5ddf7e927cd45206fb 100644 (file)
@@ -268,6 +268,12 @@ err_out:
        return ret;
 }
 
+static gint compare_probe_id(struct srd_probe *a, char *probe_id)
+{
+
+       return strcmp(a->id, probe_id);
+}
+
 /**
  * Set probes in a decoder instance.
  *
@@ -276,34 +282,57 @@ err_out:
  * the probe number. Samples passed to this instance will be arranged in this
  * order.
  *
- * Handled probes are removed from the hash.
- *
  * @return SRD_OK upon success, a (negative) error code otherwise.
  */
 int srd_instance_set_probes(struct srd_decoder_instance *di,
-               GHashTable *probes)
+               GHashTable *new_probes)
 {
-       int ret;
+       GList *l;
+       GSList *sl;
+       struct srd_probe *p;
+       int *new_probemap, new_probenum;
+       char *probe_id;
 
-       if (g_hash_table_size(probes) == 0)
+       if (g_hash_table_size(new_probes) == 0)
                /* No probes provided. */
                return SRD_OK;
 
-       if(!PyObject_HasAttrString(di->decoder->py_dec, "probes"))
+       if(!PyObject_HasAttrString(di->decoder->py_dec, "probes")
+               && !PyObject_HasAttrString(di->decoder->py_dec, "extra_probes")) {
                /* Decoder has no probes. */
-               return SRD_OK;
+               srd_err("Protocol decoder %s has no probes to define.",
+                               di->decoder->name);
+               return SRD_ERR_ARG;
+       }
 
-       ret = SRD_ERR_PYTHON;
+       new_probemap = NULL;
 
-       /* TODO */
-       if (g_hash_table_size(probes) > 0) {
-               srd_err("Setting probes is not yet supported.");
-               return SRD_ERR_PYTHON;
+       if (!(new_probemap = g_try_malloc(sizeof(int) * di->dec_num_probes))) {
+               srd_err("Failed to malloc new probe map.");
+               return SRD_ERR_MALLOC;
        }
 
-       ret = SRD_OK;
+       for (l = g_hash_table_get_keys(new_probes); l; l = l->next) {
+               probe_id = l->data;
+               new_probenum = strtol(g_hash_table_lookup(new_probes, probe_id), NULL, 10);
+               if (!(sl = g_slist_find_custom(di->decoder->probes, probe_id,
+                               (GCompareFunc)compare_probe_id))) {
+                       /* Fall back on optional probes. */
+                       if (!(sl = g_slist_find_custom(di->decoder->extra_probes,
+                                       probe_id, (GCompareFunc)compare_probe_id))) {
+                               srd_err("Protocol decoder %s has no probe '%s'",
+                                               di->decoder->name, probe_id);
+                               g_free(new_probemap);
+                               return SRD_ERR_ARG;
+                       }
+               }
+               p = sl->data;
+               new_probemap[p->order] = new_probenum;
+       }
+       g_free(di->dec_probemap);
+       di->dec_probemap = new_probemap;
 
-       return ret;
+       return SRD_OK;
 }
 
 /**
@@ -320,6 +349,7 @@ struct srd_decoder_instance *srd_instance_new(const char *decoder_id,
 {
        struct srd_decoder *dec;
        struct srd_decoder_instance *di;
+       int i;
        char *instance_id;
 
        srd_dbg("%s: creating new %s instance", __func__, decoder_id);
@@ -339,23 +369,37 @@ struct srd_decoder_instance *srd_instance_new(const char *decoder_id,
        di->instance_id = g_strdup(instance_id ? instance_id : decoder_id);
        g_hash_table_remove(options, "id");
 
+       /* Prepare a default probe map, where samples come in the
+        * order in which the decoder class defined them.
+        */
+       di->dec_num_probes = g_slist_length(di->decoder->probes) +
+                       g_slist_length(di->decoder->extra_probes);
+       if (!(di->dec_probemap = g_try_malloc(sizeof(int) * di->dec_num_probes))) {
+               srd_err("Failed to malloc probe map.");
+               g_free(di);
+               return NULL;
+       }
+       for (i = 0; i < di->dec_num_probes; i++)
+               di->dec_probemap[i] = i;
+
        /* Create a new instance of this decoder class. */
        if (!(di->py_instance = PyObject_CallObject(dec->py_dec, NULL))) {
                if (PyErr_Occurred())
                        PyErr_Print();
+               g_free(di->dec_probemap);
                g_free(di);
                return NULL;
        }
 
-       /* Instance takes input from a frontend by default. */
-       di_list = g_slist_append(di_list, di);
-
        if (srd_instance_set_options(di, options) != SRD_OK) {
-               di_list = g_slist_remove(di_list, di);
+               g_free(di->dec_probemap);
                g_free(di);
                return NULL;
        }
 
+       /* Instance takes input from a frontend by default. */
+       di_list = g_slist_append(di_list, di);
+
        return di;
 }
 
@@ -421,8 +465,8 @@ int srd_instance_start(struct srd_decoder_instance *di, PyObject *args)
                return SRD_ERR_PYTHON;
        }
 
-       Py_XDECREF(py_res);
-       Py_DECREF(py_name);
+       Py_DecRef(py_res);
+       Py_DecRef(py_name);
 
        return SRD_OK;
 }
@@ -465,7 +509,7 @@ int srd_instance_decode(uint64_t start_samplenum,
        logic->sample = PyList_New(2);
        Py_INCREF(logic->sample);
 
-       end_samplenum = start_samplenum + inbuflen / di->unitsize;
+       end_samplenum = start_samplenum + inbuflen / di->data_unitsize;
        if (!(py_res = PyObject_CallMethod(py_instance, "decode",
                        "KKO", logic->start_samplenum, end_samplenum, logic))) {
                if (PyErr_Occurred())
@@ -495,9 +539,9 @@ int srd_session_start(int num_probes, int unitsize, uint64_t samplerate)
        /* Run the start() method on all decoders receiving frontend data. */
        for (d = di_list; d; d = d->next) {
                di = d->data;
-               di->num_probes = num_probes;
-               di->unitsize = unitsize;
-               di->samplerate = samplerate;
+               di->data_num_probes = num_probes;
+               di->data_unitsize = unitsize;
+               di->data_samplerate = samplerate;
                if ((ret = srd_instance_start(di, args) != SRD_OK))
                        return ret;
 
index 5b9223c630812599548e0dcebfeac1a5104161b0..d0e5734a14971058d1e27224afa2dad30b68418e 100644 (file)
--- a/decoder.c
+++ b/decoder.c
@@ -65,6 +65,63 @@ struct srd_decoder *srd_get_decoder_by_id(const char *id)
 }
 
 
+static int get_probes(struct srd_decoder *d, char *attr, GSList **pl)
+{
+       PyObject *py_probelist, *py_entry;
+       struct srd_probe *p;
+       int ret, num_probes, i;
+
+       if (!PyObject_HasAttrString(d->py_dec, attr))
+               /* No probes of this type specified. */
+               return SRD_OK;
+
+       ret = SRD_ERR_PYTHON;
+       py_probelist = py_entry = NULL;
+
+       py_probelist = PyObject_GetAttrString(d->py_dec, attr);
+       if (!PyList_Check(py_probelist)) {
+               srd_err("Protocol decoder %s %s attribute is not "
+                               "a list.", d->name, attr);
+               goto err_out;
+       }
+
+       num_probes = PyList_Size(py_probelist);
+       if (num_probes == 0)
+               /* Empty probelist. */
+               return SRD_OK;
+
+       for (i = 0; i < num_probes; i++) {
+               py_entry = PyList_GetItem(py_probelist, i);
+               if (!PyDict_Check(py_entry)) {
+                       srd_err("Protocol decoder %s %s attribute is not "
+                                       "a list with dict elements.", d->name, attr);
+                       goto err_out;
+               }
+
+               if (!(p = g_try_malloc(sizeof(struct srd_probe)))) {
+                       ret = SRD_ERR_MALLOC;
+                       goto err_out;
+               }
+
+               if ((py_dictitem_as_str(py_entry, "id", &p->id)) != SRD_OK)
+                       goto err_out;
+               if ((py_dictitem_as_str(py_entry, "name", &p->name)) != SRD_OK)
+                       goto err_out;
+               if ((py_dictitem_as_str(py_entry, "desc", &p->desc)) != SRD_OK)
+                       goto err_out;
+               p->order = i;
+
+               *pl = g_slist_append(*pl, p);
+       }
+       ret = SRD_OK;
+
+err_out:
+       Py_DecRef(py_entry);
+       Py_DecRef(py_probelist);
+
+       return ret;
+}
+
 /**
  * Load a protocol decoder module into the embedded Python interpreter.
  *
@@ -161,6 +218,15 @@ int srd_load_decoder(const char *name, struct srd_decoder **dec)
                Py_DecRef(py_attr);
        }
 
+       /* Check and import required probes. */
+       if (get_probes(d, "probes", &d->probes) != SRD_OK)
+               goto err_out;
+
+       /* Check and import optional probes. */
+       if (get_probes(d, "extra_probes", &d->extra_probes) != SRD_OK)
+               goto err_out;
+
+       /* Store required fields in newly allocated strings. */
        if (py_attr_as_str(d->py_dec, "id", &(d->id)) != SRD_OK)
                goto err_out;
 
index 2649d868018623920a341fe41da0f871d57cf18a..70652a4f8cdcbf444c6316e5508a99d6b48a9112 100644 (file)
@@ -99,6 +99,12 @@ struct srd_decoder {
        /** TODO */
        GSList *outputformats;
 
+       /** Probes */
+       GSList *probes;
+
+       /** Optional probes */
+       GSList *extra_probes;
+
        /* List of NULL-terminated char[], containing descriptions of the
         * supported annotation output.
         */
@@ -111,14 +117,23 @@ struct srd_decoder {
        PyObject *py_dec;
 };
 
+struct srd_probe {
+       char *id;
+       char *name;
+       char *desc;
+       int order;
+};
+
 struct srd_decoder_instance {
        struct srd_decoder *decoder;
        PyObject *py_instance;
        char *instance_id;
        GSList *pd_output;
-       int num_probes;
-       int unitsize;
-       uint64_t samplerate;
+       int dec_num_probes;
+       int *dec_probemap;
+       int data_num_probes;
+       int data_unitsize;
+       uint64_t data_samplerate;
        GSList *next_di;
 };
 
@@ -193,6 +208,7 @@ char *srd_decoder_doc(struct srd_decoder *dec);
 
 /*--- util.c ----------------------------------------------------------------*/
 int py_attr_as_str(PyObject *py_obj, const char *attr, char **outstr);
+int py_dictitem_as_str(PyObject *py_obj, const char *key, char **outstr);
 int py_str_as_str(PyObject *py_str, char **outstr);
 int py_strlist_to_char(PyObject *py_strlist, char ***outstr);
 
index 851a42ead51070334db360985b698962165df6be..28c36707b9a789d9bf4dcf5191960661e9079163 100644 (file)
@@ -38,21 +38,18 @@ PyObject *srd_logic_iternext(PyObject *self)
        unsigned char probe_samples[SRD_MAX_NUM_PROBES];
 
        logic = (srd_logic *) self;
-       if (logic->itercnt >= logic->inbuflen / logic->di->unitsize) {
+       if (logic->itercnt >= logic->inbuflen / logic->di->data_unitsize) {
                /* End iteration loop. */
                return NULL;
        }
 
-       /* TODO: use number of probes defined in the PD, in the order the PD
-        * defined them -- not whatever came in from the driver.
-        */
        /* Convert the bit-packed sample to an array of bytes, with only 0x01
         * and 0x00 values, so the PD doesn't need to do any bitshifting.
         */
-       memcpy(&sample, logic->inbuf + logic->itercnt * logic->di->unitsize,
-                       logic->di->unitsize);
-       for (i = 0; i < logic->di->num_probes; i++) {
-               probe_samples[i] = sample & 0x01;
+       memcpy(&sample, logic->inbuf + logic->itercnt * logic->di->data_unitsize,
+                       logic->di->data_unitsize);
+       for (i = 0; i < logic->di->dec_num_probes; i++) {
+               probe_samples[logic->di->dec_probemap[i]] = sample & 0x01;
                sample >>= 1;
        }
 
@@ -60,7 +57,7 @@ PyObject *srd_logic_iternext(PyObject *self)
        py_samplenum = PyLong_FromUnsignedLongLong(logic->start_samplenum + logic->itercnt);
        PyList_SetItem(logic->sample, 0, py_samplenum);
        py_samples = PyBytes_FromStringAndSize((const char *)probe_samples,
-                       logic->di->num_probes);
+                       logic->di->dec_num_probes);
        PyList_SetItem(logic->sample, 1, py_samples);
        Py_INCREF(logic->sample);
        logic->itercnt++;