}
/* Returns the next enabled channel, wrapping around if necessary. */
+/** @private */
SR_PRIV struct sr_channel *sr_next_enabled_channel(const struct sr_dev_inst *sdi,
+
struct sr_channel *cur_channel)
{
struct sr_channel *next_channel;
/**
* Free device instance struct created by sr_dev_inst().
*
- * @param sdi Device instance to free. Must not be NULL.
+ * @param sdi Device instance to free. If NULL, the function will do nothing.
*
* @private
*/
struct sr_channel_group *cg;
GSList *l;
+ if (!sdi)
+ return;
+
for (l = sdi->channels; l; l = l->next) {
ch = l->data;
g_free(ch->name);
/**
* Free struct sr_usb_dev_inst * allocated by sr_usb_dev_inst().
*
- * @param usb The struct sr_usb_dev_inst * to free. Must not be NULL.
+ * @param usb The struct sr_usb_dev_inst * to free. If NULL, this
+ * function does nothing.
*
* @private
*/
/**
* Free struct sr_serial_dev_inst * allocated by sr_serial_dev_inst().
*
- * @param serial The struct sr_serial_dev_inst * to free. Must not be NULL.
+ * @param serial The struct sr_serial_dev_inst * to free. If NULL, this
+ * function will do nothing.
*
* @private
*/
SR_PRIV void sr_serial_dev_inst_free(struct sr_serial_dev_inst *serial)
{
+ if (!serial)
+ return;
+
g_free(serial->port);
g_free(serial->serialcomm);
g_free(serial);
/** @private */
SR_PRIV void sr_usbtmc_dev_inst_free(struct sr_usbtmc_dev_inst *usbtmc)
{
+ if (!usbtmc)
+ return;
+
g_free(usbtmc->device);
g_free(usbtmc);
}
*/
SR_API int sr_dev_clear(const struct sr_dev_driver *driver)
{
- int ret;
-
if (!driver) {
sr_err("Invalid driver.");
return SR_ERR_ARG;
}
- if (driver->dev_clear)
- ret = driver->dev_clear(driver);
- else
- ret = std_dev_clear(driver, NULL);
+ if (!driver->context) {
+ /*
+ * Driver was never initialized, nothing to do.
+ *
+ * No log message since this usually gets called for all
+ * drivers, whether they were initialized or not.
+ */
+ return SR_OK;
+ }
- return ret;
+ /* No log message here, too verbose and not very useful. */
+
+ return driver->dev_clear(driver);
}
/**
- * Open the specified device.
+ * Open the specified device instance.
+ *
+ * If the device instance is already open (sdi->status == SR_ST_ACTIVE),
+ * SR_ERR will be returned and no re-opening of the device will be attempted.
+ *
+ * If opening was successful, sdi->status is set to SR_ST_ACTIVE, otherwise
+ * it will be left unchanged.
*
* @param sdi Device instance to use. Must not be NULL.
*
- * @return SR_OK upon success, a negative error code upon errors.
+ * @retval SR_OK Success.
+ * @retval SR_ERR_ARG Invalid arguments.
+ * @retval SR_ERR Device instance was already active, or other error.
*
* @since 0.2.0
*/
int ret;
if (!sdi || !sdi->driver || !sdi->driver->dev_open)
+ return SR_ERR_ARG;
+
+ if (sdi->status == SR_ST_ACTIVE) {
+ sr_err("%s: Device instance already active, can't re-open.",
+ sdi->driver->name);
return SR_ERR;
+ }
+
+ sr_dbg("%s: Opening device instance.", sdi->driver->name);
ret = sdi->driver->dev_open(sdi);
+ if (ret == SR_OK)
+ sdi->status = SR_ST_ACTIVE;
+
return ret;
}
/**
- * Close the specified device.
+ * Close the specified device instance.
+ *
+ * If the device instance is not open (sdi->status != SR_ST_ACTIVE),
+ * SR_ERR_DEV_CLOSED will be returned and no closing will be attempted.
+ *
+ * Note: sdi->status will be set to SR_ST_INACTIVE, regardless of whether
+ * there are any errors during closing of the device instance (any errors
+ * will be reported via error code and log message, though).
*
* @param sdi Device instance to use. Must not be NULL.
*
- * @return SR_OK upon success, a negative error code upon errors.
+ * @retval SR_OK Success.
+ * @retval SR_ERR_ARG Invalid arguments.
+ * @retval SR_ERR_DEV_CLOSED Device instance was not active.
+ * @retval SR_ERR Other error.
*
* @since 0.2.0
*/
int ret;
if (!sdi || !sdi->driver || !sdi->driver->dev_close)
- return SR_ERR;
+ return SR_ERR_ARG;
+
+ if (sdi->status != SR_ST_ACTIVE) {
+ sr_err("%s: Device instance not active, can't close.",
+ sdi->driver->name);
+ return SR_ERR_DEV_CLOSED;
+ }
+
+ sdi->status = SR_ST_INACTIVE;
+
+ sr_dbg("%s: Closing device instance.", sdi->driver->name);
ret = sdi->driver->dev_close(sdi);