From f38ec2855ce41154bc1035dd7f1ab9a21f411f0d Mon Sep 17 00:00:00 2001 From: Bert Vermeulen Date: Fri, 20 Jan 2012 22:25:42 +0100 Subject: [PATCH] srd: support for mapping probes --- controller.c | 92 +++++++++++++++++++++++++++++++++++++------------- decoder.c | 66 ++++++++++++++++++++++++++++++++++++ sigrokdecode.h | 22 ++++++++++-- type_logic.c | 15 ++++---- 4 files changed, 159 insertions(+), 36 deletions(-) diff --git a/controller.c b/controller.c index fa67004..3292603 100644 --- a/controller.c +++ b/controller.c @@ -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; diff --git a/decoder.c b/decoder.c index 5b9223c..d0e5734 100644 --- 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; diff --git a/sigrokdecode.h b/sigrokdecode.h index 2649d86..70652a4 100644 --- a/sigrokdecode.h +++ b/sigrokdecode.h @@ -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); diff --git a/type_logic.c b/type_logic.c index 851a42e..28c3670 100644 --- a/type_logic.c +++ b/type_logic.c @@ -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++; -- 2.30.2