static int dev_open(struct sr_dev_inst *sdi) { struct dev_context *devc; struct sr_scpi_dev_inst *scpi; GVariant *beeper; if (sdi->status != SR_ST_INACTIVE) return SR_ERR; scpi = sdi->conn; if (sr_scpi_open(scpi) < 0) return SR_ERR; sdi->status = SR_ST_ACTIVE; 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, 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; }
SR_PRIV int select_channel(const struct sr_dev_inst *sdi, struct sr_channel *ch) { struct dev_context *devc; struct pps_channel *cur_pch, *new_pch; int ret; if (g_slist_length(sdi->channels) == 1) return SR_OK; devc = sdi->priv; if (ch == devc->cur_channel) return SR_OK; new_pch = ch->priv; if (devc->cur_channel) { cur_pch = devc->cur_channel->priv; if (cur_pch->hw_output_idx == new_pch->hw_output_idx) { /* Same underlying output channel. */ devc->cur_channel = ch; return SR_OK; } } if ((ret = scpi_cmd(sdi, SCPI_CMD_SELECT_CHANNEL, new_pch->hwname)) == SR_OK) devc->cur_channel = ch; return ret; }
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) { if (devc->beeper_was_set) 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; } return SR_OK; }
static int dev_acquisition_start(const struct sr_dev_inst *sdi, void *cb_data) { struct dev_context *devc; struct sr_scpi_dev_inst *scpi; struct sr_channel *ch; 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); /* Prime the pipe with the first channel's fetch. */ ch = sr_next_enabled_channel(sdi, NULL); pch = ch->priv; 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, devc->device->commands, cmd, pch->hwname); return SR_OK; }
static struct sr_dev_inst *probe_device(struct sr_scpi_dev_inst *scpi) { struct dev_context *devc; struct sr_dev_inst *sdi; struct sr_scpi_hw_info *hw_info; struct sr_channel_group *cg; struct sr_channel *ch; const struct scpi_pps *device; struct pps_channel *pch; 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 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) { sr_info("Couldn't get IDN response."); return NULL; } device = NULL; for (i = 0; i < num_pps_profiles; i++) { 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)) device = &pps_profiles[i]; g_match_info_unref(model_mi); g_regex_unref(model_re); if (device) break; } if (!device) { sr_scpi_hw_info_free(hw_info); return NULL; } sdi = g_malloc0(sizeof(struct sr_dev_inst)); sdi->status = SR_ST_INACTIVE; 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 = &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 < num_channels; ch_num++) { /* Create one channel per measurable output unit. */ for (i = 0; i < ARRAY_SIZE(pci); i++) { 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); 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 = channels[ch_num].name; pch->mq = pci[i].mq; ch->priv = pch; } } 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) { if (cgs->channel_index_mask & mask) { for (l = sdi->channels; l; l = l->next) { ch = l->data; pch = ch->priv; if (pch->hw_output_idx == j) cg->channels = g_slist_append(cg->channels, ch); } } } pcg = g_malloc0(sizeof(struct pps_channel_group)); pcg->features = cgs->features; cg->priv = pcg; sdi->channel_groups = g_slist_append(sdi->channel_groups, cg); } sr_scpi_hw_info_free(hw_info); hw_info = NULL; scpi_cmd(sdi, devc->device->commands, SCPI_CMD_LOCAL); sr_scpi_close(scpi); return sdi; }
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); devc = sdi->priv; ret = SR_OK; switch (key) { case SR_CONF_ENABLED: if (g_variant_get_boolean(data)) ret = scpi_cmd(sdi, devc->device->commands, SCPI_CMD_SET_OUTPUT_ENABLE); else 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_FREQUENCY_TARGET: d = g_variant_get_double(data); 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, 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, devc->device->commands, SCPI_CMD_SET_OVER_VOLTAGE_PROTECTION_ENABLE); else 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, 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, devc->device->commands, SCPI_CMD_SET_OVER_CURRENT_PROTECTION_ENABLE); else 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, 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, devc->device->commands, SCPI_CMD_SET_OVER_TEMPERATURE_PROTECTION_ENABLE); else ret = scpi_cmd(sdi, devc->device->commands, SCPI_CMD_SET_OVER_TEMPERATURE_PROTECTION_DISABLE); break; default: ret = SR_ERR_NA; } return ret; }
SR_PRIV int scpi_pps_receive_data(int fd, int revents, void *cb_data) { struct dev_context *devc; struct sr_datafeed_packet packet; struct sr_datafeed_analog analog; const struct sr_dev_inst *sdi; struct sr_channel *next_channel; struct sr_scpi_dev_inst *scpi; struct pps_channel *pch; float f; int cmd; (void)fd; (void)revents; if (!(sdi = cb_data)) return TRUE; if (!(devc = sdi->priv)) return TRUE; scpi = sdi->conn; /* Retrieve requested value for this state. */ if (sr_scpi_get_float(scpi, NULL, &f) == SR_OK) { pch = devc->cur_channel->priv; packet.type = SR_DF_ANALOG; packet.payload = &analog; analog.channels = g_slist_append(NULL, devc->cur_channel); analog.num_samples = 1; analog.mq = pch->mq; if (pch->mq == SR_MQ_VOLTAGE) analog.unit = SR_UNIT_VOLT; else if (pch->mq == SR_MQ_CURRENT) analog.unit = SR_UNIT_AMPERE; else if (pch->mq == SR_MQ_POWER) analog.unit = SR_UNIT_WATT; analog.mqflags = SR_MQFLAG_DC; analog.data = &f; sr_session_send(sdi, &packet); g_slist_free(analog.channels); } if (g_slist_length(sdi->channels) > 1) { next_channel = next_enabled_channel(sdi, devc->cur_channel); if (select_channel(sdi, next_channel) != SR_OK) { sr_err("Failed to select channel %s", next_channel->name); return FALSE; } } pch = devc->cur_channel->priv; 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); return TRUE; }
SR_PRIV int scpi_pps_receive_data(int fd, int revents, void *cb_data) { struct dev_context *devc; struct sr_datafeed_packet packet; struct sr_datafeed_analog analog; struct sr_analog_encoding encoding; struct sr_analog_meaning meaning; struct sr_analog_spec spec; const struct sr_dev_inst *sdi; struct sr_channel *next_channel; struct sr_scpi_dev_inst *scpi; struct pps_channel *pch; const struct channel_spec *ch_spec; float f; int cmd; (void)fd; (void)revents; if (!(sdi = cb_data)) return TRUE; if (!(devc = sdi->priv)) return TRUE; scpi = sdi->conn; /* Retrieve requested value for this state. */ if (sr_scpi_get_float(scpi, NULL, &f) == SR_OK) { pch = devc->cur_channel->priv; ch_spec = &devc->device->channels[pch->hw_output_idx]; packet.type = SR_DF_ANALOG; packet.payload = &analog; /* Note: digits/spec_digits will be overridden later. */ sr_analog_init(&analog, &encoding, &meaning, &spec, 0); analog.meaning->channels = g_slist_append(NULL, devc->cur_channel); analog.num_samples = 1; analog.meaning->mq = pch->mq; if (pch->mq == SR_MQ_VOLTAGE) { analog.meaning->unit = SR_UNIT_VOLT; analog.encoding->digits = ch_spec->voltage[4]; analog.spec->spec_digits = ch_spec->voltage[3]; } else if (pch->mq == SR_MQ_CURRENT) { analog.meaning->unit = SR_UNIT_AMPERE; analog.encoding->digits = ch_spec->current[4]; analog.spec->spec_digits = ch_spec->current[3]; } else if (pch->mq == SR_MQ_POWER) { analog.meaning->unit = SR_UNIT_WATT; analog.encoding->digits = ch_spec->power[4]; analog.spec->spec_digits = ch_spec->power[3]; } analog.meaning->mqflags = SR_MQFLAG_DC; analog.data = &f; sr_session_send(sdi, &packet); g_slist_free(analog.meaning->channels); } if (g_slist_length(sdi->channels) > 1) { next_channel = sr_next_enabled_channel(sdi, devc->cur_channel); if (select_channel(sdi, next_channel) != SR_OK) { sr_err("Failed to select channel %s", next_channel->name); return FALSE; } } pch = devc->cur_channel->priv; 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, devc->device->commands, cmd); return TRUE; }