Example #1
0
/**
 * 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;
}
Example #2
0
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;
}
Example #3
0
/**
 * 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;
}
Example #4
0
/**
 * 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;
}
Example #5
0
/**
 * 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;
}
Example #6
0
/**
 * 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;
}
Example #7
0
/* @private */
SRD_PRIV gboolean srd_check_init(void)
{
	if (max_session_id < 0) {
		srd_err("Library is not initialized.");
		return FALSE;
	} else
		return TRUE;
}
Example #8
0
/**
 * 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;
}
Example #9
0
/** @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);
}
Example #10
0
/**
 * 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;
}
Example #11
0
/**
 * 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;
}
Example #12
0
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;
}
Example #13
0
/**
 * 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;
}
Example #14
0
/**
 * 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;
}
Example #15
0
/**
 * 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;
}
Example #16
0
/**
 * 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;
}
Example #17
0
/**
 * 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;
}
Example #18
0
/**
 * 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;
}
Example #19
0
/**
 * 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;
}
Example #20
0
/**
 * 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;
}
Example #21
0
/**
 * 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;
}
Example #22
0
/**
 * 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;
}
Example #23
0
/**
 * 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);
}
Example #24
0
/** @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;
}
Example #25
0
/** @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;
	}
}
Example #26
0
/**
 * 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;
}
Example #27
0
/* 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;
}
Example #28
0
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;
}
Example #29
0
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;
}
Example #30
0
/**
 * 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;
}