X-Git-Url: https://sigrok.org/gitweb/?p=libsigrokdecode.git;a=blobdiff_plain;f=controller.c;h=9f9b7b1820481c8e82e4c5992299b6a8cf370c24;hp=d8325ac285988c536d7237f0f8abd5510aa9bfa9;hb=0169f19c53e195df2f96c4df731ad3214c59e20a;hpb=119d62586036f4436de8e11824e388c3f0a882c4 diff --git a/controller.c b/controller.c index d8325ac..9f9b7b1 100644 --- a/controller.c +++ b/controller.c @@ -305,6 +305,16 @@ SRD_API int srd_inst_option_set(struct srd_decoder_inst *di, const char *val_str; char *dbg, *key; + if (!di) { + srd_err("Invalid decoder instance."); + return SRD_ERR_ARG; + } + + if (!options) { + srd_err("Invalid options GHashTable."); + return SRD_ERR_ARG; + } + if (!PyObject_HasAttrString(di->decoder->py_dec, "options")) { /* Decoder has no options. */ if (g_hash_table_size(options) == 0) { @@ -457,9 +467,8 @@ SRD_API int srd_inst_probe_set_all(struct srd_decoder_inst *di, GList *l; GSList *sl; struct srd_probe *p; - int *new_probemap, new_probenum; + int *new_probemap, new_probenum, num_required_probes, num_probes, i; char *probe_id; - int i, num_required_probes; srd_dbg("set probes called for instance %s with list of %d probes", di->inst_id, g_hash_table_size(new_probes)); @@ -489,9 +498,10 @@ SRD_API int srd_inst_probe_set_all(struct srd_decoder_inst *di, for (i = 0; i < di->dec_num_probes; i++) new_probemap[i] = -1; + num_probes = 0; for (l = g_hash_table_get_keys(new_probes); l; l = l->next) { probe_id = l->data; - probe_val= g_hash_table_lookup(new_probes, probe_id); + probe_val = g_hash_table_lookup(new_probes, probe_id); if (!g_variant_is_of_type(probe_val, G_VARIANT_TYPE_INT32)) { /* Probe name was specified without a value. */ srd_err("No probe number was specified for %s.", @@ -515,7 +525,9 @@ SRD_API int srd_inst_probe_set_all(struct srd_decoder_inst *di, new_probemap[p->order] = new_probenum; srd_dbg("Setting probe mapping: %s (index %d) = probe %d.", p->id, p->order, new_probenum); + num_probes++; } + di->data_unitsize = (num_probes + 7) / 8; srd_dbg("Final probe map:"); num_required_probes = g_slist_length(di->decoder->probes); @@ -541,7 +553,7 @@ SRD_API int srd_inst_probe_set_all(struct srd_decoder_inst *di, * @return Pointer to a newly allocated struct srd_decoder_inst, or * NULL in case of failure. * - * @since 0.1.0 + * @since 0.3.0 */ SRD_API struct srd_decoder_inst *srd_inst_new(struct srd_session *sess, const char *decoder_id, GHashTable *options) @@ -582,10 +594,10 @@ SRD_API struct srd_decoder_inst *srd_inst_new(struct srd_session *sess, * order in which the decoder class defined them. */ di->dec_num_probes = g_slist_length(di->decoder->probes) + - g_slist_length(di->decoder->opt_probes); + g_slist_length(di->decoder->opt_probes); if (di->dec_num_probes) { if (!(di->dec_probemap = - g_try_malloc(sizeof(int) * di->dec_num_probes))) { + g_try_malloc(sizeof(int) * di->dec_num_probes))) { srd_err("Failed to g_malloc() probe map."); g_free(di); return NULL; @@ -593,12 +605,13 @@ SRD_API struct srd_decoder_inst *srd_inst_new(struct srd_session *sess, for (i = 0; i < di->dec_num_probes; i++) di->dec_probemap[i] = i; } + di->data_unitsize = (di->dec_num_probes + 7) / 8; /* Create a new instance of this decoder class. */ if (!(di->py_inst = PyObject_CallObject(dec->py_dec, NULL))) { if (PyErr_Occurred()) srd_exception_catch("failed to create %s instance: ", - decoder_id); + decoder_id); g_free(di->dec_probemap); g_free(di); return NULL; @@ -625,7 +638,7 @@ SRD_API struct srd_decoder_inst *srd_inst_new(struct srd_session *sess, * * @return SRD_OK upon success, a (negative) error code otherwise. * - * @since 0.1.0 + * @since 0.3.0 */ SRD_API int srd_inst_stack(struct srd_session *sess, struct srd_decoder_inst *di_from, struct srd_decoder_inst *di_to) @@ -663,7 +676,7 @@ SRD_API int srd_inst_stack(struct srd_session *sess, * * @return Pointer to struct srd_decoder_inst, or NULL if not found. * - * @since 0.1.0 + * @since 0.3.0 */ SRD_API struct srd_decoder_inst *srd_inst_find_by_id(struct srd_session *sess, const char *inst_id) @@ -747,40 +760,28 @@ SRD_PRIV struct srd_decoder_inst *srd_inst_find_by_obj(const GSList *stack, } /** @private */ -SRD_PRIV int srd_inst_start(struct srd_decoder_inst *di, PyObject *args) +SRD_PRIV int srd_inst_start(struct srd_decoder_inst *di) { - PyObject *py_name, *py_res; + PyObject *py_res; GSList *l; struct srd_decoder_inst *next_di; + int ret; srd_dbg("Calling start() method on protocol decoder instance %s.", - di->inst_id); + di->inst_id); - if (!(py_name = PyUnicode_FromString("start"))) { - srd_err("Unable to build Python object for 'start'."); + if (!(py_res = PyObject_CallMethod(di->py_inst, "start", NULL))) { srd_exception_catch("Protocol decoder instance %s: ", - di->inst_id); + di->inst_id); return SRD_ERR_PYTHON; } - - if (!(py_res = PyObject_CallMethodObjArgs(di->py_inst, - py_name, args, NULL))) { - srd_exception_catch("Protocol decoder instance %s: ", - di->inst_id); - return SRD_ERR_PYTHON; - } - Py_DecRef(py_res); - Py_DecRef(py_name); - /* - * Start all the PDs stacked on top of this one. Pass along the - * metadata all the way from the bottom PD, even though it's only - * applicable to logic data for now. - */ + /* Start all the PDs stacked on top of this one. */ for (l = di->next_di; l; l = l->next) { next_di = l->data; - srd_inst_start(next_di, args); + if ((ret = srd_inst_start(next_di)) != SRD_OK) + return ret; } return SRD_OK; @@ -789,9 +790,11 @@ SRD_PRIV int srd_inst_start(struct srd_decoder_inst *di, PyObject *args) /** * Run the specified decoder function. * + * @param di The decoder instance to call. Must not be NULL. * @param start_samplenum The starting sample number for the buffer's sample * set, relative to the start of capture. - * @param di The decoder instance to call. Must not be NULL. + * @param end_samplenum The ending sample number for the buffer's sample + * set, relative to the start of capture. * @param inbuf The buffer to decode. Must not be NULL. * @param inbuflen Length of the buffer. Must be > 0. * @@ -801,16 +804,16 @@ SRD_PRIV int srd_inst_start(struct srd_decoder_inst *di, PyObject *args) * * @since 0.1.0 */ -SRD_PRIV int srd_inst_decode(uint64_t start_samplenum, - const struct srd_decoder_inst *di, const uint8_t *inbuf, - uint64_t inbuflen) +SRD_PRIV int srd_inst_decode(const struct srd_decoder_inst *di, + uint64_t start_samplenum, uint64_t end_samplenum, + const uint8_t *inbuf, uint64_t inbuflen) { PyObject *py_res; srd_logic *logic; - uint64_t end_samplenum; - srd_dbg("Calling decode() on instance %s with %d bytes starting " - "at sample %d.", di->inst_id, inbuflen, start_samplenum); + srd_dbg("Calling decode() on instance %s with %" PRIu64 " bytes " + "starting at sample %" PRIu64 ".", di->inst_id, inbuflen, + start_samplenum); /* Return an error upon unusable input. */ if (!di) { @@ -841,12 +844,9 @@ SRD_PRIV int srd_inst_decode(uint64_t start_samplenum, Py_INCREF(logic->sample); Py_IncRef(di->py_inst); - end_samplenum = start_samplenum + inbuflen / di->data_unitsize; if (!(py_res = PyObject_CallMethod(di->py_inst, "decode", - "KKO", logic->start_samplenum, - end_samplenum, logic))) { - srd_exception_catch("Protocol decoder instance %s: ", - di->inst_id); + "KKO", start_samplenum, end_samplenum, logic))) { + srd_exception_catch("Protocol decoder instance %s: ", di->inst_id); return SRD_ERR_PYTHON; } Py_DecRef(py_res); @@ -924,8 +924,8 @@ static int session_is_valid(struct srd_session *sess) * A session holds all decoder instances, their stack relationships and * output callbacks. * - * @param sess. A pointer which will hold a pointer to a newly - * initialized session on return. + * @param sess A pointer which will hold a pointer to a newly + * initialized session on return. * * @return SRD_OK upon success, a (negative) error code otherwise. * @@ -936,13 +936,12 @@ SRD_API int srd_session_new(struct srd_session **sess) if (!sess) { srd_err("Invalid session pointer."); - return SRD_ERR; + return SRD_ERR_ARG; } if (!(*sess = g_try_malloc(sizeof(struct srd_session)))) return SRD_ERR_MALLOC; (*sess)->session_id = ++max_session_id; - (*sess)->num_probes = (*sess)->unitsize = (*sess)->samplerate = 0; (*sess)->di_list = (*sess)->callbacks = NULL; /* Keep a list of all sessions, so we can clean up as needed. */ @@ -963,11 +962,10 @@ SRD_API int srd_session_new(struct srd_session **sess) * * @return SRD_OK upon success, a (negative) error code otherwise. * - * @since 0.1.0 + * @since 0.3.0 */ SRD_API int srd_session_start(struct srd_session *sess) { - PyObject *args; GSList *d; struct srd_decoder_inst *di; int ret; @@ -976,51 +974,43 @@ SRD_API int srd_session_start(struct srd_session *sess) srd_err("Invalid session pointer."); return SRD_ERR; } - if (sess->num_probes == 0) { - srd_err("Session has invalid number of probes."); - return SRD_ERR; - } - if (sess->unitsize == 0) { - srd_err("Session has invalid unitsize."); - return SRD_ERR; - } - if (sess->samplerate == 0) { - srd_err("Session has invalid samplerate."); - return SRD_ERR; - } - - ret = SRD_OK; - srd_dbg("Calling start() on all instances in session %d with " - "%d probes, unitsize %d samplerate %d.", sess->session_id, - sess->num_probes, sess->unitsize, sess->samplerate); - - /* - * Currently only one item of metadata is passed along to decoders, - * samplerate. This can be extended as needed. - */ - if (!(args = Py_BuildValue("{s:l}", "samplerate", (long)sess->samplerate))) { - srd_err("Unable to build Python object for metadata."); - return SRD_ERR_PYTHON; - } + srd_dbg("Calling start() on all instances in session %d.", sess->session_id); /* Run the start() method on all decoders receiving frontend data. */ + ret = SRD_OK; for (d = sess->di_list; d; d = d->next) { di = d->data; - di->data_num_probes = sess->num_probes; - di->data_unitsize = sess->unitsize; - di->data_samplerate = sess->samplerate; - if ((ret = srd_inst_start(di, args)) != SRD_OK) + if ((ret = srd_inst_start(di)) != SRD_OK) break; } - Py_DecRef(args); - return ret; } +SRD_PRIV int srd_inst_send_meta(struct srd_decoder_inst *di, int key, + GVariant *data) +{ + PyObject *py_ret; + + if (key != SRD_CONF_SAMPLERATE) + /* This is the only key we pass on to the decoder for now. */ + return SRD_OK; + + if (!PyObject_HasAttrString(di->py_inst, "metadata")) + /* This decoder doesn't want metadata, that's fine. */ + return SRD_OK; + + py_ret = PyObject_CallMethod(di->py_inst, "metadata", "lK", + (long)SRD_CONF_SAMPLERATE, + (unsigned long long)g_variant_get_uint64(data)); + Py_XDECREF(py_ret); + + return SRD_OK; +} + /** - * Set a configuration key in a session. + * Set a metadata configuration key in a session. * * @param sess The session to configure. * @param key The configuration key (SRD_CONF_*). @@ -1032,50 +1022,58 @@ SRD_API int srd_session_start(struct srd_session *sess) * * @since 0.3.0 */ -SRD_API int srd_session_config_set(struct srd_session *sess, int key, +SRD_API int srd_session_metadata_set(struct srd_session *sess, int key, GVariant *data) { + GSList *l; + int ret; if (session_is_valid(sess) != SRD_OK) { srd_err("Invalid session."); return SRD_ERR_ARG; } - if (!g_variant_is_of_type(data, G_VARIANT_TYPE_UINT64)) { - srd_err("Value for key %d should be of type uint64."); + if (key != SRD_CONF_SAMPLERATE) { + srd_err("Unknown config key %d.", key); return SRD_ERR_ARG; } - switch (key) { - case SRD_CONF_NUM_PROBES: - sess->num_probes = g_variant_get_uint64(data); - break; - case SRD_CONF_UNITSIZE: - sess->unitsize = g_variant_get_uint64(data); - break; - case SRD_CONF_SAMPLERATE: - sess->samplerate = g_variant_get_uint64(data); - break; + srd_dbg("Setting session %d samplerate to %"PRIu64".", + sess->session_id, g_variant_get_uint64(data)); + + ret = SRD_OK; + for (l = sess->di_list; l; l = l->next) { + if ((ret = srd_inst_send_meta(l->data, key, data)) != SRD_OK) + break; } g_variant_unref(data); - return SRD_OK; + return ret; } /** * Send a chunk of logic sample data to a running decoder session. * + * The logic samples must be arranged in probe order, in the least + * amount of space possible. If no probes were configured, the default + * probe set consists of all required probes + all optional probes. + * + * The size of a sample in inbuf is the minimum number of bytes needed + * to store the configured (or default) probes. + * * @param sess The session to use. * @param start_samplenum The sample number of the first sample in this chunk. + * @param end_samplenum The sample number of the last sample in this chunk. * @param inbuf Pointer to sample data. * @param inbuflen Length in bytes of the buffer. * * @return SRD_OK upon success, a (negative) error code otherwise. * - * @since 0.1.0 + * @since 0.3.0 */ -SRD_API int srd_session_send(struct srd_session *sess, uint64_t start_samplenum, +SRD_API int srd_session_send(struct srd_session *sess, + uint64_t start_samplenum, uint64_t end_samplenum, const uint8_t *inbuf, uint64_t inbuflen) { GSList *d; @@ -1087,12 +1085,12 @@ SRD_API int srd_session_send(struct srd_session *sess, uint64_t start_samplenum, } srd_dbg("Calling decode() on all instances with starting sample " - "number %" PRIu64 ", %" PRIu64 " bytes at 0x%p", - start_samplenum, inbuflen, inbuf); + "number %" PRIu64 ", %" PRIu64 " bytes at 0x%p", + start_samplenum, inbuflen, inbuf); for (d = sess->di_list; d; d = d->next) { - if ((ret = srd_inst_decode(start_samplenum, d->data, inbuf, - inbuflen)) != SRD_OK) + if ((ret = srd_inst_decode(d->data, start_samplenum, + end_samplenum, inbuf, inbuflen)) != SRD_OK) return ret; } @@ -1104,16 +1102,21 @@ SRD_API int srd_session_send(struct srd_session *sess, uint64_t start_samplenum, * * All decoder instances and output callbacks are properly released. * - * @param sess. The session to be destroyed. + * @param sess The session to be destroyed. * * @return SRD_OK upon success, a (negative) error code otherwise. * - * @since 0.1.0 + * @since 0.3.0 */ SRD_API int srd_session_destroy(struct srd_session *sess) { int session_id; + if (!sess) { + srd_err("Invalid session."); + return SRD_ERR_ARG; + } + session_id = sess->session_id; if (sess->di_list) srd_inst_free_all(sess, NULL); @@ -1140,7 +1143,7 @@ SRD_API int srd_session_destroy(struct srd_session *sess) * @param cb The function to call. Must not be NULL. * @param cb_data Private data for the callback function. Can be NULL. * - * @since 0.1.0 + * @since 0.3.0 */ SRD_API int srd_pd_output_callback_add(struct srd_session *sess, int output_type, srd_pd_output_callback_t cb, void *cb_data) @@ -1191,29 +1194,4 @@ SRD_PRIV struct srd_pd_callback *srd_pd_output_callback_find( return pd_cb; } -/* This is the backend function to Python sigrokdecode.add() call. */ -/** @private */ -SRD_PRIV int srd_inst_pd_output_add(struct srd_decoder_inst *di, - int output_type, const char *proto_id) -{ - struct srd_pd_output *pdo; - - srd_dbg("Instance %s creating new output type %d for %s.", - di->inst_id, output_type, proto_id); - - if (!(pdo = g_try_malloc(sizeof(struct srd_pd_output)))) { - srd_err("Failed to g_malloc() struct srd_pd_output."); - return -1; - } - - /* pdo_id is just a simple index, nothing is deleted from this list anyway. */ - pdo->pdo_id = g_slist_length(di->pd_output); - pdo->output_type = output_type; - pdo->di = di; - pdo->proto_id = g_strdup(proto_id); - di->pd_output = g_slist_append(di->pd_output, pdo); - - return pdo->pdo_id; -} - /** @} */