X-Git-Url: https://sigrok.org/gitweb/?p=libsigrokdecode.git;a=blobdiff_plain;f=type_decoder.c;h=ab2e21fa3aafbc56f96e3b145313fc7ed71744d3;hp=c097c7fce5b94cb950d3cb03c0fb4e52371a0df2;hb=ddcde1861eb029e17d2592b2fbf644e2e00f4835;hpb=99e264892acc0d81b31a219d806a5e5c5efa46f8 diff --git a/type_decoder.c b/type_decoder.c index c097c7f..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. */ @@ -605,13 +703,13 @@ static PyObject *get_current_pinvalues(const struct srd_decoder_inst *di) /* A channelmap value of -1 means "unused optional channel". */ if (di->dec_channelmap[i] == -1) { /* Value of unused channel is 0xff, instead of 0 or 1. */ - PyTuple_SetItem(py_pinvalues, i, PyLong_FromLong(0xff)); + PyTuple_SetItem(py_pinvalues, i, PyLong_FromUnsignedLong(0xff)); } else { sample_pos = di->inbuf + ((di->abs_cur_samplenum - di->abs_start_samplenum) * di->data_unitsize); byte_offset = di->dec_channelmap[i] / 8; bit_offset = di->dec_channelmap[i] % 8; sample = *(sample_pos + byte_offset) & (1 << bit_offset) ? 1 : 0; - PyTuple_SetItem(py_pinvalues, i, PyLong_FromLong(sample)); + PyTuple_SetItem(py_pinvalues, i, PyLong_FromUnsignedLong(sample)); } } @@ -922,7 +1020,7 @@ static PyObject *Decoder_wait(PyObject *self, PyObject *args) /* If there's a match, set self.samplenum etc. and return. */ if (found_match) { /* Set self.samplenum to the (absolute) sample number that matched. */ - py_samplenum = PyLong_FromLong(di->abs_cur_samplenum); + py_samplenum = PyLong_FromUnsignedLongLong(di->abs_cur_samplenum); PyObject_SetAttrString(di->py_inst, "samplenum", py_samplenum); Py_DECREF(py_samplenum); @@ -1037,7 +1135,7 @@ err: static PyMethodDef Decoder_methods[] = { { "put", Decoder_put, METH_VARARGS, "Accepts a dictionary with the following keys: startsample, endsample, data" }, - { "register", (PyCFunction)Decoder_register, METH_VARARGS|METH_KEYWORDS, + { "register", (PyCFunction)(void(*)(void))Decoder_register, METH_VARARGS|METH_KEYWORDS, "Register a new output stream" }, { "wait", Decoder_wait, METH_VARARGS, "Wait for one or more conditions to occur" },