]> sigrok.org Git - libsigrok.git/commitdiff
scpi: Make helper functions from scpi-pps available library-wide.
authorBert Vermeulen <redacted>
Sun, 16 Aug 2015 13:12:34 +0000 (15:12 +0200)
committerUwe Hermann <redacted>
Tue, 25 Aug 2015 17:13:17 +0000 (19:13 +0200)
Makefile.am
src/hardware/scpi-pps/api.c
src/hardware/scpi-pps/profiles.c
src/hardware/scpi-pps/protocol.c
src/hardware/scpi-pps/protocol.h
src/scpi.h
src/scpi/helpers.c [new file with mode: 0644]

index 95190567b06d0e37e18c50fffe6df78b6b5f09cc..c6f61a1532d844943f67a45b3109155fa343244b 100644 (file)
@@ -92,6 +92,7 @@ libsigrok_la_SOURCES += \
 # SCPI support
 libsigrok_la_SOURCES += \
        src/scpi/scpi.c \
+       src/scpi/helpers.c \
        src/scpi/scpi_tcp.c
 if NEED_RPC
 libsigrok_la_SOURCES += \
index e2c15ac88cc43a86b7d37d2219d03b49decf76dd..58e14f6e08abdaf9cf8848efad9fc0a0a6611401 100644 (file)
@@ -19,6 +19,7 @@
 
 #include <string.h>
 #include <strings.h>
+#include "scpi.h"
 #include "protocol.h"
 
 SR_PRIV struct sr_dev_driver scpi_pps_driver_info;
@@ -72,7 +73,7 @@ static struct sr_dev_inst *probe_device(struct sr_scpi_dev_inst *scpi)
 
        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);
@@ -128,7 +129,7 @@ static struct sr_dev_inst *probe_device(struct sr_scpi_dev_inst *scpi)
        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);
@@ -165,7 +166,7 @@ static struct sr_dev_inst *probe_device(struct sr_scpi_dev_inst *scpi)
        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;
@@ -201,13 +202,15 @@ static int dev_open(struct sr_dev_inst *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);
        }
@@ -227,8 +230,8 @@ static int dev_close(struct sr_dev_inst *sdi)
        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;
        }
@@ -258,6 +261,7 @@ static int config_get(uint32_t key, GVariant **data, const struct sr_dev_inst *s
        const GVariantType *gvtype;
        unsigned int i;
        int cmd, ret;
+       char *s;
 
        if (!sdi)
                return SR_ERR_ARG;
@@ -347,12 +351,33 @@ static int config_get(uint32_t key, GVariant **data, const struct sr_dev_inst *s
                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;
 }
@@ -360,6 +385,7 @@ static int config_get(uint32_t key, GVariant **data, const struct sr_dev_inst *s
 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;
 
@@ -373,51 +399,65 @@ static int config_set(uint32_t key, GVariant *data, const struct sr_dev_inst *sd
                /* 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;
@@ -536,8 +576,7 @@ static int config_list(uint32_t key, GVariant **data, const struct sr_dev_inst *
        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;
@@ -572,7 +611,7 @@ static int dev_acquisition_start(const struct sr_dev_inst *sdi,
                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;
 }
index c8c7e3720f0ba077730ca3391087411ff72e1a28..cc5c0ce3c6bdd4dd637a68dc2a3a16c3411f8e4e 100644 (file)
 #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 */
@@ -96,6 +75,7 @@ static const struct scpi_command agilent_n5700a_cmd[] = {
        /* 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 */
@@ -141,6 +121,7 @@ static const struct scpi_command chroma_61604_cmd[] = {
        /* 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 */
@@ -183,6 +164,7 @@ static const struct scpi_command chroma_62000_cmd[] = {
        { 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,
@@ -307,6 +289,7 @@ static const struct scpi_command rigol_dp800_cmd[] = {
        { 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 */
@@ -337,6 +320,7 @@ static const struct scpi_command hp_6632b_cmd[] = {
        { 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 */
@@ -483,6 +467,7 @@ static const struct scpi_command philips_pm2800_cmd[] = {
        { 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[] = {
@@ -492,7 +477,7 @@ 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 */
@@ -501,7 +486,7 @@ SR_PRIV const struct scpi_pps pps_profiles[] = {
                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 */
@@ -510,7 +495,7 @@ SR_PRIV const struct scpi_pps pps_profiles[] = {
                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 */
@@ -519,7 +504,7 @@ SR_PRIV const struct scpi_pps pps_profiles[] = {
                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,
        },
 
@@ -529,7 +514,7 @@ SR_PRIV const struct scpi_pps pps_profiles[] = {
                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,
@@ -537,7 +522,7 @@ SR_PRIV const struct scpi_pps pps_profiles[] = {
                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,
@@ -545,7 +530,7 @@ SR_PRIV const struct scpi_pps pps_profiles[] = {
                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,
        },
 
@@ -555,7 +540,7 @@ SR_PRIV const struct scpi_pps pps_profiles[] = {
                ARRAY_AND_SIZE(philips_pm2800_devopts_cg),
                NULL, 0,
                NULL, 0,
-               ARRAY_AND_SIZE(philips_pm2800_cmd),
+               philips_pm2800_cmd,
                philips_pm2800_probe_channels,
        },
 };
index a27089f52a7981f1b936ee2c46599abede38dd3e..c4b73add15b3dec0605caf67aa766efa218f825a 100644 (file)
 #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;
@@ -149,7 +46,8 @@ SR_PRIV int select_channel(const struct sr_dev_inst *sdi, struct sr_channel *ch)
                }
        }
 
-       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;
@@ -235,7 +133,7 @@ SR_PRIV int scpi_pps_receive_data(int fd, int revents, void *cb_data)
                cmd = SCPI_CMD_GET_MEAS_POWER;
        else
                return SR_ERR;
-       scpi_cmd(sdi, cmd);
+       scpi_cmd(sdi, devc->device->commands, cmd);
 
        return TRUE;
 }
index 063fddc1b563fe7bda406e4ff91447a40647cf54..7758924581958d699514359769629e2c11c8f207 100644 (file)
@@ -24,6 +24,7 @@
 #include <glib.h>
 #include <libsigrok/libsigrok.h>
 #include "libsigrok-internal.h"
+#include "scpi.h"
 
 #define LOG_PREFIX "scpi-pps"
 
@@ -92,7 +93,6 @@ struct 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);
@@ -106,11 +106,6 @@ struct channel_spec {
        float frequency[3];
 };
 
-struct scpi_command {
-       int command;
-       const char *string;
-};
-
 struct channel_group_spec {
        const char *name;
        uint64_t channel_index_mask;
@@ -160,10 +155,6 @@ SR_PRIV extern unsigned int num_pps_profiles;
 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);
index 36bc16270c6e3c19bcbc6f5e3a2340ec3c456ecc..28b33287629faf492f618f61657e6946089b3136 100644 (file)
@@ -58,6 +58,11 @@ enum {
        SCPI_CMD_GET_SAMPLE_RATE_LIVE,
 };
 
+struct scpi_command {
+       int command;
+       const char *string;
+};
+
 struct sr_scpi_hw_info {
        char *manufacturer;
        char *model;
@@ -125,4 +130,12 @@ SR_PRIV int sr_scpi_get_hw_id(struct sr_scpi_dev_inst *scpi,
                        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
diff --git a/src/scpi/helpers.c b/src/scpi/helpers.c
new file mode 100644 (file)
index 0000000..d93d9e2
--- /dev/null
@@ -0,0 +1,136 @@
+/*
+ * 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;
+}