X-Git-Url: https://sigrok.org/gitweb/?a=blobdiff_plain;f=type_decoder.c;h=95081835038388f5b9aef30b0799d3f9c087f941;hb=114adb4997b71e93267e3816710c8b019ae927c0;hp=1b378f1ac6e8b53d2e037310c60bd659923ee0b1;hpb=3d9e87aadacf3f8f8a93ad09432c67a257b51633;p=libsigrokdecode.git diff --git a/type_decoder.c b/type_decoder.c index 1b378f1..9508183 100644 --- a/type_decoder.c +++ b/type_decoder.c @@ -37,6 +37,7 @@ SRD_PRIV const char *output_type_name(unsigned int idx) "OUTPUT_ANN", "OUTPUT_PYTHON", "OUTPUT_BINARY", + "OUTPUT_LOGIC", "OUTPUT_META", "(invalid)" }; @@ -123,6 +124,89 @@ err: return SRD_ERR_PYTHON; } +static void release_logic(struct srd_proto_data_logic *pdl) +{ + if (!pdl) + return; + g_free((void *)pdl->data); +} + +static int convert_logic(struct srd_decoder_inst *di, PyObject *obj, + struct srd_proto_data *pdata) +{ + struct srd_proto_data_logic *pdl; + PyObject *py_tmp; + Py_ssize_t size; + int logic_group; + char *group_name, *buf; + PyGILState_STATE gstate; + + gstate = PyGILState_Ensure(); + + /* Should be a list of [logic group, bytes]. */ + if (!PyList_Check(obj)) { + srd_err("Protocol decoder %s submitted non-list for SRD_OUTPUT_LOGIC.", + di->decoder->name); + goto err; + } + + /* Should have 2 elements. */ + if (PyList_Size(obj) != 2) { + srd_err("Protocol decoder %s submitted SRD_OUTPUT_LOGIC list " + "with %zd elements instead of 2", di->decoder->name, + PyList_Size(obj)); + goto err; + } + + /* The first element should be an integer. */ + py_tmp = PyList_GetItem(obj, 0); + if (!PyLong_Check(py_tmp)) { + srd_err("Protocol decoder %s submitted SRD_OUTPUT_LOGIC list, " + "but first element was not an integer.", di->decoder->name); + goto err; + } + logic_group = PyLong_AsLong(py_tmp); + if (!(group_name = g_slist_nth_data(di->decoder->logic_output_channels, logic_group))) { + srd_err("Protocol decoder %s submitted SRD_OUTPUT_LOGIC with " + "unregistered logic group %d.", di->decoder->name, logic_group); + goto err; + } + + /* Second element should be bytes. */ + py_tmp = PyList_GetItem(obj, 1); + if (!PyBytes_Check(py_tmp)) { + srd_err("Protocol decoder %s submitted SRD_OUTPUT_LOGIC list, " + "but second element was not bytes.", di->decoder->name); + goto err; + } + + /* Consider an empty set of bytes a bug. */ + if (PyBytes_Size(py_tmp) == 0) { + srd_err("Protocol decoder %s submitted SRD_OUTPUT_LOGIC " + "with empty data set.", di->decoder->name); + goto err; + } + + if (PyBytes_AsStringAndSize(py_tmp, &buf, &size) == -1) + goto err; + + PyGILState_Release(gstate); + + pdl = pdata->data; + pdl->logic_group = logic_group; + /* pdl->repeat_count is set by the caller as it depends on the sample range */ + if (!(pdl->data = g_try_malloc(size))) + return SRD_ERR_MALLOC; + memcpy((void *)pdl->data, (const void *)buf, size); + + return SRD_OK; + +err: + PyGILState_Release(gstate); + + return SRD_ERR_PYTHON; +} + static void release_binary(struct srd_proto_data_binary *pdb) { if (!pdb) @@ -321,6 +405,7 @@ static PyObject *Decoder_put(PyObject *self, PyObject *args) struct srd_proto_data pdata; struct srd_proto_data_annotation pda; struct srd_proto_data_binary pdb; + struct srd_proto_data_logic pdl; uint64_t start_sample, end_sample; int output_id; struct srd_pd_callback *cb; @@ -421,6 +506,25 @@ static PyObject *Decoder_put(PyObject *self, PyObject *args) release_binary(pdata.data); } break; + case SRD_OUTPUT_LOGIC: + if ((cb = srd_pd_output_callback_find(di->sess, pdo->output_type))) { + pdata.data = &pdl; + /* Convert from PyDict to srd_proto_data_logic. */ + if (convert_logic(di, py_data, &pdata) != SRD_OK) { + /* An error was already logged. */ + break; + } + if (end_sample <= start_sample) { + srd_err("Ignored SRD_OUTPUT_LOGIC with invalid sample range."); + break; + } + pdl.repeat_count = (end_sample - start_sample) - 1; + Py_BEGIN_ALLOW_THREADS + cb->cb(&pdata, cb->cb_data); + Py_END_ALLOW_THREADS + release_logic(pdata.data); + } + break; case SRD_OUTPUT_META: if ((cb = srd_pd_output_callback_find(di->sess, pdo->output_type))) { /* Annotations need converting from PyObject. */