X-Git-Url: https://sigrok.org/gitweb/?a=blobdiff_plain;f=src%2Fhardware%2Fscpi-pps%2Fapi.c;h=7448796298ddb082a777d123ed75b428e303bb0e;hb=e66d1892d0dd16ed166fc8f13493f95de0607362;hp=8bb0ac0ce4450bc70ab45a84f74d064674cfee83;hpb=bf48ccebeed885652312188770ec893f7425cb43;p=libsigrok.git diff --git a/src/hardware/scpi-pps/api.c b/src/hardware/scpi-pps/api.c index 8bb0ac0c..74487962 100644 --- a/src/hardware/scpi-pps/api.c +++ b/src/hardware/scpi-pps/api.c @@ -17,31 +17,34 @@ * along with this program. If not, see . */ +#include #include +#include +#include "scpi.h" #include "protocol.h" -SR_PRIV struct sr_dev_driver scpi_pps_driver_info; -static struct sr_dev_driver *di = &scpi_pps_driver_info; -extern unsigned int num_pps_profiles; -extern const struct scpi_pps pps_profiles[]; +static struct sr_dev_driver scpi_pps_driver_info; +static struct sr_dev_driver hp_ib_pps_driver_info; static const uint32_t scanopts[] = { SR_CONF_CONN, SR_CONF_SERIALCOMM, }; -static struct pps_channel_instance pci[] = { +static const uint32_t drvopts[] = { + SR_CONF_POWER_SUPPLY, +}; + +static const struct pps_channel_instance pci[] = { { SR_MQ_VOLTAGE, SCPI_CMD_GET_MEAS_VOLTAGE, "V" }, { SR_MQ_CURRENT, SCPI_CMD_GET_MEAS_CURRENT, "I" }, { SR_MQ_POWER, SCPI_CMD_GET_MEAS_POWER, "P" }, + { SR_MQ_FREQUENCY, SCPI_CMD_GET_MEAS_FREQUENCY, "F" }, }; -static int init(struct sr_context *sr_ctx) -{ - return std_init(sr_ctx, di, LOG_PREFIX); -} - -static struct sr_dev_inst *probe_device(struct sr_scpi_dev_inst *scpi) +static struct sr_dev_inst *probe_device(struct sr_scpi_dev_inst *scpi, + int (*get_hw_id)(struct sr_scpi_dev_inst *scpi, + struct sr_scpi_hw_info **scpi_response)) { struct dev_context *devc; struct sr_dev_inst *sdi; @@ -50,25 +53,27 @@ static struct sr_dev_inst *probe_device(struct sr_scpi_dev_inst *scpi) struct sr_channel *ch; const struct scpi_pps *device; struct pps_channel *pch; - const struct channel_group_spec *cgs; + struct channel_spec *channels; + struct channel_group_spec *channel_groups, *cgs; struct pps_channel_group *pcg; GRegex *model_re; GMatchInfo *model_mi; GSList *l; uint64_t mask; - unsigned int ch_num, ch_idx, i, j; + unsigned int num_channels, num_channel_groups, ch_num, ch_idx, i, j; + int ret; const char *vendor; char ch_name[16]; - if (sr_scpi_get_hw_id(scpi, &hw_info) != SR_OK) { + if (get_hw_id(scpi, &hw_info) != SR_OK) { sr_info("Couldn't get IDN response."); return NULL; } device = NULL; for (i = 0; i < num_pps_profiles; i++) { - vendor = get_vendor(hw_info->manufacturer); - if (strcasecmp(vendor, pps_profiles[i].vendor)) + vendor = sr_vendor_alias(hw_info->manufacturer); + if (g_ascii_strcasecmp(vendor, pps_profiles[i].vendor)) continue; model_re = g_regex_new(pps_profiles[i].model, 0, 0, NULL); if (g_regex_match(model_re, hw_info->model, 0, &model_mi)) @@ -83,35 +88,61 @@ static struct sr_dev_inst *probe_device(struct sr_scpi_dev_inst *scpi) return NULL; } - sdi = sr_dev_inst_new(SR_ST_ACTIVE, vendor, hw_info->model, - hw_info->firmware_version); + sdi = g_malloc0(sizeof(struct sr_dev_inst)); + sdi->vendor = g_strdup(vendor); + sdi->model = g_strdup(hw_info->model); + sdi->version = g_strdup(hw_info->firmware_version); sdi->conn = scpi; - sdi->driver = di; + sdi->driver = &scpi_pps_driver_info; sdi->inst_type = SR_INST_SCPI; + sdi->serial_num = g_strdup(hw_info->serial_number); + devc = g_malloc0(sizeof(struct dev_context)); devc->device = device; sdi->priv = devc; + if (device->num_channels) { + /* Static channels and groups. */ + channels = (struct channel_spec *)device->channels; + num_channels = device->num_channels; + channel_groups = (struct channel_group_spec *)device->channel_groups; + num_channel_groups = device->num_channel_groups; + } else { + /* Channels and groups need to be probed. */ + ret = device->probe_channels(sdi, hw_info, &channels, &num_channels, + &channel_groups, &num_channel_groups); + if (ret != SR_OK) { + sr_err("Failed to probe for channels."); + return NULL; + } + /* + * Since these were dynamically allocated, we'll need to free them + * later. + */ + devc->channels = channels; + devc->channel_groups = channel_groups; + } + ch_idx = 0; - for (ch_num = 0; ch_num < device->num_channels; ch_num++) { + 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, - device->channels[ch_num].name); - ch = sr_channel_new(ch_idx++, SR_CHANNEL_ANALOG, TRUE, ch_name); + channels[ch_num].name); + ch = sr_channel_new(sdi, ch_idx++, SR_CHANNEL_ANALOG, TRUE, + ch_name); pch = g_malloc0(sizeof(struct pps_channel)); pch->hw_output_idx = ch_num; - pch->hwname = device->channels[ch_num].name; + pch->hwname = channels[ch_num].name; pch->mq = pci[i].mq; ch->priv = pch; - sdi->channels = g_slist_append(sdi->channels, ch); } } - for (i = 0; i < device->num_channel_groups; i++) { - cgs = &device->channel_groups[i]; + for (i = 0; i < num_channel_groups; i++) { + cgs = &channel_groups[i]; cg = g_malloc0(sizeof(struct sr_channel_group)); cg->name = g_strdup(cgs->name); for (j = 0, mask = 1; j < 64; j++, mask <<= 1) { @@ -130,41 +161,111 @@ static struct sr_dev_inst *probe_device(struct sr_scpi_dev_inst *scpi) sdi->channel_groups = g_slist_append(sdi->channel_groups, cg); } - scpi_cmd(sdi, SCPI_CMD_LOCAL); - sr_scpi_close(scpi); + sr_scpi_hw_info_free(hw_info); + hw_info = NULL; + + scpi_cmd(sdi, devc->device->commands, SCPI_CMD_LOCAL); return sdi; } -static GSList *scan(GSList *options) +static gchar *hpib_get_revision(struct sr_scpi_dev_inst *scpi) +{ + int ret; + gboolean matches; + char *response; + GRegex *version_regex; + + ret = sr_scpi_get_string(scpi, "ROM?", &response); + if (ret != SR_OK && !response) + return NULL; + + /* Example version string: "B01 B01" */ + version_regex = g_regex_new("[A-Z][0-9]{2} [A-Z][0-9]{2}", 0, 0, NULL); + matches = g_regex_match(version_regex, response, 0, NULL); + g_regex_unref(version_regex); + + if (!matches) { + /* Not a valid version string. Ignore it. */ + g_free(response); + response = NULL; + } else { + /* Replace space with dot. */ + response[3] = '.'; + } + + return response; +} + +/* + * This function assumes the response is in the form "HP" + * + * HP made many GPIB (then called HP-IB) instruments before the SCPI command + * set was introduced into the standard. We haven't seen any non-HP instruments + * which respond to the "ID?" query, so assume all are HP for now. + */ +static int hpib_get_hw_id(struct sr_scpi_dev_inst *scpi, + struct sr_scpi_hw_info **scpi_response) +{ + int ret; + char *response; + struct sr_scpi_hw_info *hw_info; + + ret = sr_scpi_get_string(scpi, "ID?", &response); + if ((ret != SR_OK) || !response) + return SR_ERR; + + hw_info = g_malloc0(sizeof(struct sr_scpi_hw_info)); + + *scpi_response = hw_info; + hw_info->model = response; + hw_info->firmware_version = hpib_get_revision(scpi); + hw_info->manufacturer = g_strdup("HP"); + + return SR_OK; +} + +static struct sr_dev_inst *probe_scpi_pps_device(struct sr_scpi_dev_inst *scpi) { - return sr_scpi_scan(di->priv, options, probe_device); + return probe_device(scpi, sr_scpi_get_hw_id); } -static GSList *dev_list(void) +static struct sr_dev_inst *probe_hpib_pps_device(struct sr_scpi_dev_inst *scpi) { - return ((struct drv_context *)(di->priv))->instances; + return probe_device(scpi, hpib_get_hw_id); } -static int dev_clear(void) +static GSList *scan_scpi_pps(struct sr_dev_driver *di, GSList *options) { - return std_dev_clear(di, NULL); + return sr_scpi_scan(di->context, options, probe_scpi_pps_device); +} + +static GSList *scan_hpib_pps(struct sr_dev_driver *di, GSList *options) +{ + return sr_scpi_scan(di->context, options, probe_hpib_pps_device); } static int dev_open(struct sr_dev_inst *sdi) { + struct dev_context *devc; struct sr_scpi_dev_inst *scpi; - - if (sdi->status != SR_ST_ACTIVE) - return SR_ERR; + GVariant *beeper; scpi = sdi->conn; if (sr_scpi_open(scpi) < 0) return SR_ERR; - sdi->status = SR_ST_ACTIVE; - - scpi_cmd(sdi, SCPI_CMD_REMOTE); + devc = sdi->priv; + scpi_cmd(sdi, devc->device->commands, SCPI_CMD_REMOTE); + devc->beeper_was_set = FALSE; + 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, devc->device->commands, SCPI_CMD_BEEPER_DISABLE); + } + g_variant_unref(beeper); + } return SR_OK; } @@ -172,23 +273,30 @@ static int dev_open(struct sr_dev_inst *sdi) static int dev_close(struct sr_dev_inst *sdi) { struct sr_scpi_dev_inst *scpi; + struct dev_context *devc; - if (sdi->status != SR_ST_ACTIVE) - return SR_ERR_DEV_CLOSED; - + devc = sdi->priv; scpi = sdi->conn; - if (scpi) { - scpi_cmd(sdi, SCPI_CMD_LOCAL); - sr_scpi_close(scpi); - sdi->status = SR_ST_INACTIVE; - } - return SR_OK; + if (!scpi) + return SR_ERR_BUG; + + if (devc->beeper_was_set) + scpi_cmd(sdi, devc->device->commands, SCPI_CMD_BEEPER_ENABLE); + scpi_cmd(sdi, devc->device->commands, SCPI_CMD_LOCAL); + + return sr_scpi_close(scpi); +} + +static void clear_helper(struct dev_context *devc) +{ + g_free(devc->channels); + g_free(devc->channel_groups); } -static int cleanup(void) +static int dev_clear(const struct sr_dev_driver *di) { - return std_dev_clear(di, NULL); + return std_dev_clear_with_callback(di, (std_dev_clear_callback)clear_helper); } static int config_get(uint32_t key, GVariant **data, const struct sr_dev_inst *sdi, @@ -228,23 +336,31 @@ static int config_get(uint32_t key, GVariant **data, const struct sr_dev_inst *s gvtype = NULL; cmd = -1; switch (key) { - case SR_CONF_OUTPUT_ENABLED: + case SR_CONF_ENABLED: gvtype = G_VARIANT_TYPE_BOOLEAN; cmd = SCPI_CMD_GET_OUTPUT_ENABLED; break; - case SR_CONF_OUTPUT_VOLTAGE: + case SR_CONF_VOLTAGE: gvtype = G_VARIANT_TYPE_DOUBLE; cmd = SCPI_CMD_GET_MEAS_VOLTAGE; break; - case SR_CONF_OUTPUT_VOLTAGE_TARGET: + case SR_CONF_VOLTAGE_TARGET: gvtype = G_VARIANT_TYPE_DOUBLE; cmd = SCPI_CMD_GET_VOLTAGE_TARGET; break; - case SR_CONF_OUTPUT_CURRENT: + case SR_CONF_OUTPUT_FREQUENCY: + gvtype = G_VARIANT_TYPE_DOUBLE; + cmd = SCPI_CMD_GET_MEAS_FREQUENCY; + break; + case SR_CONF_OUTPUT_FREQUENCY_TARGET: + gvtype = G_VARIANT_TYPE_DOUBLE; + cmd = SCPI_CMD_GET_FREQUENCY_TARGET; + break; + case SR_CONF_CURRENT: gvtype = G_VARIANT_TYPE_DOUBLE; cmd = SCPI_CMD_GET_MEAS_CURRENT; break; - case SR_CONF_OUTPUT_CURRENT_LIMIT: + case SR_CONF_CURRENT_LIMIT: gvtype = G_VARIANT_TYPE_DOUBLE; cmd = SCPI_CMD_GET_CURRENT_LIMIT; break; @@ -276,35 +392,38 @@ static int config_get(uint32_t key, GVariant **data, const struct sr_dev_inst *s gvtype = G_VARIANT_TYPE_BOOLEAN; cmd = SCPI_CMD_GET_OVER_TEMPERATURE_PROTECTION; break; - case SR_CONF_OUTPUT_REGULATION: + case SR_CONF_REGULATION: 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); - - if (gvtype == G_VARIANT_TYPE_STRING && ret == SR_OK) { - /* Non-standard data type responses. */ - switch (key) { - case SCPI_CMD_GET_OUTPUT_REGULATION: - /* - * This is specific to the Rigol DP800 series. - * We return the same string for now until more - * models with this key are supported. Do a check - * just for the hell of it. - */ - s = g_variant_get_string(*data, NULL); - if (strcmp(s, "CC") && strcmp(s, "CV") && strcmp(s, "UR")) { - sr_dbg("Unknown response to SCPI_CMD_GET_OUTPUT_REGULATION: %s", s); - ret = SR_ERR_DATA; - } - break; - } + 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. + */ + s = g_variant_get_string(*data, NULL); + if (!strcmp(s, "VOLT")) { + g_variant_unref(*data); + *data = g_variant_new_string("CV"); + } else if (!strcmp(s, "CURR")) { + g_variant_unref(*data); + *data = g_variant_new_string("CC"); } - } else - ret = SR_ERR_NA; + + s = g_variant_get_string(*data, NULL); + if (strcmp(s, "CV") && strcmp(s, "CC") && strcmp(s, "UR")) { + sr_dbg("Unknown response to SCPI_CMD_GET_OUTPUT_REGULATION: %s", s); + ret = SR_ERR_DATA; + } + } return ret; } @@ -312,60 +431,76 @@ 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; if (!sdi) return SR_ERR_ARG; - if (sdi->status != SR_ST_ACTIVE) - return SR_ERR_DEV_CLOSED; - if (cg) /* Channel group specified. */ select_channel(sdi, cg->channels->data); - ret = SR_OK; + devc = sdi->priv; + switch (key) { - case SR_CONF_OUTPUT_ENABLED: + 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, devc->device->commands, + SCPI_CMD_SET_VOLTAGE_TARGET, d); break; - case SR_CONF_OUTPUT_VOLTAGE_TARGET: + case SR_CONF_OUTPUT_FREQUENCY_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_FREQUENCY_TARGET, d); break; - case SR_CONF_OUTPUT_CURRENT_LIMIT: + 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; @@ -379,33 +514,26 @@ static int config_list(uint32_t key, GVariant **data, const struct sr_dev_inst * { struct dev_context *devc; struct sr_channel *ch; - struct channel_spec *ch_spec; + const struct channel_spec *ch_spec; GVariant *gvar; GVariantBuilder gvb; - int ret, i; + int i; const char *s[16]; - /* Always available, even without sdi. */ - if (key == SR_CONF_SCAN_OPTIONS) { - *data = g_variant_new_fixed_array(G_VARIANT_TYPE_UINT32, - scanopts, ARRAY_SIZE(scanopts), sizeof(uint32_t)); - return SR_OK; - } - - if (!sdi) - return SR_ERR_ARG; - devc = sdi->priv; + devc = (sdi) ? sdi->priv : NULL; - ret = SR_OK; if (!cg) { /* No channel group: global options. */ switch (key) { + case SR_CONF_SCAN_OPTIONS: case SR_CONF_DEVICE_OPTIONS: - *data = g_variant_new_fixed_array(G_VARIANT_TYPE_UINT32, - devc->device->devopts, devc->device->num_devopts, - sizeof(uint32_t)); + return std_opts_config_list(key, data, sdi, cg, + scanopts, ARRAY_SIZE(scanopts), + drvopts, ARRAY_SIZE(drvopts), + (devc) ? devc->device->devopts : NULL, + (devc) ? devc->device->num_devopts : 0); break; - case SR_CONF_OUTPUT_CHANNEL_CONFIG: + case SR_CONF_CHANNEL_CONFIG: /* Not used. */ i = 0; if (devc->device->features & PPS_INDEPENDENT) @@ -442,7 +570,7 @@ static int config_list(uint32_t key, GVariant **data, const struct sr_dev_inst * devc->device->devopts_cg, devc->device->num_devopts_cg, sizeof(uint32_t)); break; - case SR_CONF_OUTPUT_VOLTAGE_TARGET: + case SR_CONF_VOLTAGE_TARGET: ch_spec = &(devc->device->channels[ch->index]); g_variant_builder_init(&gvb, G_VARIANT_TYPE_ARRAY); /* Min, max, write resolution. */ @@ -452,7 +580,17 @@ static int config_list(uint32_t key, GVariant **data, const struct sr_dev_inst * } *data = g_variant_builder_end(&gvb); break; - case SR_CONF_OUTPUT_CURRENT_LIMIT: + case SR_CONF_OUTPUT_FREQUENCY_TARGET: + ch_spec = &(devc->device->channels[ch->index]); + g_variant_builder_init(&gvb, G_VARIANT_TYPE_ARRAY); + /* Min, max, write resolution. */ + for (i = 0; i < 3; i++) { + gvar = g_variant_new_double(ch_spec->frequency[i]); + g_variant_builder_add_value(&gvb, gvar); + } + *data = g_variant_builder_end(&gvb); + break; + case SR_CONF_CURRENT_LIMIT: g_variant_builder_init(&gvb, G_VARIANT_TYPE_ARRAY); /* Min, max, step. */ for (i = 0; i < 3; i++) { @@ -467,11 +605,10 @@ static int config_list(uint32_t key, GVariant **data, const struct sr_dev_inst * } } - return ret; + return SR_OK; } -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) { struct dev_context *devc; struct sr_scpi_dev_inst *scpi; @@ -479,46 +616,39 @@ static int dev_acquisition_start(const struct sr_dev_inst *sdi, struct pps_channel *pch; int cmd, ret; - if (sdi->status != SR_ST_ACTIVE) - return SR_ERR_DEV_CLOSED; - devc = sdi->priv; scpi = sdi->conn; - devc->cb_data = cb_data; if ((ret = sr_scpi_source_add(sdi->session, scpi, G_IO_IN, 10, scpi_pps_receive_data, (void *)sdi)) != SR_OK) return ret; - std_session_send_df_header(sdi, LOG_PREFIX); + std_session_send_df_header(sdi); /* Prime the pipe with the first channel's fetch. */ - ch = sdi->channels->data; + ch = sr_next_enabled_channel(sdi, NULL); pch = ch->priv; - select_channel(sdi, ch); + if ((ret = select_channel(sdi, ch)) < 0) + return ret; if (pch->mq == SR_MQ_VOLTAGE) cmd = SCPI_CMD_GET_MEAS_VOLTAGE; + else if (pch->mq == SR_MQ_FREQUENCY) + cmd = SCPI_CMD_GET_MEAS_FREQUENCY; else if (pch->mq == SR_MQ_CURRENT) cmd = SCPI_CMD_GET_MEAS_CURRENT; else if (pch->mq == SR_MQ_POWER) 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; } -static int dev_acquisition_stop(struct sr_dev_inst *sdi, void *cb_data) +static int dev_acquisition_stop(struct sr_dev_inst *sdi) { - struct sr_datafeed_packet packet; struct sr_scpi_dev_inst *scpi; float f; - (void)cb_data; - - if (sdi->status != SR_ST_ACTIVE) - return SR_ERR_DEV_CLOSED; - scpi = sdi->conn; /* @@ -529,20 +659,38 @@ static int dev_acquisition_stop(struct sr_dev_inst *sdi, void *cb_data) sr_scpi_get_float(scpi, NULL, &f); sr_scpi_source_remove(sdi->session, scpi); - packet.type = SR_DF_END; - sr_session_send(sdi, &packet); + std_session_send_df_end(sdi); return SR_OK; } -SR_PRIV struct sr_dev_driver scpi_pps_driver_info = { +static struct sr_dev_driver scpi_pps_driver_info = { .name = "scpi-pps", .longname = "SCPI PPS", .api_version = 1, - .init = init, - .cleanup = cleanup, - .scan = scan, - .dev_list = dev_list, + .init = std_init, + .cleanup = std_cleanup, + .scan = scan_scpi_pps, + .dev_list = std_dev_list, + .dev_clear = dev_clear, + .config_get = config_get, + .config_set = config_set, + .config_list = config_list, + .dev_open = dev_open, + .dev_close = dev_close, + .dev_acquisition_start = dev_acquisition_start, + .dev_acquisition_stop = dev_acquisition_stop, + .context = NULL, +}; + +static struct sr_dev_driver hp_ib_pps_driver_info = { + .name = "hpib-pps", + .longname = "HP-IB PPS", + .api_version = 1, + .init = std_init, + .cleanup = std_cleanup, + .scan = scan_hpib_pps, + .dev_list = std_dev_list, .dev_clear = dev_clear, .config_get = config_get, .config_set = config_set, @@ -551,5 +699,7 @@ SR_PRIV struct sr_dev_driver scpi_pps_driver_info = { .dev_close = dev_close, .dev_acquisition_start = dev_acquisition_start, .dev_acquisition_stop = dev_acquisition_stop, - .priv = NULL, + .context = NULL, }; +SR_REGISTER_DEV_DRIVER(scpi_pps_driver_info); +SR_REGISTER_DEV_DRIVER(hp_ib_pps_driver_info);