# SCPI support
libsigrok_la_SOURCES += \
src/scpi/scpi.c \
+ src/scpi/helpers.c \
src/scpi/scpi_tcp.c
if NEED_RPC
libsigrok_la_SOURCES += \
#include <string.h>
#include <strings.h>
+#include "scpi.h"
#include "protocol.h"
SR_PRIV struct sr_dev_driver scpi_pps_driver_info;
device = NULL;
for (i = 0; i < num_pps_profiles; i++) {
- vendor = get_vendor(hw_info->manufacturer);
+ vendor = sr_vendor_alias(hw_info->manufacturer);
if (strcasecmp(vendor, pps_profiles[i].vendor))
continue;
model_re = g_regex_new(pps_profiles[i].model, 0, 0, NULL);
for (ch_num = 0; ch_num < num_channels; ch_num++) {
/* Create one channel per measurable output unit. */
for (i = 0; i < ARRAY_SIZE(pci); i++) {
- if (!scpi_cmd_get(sdi, pci[i].command))
+ if (!scpi_cmd_get(devc->device->commands, pci[i].command))
continue;
g_snprintf(ch_name, 16, "%s%s", pci[i].prefix,
channels[ch_num].name);
sr_scpi_hw_info_free(hw_info);
hw_info = NULL;
- scpi_cmd(sdi, SCPI_CMD_LOCAL);
+ scpi_cmd(sdi, devc->device->commands, SCPI_CMD_LOCAL);
sr_scpi_close(scpi);
return sdi;
sdi->status = SR_ST_ACTIVE;
- scpi_cmd(sdi, SCPI_CMD_REMOTE);
+ devc = sdi->priv;
+ scpi_cmd(sdi, devc->device->commands, SCPI_CMD_REMOTE);
devc = sdi->priv;
devc->beeper_was_set = FALSE;
- if (scpi_cmd_resp(sdi, &beeper, G_VARIANT_TYPE_BOOLEAN, SCPI_CMD_BEEPER) == SR_OK) {
+ if (scpi_cmd_resp(sdi, devc->device->commands, &beeper,
+ G_VARIANT_TYPE_BOOLEAN, SCPI_CMD_BEEPER) == SR_OK) {
if (g_variant_get_boolean(beeper)) {
devc->beeper_was_set = TRUE;
- scpi_cmd(sdi, SCPI_CMD_BEEPER_DISABLE);
+ scpi_cmd(sdi, devc->device->commands, SCPI_CMD_BEEPER_DISABLE);
}
g_variant_unref(beeper);
}
scpi = sdi->conn;
if (scpi) {
if (devc->beeper_was_set)
- scpi_cmd(sdi, SCPI_CMD_BEEPER_ENABLE);
- scpi_cmd(sdi, SCPI_CMD_LOCAL);
+ scpi_cmd(sdi, devc->device->commands, SCPI_CMD_BEEPER_ENABLE);
+ scpi_cmd(sdi, devc->device->commands, SCPI_CMD_LOCAL);
sr_scpi_close(scpi);
sdi->status = SR_ST_INACTIVE;
}
const GVariantType *gvtype;
unsigned int i;
int cmd, ret;
+ char *s;
if (!sdi)
return SR_ERR_ARG;
gvtype = G_VARIANT_TYPE_STRING;
cmd = SCPI_CMD_GET_OUTPUT_REGULATION;
}
- if (gvtype) {
- if (cg)
- select_channel(sdi, cg->channels->data);
- ret = scpi_cmd_resp(sdi, data, gvtype, cmd);
- } else
- ret = SR_ERR_NA;
+ if (!gvtype)
+ return SR_ERR_NA;
+
+ if (cg)
+ select_channel(sdi, cg->channels->data);
+ ret = scpi_cmd_resp(sdi, devc->device->commands, data, gvtype, cmd);
+
+ if (cmd == SCPI_CMD_GET_OUTPUT_REGULATION) {
+ /*
+ * The Rigol DP800 series return CV/CC/UR, Philips PM2800
+ * return VOLT/CURR. We always return a GVariant string in
+ * the Rigol notation.
+ */
+ if ((ret = sr_scpi_get_string(sdi->conn, NULL, &s)) != SR_OK)
+ return ret;
+ if (!strcmp(s, "CV") || !strcmp(s, "VOLT")) {
+ *data = g_variant_new_string("CV");
+ } else if (!strcmp(s, "CC") || !strcmp(s, "CURR")) {
+ *data = g_variant_new_string("CC");
+ } else if (!strcmp(s, "UR")) {
+ *data = g_variant_new_string("UR");
+ } else {
+ sr_dbg("Unknown response to SCPI_CMD_GET_OUTPUT_REGULATION: %s", s);
+ ret = SR_ERR_DATA;
+ }
+ g_free(s);
+ }
return ret;
}
static int config_set(uint32_t key, GVariant *data, const struct sr_dev_inst *sdi,
const struct sr_channel_group *cg)
{
+ struct dev_context *devc;
double d;
int ret;
/* Channel group specified. */
select_channel(sdi, cg->channels->data);
+ devc = sdi->priv;
ret = SR_OK;
switch (key) {
case SR_CONF_ENABLED:
if (g_variant_get_boolean(data))
- ret = scpi_cmd(sdi, SCPI_CMD_SET_OUTPUT_ENABLE);
+ ret = scpi_cmd(sdi, devc->device->commands,
+ SCPI_CMD_SET_OUTPUT_ENABLE);
else
- ret = scpi_cmd(sdi, SCPI_CMD_SET_OUTPUT_DISABLE);
+ ret = scpi_cmd(sdi, devc->device->commands,
+ SCPI_CMD_SET_OUTPUT_DISABLE);
break;
case SR_CONF_VOLTAGE_TARGET:
d = g_variant_get_double(data);
- ret = scpi_cmd(sdi, SCPI_CMD_SET_VOLTAGE_TARGET, d);
+ ret = scpi_cmd(sdi, devc->device->commands,
+ SCPI_CMD_SET_VOLTAGE_TARGET, d);
break;
case SR_CONF_OUTPUT_FREQUENCY_TARGET:
d = g_variant_get_double(data);
- ret = scpi_cmd(sdi, SCPI_CMD_SET_FREQUENCY_TARGET, d);
+ ret = scpi_cmd(sdi, devc->device->commands,
+ SCPI_CMD_SET_FREQUENCY_TARGET, d);
break;
case SR_CONF_CURRENT_LIMIT:
d = g_variant_get_double(data);
- ret = scpi_cmd(sdi, SCPI_CMD_SET_CURRENT_LIMIT, d);
+ ret = scpi_cmd(sdi, devc->device->commands,
+ SCPI_CMD_SET_CURRENT_LIMIT, d);
break;
case SR_CONF_OVER_VOLTAGE_PROTECTION_ENABLED:
if (g_variant_get_boolean(data))
- ret = scpi_cmd(sdi, SCPI_CMD_SET_OVER_VOLTAGE_PROTECTION_ENABLE);
+ ret = scpi_cmd(sdi, devc->device->commands,
+ SCPI_CMD_SET_OVER_VOLTAGE_PROTECTION_ENABLE);
else
- ret = scpi_cmd(sdi, SCPI_CMD_SET_OVER_VOLTAGE_PROTECTION_DISABLE);
+ ret = scpi_cmd(sdi, devc->device->commands,
+ SCPI_CMD_SET_OVER_VOLTAGE_PROTECTION_DISABLE);
break;
case SR_CONF_OVER_VOLTAGE_PROTECTION_THRESHOLD:
d = g_variant_get_double(data);
- ret = scpi_cmd(sdi, SCPI_CMD_SET_OVER_VOLTAGE_PROTECTION_THRESHOLD, d);
+ ret = scpi_cmd(sdi, devc->device->commands,
+ SCPI_CMD_SET_OVER_VOLTAGE_PROTECTION_THRESHOLD, d);
break;
case SR_CONF_OVER_CURRENT_PROTECTION_ENABLED:
if (g_variant_get_boolean(data))
- ret = scpi_cmd(sdi, SCPI_CMD_SET_OVER_CURRENT_PROTECTION_ENABLE);
+ ret = scpi_cmd(sdi, devc->device->commands,
+ SCPI_CMD_SET_OVER_CURRENT_PROTECTION_ENABLE);
else
- ret = scpi_cmd(sdi, SCPI_CMD_SET_OVER_CURRENT_PROTECTION_DISABLE);
+ ret = scpi_cmd(sdi, devc->device->commands,
+ SCPI_CMD_SET_OVER_CURRENT_PROTECTION_DISABLE);
break;
case SR_CONF_OVER_CURRENT_PROTECTION_THRESHOLD:
d = g_variant_get_double(data);
- ret = scpi_cmd(sdi, SCPI_CMD_SET_OVER_CURRENT_PROTECTION_THRESHOLD, d);
+ ret = scpi_cmd(sdi, devc->device->commands,
+ SCPI_CMD_SET_OVER_CURRENT_PROTECTION_THRESHOLD, d);
break;
case SR_CONF_OVER_TEMPERATURE_PROTECTION:
if (g_variant_get_boolean(data))
- ret = scpi_cmd(sdi, SCPI_CMD_SET_OVER_TEMPERATURE_PROTECTION_ENABLE);
+ ret = scpi_cmd(sdi, devc->device->commands,
+ SCPI_CMD_SET_OVER_TEMPERATURE_PROTECTION_ENABLE);
else
- ret = scpi_cmd(sdi, SCPI_CMD_SET_OVER_TEMPERATURE_PROTECTION_DISABLE);
+ ret = scpi_cmd(sdi, devc->device->commands,
+ SCPI_CMD_SET_OVER_TEMPERATURE_PROTECTION_DISABLE);
break;
default:
ret = SR_ERR_NA;
return ret;
}
-static int dev_acquisition_start(const struct sr_dev_inst *sdi,
- void *cb_data)
+static int dev_acquisition_start(const struct sr_dev_inst *sdi, void *cb_data)
{
struct dev_context *devc;
struct sr_scpi_dev_inst *scpi;
cmd = SCPI_CMD_GET_MEAS_POWER;
else
return SR_ERR;
- scpi_cmd(sdi, cmd, pch->hwname);
+ scpi_cmd(sdi, devc->device->commands, cmd, pch->hwname);
return SR_OK;
}
#define CH_IDX(x) (1 << x)
#define FREQ_DC_ONLY {0, 0, 0}
-static const char *pps_vendors[][2] = {
- { "RIGOL TECHNOLOGIES", "Rigol" },
- { "HEWLETT-PACKARD", "HP" },
- { "PHILIPS", "Philips" },
- { "CHROMA", "Chroma" },
- { "Chroma ATE", "Chroma" },
- { "Agilent Technologies", "Agilent" },
-};
-
-SR_PRIV const char *get_vendor(const char *raw_vendor)
-{
- unsigned int i;
-
- for (i = 0; i < ARRAY_SIZE(pps_vendors); i++) {
- if (!strcasecmp(raw_vendor, pps_vendors[i][0]))
- return pps_vendors[i][1];
- }
-
- return raw_vendor;
-}
-
static const uint32_t devopts_none[] = { };
/* Agilent/Keysight N5700A series */
/* Current limit (CC mode) and OCP are set using the same command. */
{ SCPI_CMD_GET_OVER_CURRENT_PROTECTION_THRESHOLD, ":SOUR:CURR?" },
{ SCPI_CMD_SET_OVER_CURRENT_PROTECTION_THRESHOLD, ":SOUR:CURR %.6f" },
+ ALL_ZERO
};
/* Chroma 61600 series AC source */
/* This is not a current limit mode. It is overcurrent protection. */
{ SCPI_CMD_GET_OVER_CURRENT_PROTECTION_THRESHOLD, ":SOUR:CURR:LIM?" },
{ SCPI_CMD_SET_OVER_CURRENT_PROTECTION_THRESHOLD, ":SOUR:CURR:LIM %.2f" },
+ ALL_ZERO
};
/* Chroma 62000 series DC source */
{ SCPI_CMD_SET_OVER_VOLTAGE_PROTECTION_THRESHOLD, ":SOUR:VOLT:PROT:HIGH %.6f" },
{ SCPI_CMD_GET_OVER_CURRENT_PROTECTION_THRESHOLD, ":SOUR:CURR:PROT:HIGH?" },
{ SCPI_CMD_SET_OVER_CURRENT_PROTECTION_THRESHOLD, ":SOUR:CURR:PROT:HIGH %.6f" },
+ ALL_ZERO
};
static int chroma_62000p_probe_channels(struct sr_dev_inst *sdi,
{ SCPI_CMD_GET_OVER_CURRENT_PROTECTION_ACTIVE, ":OUTP:OCP:QUES?" },
{ SCPI_CMD_GET_OVER_CURRENT_PROTECTION_THRESHOLD, ":OUTP:OCP:VAL?" },
{ SCPI_CMD_SET_OVER_CURRENT_PROTECTION_THRESHOLD, ":OUTP:OCP:VAL %.6f" },
+ ALL_ZERO
};
/* HP 663xx series */
{ SCPI_CMD_SET_VOLTAGE_TARGET, ":SOUR:VOLT %.6f" },
{ SCPI_CMD_GET_CURRENT_LIMIT, ":SOUR:CURR?" },
{ SCPI_CMD_SET_CURRENT_LIMIT, ":SOUR:CURR %.6f" },
+ ALL_ZERO
};
/* Philips/Fluke PM2800 series */
{ SCPI_CMD_SET_OVER_CURRENT_PROTECTION_ENABLE, ":SOUR:CURR:PROT:STAT ON" },
{ SCPI_CMD_SET_OVER_CURRENT_PROTECTION_DISABLE, ":SOUR:CURR:PROT:STAT OFF" },
{ SCPI_CMD_GET_OVER_CURRENT_PROTECTION_ACTIVE, ":SOUR:CURR:PROT:TRIP?" },
+ ALL_ZERO
};
SR_PRIV const struct scpi_pps pps_profiles[] = {
ARRAY_AND_SIZE(agilent_n5700a_devopts_cg),
ARRAY_AND_SIZE(agilent_n5767a_ch),
ARRAY_AND_SIZE(agilent_n5767a_cg),
- ARRAY_AND_SIZE(agilent_n5700a_cmd),
+ agilent_n5700a_cmd,
.probe_channels = NULL,
},
/* Chroma 61604 */
ARRAY_AND_SIZE(chroma_61604_devopts_cg),
ARRAY_AND_SIZE(chroma_61604_ch),
ARRAY_AND_SIZE(chroma_61604_cg),
- ARRAY_AND_SIZE(chroma_61604_cmd),
+ chroma_61604_cmd,
.probe_channels = NULL,
},
/* Chroma 62000 series */
ARRAY_AND_SIZE(chroma_62000_devopts_cg),
NULL, 0,
NULL, 0,
- ARRAY_AND_SIZE(chroma_62000_cmd),
+ chroma_62000_cmd,
.probe_channels = chroma_62000p_probe_channels,
},
/* HP 6632B */
ARRAY_AND_SIZE(devopts_none),
ARRAY_AND_SIZE(hp_6632b_ch),
ARRAY_AND_SIZE(hp_6632b_cg),
- ARRAY_AND_SIZE(hp_6632b_cmd),
+ hp_6632b_cmd,
.probe_channels = NULL,
},
ARRAY_AND_SIZE(rigol_dp800_devopts_cg),
ARRAY_AND_SIZE(rigol_dp821a_ch),
ARRAY_AND_SIZE(rigol_dp820_cg),
- ARRAY_AND_SIZE(rigol_dp800_cmd),
+ rigol_dp800_cmd,
.probe_channels = NULL,
},
{ "Rigol", "^DP831A$", PPS_OTP,
ARRAY_AND_SIZE(rigol_dp800_devopts_cg),
ARRAY_AND_SIZE(rigol_dp831_ch),
ARRAY_AND_SIZE(rigol_dp830_cg),
- ARRAY_AND_SIZE(rigol_dp800_cmd),
+ rigol_dp800_cmd,
.probe_channels = NULL,
},
{ "Rigol", "^(DP832|DP832A)$", PPS_OTP,
ARRAY_AND_SIZE(rigol_dp800_devopts_cg),
ARRAY_AND_SIZE(rigol_dp832_ch),
ARRAY_AND_SIZE(rigol_dp830_cg),
- ARRAY_AND_SIZE(rigol_dp800_cmd),
+ rigol_dp800_cmd,
.probe_channels = NULL,
},
ARRAY_AND_SIZE(philips_pm2800_devopts_cg),
NULL, 0,
NULL, 0,
- ARRAY_AND_SIZE(philips_pm2800_cmd),
+ philips_pm2800_cmd,
philips_pm2800_probe_channels,
},
};
#include <string.h>
#include <strings.h>
#include <stdarg.h>
+#include "scpi.h"
#include "protocol.h"
-SR_PRIV const char *scpi_cmd_get(const struct sr_dev_inst *sdi, int command)
-{
- struct dev_context *devc;
- unsigned int i;
- const char *cmd;
-
- devc = sdi->priv;
- cmd = NULL;
- for (i = 0; i < devc->device->num_commands; i++) {
- if (devc->device->commands[i].command == command) {
- cmd = devc->device->commands[i].string;
- break;
- }
- }
-
- 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;
- const char *cmd;
-
- 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);
-
- 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 *s;
- const char *cmd;
-
- 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;
-
- /* Non-standard data type responses. */
- if (command == SCPI_CMD_GET_OUTPUT_REGULATION) {
- /*
- * The Rigol DP800 series return CV/CC/UR, Philips PM2800
- * return VOLT/CURR. We always return a GVariant string in
- * the Rigol notation.
- */
- if ((ret = sr_scpi_get_string(scpi, NULL, &s)) != SR_OK)
- return ret;
- if (!strcmp(s, "CV") || !strcmp(s, "VOLT")) {
- *gvar = g_variant_new_string("CV");
- } else if (!strcmp(s, "CC") || !strcmp(s, "CURR")) {
- *gvar = g_variant_new_string("CC");
- } else if (!strcmp(s, "UR")) {
- *gvar = g_variant_new_string("UR");
- } else {
- sr_dbg("Unknown response to SCPI_CMD_GET_OUTPUT_REGULATION: %s", s);
- ret = SR_ERR_DATA;
- }
- g_free(s);
- } else {
- /* Straight SCPI getters to GVariant types. */
- 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;
- g_free(s);
- } 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 select_channel(const struct sr_dev_inst *sdi, struct sr_channel *ch)
{
struct dev_context *devc;
}
}
- if ((ret = scpi_cmd(sdi, SCPI_CMD_SELECT_CHANNEL, new_pch->hwname)) >= 0)
+ if ((ret = scpi_cmd(sdi, devc->device->commands, SCPI_CMD_SELECT_CHANNEL,
+ new_pch->hwname)) >= 0)
devc->cur_channel = ch;
return ret;
cmd = SCPI_CMD_GET_MEAS_POWER;
else
return SR_ERR;
- scpi_cmd(sdi, cmd);
+ scpi_cmd(sdi, devc->device->commands, cmd);
return TRUE;
}
#include <glib.h>
#include <libsigrok/libsigrok.h>
#include "libsigrok-internal.h"
+#include "scpi.h"
#define LOG_PREFIX "scpi-pps"
const struct channel_group_spec *channel_groups;
unsigned int num_channel_groups;
const struct scpi_command *commands;
- unsigned int num_commands;
int (*probe_channels) (struct sr_dev_inst *sdi, struct sr_scpi_hw_info *hwinfo,
struct channel_spec **channels, unsigned int *num_channels,
struct channel_group_spec **channel_groups, unsigned int *num_channel_groups);
float frequency[3];
};
-struct scpi_command {
- int command;
- const char *string;
-};
-
struct channel_group_spec {
const char *name;
uint64_t channel_index_mask;
SR_PRIV extern const struct scpi_pps pps_profiles[];
SR_PRIV const char *get_vendor(const char *raw_vendor);
-SR_PRIV const 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 select_channel(const struct sr_dev_inst *sdi, struct sr_channel *ch);
SR_PRIV struct sr_channel *next_enabled_channel(const struct sr_dev_inst *sdi,
struct sr_channel *cur_channel);
SCPI_CMD_GET_SAMPLE_RATE_LIVE,
};
+struct scpi_command {
+ int command;
+ const char *string;
+};
+
struct sr_scpi_hw_info {
char *manufacturer;
char *model;
struct sr_scpi_hw_info **scpi_response);
SR_PRIV void sr_scpi_hw_info_free(struct sr_scpi_hw_info *hw_info);
+SR_PRIV const char *sr_vendor_alias(const char *raw_vendor);
+SR_PRIV const char *scpi_cmd_get(const struct scpi_command *cmdtable, int command);
+SR_PRIV int scpi_cmd(const struct sr_dev_inst *sdi,
+ const struct scpi_command *cmdtable, int command, ...);
+SR_PRIV int scpi_cmd_resp(const struct sr_dev_inst *sdi,
+ const struct scpi_command *cmdtable,
+ GVariant **gvar, const GVariantType *gvtype, int command, ...);
+
#endif
--- /dev/null
+/*
+ * This file is part of the libsigrok project.
+ *
+ * Copyright (C) 2015 Bert Vermeulen <bert@biot.com>
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <strings.h>
+#include <libsigrok/libsigrok.h>
+#include "libsigrok-internal.h"
+#include "scpi.h"
+
+#define LOG_PREFIX "scpi/helpers"
+
+static const char *scpi_vendors[][2] = {
+ { "HEWLETT-PACKARD", "HP" },
+ { "Agilent Technologies", "Agilent" },
+ { "RIGOL TECHNOLOGIES", "Rigol" },
+ { "PHILIPS", "Philips" },
+ { "CHROMA", "Chroma" },
+ { "Chroma ATE", "Chroma" },
+};
+
+SR_PRIV const char *sr_vendor_alias(const char *raw_vendor)
+{
+ unsigned int i;
+
+ for (i = 0; i < ARRAY_SIZE(scpi_vendors); i++) {
+ if (!strcasecmp(raw_vendor, scpi_vendors[i][0]))
+ return scpi_vendors[i][1];
+ }
+
+ return raw_vendor;
+}
+
+SR_PRIV const char *scpi_cmd_get(const struct scpi_command *cmdtable, int command)
+{
+ unsigned int i;
+ const char *cmd;
+
+ if (!cmdtable)
+ return NULL;
+
+ cmd = NULL;
+ for (i = 0; cmdtable[i].command; i++) {
+ if (cmdtable[i].command == command) {
+ cmd = cmdtable[i].string;
+ break;
+ }
+ }
+
+ return cmd;
+}
+
+SR_PRIV int scpi_cmd(const struct sr_dev_inst *sdi, const struct scpi_command *cmdtable,
+ int command, ...)
+{
+ struct sr_scpi_dev_inst *scpi;
+ va_list args;
+ int ret;
+ const char *cmd;
+
+ if (!(cmd = scpi_cmd_get(cmdtable, command))) {
+ /* Device does not implement this command, that's OK. */
+ /* TODO: deprecate SR_OK_CONTINUE */
+ return SR_OK_CONTINUE;
+ }
+
+ scpi = sdi->conn;
+ va_start(args, command);
+ ret = sr_scpi_send_variadic(scpi, cmd, args);
+ va_end(args);
+
+ return ret;
+}
+
+SR_PRIV int scpi_cmd_resp(const struct sr_dev_inst *sdi, const struct scpi_command *cmdtable,
+ GVariant **gvar, const GVariantType *gvtype, int command, ...)
+{
+ struct sr_scpi_dev_inst *scpi;
+ va_list args;
+ double d;
+ int ret;
+ char *s;
+ const char *cmd;
+
+ if (!(cmd = scpi_cmd_get(cmdtable, 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;
+
+ /* Straight SCPI getters to GVariant types. */
+ 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;
+ g_free(s);
+ } 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);
+ } else {
+ sr_err("Unable to convert to desired GVariant type.");
+ ret = SR_ERR_NA;
+ }
+
+ return ret;
+}