X-Git-Url: http://sigrok.org/gitweb/?a=blobdiff_plain;f=session.c;h=0c379c50259fc3802564377107fc02cd5c9bb454;hb=c2fa697afa86a8e6f37bef13acb5b8532714274e;hp=acf1158b4e3ad0e75061c4aa9ab831f5c5aadbd1;hpb=33c6e4c5a428115965f980e88e6415fb782658e9;p=libsigrok.git diff --git a/session.c b/session.c index acf1158b..0c379c50 100644 --- a/session.c +++ b/session.c @@ -1,5 +1,5 @@ /* - * This file is part of the sigrok project. + * This file is part of the libsigrok project. * * Copyright (C) 2010-2012 Bert Vermeulen * @@ -59,6 +59,11 @@ struct source { gintptr poll_object; }; +struct datafeed_callback { + sr_datafeed_callback_t cb; + void *cb_data; +}; + /* There can only be one session at a time. */ /* 'session' is not static, it's used elsewhere (via 'extern'). */ struct sr_session *session; @@ -111,48 +116,6 @@ SR_API int sr_session_destroy(void) return SR_OK; } -/** - * Close a device instance. - * - * @param sdi The device instance to close. Must not be NULL. Also, - * sdi->driver, sdi->driver->priv, and sdi->priv must not be NULL. - */ -static void sr_dev_close(struct sr_dev_inst *sdi) -{ - int ret; - - if (!sdi) { - sr_err("Invalid device instance, can't close device."); - return; - } - - /* In the drivers sdi->priv is a 'struct dev_context *devc'. */ - if (!sdi->priv) { - /* - * Should be sr_err() in theory, but the 'demo' driver has - * NULL for sdi->priv, so we use sr_dbg() until that's fixed. - */ - sr_dbg("Invalid device context, can't close device."); - return; - } - - if (!sdi->driver) { - sr_err("Invalid driver, can't close device."); - return; - } - - if (!sdi->driver->priv) { - sr_err("Driver not initialized, can't close device."); - return; - } - - sr_spew("Closing '%s' device instance %d.", sdi->driver->name, - sdi->index); - - if ((ret = sdi->driver->dev_close(sdi)) < 0) - sr_err("Failed to close device instance: %d.", ret); -} - /** * Remove all the devices from the current session. * @@ -168,7 +131,7 @@ SR_API int sr_session_dev_remove_all(void) return SR_ERR_BUG; } - g_slist_free_full(session->devs, (GDestroyNotify)sr_dev_close); + g_slist_free(session->devs); session->devs = NULL; return SR_OK; @@ -185,7 +148,6 @@ SR_API int sr_session_dev_remove_all(void) */ SR_API int sr_session_dev_add(const struct sr_dev_inst *sdi) { - int ret; if (!sdi) { sr_err("%s: sdi was NULL", __func__); @@ -212,11 +174,6 @@ SR_API int sr_session_dev_add(const struct sr_dev_inst *sdi) return SR_ERR_BUG; } - if ((ret = sdi->driver->dev_open((struct sr_dev_inst *)sdi)) != SR_OK) { - sr_err("%s: dev_open failed (%d)", __func__, ret); - return ret; - } - session->devs = g_slist_append(session->devs, (gpointer)sdi); return SR_OK; @@ -234,7 +191,7 @@ SR_API int sr_session_datafeed_callback_remove_all(void) return SR_ERR_BUG; } - g_slist_free(session->datafeed_callbacks); + g_slist_free_full(session->datafeed_callbacks, g_free); session->datafeed_callbacks = NULL; return SR_OK; @@ -245,11 +202,14 @@ SR_API int sr_session_datafeed_callback_remove_all(void) * * @param cb Function to call when a chunk of data is received. * Must not be NULL. + * @param cb_data Opaque pointer passed in by the caller. * * @return SR_OK upon success, SR_ERR_BUG if no session exists. */ -SR_API int sr_session_datafeed_callback_add(sr_datafeed_callback_t cb) +SR_API int sr_session_datafeed_callback_add(sr_datafeed_callback_t cb, void *cb_data) { + struct datafeed_callback *cb_struct; + if (!session) { sr_err("%s: session was NULL", __func__); return SR_ERR_BUG; @@ -260,8 +220,14 @@ SR_API int sr_session_datafeed_callback_add(sr_datafeed_callback_t cb) return SR_ERR_ARG; } + if (!(cb_struct = g_try_malloc0(sizeof(struct datafeed_callback)))) + return SR_ERR_MALLOC; + + cb_struct->cb = cb; + cb_struct->cb_data = cb_data; + session->datafeed_callbacks = - g_slist_append(session->datafeed_callbacks, cb); + g_slist_append(session->datafeed_callbacks, cb_struct); return SR_OK; } @@ -294,8 +260,11 @@ static int sr_session_run_poll(void) * just once per main event loop. */ g_mutex_lock(&session->stop_mutex); - if (session->abort_session) + if (session->abort_session) { sr_session_stop_sync(); + /* But once is enough. */ + session->abort_session = FALSE; + } g_mutex_unlock(&session->stop_mutex); } } @@ -411,15 +380,6 @@ SR_PRIV int sr_session_stop_sync(void) } } - /* - * Some sources may not be necessarily associated with a device. - * Those sources may still be present even after stopping all devices. - * We need to make sure all sources are removed, or we risk running the - * session in an infinite loop. - */ - while (session->num_sources) - sr_session_source_remove(session->sources[0].poll_object); - return SR_OK; } @@ -511,7 +471,7 @@ SR_PRIV int sr_session_send(const struct sr_dev_inst *sdi, const struct sr_datafeed_packet *packet) { GSList *l; - sr_datafeed_callback_t cb; + struct datafeed_callback *cb_struct; if (!sdi) { sr_err("%s: sdi was NULL", __func__); @@ -526,8 +486,8 @@ SR_PRIV int sr_session_send(const struct sr_dev_inst *sdi, for (l = session->datafeed_callbacks; l; l = l->next) { if (sr_log_loglevel_get() >= SR_LOG_DBG) datafeed_dump(packet); - cb = l->data; - cb(sdi, packet); + cb_struct = l->data; + cb_struct->cb(sdi, packet, cb_struct->cb_data); } return SR_OK;