/** * Stack a decoder instance on top of another. * * @param sess The session holding the protocol decoder instances. * @param di_bottom The instance on top of which di_top will be stacked. * @param di_top The instance to go on top. * * @return SRD_OK upon success, a (negative) error code otherwise. * * @since 0.3.0 */ SRD_API int srd_inst_stack(struct srd_session *sess, struct srd_decoder_inst *di_bottom, struct srd_decoder_inst *di_top) { if (session_is_valid(sess) != SRD_OK) { srd_err("Invalid session."); return SRD_ERR_ARG; } if (!di_bottom || !di_top) { srd_err("Invalid from/to instance pair."); return SRD_ERR_ARG; } if (g_slist_find(sess->di_list, di_top)) { /* Remove from the unstacked list. */ sess->di_list = g_slist_remove(sess->di_list, di_top); } /* Stack on top of source di. */ di_bottom->next_di = g_slist_append(di_bottom->next_di, di_top); srd_dbg("Stacked %s on top of %s.", di_top->inst_id, di_bottom->inst_id); return SRD_OK; }
static int get_probes(const struct srd_decoder *d, const char *attr, GSList **pl) { PyObject *py_probelist, *py_entry; struct srd_probe *p; int ret, num_probes, i; if (!PyObject_HasAttrString(d->py_dec, attr)) /* No probes of this type specified. */ return SRD_OK; ret = SRD_ERR_PYTHON; py_probelist = py_entry = NULL; py_probelist = PyObject_GetAttrString(d->py_dec, attr); if (!PyList_Check(py_probelist)) { srd_err("Protocol decoder %s %s attribute is not " "a list.", d->name, attr); goto err_out; } num_probes = PyList_Size(py_probelist); if (num_probes == 0) /* Empty probelist. */ return SRD_OK; for (i = 0; i < num_probes; i++) { py_entry = PyList_GetItem(py_probelist, i); if (!PyDict_Check(py_entry)) { srd_err("Protocol decoder %s %s attribute is not " "a list with dict elements.", d->name, attr); goto err_out; } if (!(p = g_try_malloc(sizeof(struct srd_probe)))) { srd_err("Failed to g_malloc() struct srd_probe."); ret = SRD_ERR_MALLOC; goto err_out; } if ((py_dictitem_as_str(py_entry, "id", &p->id)) != SRD_OK) goto err_out; if ((py_dictitem_as_str(py_entry, "name", &p->name)) != SRD_OK) goto err_out; if ((py_dictitem_as_str(py_entry, "desc", &p->desc)) != SRD_OK) goto err_out; p->order = i; *pl = g_slist_append(*pl, p); } ret = SRD_OK; err_out: Py_DecRef(py_entry); Py_DecRef(py_probelist); return ret; }
/** * Create a list of terms in the specified condition. * * If there are no terms in the condition, 'term_list' will be NULL. * * @param py_dict A Python dict containing terms. Must not be NULL. * @param term_list Pointer to a GSList which will be set to the newly * created list of terms. Must not be NULL. * * @return SRD_OK upon success, a negative error code otherwise. */ static int create_term_list(PyObject *py_dict, GSList **term_list) { Py_ssize_t pos = 0; PyObject *py_key, *py_value; struct srd_term *term; uint64_t num_samples_to_skip; char *term_str; if (!py_dict || !term_list) return SRD_ERR_ARG; /* "Create" an empty GSList of terms. */ *term_list = NULL; /* Iterate over all items in the current dict. */ while (PyDict_Next(py_dict, &pos, &py_key, &py_value)) { /* Check whether the current key is a string or a number. */ if (PyLong_Check(py_key)) { /* The key is a number. */ /* TODO: Check if the number is a valid channel. */ /* Get the value string. */ if ((py_pydictitem_as_str(py_dict, py_key, &term_str)) != SRD_OK) { srd_err("Failed to get the value."); return SRD_ERR; } term = g_malloc0(sizeof(struct srd_term)); term->type = get_term_type(term_str); term->channel = PyLong_AsLong(py_key); g_free(term_str); } else if (PyUnicode_Check(py_key)) { /* The key is a string. */ /* TODO: Check if it's "skip". */ if ((py_pydictitem_as_long(py_dict, py_key, &num_samples_to_skip)) != SRD_OK) { srd_err("Failed to get number of samples to skip."); return SRD_ERR; } term = g_malloc0(sizeof(struct srd_term)); term->type = SRD_TERM_SKIP; term->num_samples_to_skip = num_samples_to_skip; term->num_samples_already_skipped = 0; } else { srd_err("Term key is neither a string nor a number."); return SRD_ERR; } /* Add the term to the list of terms. */ *term_list = g_slist_append(*term_list, term); } return SRD_OK; }
/** * Convert a Python list of unicode strings to a NULL-terminated UTF8-encoded * char * array. The caller must g_free() each string when finished. * * @param py_strlist The list object. * @param outstr ptr to char ** storage to be filled in. * * @return SRD_OK upon success, a (negative) error code otherwise. * The 'outstr' argument points to a g_malloc()ed char** upon success. * * @private */ SRD_PRIV int py_strseq_to_char(const PyObject *py_strseq, char ***outstr) { PyObject *py_str; int list_len, i; char **out, *str; list_len = PySequence_Size((PyObject *)py_strseq); if (!(out = g_try_malloc(sizeof(char *) * (list_len + 1)))) { srd_err("Failed to g_malloc() 'out'."); return SRD_ERR_MALLOC; } for (i = 0; i < list_len; i++) { if (!(py_str = PyUnicode_AsEncodedString( PySequence_GetItem((PyObject *)py_strseq, i), "utf-8", NULL))) return SRD_ERR_PYTHON; if (!(str = PyBytes_AS_STRING(py_str))) return SRD_ERR_PYTHON; out[i] = g_strdup(str); Py_DECREF(py_str); } out[i] = NULL; *outstr = out; return SRD_OK; }
/** * Start a decoding session. * * Decoders, instances and stack must have been prepared beforehand. * * @param num_probes The number of probes which the incoming feed will contain. * @param unitsize The number of bytes per sample in the incoming feed. * @param samplerate The samplerate of the incoming feed. * * @return SRD_OK upon success, a (negative) error code otherwise. */ SRD_API int srd_session_start(int num_probes, int unitsize, uint64_t samplerate) { PyObject *args; GSList *d; struct srd_decoder_inst *di; int ret; srd_dbg("Calling start() on all instances with %d probes, " "unitsize %d samplerate %d.", num_probes, unitsize, samplerate); /* * Currently only one item of metadata is passed along to decoders, * samplerate. This can be extended as needed. */ if (!(args = Py_BuildValue("{s:l}", "samplerate", (long)samplerate))) { srd_err("Unable to build Python object for metadata."); return SRD_ERR_PYTHON; } /* Run the start() method on all decoders receiving frontend data. */ for (d = di_list; d; d = d->next) { di = d->data; di->data_num_probes = num_probes; di->data_unitsize = unitsize; di->data_samplerate = samplerate; if ((ret = srd_inst_start(di, args) != SRD_OK)) break; } Py_DecRef(args); return ret; }
/** * Get the pin values at the current sample number. * * @param di The decoder instance to use. Must not be NULL. * The number of channels must be >= 1. * * @return A newly allocated PyTuple containing the pin values at the * current sample number. */ static PyObject *get_current_pinvalues(const struct srd_decoder_inst *di) { int i; uint8_t sample; const uint8_t *sample_pos; int byte_offset, bit_offset; PyObject *py_pinvalues; if (!di) { srd_err("Invalid decoder instance."); return NULL; } py_pinvalues = PyTuple_New(di->dec_num_channels); for (i = 0; i < di->dec_num_channels; i++) { /* 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)); } 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)); } } return py_pinvalues; }
/* @private */ SRD_PRIV gboolean srd_check_init(void) { if (max_session_id < 0) { srd_err("Library is not initialized."); return FALSE; } else return TRUE; }
/** * Set a metadata configuration key in a session. * * @param sess The session to configure. * @param key The configuration key (SRD_CONF_*). * @param data The new value for the key, as a GVariant with GVariantType * appropriate to that key. A floating reference can be passed * in; its refcount will be sunk and unreferenced after use. * * @return SRD_OK upon success, a (negative) error code otherwise. * * @since 0.3.0 */ SRD_API int srd_session_metadata_set(struct srd_session *sess, int key, GVariant *data) { GSList *l; int ret; if (session_is_valid(sess) != SRD_OK) { srd_err("Invalid session."); return SRD_ERR_ARG; } if (!key) { srd_err("Invalid key."); return SRD_ERR_ARG; } if (!data) { srd_err("Invalid value."); return SRD_ERR_ARG; } /* Hardcoded to samplerate/uint64 for now. */ if (key != SRD_CONF_SAMPLERATE) { srd_err("Unknown config key %d.", key); return SRD_ERR_ARG; } if (!g_variant_is_of_type(data, G_VARIANT_TYPE_UINT64)) { srd_err("Invalid value type: expected uint64, got %s", g_variant_get_type_string(data)); return SRD_ERR_ARG; } srd_dbg("Setting session %d samplerate to %"PRIu64".", sess->session_id, g_variant_get_uint64(data)); ret = SRD_OK; for (l = sess->di_list; l; l = l->next) { if ((ret = srd_inst_send_meta(l->data, key, data)) != SRD_OK) break; } g_variant_unref(data); return ret; }
/** @private */ SRD_PRIV void srd_inst_free_all(struct srd_session *sess) { if (session_is_valid(sess) != SRD_OK) { srd_err("Invalid session."); return; } g_slist_free_full(sess->di_list, (GDestroyNotify)srd_inst_free); }
/** * Set the libsigrokdecode loglevel. * * This influences the amount of log messages (debug messages, error messages, * and so on) libsigrokdecode will output. Using SRD_LOG_NONE disables all * messages. * * Note that this function itself will also output log messages. After the * loglevel has changed, it will output a debug message with SRD_LOG_DBG for * example. Whether this message is shown depends on the (new) loglevel. * * @param loglevel The loglevel to set (SRD_LOG_NONE, SRD_LOG_ERR, * SRD_LOG_WARN, SRD_LOG_INFO, SRD_LOG_DBG, or SRD_LOG_SPEW). * * @return SRD_OK upon success, SRD_ERR_ARG upon invalid loglevel. * * @since 0.1.0 */ SRD_API int srd_log_loglevel_set(int loglevel) { if (loglevel < SRD_LOG_NONE || loglevel > SRD_LOG_SPEW) { srd_err("Invalid loglevel %d.", loglevel); return SRD_ERR_ARG; } cur_loglevel = loglevel; srd_dbg("libsigrokdecode loglevel set to %d.", loglevel); return SRD_OK; }
/** * Set the libsigrokdecode log callback to the specified function. * * @param cb Function pointer to the log callback function to use. * Must not be NULL. * @param cb_data Pointer to private data to be passed on. This can be used * by the caller to pass arbitrary data to the log functions. * This pointer is only stored or passed on by libsigrokdecode, * and is never used or interpreted in any way. The pointer * is allowed to be NULL if the caller doesn't need/want to * pass any data. * * @return SRD_OK upon success, SRD_ERR_ARG upon invalid arguments. * * @since 0.3.0 */ SRD_API int srd_log_callback_set(srd_log_callback cb, void *cb_data) { if (!cb) { srd_err("log: %s: cb was NULL", __func__); return SRD_ERR_ARG; } /* Note: 'cb_data' is allowed to be NULL. */ srd_log_cb = cb; srd_log_cb_data = cb_data; return SRD_OK; }
static int convert_pyobj(struct srd_decoder_inst *di, PyObject *obj, int *ann_format, char ***ann) { PyObject *py_tmp; struct srd_pd_output *pdo; int ann_id; /* Should be a list of [annotation format, [string, ...]]. */ if (!PyList_Check(obj) && !PyTuple_Check(obj)) { srd_err("Protocol decoder %s submitted %s instead of list.", di->decoder->name, obj->ob_type->tp_name); return SRD_ERR_PYTHON; } /* Should have 2 elements. */ if (PyList_Size(obj) != 2) { srd_err("Protocol decoder %s submitted annotation list with " "%d elements instead of 2", di->decoder->name, PyList_Size(obj)); return SRD_ERR_PYTHON; } /* * The first element should be an integer matching a previously * registered annotation format. */ py_tmp = PyList_GetItem(obj, 0); if (!PyLong_Check(py_tmp)) { srd_err("Protocol decoder %s submitted annotation list, but " "first element was not an integer.", di->decoder->name); return SRD_ERR_PYTHON; } ann_id = PyLong_AsLong(py_tmp); if (!(pdo = g_slist_nth_data(di->decoder->annotations, ann_id))) { srd_err("Protocol decoder %s submitted data to unregistered " "annotation format %d.", di->decoder->name, ann_id); return SRD_ERR_PYTHON; } *ann_format = ann_id; /* Second element must be a list. */ py_tmp = PyList_GetItem(obj, 1); if (!PyList_Check(py_tmp)) { srd_err("Protocol decoder %s submitted annotation list, but " "second element was not a list.", di->decoder->name); return SRD_ERR_PYTHON; } if (py_strlist_to_char(py_tmp, ann) != SRD_OK) { srd_err("Protocol decoder %s submitted annotation list, but " "second element was malformed.", di->decoder->name); return SRD_ERR_PYTHON; } return SRD_OK; }
/** * Stack a decoder instance on top of another. * * @param di_from The instance to move. * @param di_to The instance on top of which di_from will be stacked. * * @return SRD_OK upon success, a (negative) error code otherwise. */ SRD_API int srd_inst_stack(struct srd_decoder_inst *di_from, struct srd_decoder_inst *di_to) { if (!di_from || !di_to) { srd_err("Invalid from/to instance pair."); return SRD_ERR_ARG; } if (g_slist_find(di_list, di_to)) { /* Remove from the unstacked list. */ di_list = g_slist_remove(di_list, di_to); } /* Stack on top of source di. */ di_from->next_di = g_slist_append(di_from->next_di, di_to); return SRD_OK; }
/** * 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) { int ret; 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_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; } } max_session_id = 0; return SRD_OK; }
/** * Register/add a decoder output callback function. * * The function will be called when a protocol decoder sends output back * to the PD controller (except for Python objects, which only go up the * stack). * * @param output_type The output type this callback will receive. Only one * callback per output type can be registered. * @param cb The function to call. Must not be NULL. * @param cb_data Private data for the callback function. Can be NULL. */ SRD_API int srd_pd_output_callback_add(int output_type, srd_pd_output_callback_t cb, void *cb_data) { struct srd_pd_callback *pd_cb; srd_dbg("Registering new callback for output type %d.", output_type); if (!(pd_cb = g_try_malloc(sizeof(struct srd_pd_callback)))) { srd_err("Failed to g_malloc() struct srd_pd_callback."); return SRD_ERR_MALLOC; } pd_cb->output_type = output_type; pd_cb->cb = cb; pd_cb->cb_data = cb_data; callbacks = g_slist_append(callbacks, pd_cb); return SRD_OK; }
/** * Create a decoding session. * * A session holds all decoder instances, their stack relationships and * output callbacks. * * @param sess A pointer which will hold a pointer to a newly * initialized session on return. * * @return SRD_OK upon success, a (negative) error code otherwise. * * @since 0.3.0 */ SRD_API int srd_session_new(struct srd_session **sess) { if (!sess) { srd_err("Invalid session pointer."); return SRD_ERR_ARG; } *sess = g_malloc(sizeof(struct srd_session)); (*sess)->session_id = ++max_session_id; (*sess)->di_list = (*sess)->callbacks = NULL; /* Keep a list of all sessions, so we can clean up as needed. */ sessions = g_slist_append(sessions, *sess); srd_dbg("Created session %d.", (*sess)->session_id); return SRD_OK; }
/** * Load all installed protocol decoders. * * @return SRD_OK upon success, a (negative) error code otherwise. */ SRD_API int srd_decoder_load_all(void) { GDir *dir; GError *error; const gchar *direntry; if (!(dir = g_dir_open(DECODERS_DIR, 0, &error))) { srd_err("Unable to open %s for reading.", DECODERS_DIR); return SRD_ERR_DECODERS_DIR; } while ((direntry = g_dir_read_name(dir)) != NULL) { /* The directory name is the module name (e.g. "i2c"). */ srd_decoder_load(direntry); } g_dir_close(dir); return SRD_OK; }
/** * Check whether the specified sample matches the specified term. * * In the case of SRD_TERM_SKIP, this function can modify * term->num_samples_already_skipped. * * @param old_sample The value of the previous sample (0/1). * @param sample The value of the current sample (0/1). * @param term The term that should be checked for a match. Must not be NULL. * * @retval TRUE The current sample matches the specified term. * @retval FALSE The current sample doesn't match the specified term, or an * invalid term was provided. * * @private */ static gboolean sample_matches(uint8_t old_sample, uint8_t sample, struct srd_term *term) { if (!term) return FALSE; switch (term->type) { case SRD_TERM_HIGH: if (sample == 1) return TRUE; break; case SRD_TERM_LOW: if (sample == 0) return TRUE; break; case SRD_TERM_RISING_EDGE: if (old_sample == 0 && sample == 1) return TRUE; break; case SRD_TERM_FALLING_EDGE: if (old_sample == 1 && sample == 0) return TRUE; break; case SRD_TERM_EITHER_EDGE: if ((old_sample == 1 && sample == 0) || (old_sample == 0 && sample == 1)) return TRUE; break; case SRD_TERM_NO_EDGE: if ((old_sample == 0 && sample == 0) || (old_sample == 1 && sample == 1)) return TRUE; break; case SRD_TERM_SKIP: if (term->num_samples_already_skipped == term->num_samples_to_skip) return TRUE; term->num_samples_already_skipped++; break; default: srd_err("Unknown term type %d.", term->type); break; } return FALSE; }
/** * Register/add a decoder output callback function. * * The function will be called when a protocol decoder sends output back * to the PD controller (except for Python objects, which only go up the * stack). * * @param sess The output session in which to register the callback. * @param output_type The output type this callback will receive. Only one * callback per output type can be registered. * @param cb The function to call. Must not be NULL. * @param cb_data Private data for the callback function. Can be NULL. * * @since 0.3.0 */ SRD_API int srd_pd_output_callback_add(struct srd_session *sess, int output_type, srd_pd_output_callback cb, void *cb_data) { struct srd_pd_callback *pd_cb; if (session_is_valid(sess) != SRD_OK) { srd_err("Invalid session."); return SRD_ERR_ARG; } srd_dbg("Registering new callback for output type %d.", output_type); pd_cb = g_malloc(sizeof(struct srd_pd_callback)); pd_cb->output_type = output_type; pd_cb->cb = cb; pd_cb->cb_data = cb_data; sess->callbacks = g_slist_append(sess->callbacks, pd_cb); 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 'unitsize' bytes. 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. * @param unitsize The number of bytes per sample. * * @return SRD_OK upon success, a (negative) error code otherwise. * * @since 0.4.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, uint64_t unitsize) { GSList *d; int ret; if (session_is_valid(sess) != SRD_OK) { srd_err("Invalid session."); return SRD_ERR_ARG; } for (d = sess->di_list; d; d = d->next) { if ((ret = srd_inst_decode(d->data, start_samplenum, end_samplenum, inbuf, inbuflen, unitsize)) != SRD_OK) return ret; } return SRD_OK; }
/** * Find a decoder instance by its instance ID. * * This will recurse to find the instance anywhere in the stack tree of the * given session. * * @param sess The session holding the protocol decoder instance. * @param inst_id The instance ID to be found. * * @return Pointer to struct srd_decoder_inst, or NULL if not found. * * @since 0.3.0 */ SRD_API struct srd_decoder_inst *srd_inst_find_by_id(struct srd_session *sess, const char *inst_id) { GSList *l; struct srd_decoder_inst *tmp, *di; if (session_is_valid(sess) != SRD_OK) { srd_err("Invalid session."); return NULL; } di = NULL; for (l = sess->di_list; l; l = l->next) { tmp = l->data; if ((di = srd_inst_find_by_id_stack(inst_id, tmp)) != NULL) break; } return di; }
/** * Destroy a decoding session. * * All decoder instances and output callbacks are properly released. * * @param sess The session to be destroyed. * * @return SRD_OK upon success, a (negative) error code otherwise. * * @since 0.3.0 */ SRD_API int srd_session_destroy(struct srd_session *sess) { int session_id; if (!sess) { srd_err("Invalid session."); return SRD_ERR_ARG; } session_id = sess->session_id; if (sess->di_list) srd_inst_free_all(sess, NULL); if (sess->callbacks) g_slist_free_full(sess->callbacks, g_free); sessions = g_slist_remove(sessions, sess); g_free(sess); srd_dbg("Destroyed session %d.", session_id); return SRD_OK; }
/** * Set the list of initial (assumed) pin values. * * If the list already exists, do nothing. * * @param di Decoder instance to use. Must not be NULL. * * @private */ static void set_initial_pin_values(struct srd_decoder_inst *di) { int i; GString *s; PyObject *py_initial_pins; if (!di || !di->py_inst) { srd_err("Invalid decoder instance."); return; } /* Nothing to do if di->old_pins_array is already != NULL. */ if (di->old_pins_array) { srd_dbg("Initial pins already set, nothing to do."); return; } /* Create an array of old (previous sample) pins, init to 0. */ di->old_pins_array = g_array_sized_new(FALSE, TRUE, sizeof(uint8_t), di->dec_num_channels); g_array_set_size(di->old_pins_array, di->dec_num_channels); /* Check if the decoder has set self.initial_pins. */ if (!PyObject_HasAttrString(di->py_inst, "initial_pins")) { srd_dbg("Initial pins: all 0 (self.initial_pins not set)."); return; } /* Get self.initial_pins. */ py_initial_pins = PyObject_GetAttrString(di->py_inst, "initial_pins"); /* Fill di->old_pins_array based on self.initial_pins. */ s = g_string_sized_new(100); for (i = 0; i < di->dec_num_channels; i++) { di->old_pins_array->data[i] = PyLong_AsLong(PyList_GetItem(py_initial_pins, i)); g_string_append_printf(s, "%d, ", di->old_pins_array->data[i]); } s = g_string_truncate(s, s->len - 2); srd_dbg("Initial pins: %s.", s->str); g_string_free(s, TRUE); }
/** @private */ SRD_PRIV struct srd_pd_callback *srd_pd_output_callback_find( struct srd_session *sess, int output_type) { GSList *l; struct srd_pd_callback *tmp, *pd_cb; if (session_is_valid(sess) != SRD_OK) { srd_err("Invalid session."); return NULL; } pd_cb = NULL; for (l = sess->callbacks; l; l = l->next) { tmp = l->data; if (tmp->output_type == output_type) { pd_cb = tmp; break; } } return pd_cb; }
/** @private */ SRD_PRIV void srd_inst_free_all(struct srd_session *sess, GSList *stack) { GSList *l; struct srd_decoder_inst *di; if (session_is_valid(sess) != SRD_OK) { srd_err("Invalid session."); return; } di = NULL; for (l = stack ? stack : sess->di_list; di == NULL && l != NULL; l = l->next) { di = l->data; if (di->next_di) srd_inst_free_all(sess, di->next_di); srd_inst_free(di); } if (!stack) { g_slist_free(sess->di_list); sess->di_list = NULL; } }
/** * Find a decoder instance by its instance ID. * * Only the bottom level of instances are searched -- instances already stacked * on top of another one will not be found. * * @param sess The session holding the protocol decoder instance. * @param inst_id The instance ID to be found. * * @return Pointer to struct srd_decoder_inst, or NULL if not found. * * @since 0.3.0 */ SRD_API struct srd_decoder_inst *srd_inst_find_by_id(struct srd_session *sess, const char *inst_id) { GSList *l; struct srd_decoder_inst *tmp, *di; if (session_is_valid(sess) != SRD_OK) { srd_err("Invalid session."); return NULL; } di = NULL; for (l = sess->di_list; l; l = l->next) { tmp = l->data; if (!strcmp(tmp->inst_id, inst_id)) { di = tmp; break; } } return di; }
/* This is the backend function to Python sigrokdecode.add() call. */ SRD_PRIV int srd_inst_pd_output_add(struct srd_decoder_inst *di, int output_type, const char *proto_id) { struct srd_pd_output *pdo; 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)))) { srd_err("Failed to g_malloc() struct srd_pd_output."); return -1; } /* 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); di->pd_output = g_slist_append(di->pd_output, pdo); return pdo->pdo_id; }
SRD_PRIV int srd_inst_start(struct srd_decoder_inst *di, PyObject *args) { PyObject *py_name, *py_res; GSList *l; struct srd_decoder_inst *next_di; srd_dbg("Calling start() method on protocol decoder instance %s.", di->inst_id); if (!(py_name = PyUnicode_FromString("start"))) { srd_err("Unable to build Python object for 'start'."); srd_exception_catch("Protocol decoder instance %s: ", di->inst_id); return SRD_ERR_PYTHON; } if (!(py_res = PyObject_CallMethodObjArgs(di->py_inst, py_name, args, NULL))) { srd_exception_catch("Protocol decoder instance %s: ", di->inst_id); return SRD_ERR_PYTHON; } Py_DecRef(py_res); Py_DecRef(py_name); /* * Start all the PDs stacked on top of this one. Pass along the * metadata all the way from the bottom PD, even though it's only * applicable to logic data for now. */ for (l = di->next_di; l; l = l->next) { next_di = l->data; srd_inst_start(next_di, args); } return SRD_OK; }
static struct srd_decoder_inst *srd_sess_inst_find_by_obj( struct srd_session *sess, const GSList *stack, const PyObject *obj) { const GSList *l; struct srd_decoder_inst *tmp, *di; if (session_is_valid(sess) != SRD_OK) { srd_err("Invalid session."); return NULL; } di = NULL; for (l = stack ? stack : sess->di_list; di == NULL && l != NULL; l = l->next) { tmp = l->data; if (tmp->py_inst == obj) di = tmp; else if (tmp->next_di) di = srd_sess_inst_find_by_obj(sess, tmp->next_di, obj); } return di; }
/** * Start a decoding session. * * Decoders, instances and stack must have been prepared beforehand, * and all SRD_CONF parameters set. * * @param sess The session to start. * * @return SRD_OK upon success, a (negative) error code otherwise. * * @since 0.3.0 */ SRD_API int srd_session_start(struct srd_session *sess) { GSList *d; struct srd_decoder_inst *di; int ret; if (session_is_valid(sess) != SRD_OK) { srd_err("Invalid session pointer."); return SRD_ERR; } srd_dbg("Calling start() on all instances in session %d.", sess->session_id); /* Run the start() method on all decoders receiving frontend data. */ ret = SRD_OK; for (d = sess->di_list; d; d = d->next) { di = d->data; if ((ret = srd_inst_start(di)) != SRD_OK) break; } return ret; }