]> sigrok.org Git - libsigrokdecode.git/blobdiff - type_decoder.c
Use uint8_t instead of unsigned char for raw byte data
[libsigrokdecode.git] / type_decoder.c
index 454e7ea90deea3b0a89ecf1ba6b90aaad62978e4..95081835038388f5b9aef30b0799d3f9c087f941 100644 (file)
@@ -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. */
@@ -605,13 +709,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));
                }
        }
 
@@ -677,7 +781,7 @@ static int create_term_list(struct srd_decoder_inst *di,
                        term->type = SRD_TERM_SKIP;
                        term->num_samples_to_skip = num_samples_to_skip;
                        term->num_samples_already_skipped = 0;
-                       if (num_samples_to_skip < 1)
+                       if (num_samples_to_skip < 0)
                                term->type = SRD_TERM_ALWAYS_FALSE;
                } else {
                        srd_err("Term key is neither a string nor a number.");
@@ -922,7 +1026,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 +1141,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" },