scpi-pps: Simplify SCPI command handling.

This commit is contained in:
Bert Vermeulen 2014-09-08 00:02:03 +02:00
parent 3222ee103d
commit 478c8d923e
3 changed files with 166 additions and 175 deletions

View File

@ -171,8 +171,9 @@ static int config_get(int key, GVariant **data, const struct sr_dev_inst *sdi,
struct dev_context *devc;
struct sr_scpi_dev_inst *scpi;
struct sr_channel *ch;
double d;
int ret;
const GVariantType *gvtype;
unsigned int i;
int cmd, ret;
char *s;
if (!sdi)
@ -181,43 +182,88 @@ static int config_get(int key, GVariant **data, const struct sr_dev_inst *sdi,
devc = sdi->priv;
scpi = sdi->conn;
ret = SR_OK;
if (!cg) {
/* No channel group: global options. */
switch (key) {
case SR_CONF_OVER_TEMPERATURE_PROTECTION:
ret = SR_ERR;
if (scpi_cmd(sdi, SCPI_CMD_GET_OVER_TEMPERATURE_PROTECTION) == SR_OK) {
if (sr_scpi_get_string(scpi, NULL, &s) == SR_OK) {
*data = g_variant_new_boolean(!strcmp(s, "ON"));
ret = SR_OK;
}
}
break;
return SR_ERR_NA;
break;
case SR_CONF_OUTPUT_CHANNEL_CONFIG:
ret = SR_ERR;
if (scpi_cmd(sdi, SCPI_CMD_GET_OUTPUT_CHANNEL_CONFIG) == SR_OK) {
if (sr_scpi_get_string(scpi, NULL, &s) == SR_OK) {
*data = g_variant_new_string(s);
g_free(s);
ret = SR_OK;
}
}
break;
default:
return SR_ERR_NA;
}
} else {
if (cg) {
/*
* These options only apply to channel groups with a single
* channel -- they're per-channel settings for the device.
*/
if (g_slist_length(cg->channels) > 1)
return SR_ERR_NA;
ch = cg->channels->data;
/*
* Config keys are handled below depending on whether a channel
* group was provided by the frontend. However some of these
* take a CG on one PPS but not on others. Check the device's
* profile for that here, and NULL out the channel group as needed.
*/
for (i = 0; i < devc->device->num_devopts; i++) {
if (devc->device->devopts[i] == key) {
cg = NULL;
break;
}
}
ch = cg->channels->data;
}
gvtype = NULL;
cmd = -1;
switch (key) {
case SR_CONF_OUTPUT_ENABLED:
gvtype = G_VARIANT_TYPE_BOOLEAN;
cmd = SCPI_CMD_GET_OUTPUT_ENABLED;
break;
case SR_CONF_OUTPUT_VOLTAGE:
gvtype = G_VARIANT_TYPE_DOUBLE;
cmd = SCPI_CMD_GET_MEAS_VOLTAGE;
break;
case SR_CONF_OUTPUT_VOLTAGE_MAX:
gvtype = G_VARIANT_TYPE_DOUBLE;
cmd = SCPI_CMD_GET_VOLTAGE_MAX;
break;
case SR_CONF_OUTPUT_CURRENT:
gvtype = G_VARIANT_TYPE_DOUBLE;
cmd = SCPI_CMD_GET_MEAS_CURRENT;
break;
case SR_CONF_OUTPUT_CURRENT_MAX:
gvtype = G_VARIANT_TYPE_DOUBLE;
cmd = SCPI_CMD_GET_CURRENT_MAX;
break;
case SR_CONF_OVER_VOLTAGE_PROTECTION_ENABLED:
gvtype = G_VARIANT_TYPE_BOOLEAN;
cmd = SCPI_CMD_GET_OVER_VOLTAGE_PROTECTION_ENABLED;
break;
case SR_CONF_OVER_VOLTAGE_PROTECTION_ACTIVE:
gvtype = G_VARIANT_TYPE_BOOLEAN;
cmd = SCPI_CMD_GET_OVER_VOLTAGE_PROTECTION_ACTIVE;
break;
case SR_CONF_OVER_VOLTAGE_PROTECTION_THRESHOLD:
gvtype = G_VARIANT_TYPE_DOUBLE;
cmd = SCPI_CMD_GET_OVER_VOLTAGE_PROTECTION_THRESHOLD;
break;
case SR_CONF_OVER_CURRENT_PROTECTION_ENABLED:
gvtype = G_VARIANT_TYPE_BOOLEAN;
cmd = SCPI_CMD_GET_OVER_CURRENT_PROTECTION_ENABLED;
break;
case SR_CONF_OVER_CURRENT_PROTECTION_ACTIVE:
gvtype = G_VARIANT_TYPE_BOOLEAN;
cmd = SCPI_CMD_GET_OVER_CURRENT_PROTECTION_ACTIVE;
break;
case SR_CONF_OVER_CURRENT_PROTECTION_THRESHOLD:
gvtype = G_VARIANT_TYPE_DOUBLE;
cmd = SCPI_CMD_GET_OVER_CURRENT_PROTECTION_THRESHOLD;
break;
case SR_CONF_OVER_TEMPERATURE_PROTECTION:
gvtype = G_VARIANT_TYPE_BOOLEAN;
cmd = SCPI_CMD_GET_OVER_TEMPERATURE_PROTECTION;
break;
}
if (gvtype) {
if (cg)
ret = scpi_cmd_resp(sdi, data, gvtype, cmd, ch->name);
else
ret = scpi_cmd_resp(sdi, data, gvtype, cmd);
} else if (cg) {
switch (key) {
case SR_CONF_OUTPUT_REGULATION:
ret = SR_ERR;
@ -233,115 +279,11 @@ static int config_get(int key, GVariant **data, const struct sr_dev_inst *sdi,
}
}
break;
case SR_CONF_OVER_VOLTAGE_PROTECTION_ENABLED:
ret = SR_ERR;
if (scpi_cmd(sdi, SCPI_CMD_GET_OVER_VOLTAGE_PROTECTION_ENABLED,
ch->name) == SR_OK) {
if (sr_scpi_get_string(scpi, NULL, &s) == SR_OK) {
*data = g_variant_new_boolean(!strcmp(s, "ON"));
ret = SR_OK;
}
}
break;
case SR_CONF_OVER_VOLTAGE_PROTECTION_ACTIVE:
ret = SR_ERR;
if (scpi_cmd(sdi, SCPI_CMD_GET_OVER_VOLTAGE_PROTECTION_ACTIVE,
ch->name) == SR_OK) {
if (sr_scpi_get_string(scpi, NULL, &s) == SR_OK) {
*data = g_variant_new_boolean(!strcmp(s, "YES"));
ret = SR_OK;
}
}
break;
case SR_CONF_OVER_VOLTAGE_PROTECTION_THRESHOLD:
ret = SR_ERR;
if (scpi_cmd(sdi, SCPI_CMD_GET_OVER_VOLTAGE_PROTECTION_THRESHOLD,
ch->name) == SR_OK) {
if (sr_scpi_get_double(scpi, NULL, &d) == SR_OK) {
*data = g_variant_new_double(d);
ret = SR_OK;
}
}
break;
case SR_CONF_OVER_CURRENT_PROTECTION_ENABLED:
ret = SR_ERR;
if (scpi_cmd(sdi, SCPI_CMD_GET_OVER_CURRENT_PROTECTION_ENABLED,
ch->name) == SR_OK) {
if (sr_scpi_get_string(scpi, NULL, &s) == SR_OK) {
*data = g_variant_new_boolean(!strcmp(s, "ON"));
ret = SR_OK;
}
}
break;
case SR_CONF_OVER_CURRENT_PROTECTION_ACTIVE:
ret = SR_ERR;
if (scpi_cmd(sdi, SCPI_CMD_GET_OVER_CURRENT_PROTECTION_ACTIVE,
ch->name) == SR_OK) {
if (sr_scpi_get_string(scpi, NULL, &s) == SR_OK) {
*data = g_variant_new_boolean(!strcmp(s, "YES"));
ret = SR_OK;
}
}
break;
case SR_CONF_OVER_CURRENT_PROTECTION_THRESHOLD:
ret = SR_ERR;
if (scpi_cmd(sdi, SCPI_CMD_GET_OVER_CURRENT_PROTECTION_THRESHOLD,
ch->name) == SR_OK) {
if (sr_scpi_get_double(scpi, NULL, &d) == SR_OK) {
*data = g_variant_new_double(d);
ret = SR_OK;
}
}
break;
case SR_CONF_OUTPUT_VOLTAGE:
ret = SR_ERR;
if (scpi_cmd(sdi, SCPI_CMD_GET_MEAS_VOLTAGE, ch->name) == SR_OK) {
if (sr_scpi_get_double(scpi, NULL, &d) == SR_OK) {
*data = g_variant_new_double(d);
ret = SR_OK;
}
}
break;
case SR_CONF_OUTPUT_VOLTAGE_MAX:
ret = SR_ERR;
if (scpi_cmd(sdi, SCPI_CMD_GET_VOLTAGE_MAX, ch->name) == SR_OK) {
if (sr_scpi_get_double(scpi, NULL, &d) == SR_OK) {
*data = g_variant_new_double(d);
ret = SR_OK;
}
}
break;
case SR_CONF_OUTPUT_CURRENT:
ret = SR_ERR;
if (scpi_cmd(sdi, SCPI_CMD_GET_MEAS_CURRENT, ch->name) == SR_OK) {
if (sr_scpi_get_double(scpi, NULL, &d) == SR_OK) {
*data = g_variant_new_double(d);
ret = SR_OK;
}
}
break;
case SR_CONF_OUTPUT_CURRENT_MAX:
ret = SR_ERR;
if (scpi_cmd(sdi, SCPI_CMD_GET_CURRENT_MAX, ch->name) == SR_OK) {
if (sr_scpi_get_double(scpi, NULL, &d) == SR_OK) {
*data = g_variant_new_double(d);
ret = SR_OK;
}
}
break;
case SR_CONF_OUTPUT_ENABLED:
ret = SR_ERR;
if (scpi_cmd(sdi, SCPI_CMD_GET_OUTPUT_ENABLED, ch->name) == SR_OK) {
if (sr_scpi_get_string(scpi, NULL, &s) == SR_OK) {
*data = g_variant_new_boolean(!strcmp(s, "ON"));
ret = SR_OK;
}
}
break;
default:
return SR_ERR_NA;
ret = SR_ERR_NA;
}
}
} else
ret = SR_ERR_NA;
return ret;
}
@ -357,20 +299,25 @@ static int config_set(int key, GVariant *data, const struct sr_dev_inst *sdi,
if (sdi->status != SR_ST_ACTIVE)
return SR_ERR_DEV_CLOSED;
ret = SR_OK;
if (!cg) {
switch (key) {
/* No channel group: global options. */
case SR_CONF_OUTPUT_ENABLED:
s = g_variant_get_boolean(data) ? "ON" : "OFF";
ret = scpi_cmd(sdi, SCPI_CMD_SET_OUTPUT_ENABLED, s);
break;
case SR_CONF_OUTPUT_VOLTAGE_MAX:
d = g_variant_get_double(data);
ret = scpi_cmd(sdi, SCPI_CMD_SET_VOLTAGE_MAX, d);
break;
case SR_CONF_OUTPUT_CURRENT_MAX:
d = g_variant_get_double(data);
ret = scpi_cmd(sdi, SCPI_CMD_SET_CURRENT_MAX, d);
break;
case SR_CONF_OVER_TEMPERATURE_PROTECTION:
s = g_variant_get_boolean(data) ? "ON" : "OFF";
if (scpi_cmd(sdi, SCPI_CMD_SET_OVER_TEMPERATURE_PROTECTION, s) < 0)
ret = SR_ERR;
break;
case SR_CONF_OUTPUT_CHANNEL_CONFIG:
s = g_variant_get_string(data, NULL);
if (scpi_cmd(sdi, SCPI_CMD_SET_OUTPUT_CHANNEL_CONFIG, s) < 0)
ret = SR_ERR;
ret = scpi_cmd(sdi, SCPI_CMD_SET_OVER_TEMPERATURE_PROTECTION, s);
break;
default:
ret = SR_ERR_NA;
@ -383,44 +330,37 @@ static int config_set(int key, GVariant *data, const struct sr_dev_inst *sdi,
return SR_ERR_NA;
ch = cg->channels->data;
switch (key) {
case SR_CONF_OUTPUT_ENABLED:
s = g_variant_get_boolean(data) ? "ON" : "OFF";
ret = scpi_cmd(sdi, SCPI_CMD_SET_OUTPUT_ENABLED, ch->name, s);
break;
case SR_CONF_OUTPUT_VOLTAGE_MAX:
d = g_variant_get_double(data);
if (scpi_cmd(sdi, SCPI_CMD_SET_VOLTAGE_MAX, ch->name, d) < 0)
ret = SR_ERR;
ret = scpi_cmd(sdi, SCPI_CMD_SET_VOLTAGE_MAX, ch->name, d);
break;
case SR_CONF_OUTPUT_CURRENT_MAX:
d = g_variant_get_double(data);
if (scpi_cmd(sdi, SCPI_CMD_SET_CURRENT_MAX, ch->name, d) < 0)
ret = SR_ERR;
break;
case SR_CONF_OUTPUT_ENABLED:
s = g_variant_get_boolean(data) ? "ON" : "OFF";
if (scpi_cmd(sdi, SCPI_CMD_SET_OUTPUT_ENABLED, ch->name, s) < 0)
ret = SR_ERR;
ret = scpi_cmd(sdi, SCPI_CMD_SET_CURRENT_MAX, ch->name, d);
break;
case SR_CONF_OVER_VOLTAGE_PROTECTION_ENABLED:
s = g_variant_get_boolean(data) ? "ON" : "OFF";
if (scpi_cmd(sdi, SCPI_CMD_SET_OVER_VOLTAGE_PROTECTION_ENABLED,
ch->name, s) < 0)
ret = SR_ERR;
ret = scpi_cmd(sdi, SCPI_CMD_SET_OVER_VOLTAGE_PROTECTION_ENABLED,
ch->name, s);
break;
case SR_CONF_OVER_VOLTAGE_PROTECTION_THRESHOLD:
d = g_variant_get_double(data);
if (scpi_cmd(sdi, SCPI_CMD_SET_OVER_VOLTAGE_PROTECTION_THRESHOLD,
ch->name, d) < 0)
ret = SR_ERR;
ret = scpi_cmd(sdi, SCPI_CMD_SET_OVER_VOLTAGE_PROTECTION_THRESHOLD,
ch->name, d);
break;
case SR_CONF_OVER_CURRENT_PROTECTION_ENABLED:
s = g_variant_get_boolean(data) ? "ON" : "OFF";
if (scpi_cmd(sdi, SCPI_CMD_SET_OVER_CURRENT_PROTECTION_ENABLED,
ch->name, s) < 0)
ret = SR_ERR;
ret = scpi_cmd(sdi, SCPI_CMD_SET_OVER_CURRENT_PROTECTION_ENABLED,
ch->name, s);
break;
case SR_CONF_OVER_CURRENT_PROTECTION_THRESHOLD:
d = g_variant_get_double(data);
if (scpi_cmd(sdi, SCPI_CMD_SET_OVER_CURRENT_PROTECTION_THRESHOLD,
ch->name, d) < 0)
ret = SR_ERR;
ret = scpi_cmd(sdi, SCPI_CMD_SET_OVER_CURRENT_PROTECTION_THRESHOLD,
ch->name, d);
break;
default:
ret = SR_ERR_NA;
@ -462,6 +402,7 @@ static int config_list(int key, GVariant **data, const struct sr_dev_inst *sdi,
sizeof(int32_t));
break;
case SR_CONF_OUTPUT_CHANNEL_CONFIG:
/* Not used. */
i = 0;
if (devc->device->features & PPS_INDEPENDENT)
s[i++] = "Independent";

View File

@ -21,13 +21,10 @@
#include <stdarg.h>
#include "protocol.h"
SR_PRIV int scpi_cmd(const struct sr_dev_inst *sdi, int command, ...)
SR_PRIV char *scpi_cmd_get(const struct sr_dev_inst *sdi, int command)
{
va_list args;
struct dev_context *devc;
struct sr_scpi_dev_inst *scpi;
unsigned int i;
int ret;
char *cmd;
devc = sdi->priv;
@ -38,7 +35,18 @@ SR_PRIV int scpi_cmd(const struct sr_dev_inst *sdi, int command, ...)
break;
}
}
if (!cmd) {
return cmd;
}
SR_PRIV int scpi_cmd(const struct sr_dev_inst *sdi, int command, ...)
{
struct sr_scpi_dev_inst *scpi;
va_list args;
int ret;
char *cmd;
if (!(cmd = scpi_cmd_get(sdi, command))) {
/* Device does not implement this command, that's OK. */
return SR_OK_CONTINUE;
}
@ -51,6 +59,47 @@ SR_PRIV int scpi_cmd(const struct sr_dev_inst *sdi, int command, ...)
return ret;
}
SR_PRIV int scpi_cmd_resp(const struct sr_dev_inst *sdi, GVariant **gvar,
const GVariantType *gvtype, int command, ...)
{
struct sr_scpi_dev_inst *scpi;
va_list args;
double d;
int ret;
char *cmd, *s;
if (!(cmd = scpi_cmd_get(sdi, command))) {
/* Device does not implement this command, that's OK. */
return SR_OK_CONTINUE;
}
scpi = sdi->conn;
va_start(args, command);
ret = sr_scpi_send_variadic(scpi, cmd, args);
va_end(args);
if (ret != SR_OK)
return ret;
if (g_variant_type_equal(gvtype, G_VARIANT_TYPE_BOOLEAN)) {
if ((ret = sr_scpi_get_string(scpi, NULL, &s)) != SR_OK)
return ret;
if (!strcasecmp(s, "ON") || !strcasecmp(s, "1") || !strcasecmp(s, "YES"))
*gvar = g_variant_new_boolean(TRUE);
else if (!strcasecmp(s, "OFF") || !strcasecmp(s, "0") || !strcasecmp(s, "NO"))
*gvar = g_variant_new_boolean(FALSE);
else
ret = SR_ERR;
} if (g_variant_type_equal(gvtype, G_VARIANT_TYPE_DOUBLE)) {
if ((ret = sr_scpi_get_double(scpi, NULL, &d)) == SR_OK)
*gvar = g_variant_new_double(d);
} if (g_variant_type_equal(gvtype, G_VARIANT_TYPE_STRING)) {
if ((ret = sr_scpi_get_string(scpi, NULL, &s)) == SR_OK)
*gvar = g_variant_new_string(s);
}
return ret;
}
SR_PRIV int scpi_pps_receive_data(int fd, int revents, void *cb_data)
{
struct dev_context *devc;

View File

@ -51,8 +51,6 @@ enum pps_scpi_cmds {
SCPI_CMD_GET_OVER_CURRENT_PROTECTION_ACTIVE,
SCPI_CMD_GET_OVER_CURRENT_PROTECTION_THRESHOLD,
SCPI_CMD_SET_OVER_CURRENT_PROTECTION_THRESHOLD,
SCPI_CMD_GET_OUTPUT_CHANNEL_CONFIG,
SCPI_CMD_SET_OUTPUT_CHANNEL_CONFIG,
};
/*
@ -129,7 +127,10 @@ struct dev_context {
};
const char *get_vendor(const char *raw_vendor);
SR_PRIV char *scpi_cmd_get(const struct sr_dev_inst *sdi, int command);
SR_PRIV int scpi_cmd(const struct sr_dev_inst *sdi, int command, ...);
SR_PRIV int scpi_cmd_resp(const struct sr_dev_inst *sdi, GVariant **gvar,
const GVariantType *gvtype, int command, ...);
SR_PRIV int scpi_pps_receive_data(int fd, int revents, void *cb_data);
#endif