X-Git-Url: https://sigrok.org/gitweb/?p=libsigrokdecode.git;a=blobdiff_plain;f=type_decoder.c;fp=type_decoder.c;h=ab2e21fa3aafbc56f96e3b145313fc7ed71744d3;hp=1b378f1ac6e8b53d2e037310c60bd659923ee0b1;hb=ddcde1861eb029e17d2592b2fbf644e2e00f4835;hpb=88b62601d661281be74fde8e3913e66dbe2fa7b4 diff --git a/type_decoder.c b/type_decoder.c index 1b378f1..ab2e21f 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_class; + char *class_name, *buf; + PyGILState_STATE gstate; + + gstate = PyGILState_Ensure(); + + /* Should be a list of [logic class, 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_class = PyLong_AsLong(py_tmp); + if (!(class_name = g_slist_nth_data(di->decoder->logic_output_channels, logic_class))) { + srd_err("Protocol decoder %s submitted SRD_OUTPUT_LOGIC with " + "unregistered logic class %d.", di->decoder->name, logic_class); + 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_class = logic_class; + pdl->size = size; + if (!(pdl->data = g_try_malloc(pdl->size))) + return SRD_ERR_MALLOC; + memcpy((void *)pdl->data, (const void *)buf, pdl->size); + + return SRD_OK; + +err: + PyGILState_Release(gstate); + + return SRD_ERR_PYTHON; +} + static void release_binary(struct srd_proto_data_binary *pdb) { if (!pdb) @@ -421,6 +505,20 @@ 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 = &pdb; + /* Convert from PyDict to srd_proto_data_logic. */ + if (convert_logic(di, py_data, &pdata) != SRD_OK) { + /* An error was already logged. */ + break; + } + 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. */