/** * Initialize libsigrokdecode. * * This initializes the Python interpreter, and creates and initializes * a "sigrokdecode" Python module. * * Then, it searches for sigrok protocol decoder files (*.py) in the * "decoders" subdirectory of the the sigrok installation directory. * All decoders that are found are loaded into memory and added to an * internal list of decoders, which can be queried via srd_decoders_list(). * * The caller is responsible for calling the clean-up function srd_exit(), * which will properly shut down libsigrokdecode and free its allocated memory. * * Multiple calls to srd_init(), without calling srd_exit() in between, * are not allowed. * * @param path Path to an extra directory containing protocol decoders * which will be added to the Python sys.path, or NULL. * * @return SRD_OK upon success, a (negative) error code otherwise. * Upon Python errors, return SRD_ERR_PYTHON. If the sigrok decoders * directory cannot be accessed, return SRD_ERR_DECODERS_DIR. * If not enough memory could be allocated, return SRD_ERR_MALLOC. */ SRD_API int srd_init(const char *path) { int ret; char *env_path; srd_dbg("Initializing libsigrokdecode."); /* Add our own module to the list of built-in modules. */ PyImport_AppendInittab("sigrokdecode", PyInit_sigrokdecode); /* Initialize the Python interpreter. */ Py_Initialize(); /* Installed decoders. */ if ((ret = srd_decoder_searchpath_add(DECODERS_DIR)) != SRD_OK) { Py_Finalize(); return ret; } /* Path specified by the user. */ if (path) { if ((ret = srd_decoder_searchpath_add(path)) != SRD_OK) { Py_Finalize(); return ret; } } /* Environment variable overrides everything, for debugging. */ if ((env_path = getenv("SIGROKDECODE_DIR"))) { if ((ret = srd_decoder_searchpath_add(env_path)) != SRD_OK) { Py_Finalize(); return ret; } } return SRD_OK; }
/** @private */ SRD_PRIV int srd_inst_start(struct srd_decoder_inst *di) { PyObject *py_res; GSList *l; struct srd_decoder_inst *next_di; int ret; srd_dbg("Calling start() method on protocol decoder instance %s.", di->inst_id); /* Run self.start(). */ if (!(py_res = PyObject_CallMethod(di->py_inst, "start", NULL))) { srd_exception_catch("Protocol decoder instance %s", di->inst_id); return SRD_ERR_PYTHON; } Py_DecRef(py_res); /* Set the initial pins based on self.initial_pins. */ set_initial_pin_values(di); /* Set self.samplenum to 0. */ PyObject_SetAttrString(di->py_inst, "samplenum", PyLong_FromLong(0)); /* Set self.matches to None. */ PyObject_SetAttrString(di->py_inst, "matches", Py_None); /* Start all the PDs stacked on top of this one. */ for (l = di->next_di; l; l = l->next) { next_di = l->data; if ((ret = srd_inst_start(next_di)) != SRD_OK) return ret; } return SRD_OK; }
/** * Send a chunk of logic sample data to a running decoder session. * * If no channel map has been set up, the logic samples must be arranged * in channel order, in the least amount of space possible. The default * channel set consists of all required channels + all optional channels. * * The size of a sample in inbuf is the unit size passed to * srd_inst_channel_set_all(). If no channel map has been configured, it is * the minimum number of bytes needed to store the default channels. * * @param sess The session to use. * @param start_samplenum The sample number of the first sample in this chunk. * @param end_samplenum The sample number of the last sample in this chunk. * @param inbuf Pointer to sample data. * @param inbuflen Length in bytes of the buffer. * * @return SRD_OK upon success, a (negative) error code otherwise. * * @since 0.3.0 */ SRD_API int srd_session_send(struct srd_session *sess, uint64_t start_samplenum, uint64_t end_samplenum, const uint8_t *inbuf, uint64_t inbuflen) { GSList *d; int ret; if (session_is_valid(sess) != SRD_OK) { srd_err("Invalid session."); return SRD_ERR_ARG; } srd_dbg("Calling decode() on all instances with starting sample " "number %" PRIu64 ", %" PRIu64 " bytes at 0x%p", start_samplenum, inbuflen, inbuf); for (d = sess->di_list; d; d = d->next) { if ((ret = srd_inst_decode(d->data, start_samplenum, end_samplenum, inbuf, inbuflen)) != SRD_OK) return ret; } return SRD_OK; }
/** * Create a new protocol decoder instance. * * @param sess The session holding the protocol decoder instance. * @param decoder_id Decoder 'id' field. * @param options GHashtable of options which override the defaults set in * the decoder class. May be NULL. * * @return Pointer to a newly allocated struct srd_decoder_inst, or * NULL in case of failure. * * @since 0.3.0 */ SRD_API struct srd_decoder_inst *srd_inst_new(struct srd_session *sess, const char *decoder_id, GHashTable *options) { int i; struct srd_decoder *dec; struct srd_decoder_inst *di; char *inst_id; srd_dbg("Creating new %s instance.", decoder_id); if (session_is_valid(sess) != SRD_OK) { srd_err("Invalid session."); return NULL; } if (!(dec = srd_decoder_get_by_id(decoder_id))) { srd_err("Protocol decoder %s not found.", decoder_id); return NULL; } if (!(di = g_try_malloc0(sizeof(struct srd_decoder_inst)))) { srd_err("Failed to g_malloc() instance."); return NULL; } di->decoder = dec; di->sess = sess; if (options) { inst_id = g_hash_table_lookup(options, "id"); di->inst_id = g_strdup(inst_id ? inst_id : decoder_id); g_hash_table_remove(options, "id"); } else di->inst_id = g_strdup(decoder_id); /* * Prepare a default probe map, where samples come in the * order in which the decoder class defined them. */ di->dec_num_probes = g_slist_length(di->decoder->probes) + g_slist_length(di->decoder->opt_probes); if (di->dec_num_probes) { if (!(di->dec_probemap = g_try_malloc(sizeof(int) * di->dec_num_probes))) { srd_err("Failed to g_malloc() probe map."); g_free(di); return NULL; } for (i = 0; i < di->dec_num_probes; i++) di->dec_probemap[i] = i; di->data_unitsize = (di->dec_num_probes + 7) / 8; /* * Will be used to prepare a sample at every iteration * of the instance's decode() method. */ if (!(di->probe_samples = g_try_malloc(di->dec_num_probes))) { srd_err("Failed to g_malloc() sample buffer."); g_free(di->dec_probemap); g_free(di); return NULL; } } /* Create a new instance of this decoder class. */ if (!(di->py_inst = PyObject_CallObject(dec->py_dec, NULL))) { if (PyErr_Occurred()) srd_exception_catch("failed to create %s instance: ", decoder_id); g_free(di->dec_probemap); g_free(di); return NULL; } if (options && srd_inst_option_set(di, options) != SRD_OK) { g_free(di->dec_probemap); g_free(di); return NULL; } /* Instance takes input from a frontend by default. */ sess->di_list = g_slist_append(sess->di_list, di); return di; }
/** * Set all probes in a decoder instance. * * This function sets _all_ probes for the specified decoder instance, i.e., * it overwrites any probes that were already defined (if any). * * @param di Decoder instance. * @param new_probes A GHashTable of probes to set. Key is probe name, value is * the probe number. Samples passed to this instance will be * arranged in this order. * * @return SRD_OK upon success, a (negative) error code otherwise. * * @since 0.1.0 */ SRD_API int srd_inst_probe_set_all(struct srd_decoder_inst *di, GHashTable *new_probes) { GVariant *probe_val; GList *l; GSList *sl; struct srd_probe *p; int *new_probemap, new_probenum, num_required_probes, num_probes, i; char *probe_id; srd_dbg("set probes called for instance %s with list of %d probes", di->inst_id, g_hash_table_size(new_probes)); if (g_hash_table_size(new_probes) == 0) /* No probes provided. */ return SRD_OK; if (di->dec_num_probes == 0) { /* Decoder has no probes. */ srd_err("Protocol decoder %s has no probes to define.", di->decoder->name); return SRD_ERR_ARG; } new_probemap = NULL; if (!(new_probemap = g_try_malloc(sizeof(int) * di->dec_num_probes))) { srd_err("Failed to g_malloc() new probe map."); return SRD_ERR_MALLOC; } /* * For now, map all indexes to probe -1 (can be overridden later). * This -1 is interpreted as an unspecified probe later. */ for (i = 0; i < di->dec_num_probes; i++) new_probemap[i] = -1; num_probes = 0; for (l = g_hash_table_get_keys(new_probes); l; l = l->next) { probe_id = l->data; probe_val = g_hash_table_lookup(new_probes, probe_id); if (!g_variant_is_of_type(probe_val, G_VARIANT_TYPE_INT32)) { /* Probe name was specified without a value. */ srd_err("No probe number was specified for %s.", probe_id); g_free(new_probemap); return SRD_ERR_ARG; } new_probenum = g_variant_get_int32(probe_val); if (!(sl = g_slist_find_custom(di->decoder->probes, probe_id, (GCompareFunc)compare_probe_id))) { /* Fall back on optional probes. */ if (!(sl = g_slist_find_custom(di->decoder->opt_probes, probe_id, (GCompareFunc) compare_probe_id))) { srd_err("Protocol decoder %s has no probe " "'%s'.", di->decoder->name, probe_id); g_free(new_probemap); return SRD_ERR_ARG; } } p = sl->data; new_probemap[p->order] = new_probenum; srd_dbg("Setting probe mapping: %s (index %d) = probe %d.", p->id, p->order, new_probenum); num_probes++; } di->data_unitsize = (num_probes + 7) / 8; srd_dbg("Final probe map:"); num_required_probes = g_slist_length(di->decoder->probes); for (i = 0; i < di->dec_num_probes; i++) { srd_dbg(" - index %d = probe %d (%s)", i, new_probemap[i], (i < num_required_probes) ? "required" : "optional"); } /* Report an error if not all required probes were specified. */ for (i = 0; i < num_required_probes; i++) { if (new_probemap[i] != -1) continue; p = g_slist_nth(di->decoder->probes, i)->data; srd_err("Required probe '%s' (index %d) was not specified.", p->id, i); return SRD_ERR; } g_free(di->dec_probemap); di->dec_probemap = new_probemap; return SRD_OK; }
/** * Decode a chunk of samples. * * @param di The decoder instance to call. Must not be NULL. * @param start_samplenum The starting sample number for the buffer's sample * set, relative to the start of capture. * @param end_samplenum The ending sample number for the buffer's sample * set, relative to the start of capture. * @param inbuf The buffer to decode. Must not be NULL. * @param inbuflen Length of the buffer. Must be > 0. * @param unitsize The number of bytes per sample. Must be > 0. * * @return SRD_OK upon success, a (negative) error code otherwise. * * @private */ SRD_PRIV int srd_inst_decode(const struct srd_decoder_inst *di, uint64_t start_samplenum, uint64_t end_samplenum, const uint8_t *inbuf, uint64_t inbuflen, uint64_t unitsize) { PyObject *py_res; srd_logic *logic; long apiver; /* Return an error upon unusable input. */ if (!di) { srd_dbg("empty decoder instance"); return SRD_ERR_ARG; } if (!inbuf) { srd_dbg("NULL buffer pointer"); return SRD_ERR_ARG; } if (inbuflen == 0) { srd_dbg("empty buffer"); return SRD_ERR_ARG; } if (unitsize == 0) { srd_dbg("unitsize 0"); return SRD_ERR_ARG; } ((struct srd_decoder_inst *)di)->data_unitsize = unitsize; srd_dbg("Decoding: start sample %" PRIu64 ", end sample %" PRIu64 " (%" PRIu64 " samples, %" PRIu64 " bytes, unitsize = " "%d), instance %s.", start_samplenum, end_samplenum, end_samplenum - start_samplenum, inbuflen, di->data_unitsize, di->inst_id); apiver = srd_decoder_apiver(di->decoder); if (apiver == 2) { /* * Create new srd_logic object. Each iteration around the PD's * loop will fill one sample into this object. */ logic = PyObject_New(srd_logic, (PyTypeObject *)srd_logic_type); Py_INCREF(logic); logic->di = (struct srd_decoder_inst *)di; logic->start_samplenum = start_samplenum; logic->itercnt = 0; logic->inbuf = (uint8_t *)inbuf; logic->inbuflen = inbuflen; logic->sample = PyList_New(2); Py_INCREF(logic->sample); Py_IncRef(di->py_inst); if (!(py_res = PyObject_CallMethod(di->py_inst, "decode", "KKO", start_samplenum, end_samplenum, logic))) { srd_exception_catch("Protocol decoder instance %s", di->inst_id); return SRD_ERR_PYTHON; } Py_DecRef(py_res); } return SRD_OK; }
/** * Set all channels in a decoder instance. * * This function sets _all_ channels for the specified decoder instance, i.e., * it overwrites any channels that were already defined (if any). * * @param di Decoder instance. * @param new_channels A GHashTable of channels to set. Key is channel name, * value is the channel number. Samples passed to this * instance will be arranged in this order. * * @return SRD_OK upon success, a (negative) error code otherwise. * * @since 0.4.0 */ SRD_API int srd_inst_channel_set_all(struct srd_decoder_inst *di, GHashTable *new_channels) { GVariant *channel_val; GList *l; GSList *sl; struct srd_channel *pdch; int *new_channelmap, new_channelnum, num_required_channels, i; char *channel_id; srd_dbg("Setting channels for instance %s with list of %d channels.", di->inst_id, g_hash_table_size(new_channels)); if (g_hash_table_size(new_channels) == 0) /* No channels provided. */ return SRD_OK; if (di->dec_num_channels == 0) { /* Decoder has no channels. */ srd_err("Protocol decoder %s has no channels to define.", di->decoder->name); return SRD_ERR_ARG; } new_channelmap = g_malloc(sizeof(int) * di->dec_num_channels); /* * For now, map all indexes to channel -1 (can be overridden later). * This -1 is interpreted as an unspecified channel later. */ for (i = 0; i < di->dec_num_channels; i++) new_channelmap[i] = -1; for (l = g_hash_table_get_keys(new_channels); l; l = l->next) { channel_id = l->data; channel_val = g_hash_table_lookup(new_channels, channel_id); if (!g_variant_is_of_type(channel_val, G_VARIANT_TYPE_INT32)) { /* Channel name was specified without a value. */ srd_err("No channel number was specified for %s.", channel_id); g_free(new_channelmap); return SRD_ERR_ARG; } new_channelnum = g_variant_get_int32(channel_val); if (!(sl = g_slist_find_custom(di->decoder->channels, channel_id, (GCompareFunc)compare_channel_id))) { /* Fall back on optional channels. */ if (!(sl = g_slist_find_custom(di->decoder->opt_channels, channel_id, (GCompareFunc)compare_channel_id))) { srd_err("Protocol decoder %s has no channel " "'%s'.", di->decoder->name, channel_id); g_free(new_channelmap); return SRD_ERR_ARG; } } pdch = sl->data; new_channelmap[pdch->order] = new_channelnum; srd_dbg("Setting channel mapping: %s (index %d) = channel %d.", pdch->id, pdch->order, new_channelnum); } srd_dbg("Final channel map:"); num_required_channels = g_slist_length(di->decoder->channels); for (i = 0; i < di->dec_num_channels; i++) { srd_dbg(" - index %d = channel %d (%s)", i, new_channelmap[i], (i < num_required_channels) ? "required" : "optional"); } /* Report an error if not all required channels were specified. */ for (i = 0; i < num_required_channels; i++) { if (new_channelmap[i] != -1) continue; pdch = g_slist_nth(di->decoder->channels, i)->data; srd_err("Required channel '%s' (index %d) was not specified.", pdch->id, i); return SRD_ERR; } g_free(di->dec_channelmap); di->dec_channelmap = new_channelmap; return SRD_OK; }
/** * Load a protocol decoder module into the embedded Python interpreter. * * @param module_name The module name to be loaded. * * @return SRD_OK upon success, a (negative) error code otherwise. */ SRD_API int srd_decoder_load(const char *module_name) { PyObject *py_basedec, *py_method, *py_attr, *py_annlist, *py_ann; struct srd_decoder *d; int alen, ret, i; char **ann; struct srd_probe *p; GSList *l; srd_dbg("Loading protocol decoder '%s'.", module_name); py_basedec = py_method = py_attr = NULL; if (!(d = g_try_malloc0(sizeof(struct srd_decoder)))) { srd_dbg("Failed to g_malloc() struct srd_decoder."); ret = SRD_ERR_MALLOC; goto err_out; } ret = SRD_ERR_PYTHON; /* Import the Python module. */ if (!(d->py_mod = PyImport_ImportModule(module_name))) { srd_exception_catch("Import of '%s' failed.", module_name); goto err_out; } /* Get the 'Decoder' class as Python object. */ if (!(d->py_dec = PyObject_GetAttrString(d->py_mod, "Decoder"))) { /* This generated an AttributeError exception. */ PyErr_Clear(); srd_err("Decoder class not found in protocol decoder %s.", module_name); goto err_out; } if (!(py_basedec = PyObject_GetAttrString(mod_sigrokdecode, "Decoder"))) { srd_dbg("sigrokdecode module not loaded."); goto err_out; } if (!PyObject_IsSubclass(d->py_dec, py_basedec)) { srd_err("Decoder class in protocol decoder module %s is not " "a subclass of sigrokdecode.Decoder.", module_name); goto err_out; } Py_CLEAR(py_basedec); /* Check for a proper start() method. */ if (!PyObject_HasAttrString(d->py_dec, "start")) { srd_err("Protocol decoder %s has no start() method Decoder " "class.", module_name); goto err_out; } py_method = PyObject_GetAttrString(d->py_dec, "start"); if (!PyFunction_Check(py_method)) { srd_err("Protocol decoder %s Decoder class attribute 'start' " "is not a method.", module_name); goto err_out; } Py_CLEAR(py_method); /* Check for a proper decode() method. */ if (!PyObject_HasAttrString(d->py_dec, "decode")) { srd_err("Protocol decoder %s has no decode() method Decoder " "class.", module_name); goto err_out; } py_method = PyObject_GetAttrString(d->py_dec, "decode"); if (!PyFunction_Check(py_method)) { srd_err("Protocol decoder %s Decoder class attribute 'decode' " "is not a method.", module_name); goto err_out; } Py_CLEAR(py_method); /* If present, options must be a dictionary. */ if (PyObject_HasAttrString(d->py_dec, "options")) { py_attr = PyObject_GetAttrString(d->py_dec, "options"); if (!PyDict_Check(py_attr)) { srd_err("Protocol decoder %s options attribute is not " "a dictionary.", d->name); Py_DecRef(py_attr); goto err_out; } Py_DecRef(py_attr); } /* Check and import required probes. */ if (get_probes(d, "probes", &d->probes) != SRD_OK) goto err_out; /* Check and import optional probes. */ if (get_probes(d, "optional_probes", &d->opt_probes) != SRD_OK) goto err_out; /* * Fix order numbers for the optional probes. * * 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. */ for (l = d->opt_probes; l; l = l->next) { p = l->data; p->order += g_slist_length(d->probes); } /* Store required fields in newly allocated strings. */ if (py_attr_as_str(d->py_dec, "id", &(d->id)) != SRD_OK) goto err_out; if (py_attr_as_str(d->py_dec, "name", &(d->name)) != SRD_OK) goto err_out; if (py_attr_as_str(d->py_dec, "longname", &(d->longname)) != SRD_OK) goto err_out; if (py_attr_as_str(d->py_dec, "desc", &(d->desc)) != SRD_OK) goto err_out; if (py_attr_as_str(d->py_dec, "license", &(d->license)) != SRD_OK) goto err_out; /* Convert class annotation attribute to GSList of **char. */ d->annotations = NULL; if (PyObject_HasAttrString(d->py_dec, "annotations")) { py_annlist = PyObject_GetAttrString(d->py_dec, "annotations"); if (!PyList_Check(py_annlist)) { srd_err("Protocol decoder module %s annotations " "should be a list.", module_name); goto err_out; } alen = PyList_Size(py_annlist); for (i = 0; i < alen; i++) { py_ann = PyList_GetItem(py_annlist, i); if (!PyList_Check(py_ann) || PyList_Size(py_ann) != 2) { srd_err("Protocol decoder module %s " "annotation %d should be a list with " "two elements.", module_name, i + 1); goto err_out; } if (py_strlist_to_char(py_ann, &ann) != SRD_OK) { goto err_out; } d->annotations = g_slist_append(d->annotations, ann); } } /* Append it to the list of supported/loaded decoders. */ pd_list = g_slist_append(pd_list, d); ret = SRD_OK; err_out: if (ret != SRD_OK) { Py_XDECREF(py_method); Py_XDECREF(py_basedec); Py_XDECREF(d->py_dec); Py_XDECREF(d->py_mod); g_free(d); } return ret; }
static PyObject *Decoder_wait(PyObject *self, PyObject *args) { int ret; unsigned int i; gboolean found_match; struct srd_decoder_inst *di; PyObject *py_pinvalues, *py_matched; if (!self || !args) return NULL; if (!(di = srd_inst_find_by_obj(NULL, self))) { PyErr_SetString(PyExc_Exception, "decoder instance not found"); Py_RETURN_NONE; } ret = set_new_condition_list(self, args); if (ret < 0) { srd_dbg("%s: %s: Aborting wait().", di->inst_id, __func__); return NULL; } if (ret == 9999) { /* Empty condition list, automatic match. */ PyObject_SetAttrString(di->py_inst, "matched", Py_None); /* Leave self.samplenum unchanged (== di->abs_cur_samplenum). */ return get_current_pinvalues(di); } while (1) { /* Wait for new samples to process, or termination request. */ g_mutex_lock(&di->data_mutex); while (!di->got_new_samples && !di->want_wait_terminate) g_cond_wait(&di->got_new_samples_cond, &di->data_mutex); /* * Check whether any of the current condition(s) match. * Arrange for termination requests to take a code path which * won't find new samples to process, pretends to have processed * previously stored samples, and returns to the main thread, * while the termination request still gets signalled. */ found_match = FALSE; ret = process_samples_until_condition_match(di, &found_match); /* If there's a match, set self.samplenum etc. and return. */ if (found_match) { /* Set self.samplenum to the (absolute) sample number that matched. */ PyObject_SetAttrString(di->py_inst, "samplenum", PyLong_FromLong(di->abs_cur_samplenum)); if (di->match_array && di->match_array->len > 0) { py_matched = PyTuple_New(di->match_array->len); for (i = 0; i < di->match_array->len; i++) PyTuple_SetItem(py_matched, i, PyBool_FromLong(di->match_array->data[i])); PyObject_SetAttrString(di->py_inst, "matched", py_matched); match_array_free(di); } else { PyObject_SetAttrString(di->py_inst, "matched", Py_None); } py_pinvalues = get_current_pinvalues(di); g_mutex_unlock(&di->data_mutex); return py_pinvalues; } /* No match, reset state for the next chunk. */ di->got_new_samples = FALSE; di->handled_all_samples = TRUE; di->abs_start_samplenum = 0; di->abs_end_samplenum = 0; di->inbuf = NULL; di->inbuflen = 0; /* Signal the main thread that we handled all samples. */ g_cond_signal(&di->handled_all_samples_cond); /* * When termination of wait() and decode() was requested, * then exit the loop after releasing the mutex. */ if (di->want_wait_terminate) { srd_dbg("%s: %s: Will return from wait().", di->inst_id, __func__); g_mutex_unlock(&di->data_mutex); return NULL; } g_mutex_unlock(&di->data_mutex); } Py_RETURN_NONE; }
/** * Initialize libsigrokdecode. * * This initializes the Python interpreter, and creates and initializes * a "sigrokdecode" Python module. * * Then, it searches for sigrok protocol decoders in the "decoders" * subdirectory of the the libsigrokdecode installation directory. * All decoders that are found are loaded into memory and added to an * internal list of decoders, which can be queried via srd_decoder_list(). * * The caller is responsible for calling the clean-up function srd_exit(), * which will properly shut down libsigrokdecode and free its allocated memory. * * Multiple calls to srd_init(), without calling srd_exit() in between, * are not allowed. * * @param path Path to an extra directory containing protocol decoders * which will be added to the Python sys.path. May be NULL. * * @return SRD_OK upon success, a (negative) error code otherwise. * Upon Python errors, SRD_ERR_PYTHON is returned. If the decoders * directory cannot be accessed, SRD_ERR_DECODERS_DIR is returned. * If not enough memory could be allocated, SRD_ERR_MALLOC is returned. * * @since 0.1.0 */ SRD_API int srd_init(const char *path) { const char *const *sys_datadirs; size_t i; int ret; const char *env_path; if (max_session_id != -1) { srd_err("libsigrokdecode is already initialized."); return SRD_ERR; } srd_dbg("Initializing libsigrokdecode."); /* Add our own module to the list of built-in modules. */ PyImport_AppendInittab("sigrokdecode", PyInit_sigrokdecode); /* Initialize the Python interpreter. */ Py_InitializeEx(0); /* Locations relative to the XDG system data directories. */ sys_datadirs = g_get_system_data_dirs(); for (i = g_strv_length((char **)sys_datadirs); i > 0; i--) { ret = searchpath_add_xdg_dir(sys_datadirs[i-1]); if (ret != SRD_OK) { Py_Finalize(); return ret; } } #ifdef DECODERS_DIR /* Hardcoded decoders install location, if defined. */ if ((ret = srd_decoder_searchpath_add(DECODERS_DIR)) != SRD_OK) { Py_Finalize(); return ret; } #endif /* Location relative to the XDG user data directory. */ ret = searchpath_add_xdg_dir(g_get_user_data_dir()); if (ret != SRD_OK) { Py_Finalize(); return ret; } /* Path specified by the user. */ if (path) { if ((ret = srd_decoder_searchpath_add(path)) != SRD_OK) { Py_Finalize(); return ret; } } /* Environment variable overrides everything, for debugging. */ if ((env_path = g_getenv("SIGROKDECODE_DIR"))) { if ((ret = srd_decoder_searchpath_add(env_path)) != SRD_OK) { Py_Finalize(); return ret; } } max_session_id = 0; return SRD_OK; }
/** * Set all probes in a decoder instance. * * This function sets _all_ probes for the specified decoder instance, i.e., * it overwrites any probes that were already defined (if any). * * @param di Decoder instance. * @param probes A GHashTable of probes to set. Key is probe name, value is * the probe number. Samples passed to this instance will be * arranged in this order. * * @return SRD_OK upon success, a (negative) error code otherwise. */ SRD_API int srd_inst_probe_set_all(struct srd_decoder_inst *di, GHashTable *new_probes) { GList *l; GSList *sl; struct srd_probe *p; int *new_probemap, new_probenum; char *probe_id, *probenum_str; srd_dbg("set probes called for instance %s with list of %d probes", di->inst_id, g_hash_table_size(new_probes)); if (g_hash_table_size(new_probes) == 0) /* No probes provided. */ return SRD_OK; if (di->dec_num_probes == 0) { /* Decoder has no probes. */ srd_err("Protocol decoder %s has no probes to define.", di->decoder->name); return SRD_ERR_ARG; } new_probemap = NULL; if (!(new_probemap = g_try_malloc(sizeof(int) * di->dec_num_probes))) { srd_err("Failed to g_malloc() new probe map."); return SRD_ERR_MALLOC; } for (l = g_hash_table_get_keys(new_probes); l; l = l->next) { probe_id = l->data; probenum_str = g_hash_table_lookup(new_probes, probe_id); if (!probenum_str) { /* Probe name was specified without a value. */ srd_err("No probe number was specified for %s.", probe_id); g_free(new_probemap); return SRD_ERR_ARG; } new_probenum = strtol(probenum_str, NULL, 10); if (!(sl = g_slist_find_custom(di->decoder->probes, probe_id, (GCompareFunc)compare_probe_id))) { /* Fall back on optional probes. */ if (!(sl = g_slist_find_custom(di->decoder->opt_probes, probe_id, (GCompareFunc) compare_probe_id))) { srd_err("Protocol decoder %s has no probe " "'%s'.", di->decoder->name, probe_id); g_free(new_probemap); return SRD_ERR_ARG; } } p = sl->data; new_probemap[p->order] = new_probenum; srd_dbg("setting probe mapping for %d = probe %d", p->order, new_probenum); } g_free(di->dec_probemap); di->dec_probemap = new_probemap; return SRD_OK; }
static PyObject *Decoder_put(PyObject *self, PyObject *args) { GSList *l; PyObject *data, *py_res; struct srd_decoder_inst *di, *next_di; struct srd_pd_output *pdo; struct srd_proto_data *pdata; uint64_t start_sample, end_sample; int output_id; void (*cb)(); if (!(di = srd_inst_find_by_obj(NULL, self))) { /* Shouldn't happen. */ srd_dbg("put(): self instance not found."); return NULL; } if (!PyArg_ParseTuple(args, "KKiO", &start_sample, &end_sample, &output_id, &data)) { /* * This throws an exception, but by returning NULL here we let * Python raise it. This results in a much better trace in * controller.c on the decode() method call. */ return NULL; } if (!(l = g_slist_nth(di->pd_output, output_id))) { srd_err("Protocol decoder %s submitted invalid output ID %d.", di->decoder->name, output_id); return NULL; } pdo = l->data; srd_spew("Instance %s put %" PRIu64 "-%" PRIu64 " %s on oid %d.", di->inst_id, start_sample, end_sample, OUTPUT_TYPES[pdo->output_type], output_id); if (!(pdata = g_try_malloc0(sizeof(struct srd_proto_data)))) { srd_err("Failed to g_malloc() struct srd_proto_data."); return NULL; } pdata->start_sample = start_sample; pdata->end_sample = end_sample; pdata->pdo = pdo; switch (pdo->output_type) { case SRD_OUTPUT_ANN: /* Annotations are only fed to callbacks. */ if ((cb = srd_pd_output_callback_find(pdo->output_type))) { /* Annotations need converting from PyObject. */ if (convert_pyobj(di, data, &pdata->ann_format, (char ***)&pdata->data) != SRD_OK) { /* An error was already logged. */ break; } cb(pdata); } break; case SRD_OUTPUT_PROTO: for (l = di->next_di; l; l = l->next) { next_di = l->data; /* TODO: Is this needed? */ Py_XINCREF(next_di->py_inst); srd_spew("Sending %d-%d to instance %s", start_sample, end_sample, next_di->inst_id); if (!(py_res = PyObject_CallMethod( next_di->py_inst, "decode", "KKO", start_sample, end_sample, data))) { srd_exception_catch("Calling %s decode(): ", next_di->inst_id); } Py_XDECREF(py_res); } break; case SRD_OUTPUT_BINARY: srd_err("SRD_OUTPUT_BINARY not yet supported."); break; default: srd_err("Protocol decoder %s submitted invalid output type %d.", di->decoder->name, pdo->output_type); break; } g_free(pdata); Py_RETURN_NONE; }
/** * Decode a chunk of samples. * * The calls to this function must provide the samples that shall be * used by the protocol decoder * - in the correct order ([...]5, 6, 4, 7, 8[...] is a bug), * - starting from sample zero (2, 3, 4, 5, 6[...] is a bug), * - consecutively, with no gaps (0, 1, 2, 4, 5[...] is a bug). * * The start- and end-sample numbers are absolute sample numbers (relative * to the start of the whole capture/file/stream), i.e. they are not relative * sample numbers within the chunk specified by 'inbuf' and 'inbuflen'. * * Correct example (4096 samples total, 4 chunks @ 1024 samples each): * srd_inst_decode(di, 0, 1023, inbuf, 1024, 1); * srd_inst_decode(di, 1024, 2047, inbuf, 1024, 1); * srd_inst_decode(di, 2048, 3071, inbuf, 1024, 1); * srd_inst_decode(di, 3072, 4095, inbuf, 1024, 1); * * The chunk size ('inbuflen') can be arbitrary and can differ between calls. * * Correct example (4096 samples total, 7 chunks @ various samples each): * srd_inst_decode(di, 0, 1023, inbuf, 1024, 1); * srd_inst_decode(di, 1024, 1123, inbuf, 100, 1); * srd_inst_decode(di, 1124, 1423, inbuf, 300, 1); * srd_inst_decode(di, 1424, 1642, inbuf, 219, 1); * srd_inst_decode(di, 1643, 2047, inbuf, 405, 1); * srd_inst_decode(di, 2048, 3071, inbuf, 1024, 1); * srd_inst_decode(di, 3072, 4095, inbuf, 1024, 1); * * INCORRECT example (4096 samples total, 4 chunks @ 1024 samples each, but * the start- and end-samplenumbers are not absolute): * srd_inst_decode(di, 0, 1023, inbuf, 1024, 1); * srd_inst_decode(di, 0, 1023, inbuf, 1024, 1); * srd_inst_decode(di, 0, 1023, inbuf, 1024, 1); * srd_inst_decode(di, 0, 1023, inbuf, 1024, 1); * * @param di The decoder instance to call. Must not be NULL. * @param abs_start_samplenum The absolute starting sample number for the * buffer's sample set, relative to the start of capture. * @param abs_end_samplenum The absolute ending sample number for the * buffer's sample set, relative to the start of capture. * @param inbuf The buffer to decode. Must not be NULL. * @param inbuflen Length of the buffer. Must be > 0. * @param unitsize The number of bytes per sample. Must be > 0. * * @return SRD_OK upon success, a (negative) error code otherwise. * * @private */ SRD_PRIV int srd_inst_decode(struct srd_decoder_inst *di, uint64_t abs_start_samplenum, uint64_t abs_end_samplenum, const uint8_t *inbuf, uint64_t inbuflen, uint64_t unitsize) { PyObject *py_res; srd_logic *logic; long apiver; /* Return an error upon unusable input. */ if (!di) { srd_dbg("empty decoder instance"); return SRD_ERR_ARG; } if (!inbuf) { srd_dbg("NULL buffer pointer"); return SRD_ERR_ARG; } if (inbuflen == 0) { srd_dbg("empty buffer"); return SRD_ERR_ARG; } if (unitsize == 0) { srd_dbg("unitsize 0"); return SRD_ERR_ARG; } di->data_unitsize = unitsize; srd_dbg("Decoding: abs start sample %" PRIu64 ", abs end sample %" PRIu64 " (%" PRIu64 " samples, %" PRIu64 " bytes, unitsize = " "%d), instance %s.", abs_start_samplenum, abs_end_samplenum, abs_end_samplenum - abs_start_samplenum, inbuflen, di->data_unitsize, di->inst_id); apiver = srd_decoder_apiver(di->decoder); if (apiver == 2) { /* * Create new srd_logic object. Each iteration around the PD's * loop will fill one sample into this object. */ logic = PyObject_New(srd_logic, (PyTypeObject *)srd_logic_type); Py_INCREF(logic); logic->di = (struct srd_decoder_inst *)di; logic->abs_start_samplenum = abs_start_samplenum; logic->itercnt = 0; logic->inbuf = (uint8_t *)inbuf; logic->inbuflen = inbuflen; logic->sample = PyList_New(2); Py_INCREF(logic->sample); Py_IncRef(di->py_inst); if (!(py_res = PyObject_CallMethod(di->py_inst, "decode", "KKO", abs_start_samplenum, abs_end_samplenum, logic))) { srd_exception_catch("Protocol decoder instance %s", di->inst_id); return SRD_ERR_PYTHON; } Py_DecRef(py_res); } else { /* If this is the first call, start the worker thread. */ if (!di->thread_handle) di->thread_handle = g_thread_new("di_thread", di_thread, di); /* Push the new sample chunk to the worker thread. */ g_mutex_lock(&di->data_mutex); di->abs_start_samplenum = abs_start_samplenum; di->abs_end_samplenum = abs_end_samplenum; di->inbuf = inbuf; di->inbuflen = inbuflen; di->got_new_samples = TRUE; di->handled_all_samples = FALSE; /* Signal the thread that we have new data. */ g_cond_signal(&di->got_new_samples_cond); g_mutex_unlock(&di->data_mutex); /* When all samples in this chunk were handled, return. */ g_mutex_lock(&di->data_mutex); while (!di->handled_all_samples) g_cond_wait(&di->handled_all_samples_cond, &di->data_mutex); g_mutex_unlock(&di->data_mutex); } return SRD_OK; }
/** * Create a new protocol decoder instance. * * @param sess The session holding the protocol decoder instance. * @param decoder_id Decoder 'id' field. * @param options GHashtable of options which override the defaults set in * the decoder class. May be NULL. * * @return Pointer to a newly allocated struct srd_decoder_inst, or * NULL in case of failure. * * @since 0.3.0 */ SRD_API struct srd_decoder_inst *srd_inst_new(struct srd_session *sess, const char *decoder_id, GHashTable *options) { int i; struct srd_decoder *dec; struct srd_decoder_inst *di; char *inst_id; i = 1; srd_dbg("Creating new %s instance.", decoder_id); if (session_is_valid(sess) != SRD_OK) { srd_err("Invalid session."); return NULL; } if (!(dec = srd_decoder_get_by_id(decoder_id))) { srd_err("Protocol decoder %s not found.", decoder_id); return NULL; } di = g_malloc0(sizeof(struct srd_decoder_inst)); di->decoder = dec; di->sess = sess; if (options) { inst_id = g_hash_table_lookup(options, "id"); if (inst_id) di->inst_id = g_strdup(inst_id); g_hash_table_remove(options, "id"); } /* Create a unique instance ID (as none was provided). */ if (!di->inst_id) { di->inst_id = g_strdup_printf("%s-%d", decoder_id, i++); while (srd_inst_find_by_id(sess, di->inst_id)) { g_free(di->inst_id); di->inst_id = g_strdup_printf("%s-%d", decoder_id, i++); } } /* * Prepare a default channel map, where samples come in the * order in which the decoder class defined them. */ di->dec_num_channels = g_slist_length(di->decoder->channels) + g_slist_length(di->decoder->opt_channels); if (di->dec_num_channels) { di->dec_channelmap = g_malloc(sizeof(int) * di->dec_num_channels); for (i = 0; i < di->dec_num_channels; i++) di->dec_channelmap[i] = i; /* * Will be used to prepare a sample at every iteration * of the instance's decode() method. */ di->channel_samples = g_malloc(di->dec_num_channels); } /* Create a new instance of this decoder class. */ if (!(di->py_inst = PyObject_CallObject(dec->py_dec, NULL))) { if (PyErr_Occurred()) srd_exception_catch("Failed to create %s instance", decoder_id); g_free(di->dec_channelmap); g_free(di); return NULL; } if (options && srd_inst_option_set(di, options) != SRD_OK) { g_free(di->dec_channelmap); g_free(di); return NULL; } di->condition_list = NULL; di->match_array = NULL; di->abs_start_samplenum = 0; di->abs_end_samplenum = 0; di->inbuf = NULL; di->inbuflen = 0; di->abs_cur_samplenum = 0; di->old_pins_array = NULL; di->thread_handle = NULL; di->got_new_samples = FALSE; di->handled_all_samples = FALSE; /* Instance takes input from a frontend by default. */ sess->di_list = g_slist_append(sess->di_list, di); srd_dbg("Created new %s instance with ID %s.", decoder_id, di->inst_id); return di; }
/** * Set all probes in a decoder instance. * * This function sets _all_ probes for the specified decoder instance, i.e., * it overwrites any probes that were already defined (if any). * * @param di Decoder instance. * @param new_probes A GHashTable of probes to set. Key is probe name, value is * the probe number. Samples passed to this instance will be * arranged in this order. * * @return SRD_OK upon success, a (negative) error code otherwise. */ SRD_API int srd_inst_probe_set_all(struct srd_decoder_inst *di, GHashTable *new_probes) { GList *l; GSList *sl; struct srd_probe *p; int *new_probemap, new_probenum; char *probe_id, *probenum_str; int i, num_required_probes; srd_dbg("set probes called for instance %s with list of %d probes", di->inst_id, g_hash_table_size(new_probes)); if (g_hash_table_size(new_probes) == 0) /* No probes provided. */ return SRD_OK; if (di->dec_num_probes == 0) { /* Decoder has no probes. */ srd_err("Protocol decoder %s has no probes to define.", di->decoder->name); return SRD_ERR_ARG; } new_probemap = NULL; if (!(new_probemap = g_try_malloc(sizeof(int) * di->dec_num_probes))) { srd_err("Failed to g_malloc() new probe map."); return SRD_ERR_MALLOC; } /* * For now, map all indexes to probe -1 (can be overridden later). * This -1 is interpreted as an unspecified probe later. */ for (i = 0; i < di->dec_num_probes; i++) new_probemap[i] = -1; for (l = g_hash_table_get_keys(new_probes); l; l = l->next) { probe_id = l->data; probenum_str = g_hash_table_lookup(new_probes, probe_id); if (!probenum_str) { /* Probe name was specified without a value. */ srd_err("No probe number was specified for %s.", probe_id); g_free(new_probemap); return SRD_ERR_ARG; } new_probenum = strtol(probenum_str, NULL, 10); if (!(sl = g_slist_find_custom(di->decoder->probes, probe_id, (GCompareFunc)compare_probe_id))) { /* Fall back on optional probes. */ if (!(sl = g_slist_find_custom(di->decoder->opt_probes, probe_id, (GCompareFunc) compare_probe_id))) { srd_err("Protocol decoder %s has no probe " "'%s'.", di->decoder->name, probe_id); g_free(new_probemap); return SRD_ERR_ARG; } } p = sl->data; new_probemap[p->order] = new_probenum; srd_dbg("Setting probe mapping: %s (index %d) = probe %d.", p->id, p->order, new_probenum); } srd_dbg("Final probe map:"); num_required_probes = g_slist_length(di->decoder->probes); for (i = 0; i < di->dec_num_probes; i++) { srd_dbg(" - index %d = probe %d (%s)", i, new_probemap[i], (i < num_required_probes) ? "required" : "optional"); } g_free(di->dec_probemap); di->dec_probemap = new_probemap; return SRD_OK; }
/** * Set one or more options in a decoder instance. * * Handled options are removed from the hash. * * @param di Decoder instance. * @param options A GHashTable of options to set. * * @return SRD_OK upon success, a (negative) error code otherwise. * * @since 0.1.0 */ SRD_API int srd_inst_option_set(struct srd_decoder_inst *di, GHashTable *options) { PyObject *py_dec_options, *py_dec_optkeys, *py_di_options, *py_optval; PyObject *py_optlist, *py_classval; Py_UNICODE *py_ustr; GVariant *value; unsigned long long int val_ull; gint64 val_int; int num_optkeys, ret, size, i; const char *val_str; char *dbg, *key; if (!di) { srd_err("Invalid decoder instance."); return SRD_ERR_ARG; } if (!options) { srd_err("Invalid options GHashTable."); return SRD_ERR_ARG; } if (!PyObject_HasAttrString(di->decoder->py_dec, "options")) { /* Decoder has no options. */ if (g_hash_table_size(options) == 0) { /* No options provided. */ return SRD_OK; } else { srd_err("Protocol decoder has no options."); return SRD_ERR_ARG; } return SRD_OK; } ret = SRD_ERR_PYTHON; key = NULL; py_dec_options = py_dec_optkeys = py_di_options = py_optval = NULL; py_optlist = py_classval = NULL; py_dec_options = PyObject_GetAttrString(di->decoder->py_dec, "options"); /* All of these are synthesized objects, so they're good. */ py_dec_optkeys = PyDict_Keys(py_dec_options); num_optkeys = PyList_Size(py_dec_optkeys); /* * The 'options' dictionary is a class variable, but we need to * change it. Changing it directly will affect the entire class, * so we need to create a new object for it, and populate that * instead. */ if (!(py_di_options = PyObject_GetAttrString(di->py_inst, "options"))) goto err_out; Py_DECREF(py_di_options); py_di_options = PyDict_New(); PyObject_SetAttrString(di->py_inst, "options", py_di_options); for (i = 0; i < num_optkeys; i++) { /* Get the default class value for this option. */ py_str_as_str(PyList_GetItem(py_dec_optkeys, i), &key); if (!(py_optlist = PyDict_GetItemString(py_dec_options, key))) goto err_out; if (!(py_classval = PyList_GetItem(py_optlist, 1))) goto err_out; if (!PyUnicode_Check(py_classval) && !PyLong_Check(py_classval)) { srd_err("Options of type %s are not yet supported.", Py_TYPE(py_classval)->tp_name); goto err_out; } if ((value = g_hash_table_lookup(options, key))) { dbg = g_variant_print(value, TRUE); srd_dbg("got option '%s' = %s", key, dbg); g_free(dbg); /* An override for this option was provided. */ if (PyUnicode_Check(py_classval)) { if (!g_variant_is_of_type(value, G_VARIANT_TYPE_STRING)) { srd_err("Option '%s' requires a string value.", key); goto err_out; } val_str = g_variant_get_string(value, NULL); if (!(py_optval = PyUnicode_FromString(val_str))) { /* Some UTF-8 encoding error. */ PyErr_Clear(); srd_err("Option '%s' requires a UTF-8 string value.", key); goto err_out; } } else if (PyLong_Check(py_classval)) { if (!g_variant_is_of_type(value, G_VARIANT_TYPE_INT64)) { srd_err("Option '%s' requires an integer value.", key); goto err_out; } val_int = g_variant_get_int64(value); if (!(py_optval = PyLong_FromLong(val_int))) { /* ValueError Exception */ PyErr_Clear(); srd_err("Option '%s' has invalid integer value.", key); goto err_out; } } g_hash_table_remove(options, key); } else { /* Use the class default for this option. */ if (PyUnicode_Check(py_classval)) { /* Make a brand new copy of the string. */ py_ustr = PyUnicode_AS_UNICODE(py_classval); size = PyUnicode_GET_SIZE(py_classval); py_optval = PyUnicode_FromUnicode(py_ustr, size); } else if (PyLong_Check(py_classval)) { /* Make a brand new copy of the integer. */ val_ull = PyLong_AsUnsignedLongLong(py_classval); if (val_ull == (unsigned long long)-1) { /* OverFlowError exception */ PyErr_Clear(); srd_err("Invalid integer value for %s: " "expected integer.", key); goto err_out; } if (!(py_optval = PyLong_FromUnsignedLongLong(val_ull))) goto err_out; } } /* * If we got here, py_optval holds a known good new reference * to the instance option to set. */ if (PyDict_SetItemString(py_di_options, key, py_optval) == -1) goto err_out; g_free(key); key = NULL; } ret = SRD_OK; err_out: Py_XDECREF(py_di_options); Py_XDECREF(py_dec_optkeys); Py_XDECREF(py_dec_options); g_free(key); if (PyErr_Occurred()) { srd_exception_catch("Stray exception in srd_inst_option_set()."); ret = SRD_ERR_PYTHON; } return ret; }
static PyObject *Decoder_put(PyObject *self, PyObject *args) { GSList *l; PyObject *py_data, *py_res; struct srd_decoder_inst *di, *next_di; struct srd_pd_output *pdo; struct srd_proto_data *pdata; uint64_t start_sample, end_sample; int output_id; struct srd_pd_callback *cb; if (!(di = srd_inst_find_by_obj(NULL, self))) { /* Shouldn't happen. */ srd_dbg("put(): self instance not found."); return NULL; } if (!PyArg_ParseTuple(args, "KKiO", &start_sample, &end_sample, &output_id, &py_data)) { /* * This throws an exception, but by returning NULL here we let * Python raise it. This results in a much better trace in * controller.c on the decode() method call. */ return NULL; } if (!(l = g_slist_nth(di->pd_output, output_id))) { srd_err("Protocol decoder %s submitted invalid output ID %d.", di->decoder->name, output_id); return NULL; } pdo = l->data; srd_spew("Instance %s put %" PRIu64 "-%" PRIu64 " %s on oid %d.", di->inst_id, start_sample, end_sample, OUTPUT_TYPES[pdo->output_type], output_id); if (!(pdata = g_try_malloc0(sizeof(struct srd_proto_data)))) { srd_err("Failed to g_malloc() struct srd_proto_data."); return NULL; } pdata->start_sample = start_sample; pdata->end_sample = end_sample; pdata->pdo = pdo; switch (pdo->output_type) { case SRD_OUTPUT_ANN: /* Annotations are only fed to callbacks. */ if ((cb = srd_pd_output_callback_find(di->sess, pdo->output_type))) { /* Convert from PyDict to srd_proto_data_annotation. */ if (convert_annotation(di, py_data, pdata) != SRD_OK) { /* An error was already logged. */ break; } cb->cb(pdata, cb->cb_data); } break; case SRD_OUTPUT_PYTHON: for (l = di->next_di; l; l = l->next) { next_di = l->data; srd_spew("Sending %d-%d to instance %s", start_sample, end_sample, next_di->inst_id); if (!(py_res = PyObject_CallMethod( next_di->py_inst, "decode", "KKO", start_sample, end_sample, py_data))) { srd_exception_catch("Calling %s decode(): ", next_di->inst_id); } Py_XDECREF(py_res); } if ((cb = srd_pd_output_callback_find(di->sess, pdo->output_type))) { /* Frontends aren't really supposed to get Python * callbacks, but it's useful for testing. */ pdata->data = py_data; cb->cb(pdata, cb->cb_data); } break; case SRD_OUTPUT_BINARY: if ((cb = srd_pd_output_callback_find(di->sess, pdo->output_type))) { /* Convert from PyDict to srd_proto_data_binary. */ if (convert_binary(di, py_data, pdata) != SRD_OK) { /* An error was already logged. */ break; } cb->cb(pdata, cb->cb_data); } break; case SRD_OUTPUT_META: if ((cb = srd_pd_output_callback_find(di->sess, pdo->output_type))) { /* Annotations need converting from PyObject. */ if (convert_meta(pdata, py_data) != SRD_OK) { /* An exception was already set up. */ break; } cb->cb(pdata, cb->cb_data); } break; default: srd_err("Protocol decoder %s submitted invalid output type %d.", di->decoder->name, pdo->output_type); break; } g_free(pdata); Py_RETURN_NONE; }
static PyObject *Decoder_register(PyObject *self, PyObject *args, PyObject *kwargs) { struct srd_decoder_inst *di; struct srd_pd_output *pdo; PyObject *py_new_output_id; PyTypeObject *meta_type_py; const GVariantType *meta_type_gv; int output_type; char *proto_id, *meta_name, *meta_descr; char *keywords[] = {"output_type", "proto_id", "meta", NULL}; meta_type_py = NULL; meta_type_gv = NULL; meta_name = meta_descr = NULL; if (!(di = srd_inst_find_by_obj(NULL, self))) { PyErr_SetString(PyExc_Exception, "decoder instance not found"); return NULL; } /* Default to instance id, which defaults to class id. */ proto_id = di->inst_id; if (!PyArg_ParseTupleAndKeywords(args, kwargs, "i|s(Oss)", keywords, &output_type, &proto_id, &meta_type_py, &meta_name, &meta_descr)) { /* Let Python raise this exception. */ return NULL; } /* Check if the meta value's type is supported. */ if (output_type == SRD_OUTPUT_META) { if (meta_type_py == &PyLong_Type) meta_type_gv = G_VARIANT_TYPE_INT64; else if (meta_type_py == &PyFloat_Type) meta_type_gv = G_VARIANT_TYPE_DOUBLE; else { PyErr_Format(PyExc_TypeError, "Unsupported type '%s'.", meta_type_py->tp_name); return NULL; } } srd_dbg("Instance %s creating new output type %d for %s.", di->inst_id, output_type, proto_id); if (!(pdo = g_try_malloc(sizeof(struct srd_pd_output)))) { PyErr_SetString(PyExc_MemoryError, "struct srd_pd_output"); return NULL; } /* pdo_id is just a simple index, nothing is deleted from this list anyway. */ pdo->pdo_id = g_slist_length(di->pd_output); pdo->output_type = output_type; pdo->di = di; pdo->proto_id = g_strdup(proto_id); if (output_type == SRD_OUTPUT_META) { pdo->meta_type = meta_type_gv; pdo->meta_name = g_strdup(meta_name); pdo->meta_descr = g_strdup(meta_descr); } di->pd_output = g_slist_append(di->pd_output, pdo); py_new_output_id = Py_BuildValue("i", pdo->pdo_id); return py_new_output_id; }
/** @private */ SRD_PRIV void srd_exception_catch(const char *format, ...) { PyObject *etype, *evalue, *etb, *py_str; PyTracebackObject *py_tb; GString *msg; va_list args; char *ename, *str, *tracestr; if (!PyErr_Occurred()) /* Nothing is wrong. */ return; PyErr_Fetch(&etype, &evalue, &etb); PyErr_NormalizeException(&etype, &evalue, &etb); if (!(py_str = PyObject_Str(evalue))) { /* Shouldn't happen. */ srd_dbg("Failed to convert exception value to string."); return; } /* Send the exception error message(s) to srd_err(). */ if (evalue) ename = (char *)Py_TYPE(evalue)->tp_name; else /* Can be NULL. */ ename = "(unknown exception)"; msg = g_string_sized_new(128); g_string_append(msg, ename); g_string_append(msg, ": "); va_start(args, format); g_string_append_vprintf(msg, format, args); va_end(args); py_str_as_str(py_str, &str); g_string_append(msg, str); Py_DecRef(py_str); srd_err(msg->str); /* Send a more precise error location to srd_dbg(), if we have it. */ if (etb && etb != Py_None) { tracestr = NULL; py_tb = (PyTracebackObject *)etb; py_str = PyUnicode_FromFormat("%U:%d in %U", py_tb->tb_frame->f_code->co_filename, py_tb->tb_frame->f_lineno, py_tb->tb_frame->f_code->co_name); py_str_as_str(py_str, &tracestr); Py_DecRef(py_str); g_string_printf(msg, "%s in %s: %s", ename, tracestr, str); srd_dbg(msg->str); g_free(tracestr); } g_free(str); g_string_free(msg, TRUE); Py_XDECREF(etype); Py_XDECREF(evalue); Py_XDECREF(etb); /* Just in case. */ PyErr_Clear(); }
/** * Replace the current condition list with the new one. * * @param self TODO. Must not be NULL. * @param args TODO. Must not be NULL. * * @retval SRD_OK The new condition list was set successfully. * @retval SRD_ERR There was an error setting the new condition list. * The contents of di->condition_list are undefined. * @retval 9999 TODO. */ static int set_new_condition_list(PyObject *self, PyObject *args) { struct srd_decoder_inst *di; GSList *term_list; PyObject *py_conditionlist, *py_conds, *py_dict; int i, num_conditions, ret; if (!self || !args) return SRD_ERR_ARG; /* Get the decoder instance. */ if (!(di = srd_inst_find_by_obj(NULL, self))) { PyErr_SetString(PyExc_Exception, "decoder instance not found"); return SRD_ERR; } /* * Return an error condition from .wait() when termination is * requested, such that decode() will terminate. */ if (di->want_wait_terminate) { srd_dbg("%s: %s: Skip (want_term).", di->inst_id, __func__); return SRD_ERR; } /* Parse the argument of self.wait() into 'py_conds'. */ if (!PyArg_ParseTuple(args, "O", &py_conds)) { /* Let Python raise this exception. */ return SRD_ERR; } /* Check whether 'py_conds' is a dict or a list. */ if (PyList_Check(py_conds)) { /* 'py_conds' is a list. */ py_conditionlist = py_conds; num_conditions = PyList_Size(py_conditionlist); if (num_conditions == 0) return 9999; /* The PD invoked self.wait([]). */ Py_IncRef(py_conditionlist); } else if (PyDict_Check(py_conds)) { /* 'py_conds' is a dict. */ if (PyDict_Size(py_conds) == 0) return 9999; /* The PD invoked self.wait({}). */ /* Make a list and put the dict in there for convenience. */ py_conditionlist = PyList_New(1); Py_IncRef(py_conds); PyList_SetItem(py_conditionlist, 0, py_conds); num_conditions = 1; } else { srd_err("Condition list is neither a list nor a dict."); return SRD_ERR; } /* Free the old condition list. */ condition_list_free(di); ret = SRD_OK; /* Iterate over the conditions, set di->condition_list accordingly. */ for (i = 0; i < num_conditions; i++) { /* Get a condition (dict) from the condition list. */ py_dict = PyList_GetItem(py_conditionlist, i); if (!PyDict_Check(py_dict)) { srd_err("Condition is not a dict."); ret = SRD_ERR; break; } /* Create the list of terms in this condition. */ if ((ret = create_term_list(py_dict, &term_list)) < 0) break; /* Add the new condition to the PD instance's condition list. */ di->condition_list = g_slist_append(di->condition_list, term_list); } Py_DecRef(py_conditionlist); return ret; }