*/
#include "config.h"
-#include "libsigrokdecode.h" /* First, so we avoid a _POSIX_C_SOURCE warning. */
-#include "libsigrokdecode-internal.h"
+#include "libsigrokdecode-internal.h" /* First, so we avoid a _POSIX_C_SOURCE warning. */
+#include "libsigrokdecode.h"
#include <glib.h>
/**
/** @cond PRIVATE */
/* The list of protocol decoders. */
-SRD_PRIV GSList *pd_list = NULL;
+static GSList *pd_list = NULL;
/* srd.c */
-extern GSList *searchpaths;
+extern SRD_PRIV GSList *searchpaths;
/* session.c */
-extern GSList *sessions;
+extern SRD_PRIV GSList *sessions;
+extern SRD_PRIV int max_session_id;
/* module_sigrokdecode.c */
extern SRD_PRIV PyObject *mod_sigrokdecode;
/** @endcond */
+static gboolean srd_check_init(void)
+{
+ if (max_session_id < 0) {
+ srd_err("Library is not initialized.");
+ return FALSE;
+ } else
+ return TRUE;
+}
+
/**
* Returns the list of supported/loaded protocol decoders.
*
- * This is a GSList containing the names of the decoders as strings.
+ * This is a GSList of pointers to struct srd_decoder items.
*
* @return List of decoders, NULL if none are supported or loaded.
*
- * @since 0.1.0 (but the API changed in 0.2.0)
+ * @since 0.2.0
*/
SRD_API const GSList *srd_decoder_list(void)
{
return NULL;
}
-static int get_probes(const struct srd_decoder *d, const char *attr,
- GSList **pl)
+static int get_channels(const struct srd_decoder *d, const char *attr,
+ GSList **pdchl)
{
- PyObject *py_probelist, *py_entry;
- struct srd_probe *p;
- int ret, num_probes, i;
+ PyObject *py_channellist, *py_entry;
+ struct srd_channel *pdch;
+ int ret, num_channels, i;
if (!PyObject_HasAttrString(d->py_dec, attr))
- /* No probes of this type specified. */
+ /* No channels of this type specified. */
return SRD_OK;
- py_probelist = PyObject_GetAttrString(d->py_dec, attr);
- if (!PyTuple_Check(py_probelist)) {
+ py_channellist = PyObject_GetAttrString(d->py_dec, attr);
+ if (!PyTuple_Check(py_channellist)) {
srd_err("Protocol decoder %s %s attribute is not a tuple.",
d->name, attr);
return SRD_ERR_PYTHON;
}
- if ((num_probes = PyTuple_Size(py_probelist)) == 0)
- /* Empty probelist. */
+ if ((num_channels = PyTuple_Size(py_channellist)) == 0)
+ /* Empty channellist. */
return SRD_OK;
ret = SRD_OK;
- for (i = 0; i < num_probes; i++) {
- py_entry = PyTuple_GetItem(py_probelist, i);
+ for (i = 0; i < num_channels; i++) {
+ py_entry = PyTuple_GetItem(py_channellist, i);
if (!PyDict_Check(py_entry)) {
srd_err("Protocol decoder %s %s attribute is not "
"a list with dict elements.", d->name, attr);
break;
}
- if (!(p = g_try_malloc(sizeof(struct srd_probe)))) {
- srd_err("Failed to g_malloc() struct srd_probe.");
+ if (!(pdch = g_try_malloc(sizeof(struct srd_channel)))) {
+ srd_err("Failed to g_malloc() struct srd_channel.");
ret = SRD_ERR_MALLOC;
break;
}
- if ((py_dictitem_as_str(py_entry, "id", &p->id)) != SRD_OK) {
+ if ((py_dictitem_as_str(py_entry, "id", &pdch->id)) != SRD_OK) {
ret = SRD_ERR_PYTHON;
break;
}
- if ((py_dictitem_as_str(py_entry, "name", &p->name)) != SRD_OK) {
+ if ((py_dictitem_as_str(py_entry, "name", &pdch->name)) != SRD_OK) {
ret = SRD_ERR_PYTHON;
break;
}
- if ((py_dictitem_as_str(py_entry, "desc", &p->desc)) != SRD_OK) {
+ if ((py_dictitem_as_str(py_entry, "desc", &pdch->desc)) != SRD_OK) {
ret = SRD_ERR_PYTHON;
break;
}
- p->order = i;
+ pdch->order = i;
- *pl = g_slist_append(*pl, p);
+ *pdchl = g_slist_append(*pdchl, pdch);
}
- Py_DecRef(py_probelist);
+ Py_DecRef(py_channellist);
return ret;
}
struct srd_decoder *d;
int ret, i, j;
char **ann, **bin, *ann_row_id, *ann_row_desc;
- struct srd_probe *p;
+ struct srd_channel *pdch;
GSList *l, *ann_classes;
struct srd_decoder_annotation_row *ann_row;
}
Py_CLEAR(py_basedec);
+ /*
+ * Check that thіs decoder has the correct PD API version.
+ * PDs of different API versions are incompatible and cannot work.
+ */
+ py_long = PyObject_GetAttrString(d->py_dec, "api_version");
+ if (PyLong_AsLong(py_long) != 2) {
+ srd_err("Only PDs of API version 2 are supported.");
+ goto err_out;
+ }
+ Py_CLEAR(py_long);
+
/* Check for a proper start() method. */
if (!PyObject_HasAttrString(d->py_dec, "start")) {
srd_err("Protocol decoder %s has no start() method Decoder "
if (get_options(d) != SRD_OK)
goto err_out;
- /* Check and import required probes. */
- if (get_probes(d, "probes", &d->probes) != SRD_OK)
+ /* Check and import required channels. */
+ if (get_channels(d, "channels", &d->channels) != SRD_OK)
goto err_out;
- /* Check and import optional probes. */
- if (get_probes(d, "optional_probes", &d->opt_probes) != SRD_OK)
+ /* Check and import optional channels. */
+ if (get_channels(d, "optional_channels", &d->opt_channels) != SRD_OK)
goto err_out;
/*
- * Fix order numbers for the optional probes.
+ * Fix order numbers for the optional channels.
*
* Example:
- * Required probes: r1, r2, r3. Optional: o1, o2, o3, o4.
- * 'order' fields in the d->probes list = 0, 1, 2.
- * 'order' fields in the d->opt_probes list = 3, 4, 5, 6.
+ * Required channels: r1, r2, r3. Optional: o1, o2, o3, o4.
+ * 'order' fields in the d->channels list = 0, 1, 2.
+ * 'order' fields in the d->opt_channels list = 3, 4, 5, 6.
*/
- for (l = d->opt_probes; l; l = l->next) {
- p = l->data;
- p->order += g_slist_length(d->probes);
+ for (l = d->opt_channels; l; l = l->next) {
+ pdch = l->data;
+ pdch->order += g_slist_length(d->channels);
}
/* Convert annotation class attribute to GSList of char **. */
return doc;
}
-static void free_probes(GSList *probelist)
+static void free_channels(GSList *channellist)
{
GSList *l;
- struct srd_probe *p;
+ struct srd_channel *pdch;
- if (probelist == NULL)
+ if (channellist == NULL)
return;
- for (l = probelist; l; l = l->next) {
- p = l->data;
- g_free(p->id);
- g_free(p->name);
- g_free(p->desc);
- g_free(p);
+ for (l = channellist; l; l = l->next) {
+ pdch = l->data;
+ g_free(pdch->id);
+ g_free(pdch->name);
+ g_free(pdch->desc);
+ g_free(pdch);
}
- g_slist_free(probelist);
+ g_slist_free(channellist);
}
/**
}
g_slist_free(dec->options);
- free_probes(dec->probes);
- free_probes(dec->opt_probes);
+ free_channels(dec->channels);
+ free_channels(dec->opt_channels);
g_free(dec->id);
g_free(dec->name);
g_free(dec->longname);
return SRD_OK;
}
+static void srd_decoder_load_all_zip_path(char *path)
+{
+ PyObject *zipimport_mod, *zipimporter_class, *zipimporter;
+ PyObject *prefix_obj, *files, *key, *value, *set, *modname;
+ Py_ssize_t pos = 0;
+ char *prefix;
+ size_t prefix_len;
+
+ set = files = prefix_obj = zipimporter = zipimporter_class = NULL;
+
+ zipimport_mod = PyImport_ImportModule("zipimport");
+ if (zipimport_mod == NULL)
+ goto err_out;
+
+ zipimporter_class = PyObject_GetAttrString(zipimport_mod, "zipimporter");
+ if (zipimporter_class == NULL)
+ goto err_out;
+
+ zipimporter = PyObject_CallFunction(zipimporter_class, "s", path);
+ if (zipimporter == NULL)
+ goto err_out;
+
+ prefix_obj = PyObject_GetAttrString(zipimporter, "prefix");
+ if (prefix_obj == NULL)
+ goto err_out;
+
+ files = PyObject_GetAttrString(zipimporter, "_files");
+ if (files == NULL)
+ goto err_out;
+
+ set = PySet_New(NULL);
+ if (set == NULL)
+ goto err_out;
+
+ if (py_str_as_str(prefix_obj, &prefix) != SRD_OK)
+ goto err_out;
+
+ prefix_len = strlen(prefix);
+
+ while (PyDict_Next(files, &pos, &key, &value)) {
+ char *path, *slash;
+ if (py_str_as_str(key, &path) == SRD_OK) {
+ if (strlen(path) > prefix_len &&
+ !memcmp(path, prefix, prefix_len) &&
+ (slash = strchr(path+prefix_len, '/'))) {
+ modname =
+ PyUnicode_FromStringAndSize(path+prefix_len,
+ slash-(path+prefix_len));
+ if (modname == NULL) {
+ PyErr_Clear();
+ } else {
+ PySet_Add(set, modname);
+ Py_XDECREF(modname);
+ }
+ }
+ free(path);
+ }
+ }
+
+ free(prefix);
+
+ while ((modname = PySet_Pop(set))) {
+ char *modname_str;
+ if (py_str_as_str(modname, &modname_str) == SRD_OK) {
+ /* The directory name is the module name (e.g. "i2c"). */
+ srd_decoder_load(modname_str);
+ free(modname_str);
+ }
+ Py_XDECREF(modname);
+ }
+
+err_out:
+ Py_XDECREF(set);
+ Py_XDECREF(files);
+ Py_XDECREF(prefix_obj);
+ Py_XDECREF(zipimporter);
+ Py_XDECREF(zipimporter_class);
+ Py_XDECREF(zipimport_mod);
+ PyErr_Clear();
+}
+
static void srd_decoder_load_all_path(char *path)
{
GDir *dir;
const gchar *direntry;
- if (!(dir = g_dir_open(path, 0, NULL)))
+ if (!(dir = g_dir_open(path, 0, NULL))) {
/* Not really fatal */
+ /* Try zipimport method too */
+ srd_decoder_load_all_zip_path(path);
return;
+ }
/* This ignores errors returned by srd_decoder_load(). That
* function will have logged the cause, but in any case we