Example #1
0
/** Unregister an event source that has been destroyed.
 *
 * This is intended to be called from a source's finalize() method.
 *
 * @param session The session to use. Must not be NULL.
 * @param key The key used to identify @a source.
 * @param source The source object that was destroyed.
 *
 * @retval SR_OK Success.
 * @retval SR_ERR_BUG Event source for @a key does not match @a source.
 * @retval SR_ERR Other error.
 *
 * @private
 */
SR_PRIV int sr_session_source_destroyed(struct sr_session *session,
		void *key, GSource *source)
{
	GSource *registered_source;

	registered_source = g_hash_table_lookup(session->event_sources, key);
	/*
	 * Trying to remove an already removed event source is problematic
	 * since the poll_object handle may have been reused in the meantime.
	 */
	if (!registered_source) {
		sr_err("No event source for key %p found.", key);
		return SR_ERR_BUG;
	}
	if (registered_source != source) {
		sr_err("Event source for key %p does not match"
			" destroyed source.", key);
		return SR_ERR_BUG;
	}
	g_hash_table_remove(session->event_sources, key);

	if (g_hash_table_size(session->event_sources) > 0)
		return SR_OK;

	/* If no event sources are left, consider the acquisition finished.
	 * This is pretty crude, as it requires all event sources to be
	 * registered via the libsigrok API.
	 */
	return stop_check_later(session);
}
/**
 * Start a session.
 *
 * When this function returns with a status code indicating success, the
 * session is running. Use sr_session_stopped_callback_set() to receive
 * notification upon completion, or call sr_session_run() to block until
 * the session stops.
 *
 * Session events will be processed in the context of the current thread.
 * If a thread-default GLib main context has been set, and is not owned by
 * any other thread, it will be used. Otherwise, libsigrok will create its
 * own main context for the current thread.
 *
 * @param session The session to use. Must not be NULL.
 *
 * @retval SR_OK Success.
 * @retval SR_ERR_ARG Invalid session passed.
 * @retval SR_ERR Other error.
 *
 * @since 0.4.0
 */
SR_API int sr_session_start(struct sr_session *session)
{
	struct sr_dev_inst *sdi;
	struct sr_channel *ch;
	GSList *l, *c, *lend;
	int ret;

	if (!session) {
		sr_err("%s: session was NULL", __func__);
		return SR_ERR_ARG;
	}

	if (!session->devs) {
		sr_err("%s: session->devs was NULL; a session "
		       "cannot be started without devices.", __func__);
		return SR_ERR_ARG;
	}

	if (session->running) {
		sr_err("Cannot (re-)start session while it is still running.");
		return SR_ERR;
	}

	if (session->trigger) {
		ret = verify_trigger(session->trigger);
		if (ret != SR_OK)
			return ret;
	}

	/* Check enabled channels and commit settings of all devices. */
	for (l = session->devs; l; l = l->next) {
		sdi = l->data;
		for (c = sdi->channels; c; c = c->next) {
			ch = c->data;
			if (ch->enabled)
				break;
		}
		if (!c) {
			sr_err("%s device %s has no enabled channels.",
				sdi->driver->name, sdi->connection_id);
			return SR_ERR;
		}

		ret = sr_config_commit(sdi);
		if (ret != SR_OK) {
			sr_err("Failed to commit %s device %s settings "
				"before starting acquisition.",
				sdi->driver->name, sdi->connection_id);
			return ret;
		}
	}

	ret = set_main_context(session);
	if (ret != SR_OK)
		return ret;

	sr_info("Starting.");

	session->running = TRUE;

	/* Have all devices start acquisition. */
	for (l = session->devs; l; l = l->next) {
		sdi = l->data;
		ret = sdi->driver->dev_acquisition_start(sdi, sdi);
		if (ret != SR_OK) {
			sr_err("Could not start %s device %s acquisition.",
				sdi->driver->name, sdi->connection_id);
			break;
		}
	}

	if (ret != SR_OK) {
		/* If there are multiple devices, some of them may already have
		 * started successfully. Stop them now before returning. */
		lend = l->next;
		for (l = session->devs; l != lend; l = l->next) {
			sdi = l->data;
			if (sdi->driver->dev_acquisition_stop)
				sdi->driver->dev_acquisition_stop(sdi, sdi);
		}
		/* TODO: Handle delayed stops. Need to iterate the event
		 * sources... */
		session->running = FALSE;

		unset_main_context(session);
		return ret;
	}

	if (g_hash_table_size(session->event_sources) == 0)
		stop_check_later(session);

	return SR_OK;
}