diff options
author | Uwe Hermann <uwe@hermann-uwe.de> | 2019-06-26 21:25:37 +0200 |
---|---|---|
committer | Soeren Apel <soeren@apelpie.net> | 2021-02-13 22:40:15 +0100 |
commit | ddcde1861eb029e17d2592b2fbf644e2e00f4835 (patch) | |
tree | a6eda6762fb37198151b8689319670d0379fcb80 /type_decoder.c | |
parent | 88b62601d661281be74fde8e3913e66dbe2fa7b4 (diff) | |
download | libsigrokdecode-ddcde1861eb029e17d2592b2fbf644e2e00f4835.tar.gz libsigrokdecode-ddcde1861eb029e17d2592b2fbf644e2e00f4835.zip |
Add initial OUTPUT_LOGIC support.
Protocol decoders can now declare an arbitrary number of logic output
channels with a fixed assumed samplerate each.
Diffstat (limited to 'type_decoder.c')
-rw-r--r-- | type_decoder.c | 98 |
1 files changed, 98 insertions, 0 deletions
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. */ |