+ if (!session) {
+ sr_err("%s: session was NULL", __func__);
+ return SR_ERR_ARG;
+ }
+
+ /* If sdi->session is not NULL, the device is already in this or
+ * another session. */
+ if (sdi->session) {
+ sr_err("%s: already assigned to session", __func__);
+ return SR_ERR_ARG;
+ }
+
+ /* If sdi->driver is NULL, this is a virtual device. */
+ if (!sdi->driver) {
+ sr_dbg("%s: sdi->driver was NULL, this seems to be "
+ "a virtual device; continuing", __func__);
+ /* Just add the device, don't run dev_open(). */
+ session->devs = g_slist_append(session->devs, (gpointer)sdi);
+ sdi->session = session;
+ return SR_OK;
+ }
+
+ /* sdi->driver is non-NULL (i.e. we have a real device). */
+ if (!sdi->driver->dev_open) {
+ sr_err("%s: sdi->driver->dev_open was NULL", __func__);
+ return SR_ERR_BUG;
+ }
+
+ session->devs = g_slist_append(session->devs, (gpointer)sdi);
+ sdi->session = session;
+
+ if (session->running) {
+ /* Adding a device to a running session. Commit settings
+ * and start acquisition on that device now. */
+ if ((ret = sr_config_commit(sdi)) != SR_OK) {
+ sr_err("Failed to commit device settings before "
+ "starting acquisition in running session (%s)",
+ sr_strerror(ret));
+ return ret;
+ }
+ if ((ret = sdi->driver->dev_acquisition_start(sdi,
+ (void *)sdi)) != SR_OK) {
+ sr_err("Failed to start acquisition of device in "
+ "running session (%s)", sr_strerror(ret));
+ return ret;
+ }
+ }
+
+ return SR_OK;
+}
+
+/**
+ * List all device instances attached to a session.
+ *
+ * @param devlist A pointer where the device instance list will be
+ * stored on return. If no devices are in the session,
+ * this will be NULL. Each element in the list points
+ * to a struct sr_dev_inst *.
+ * The list must be freed by the caller, but not the
+ * elements pointed to.
+ *
+ * @retval SR_OK Success.
+ * @retval SR_ERR_ARG Invalid argument.
+ *
+ * @since 0.4.0
+ */
+SR_API int sr_session_dev_list(struct sr_session *session, GSList **devlist)
+{
+ if (!session)
+ return SR_ERR_ARG;
+
+ if (!devlist)
+ return SR_ERR_ARG;
+
+ *devlist = g_slist_copy(session->devs);
+
+ return SR_OK;