]> sigrok.org Git - libsigrokdecode.git/blobdiff - type_decoder.c
Add initial OUTPUT_LOGIC support.
[libsigrokdecode.git] / type_decoder.c
index 1b378f1ac6e8b53d2e037310c60bd659923ee0b1..ab2e21fa3aafbc56f96e3b145313fc7ed71744d3 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_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. */