X-Git-Url: https://sigrok.org/gitweb/?a=blobdiff_plain;f=src%2Fhardware%2Fscpi-pps%2Fapi.c;h=2746dc4019dc01b5c1f9a56446b536a882a724b8;hb=093e1cba6b7bf14cfb77fa36f59b0c16e6fca7cc;hp=c3e5d5d4ad6a90607fcea56a9304ed94889cedba;hpb=dd5c48a6d567a3cac62c4b0058588273bbeea171;p=libsigrok.git diff --git a/src/hardware/scpi-pps/api.c b/src/hardware/scpi-pps/api.c index c3e5d5d4..2746dc40 100644 --- a/src/hardware/scpi-pps/api.c +++ b/src/hardware/scpi-pps/api.c @@ -24,6 +24,7 @@ #include "protocol.h" 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, @@ -41,7 +42,9 @@ static const struct pps_channel_instance pci[] = { { SR_MQ_FREQUENCY, SCPI_CMD_GET_MEAS_FREQUENCY, "F" }, }; -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; @@ -62,7 +65,7 @@ static struct sr_dev_inst *probe_device(struct sr_scpi_dev_inst *scpi) 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; } @@ -166,9 +169,80 @@ static struct sr_dev_inst *probe_device(struct sr_scpi_dev_inst *scpi) return sdi; } -static GSList *scan(struct sr_dev_driver *di, GSList *options) +static gchar *hpib_get_revision(struct sr_scpi_dev_inst *scpi) { - return sr_scpi_scan(di->context, options, probe_device); + 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 probe_device(scpi, sr_scpi_get_hw_id); +} + +static struct sr_dev_inst *probe_hpib_pps_device(struct sr_scpi_dev_inst *scpi) +{ + return probe_device(scpi, hpib_get_hw_id); +} + +static GSList *scan_scpi_pps(struct sr_dev_driver *di, GSList *options) +{ + 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) @@ -206,9 +280,6 @@ 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) { @@ -376,9 +447,6 @@ static int config_set(uint32_t key, GVariant *data, const struct sr_dev_inst *sd 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); @@ -568,16 +636,13 @@ 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; 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 = sr_next_enabled_channel(sdi, NULL); @@ -604,9 +669,6 @@ static int dev_acquisition_stop(struct sr_dev_inst *sdi) struct sr_scpi_dev_inst *scpi; float f; - if (sdi->status != SR_ST_ACTIVE) - return SR_ERR_DEV_CLOSED; - scpi = sdi->conn; /* @@ -617,7 +679,7 @@ static int dev_acquisition_stop(struct sr_dev_inst *sdi) sr_scpi_get_float(scpi, NULL, &f); sr_scpi_source_remove(sdi->session, scpi); - std_session_send_df_end(sdi, LOG_PREFIX); + std_session_send_df_end(sdi); return SR_OK; } @@ -628,7 +690,26 @@ static struct sr_dev_driver scpi_pps_driver_info = { .api_version = 1, .init = std_init, .cleanup = std_cleanup, - .scan = scan, + .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, @@ -641,3 +722,4 @@ static struct sr_dev_driver scpi_pps_driver_info = { .context = NULL, }; SR_REGISTER_DEV_DRIVER(scpi_pps_driver_info); +SR_REGISTER_DEV_DRIVER(hp_ib_pps_driver_info);