X-Git-Url: https://sigrok.org/gitweb/?p=libsigrokdecode.git;a=blobdiff_plain;f=controller.c;h=2f766651864c2a34f8691797a2beb15b01da0246;hp=2803c6f98f62055af042cf3ea17547e348421e99;hb=3abc83b996547a69bad906ec748f30874aae4796;hpb=2218c267081268865fc90ee607c4c6ced541bfed diff --git a/controller.c b/controller.c index 2803c6f..2f76665 100644 --- a/controller.c +++ b/controller.c @@ -1,5 +1,5 @@ /* - * This file is part of the sigrok project. + * This file is part of the libsigrokdecode project. * * Copyright (C) 2010 Uwe Hermann * Copyright (C) 2012 Bert Vermeulen @@ -18,19 +18,82 @@ * along with this program. If not, see . */ -#include "sigrokdecode.h" /* First, so we avoid a _POSIX_C_SOURCE warning. */ -#include "sigrokdecode-internal.h" +#include "libsigrokdecode.h" /* First, so we avoid a _POSIX_C_SOURCE warning. */ +#include "libsigrokdecode-internal.h" #include "config.h" #include #include #include +/** + * @mainpage libsigrokdecode API + * + * @section sec_intro Introduction + * + * The sigrok project aims at creating a + * portable, cross-platform, Free/Libre/Open-Source signal analysis software + * suite that supports various device types (such as logic analyzers, + * oscilloscopes, multimeters, and more). + * + * libsigrokdecode is a + * shared library written in C which provides the basic API for (streaming) + * protocol decoding functionality. + * + * The protocol decoders + * are written in Python (>= 3.0). + * + * @section sec_api API reference + * + * See the "Modules" page for an introduction to various libsigrokdecode + * related topics and the detailed API documentation of the respective + * functions. + * + * You can also browse the API documentation by file, or review all + * data structures. + * + * @section sec_mailinglists Mailing lists + * + * There are two mailing lists for sigrok/libsigrokdecode: sigrok-devel and sigrok-commits. + * + * @section sec_irc IRC + * + * You can find the sigrok developers in the + * \#sigrok + * IRC channel on Freenode. + * + * @section sec_website Website + * + * sigrok.org/wiki/Libsigrokdecode + */ + +/** + * @file + * + * Initializing and shutting down libsigrokdecode. + */ + +/** + * @defgroup grp_init Initialization + * + * Initializing and shutting down libsigrokdecode. + * + * Before using any of the libsigrokdecode functionality, srd_init() must + * be called to initialize the library. + * + * When libsigrokdecode functionality is no longer needed, srd_exit() should + * be called. + * + * @{ + */ + /* List of decoder instances. */ static GSList *di_list = NULL; /* List of frontend callbacks to receive decoder output. */ static GSList *callbacks = NULL; +/** @cond PRIVATE */ + /* decoder.c */ extern SRD_PRIV GSList *pd_list; @@ -41,16 +104,18 @@ extern PyMODINIT_FUNC PyInit_sigrokdecode(void); /* type_logic.c */ extern SRD_PRIV PyTypeObject srd_logic_type; +/** @endcond */ + /** * 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. + * 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_decoders_list(). + * 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. @@ -59,12 +124,14 @@ extern SRD_PRIV PyTypeObject srd_logic_type; * are not allowed. * * @param path Path to an extra directory containing protocol decoders - * which will be added to the Python sys.path, or NULL. + * 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, 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. + * 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) { @@ -115,6 +182,8 @@ SRD_API int srd_init(const char *path) * any successful srd_init() calls in between, is not allowed. * * @return SRD_OK upon success, a (negative) error code otherwise. + * + * @since 0.1.0 */ SRD_API int srd_exit(void) { @@ -144,6 +213,10 @@ SRD_API int srd_exit(void) * be added to the Python sys.path, or NULL. * * @return SRD_OK upon success, a (negative) error code otherwise. + * + * @private + * + * @since 0.1.0 */ SRD_PRIV int srd_decoder_searchpath_add(const char *path) { @@ -156,10 +229,10 @@ SRD_PRIV int srd_decoder_searchpath_add(const char *path) srd_dbg("Adding '%s' to module path.", path); new_path = g_string_sized_new(256); - g_string_assign(new_path, g_strdup(path)); + g_string_assign(new_path, path); py_cur_path = PySys_GetObject("path"); for (i = 0; i < PyList_Size(py_cur_path); i++) { - g_string_append(new_path, g_strdup(G_SEARCHPATH_SEPARATOR_S)); + g_string_append(new_path, G_SEARCHPATH_SEPARATOR_S); py_item = PyList_GetItem(py_cur_path, i); if (!PyUnicode_Check(py_item)) /* Shouldn't happen. */ @@ -167,6 +240,7 @@ SRD_PRIV int srd_decoder_searchpath_add(const char *path) if (py_str_as_str(py_item, &item) != SRD_OK) continue; g_string_append(new_path, item); + g_free(item); } /* Convert to wide chars. */ @@ -198,6 +272,16 @@ SRD_PRIV int srd_decoder_searchpath_add(const char *path) return SRD_OK; } +/** @} */ + +/** + * @defgroup grp_instances Decoder instances + * + * Decoder instance handling. + * + * @{ + */ + /** * Set one or more options in a decoder instance. * @@ -207,16 +291,21 @@ SRD_PRIV int srd_decoder_searchpath_add(const char *path) * @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) + 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; - char *key, *value; + const char *val_str; + char *dbg, *key; if (!PyObject_HasAttrString(di->decoder->py_dec, "options")) { /* Decoder has no options. */ @@ -255,20 +344,32 @@ SRD_API int srd_inst_option_set(struct srd_decoder_inst *di, } 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 (!(py_optval = PyUnicode_FromString(value))) { + 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 (!(py_optval = PyLong_FromString(value, NULL, 0))) { + 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 value " - "%s: expected integer.", - key, value); + srd_err("Option '%s' has invalid integer value.", key); goto err_out; } } @@ -301,6 +402,7 @@ SRD_API int srd_inst_option_set(struct srd_decoder_inst *di, */ if (PyDict_SetItemString(py_di_options, key, py_optval) == -1) goto err_out; + g_free(key); } ret = SRD_OK; @@ -335,15 +437,18 @@ static gint compare_probe_id(const struct srd_probe *a, const char *probe_id) * 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) + GHashTable *new_probes) { + GVariant *probe_val; GList *l; GSList *sl; struct srd_probe *p; int *new_probemap, new_probenum; - char *probe_id, *probenum_str; + char *probe_id; int i, num_required_probes; srd_dbg("set probes called for instance %s with list of %d probes", @@ -376,22 +481,22 @@ SRD_API int srd_inst_probe_set_all(struct srd_decoder_inst *di, 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_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); + probe_id); g_free(new_probemap); return SRD_ERR_ARG; } - new_probenum = strtol(probenum_str, NULL, 10); + 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); + "'%s'.", di->decoder->name, probe_id); g_free(new_probemap); return SRD_ERR_ARG; } @@ -420,13 +525,15 @@ SRD_API int srd_inst_probe_set_all(struct srd_decoder_inst *di, * * @param decoder_id Decoder 'id' field. * @param options GHashtable of options which override the defaults set in - * the decoder class. + * the decoder class. May be NULL. * * @return Pointer to a newly allocated struct srd_decoder_inst, or * NULL in case of failure. + * + * @since 0.1.0 */ SRD_API struct srd_decoder_inst *srd_inst_new(const char *decoder_id, - GHashTable *options) + GHashTable *options) { int i; struct srd_decoder *dec; @@ -445,10 +552,13 @@ SRD_API struct srd_decoder_inst *srd_inst_new(const char *decoder_id, return NULL; } - inst_id = g_hash_table_lookup(options, "id"); di->decoder = dec; - di->inst_id = g_strdup(inst_id ? inst_id : decoder_id); - g_hash_table_remove(options, "id"); + 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 @@ -477,7 +587,7 @@ SRD_API struct srd_decoder_inst *srd_inst_new(const char *decoder_id, return NULL; } - if (srd_inst_option_set(di, options) != SRD_OK) { + if (options && srd_inst_option_set(di, options) != SRD_OK) { g_free(di->dec_probemap); g_free(di); return NULL; @@ -496,9 +606,11 @@ SRD_API struct srd_decoder_inst *srd_inst_new(const char *decoder_id, * @param di_to The instance on top of which di_from will be stacked. * * @return SRD_OK upon success, a (negative) error code otherwise. + * + * @since 0.1.0 */ SRD_API int srd_inst_stack(struct srd_decoder_inst *di_from, - struct srd_decoder_inst *di_to) + struct srd_decoder_inst *di_to) { if (!di_from || !di_to) { srd_err("Invalid from/to instance pair."); @@ -525,6 +637,8 @@ SRD_API int srd_inst_stack(struct srd_decoder_inst *di_from, * @param inst_id The instance ID to be found. * * @return Pointer to struct srd_decoder_inst, or NULL if not found. + * + * @since 0.1.0 */ SRD_API struct srd_decoder_inst *srd_inst_find_by_id(const char *inst_id) { @@ -555,11 +669,14 @@ SRD_API struct srd_decoder_inst *srd_inst_find_by_id(const char *inst_id) * @param obj The Python class instantiation. * * @return Pointer to struct srd_decoder_inst, or NULL if not found. + * + * @private + * + * @since 0.1.0 */ SRD_PRIV struct srd_decoder_inst *srd_inst_find_by_obj(const GSList *stack, - const PyObject *obj) + const PyObject *obj) { -// TODO? const GSList *l; struct srd_decoder_inst *tmp, *di; @@ -575,6 +692,7 @@ SRD_PRIV struct srd_decoder_inst *srd_inst_find_by_obj(const GSList *stack, return di; } +/** @private */ SRD_PRIV int srd_inst_start(struct srd_decoder_inst *di, PyObject *args) { PyObject *py_name, *py_res; @@ -624,10 +742,14 @@ SRD_PRIV int srd_inst_start(struct srd_decoder_inst *di, PyObject *args) * @param inbuflen Length of the buffer. Must be > 0. * * @return SRD_OK upon success, a (negative) error code otherwise. + * + * @private + * + * @since 0.1.0 */ SRD_PRIV int srd_inst_decode(uint64_t start_samplenum, - const struct srd_decoder_inst *di, - const uint8_t *inbuf, uint64_t inbuflen) + const struct srd_decoder_inst *di, const uint8_t *inbuf, + uint64_t inbuflen) { PyObject *py_res; srd_logic *logic; @@ -671,13 +793,14 @@ SRD_PRIV int srd_inst_decode(uint64_t start_samplenum, end_samplenum, logic))) { srd_exception_catch("Protocol decoder instance %s: ", di->inst_id); - return SRD_ERR_PYTHON; /* TODO: More specific error? */ + return SRD_ERR_PYTHON; } Py_DecRef(py_res); return SRD_OK; } +/** @private */ SRD_PRIV void srd_inst_free(struct srd_decoder_inst *di) { GSList *l; @@ -695,8 +818,10 @@ SRD_PRIV void srd_inst_free(struct srd_decoder_inst *di) g_free(pdo); } g_slist_free(di->pd_output); + g_free(di); } +/** @private */ SRD_PRIV void srd_inst_free_all(GSList *stack) { GSList *l; @@ -715,6 +840,16 @@ SRD_PRIV void srd_inst_free_all(GSList *stack) } } +/** @} */ + +/** + * @defgroup grp_session Session handling + * + * Starting and handling decoding sessions. + * + * @{ + */ + /** * Start a decoding session. * @@ -725,6 +860,8 @@ SRD_PRIV void srd_inst_free_all(GSList *stack) * @param samplerate The samplerate of the incoming feed. * * @return SRD_OK upon success, a (negative) error code otherwise. + * + * @since 0.1.0 */ SRD_API int srd_session_start(int num_probes, int unitsize, uint64_t samplerate) { @@ -770,9 +907,11 @@ SRD_API int srd_session_start(int num_probes, int unitsize, uint64_t samplerate) * @param inbuflen Length in bytes of the buffer. * * @return SRD_OK upon success, a (negative) error code otherwise. + * + * @since 0.1.0 */ SRD_API int srd_session_send(uint64_t start_samplenum, const uint8_t *inbuf, - uint64_t inbuflen) + uint64_t inbuflen) { GSList *d; int ret; @@ -801,9 +940,11 @@ SRD_API int srd_session_send(uint64_t start_samplenum, const uint8_t *inbuf, * 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.1.0 */ SRD_API int srd_pd_output_callback_add(int output_type, - srd_pd_output_callback_t cb, void *cb_data) + srd_pd_output_callback_t cb, void *cb_data) { struct srd_pd_callback *pd_cb; @@ -822,6 +963,7 @@ SRD_API int srd_pd_output_callback_add(int output_type, return SRD_OK; } +/** @private */ SRD_PRIV void *srd_pd_output_callback_find(int output_type) { GSList *l; @@ -841,6 +983,7 @@ SRD_PRIV void *srd_pd_output_callback_find(int output_type) } /* This is the backend function to Python sigrokdecode.add() call. */ +/** @private */ SRD_PRIV int srd_inst_pd_output_add(struct srd_decoder_inst *di, int output_type, const char *proto_id) { @@ -863,3 +1006,5 @@ SRD_PRIV int srd_inst_pd_output_add(struct srd_decoder_inst *di, return pdo->pdo_id; } + +/** @} */