Add shunt resistance value configuration option to libsigrok. Implement support for this option in ACME driver in the form of key-value pair where key is the probe ID and value is the desired shunt resistance in mOhms.
Signed-off-by: Bartosz Golaszewski <bgolaszew...@baylibre.com> --- include/libsigrok/libsigrok.h | 6 ++ src/hardware/acme/acme.c | 132 +++++++++++++++++++++++++++++++++++++++++- src/hwdriver.c | 2 + 3 files changed, 138 insertions(+), 2 deletions(-) diff --git a/include/libsigrok/libsigrok.h b/include/libsigrok/libsigrok.h index 65e9da8..2f4c4fc 100644 --- a/include/libsigrok/libsigrok.h +++ b/include/libsigrok/libsigrok.h @@ -903,6 +903,12 @@ enum sr_configkey { */ SR_CONF_DATA_SOURCE, + /** + * The device is a power-monitor supporting setting + * shunt resistance values. + */ + SR_CONF_SHUNT_RESISTANCE, + /*--- Acquisition modes, sample limiting ----------------------------*/ /** diff --git a/src/hardware/acme/acme.c b/src/hardware/acme/acme.c index 3af77a4..6799428 100644 --- a/src/hardware/acme/acme.c +++ b/src/hardware/acme/acme.c @@ -63,6 +63,7 @@ static const uint32_t devopts[] = { SR_CONF_LIMIT_SAMPLES | SR_CONF_GET | SR_CONF_SET, SR_CONF_LIMIT_MSEC | SR_CONF_GET | SR_CONF_SET, SR_CONF_SAMPLERATE | SR_CONF_GET | SR_CONF_SET | SR_CONF_LIST, + SR_CONF_SHUNT_RESISTANCE | SR_CONF_GET | SR_CONF_SET, }; #define MAX_SAMPLE_RATE 500 /* In HZ */ @@ -102,6 +103,8 @@ struct dev_context { int64_t last_sample_fin; int pipe_fds[2]; GIOChannel *channel; + + struct channel_group_priv *probes[MAX_PROBES]; }; SR_PRIV struct sr_dev_driver acme_driver_info; @@ -240,8 +243,11 @@ static gboolean register_probe(struct sr_dev_inst *sdi, { struct sr_channel_group *chg; struct channel_group_priv *cgp; + struct dev_context *devc; int hwmon; + devc = sdi->priv; + /* Obtain the hwmon index. */ hwmon = get_hwmon_index(addr); if (hwmon < 0) @@ -266,6 +272,7 @@ static gboolean register_probe(struct sr_dev_inst *sdi, } sdi->channel_groups = g_slist_append(sdi->channel_groups, chg); + devc->probes[prb_num - 1] = cgp; return TRUE; } @@ -398,12 +405,99 @@ static int cleanup(void) return SR_OK; } +static int read_shunt_values(const struct sr_dev_inst *sdi, GVariant **data) +{ + struct sr_channel_group *chg; + struct channel_group_priv *chgp; + char path[256]; + uint32_t in = 0, shunt; + GSList *chgl; + gboolean status; + gchar *contents, buf[512]; + gsize size; + GError *err; + + for (chgl = sdi->channel_groups; chgl; chgl = chgl->next) { + chg = chgl->data; + chgp = chg->priv; + + in += snprintf(buf + in, sizeof(buf) - in, "%s: ", chg->name); + if (chgp->prb_type == PROBE_TEMP) { + in += snprintf(buf + in, sizeof(buf) - in, "N/A, "); + } else { + snprintf(path, sizeof(path), + "/sys/class/hwmon/hwmon%d/shunt_resistor", + chgp->hwmon_num); + status = g_file_get_contents(path, &contents, + &size, &err); + if (!status) { + sr_err("Error reading shunt resistance: %s", + err->message); + return -1; + } + + shunt = strtol(contents, NULL, 10) / 1000; + in += snprintf(buf + in, sizeof(buf) - in, + "%u mOhms, ", shunt); + g_free(contents); + } + } + + buf[in - 2] = '\0'; + *data = g_variant_new_string(buf); + + return 0; +} + +static int set_shunt(const struct dev_context *devc, + unsigned probe, unsigned shunt) +{ + char path[256], out[32]; + int ret = 0, fd; + + if (probe > MAX_PROBES) { + sr_err("Invalid probe number"); + ret = -1; + goto out; + } + + if (devc->probes[probe - 1] == NULL) { + sr_err("Probe %u not present", probe); + ret = -1; + goto out; + } + + if (devc->probes[probe - 1]->prb_type == PROBE_TEMP) { + sr_err("Unable to set shunt on a temperature probe"); + ret = -1; + goto out; + } + + snprintf(path, sizeof(path), + "/sys/class/hwmon/hwmon%u/shunt_resistor", + devc->probes[probe - 1]->hwmon_num); + snprintf(out, sizeof(out), "%u\n", shunt * 1000); + + fd = open(path, O_WRONLY); + if (fd < 0) { + sr_err("Error opening: %s\n", strerror(errno)); + ret = -1; + goto out; + } + + write(fd, out, strlen(out)); + close(fd); + +out: + return ret; +} + static int config_get(uint32_t key, GVariant **data, const struct sr_dev_inst *sdi, const struct sr_channel_group *cg) { struct dev_context *devc; - int ret; + int ret, status; (void)sdi; (void)data; @@ -422,6 +516,11 @@ static int config_get(uint32_t key, GVariant **data, case SR_CONF_SAMPLERATE: *data = g_variant_new_uint64(devc->samplerate); break; + case SR_CONF_SHUNT_RESISTANCE: + status = read_shunt_values(sdi, data); + if (status < 0) + ret = SR_ERR_BUG; + break; default: return SR_ERR_NA; } @@ -435,7 +534,11 @@ static int config_set(uint32_t key, GVariant *data, { struct dev_context *devc; uint64_t samplerate; - int ret; + int ret, status; + GVariantIter iter_arr, iter_pair; + GVariant *keyval, *probe_var, *shunt_var = NULL; + const char *probe_str, *shunt_str; + unsigned probe, shunt; (void)data; (void)cg; @@ -468,6 +571,31 @@ static int config_set(uint32_t key, GVariant *data, devc->samplerate = samplerate; sr_dbg("Setting samplerate to %" PRIu64, devc->samplerate); break; + case SR_CONF_SHUNT_RESISTANCE: + g_variant_iter_init(&iter_arr, data); + keyval = g_variant_iter_next_value(&iter_arr); + g_variant_iter_init(&iter_pair, keyval); + probe_var = g_variant_iter_next_value(&iter_pair); + if (probe_var) + shunt_var = g_variant_iter_next_value(&iter_pair); + if (!shunt_var) { + sr_err("Invalid value"); + ret = SR_ERR_ARG; + break; + } + + probe_str = g_variant_get_string(probe_var, NULL); + shunt_str = g_variant_get_string(shunt_var, NULL); + probe = strtoul(probe_str, NULL, 10); + shunt = strtoul(shunt_str, NULL, 10); + status = set_shunt(devc, probe, shunt); + if (status < 0) { + ret = SR_ERR_ARG; + break; + } + + sr_dbg("Shunt resistance for probe %u set to %u", probe, shunt); + break; default: ret = SR_ERR_NA; } diff --git a/src/hwdriver.c b/src/hwdriver.c index 239592d..1848a08 100644 --- a/src/hwdriver.c +++ b/src/hwdriver.c @@ -183,6 +183,8 @@ static struct sr_config_info sr_config_info_data[] = { "Power off", NULL}, {SR_CONF_DATA_SOURCE, SR_T_STRING, "data_source", "Data source", NULL}, + {SR_CONF_SHUNT_RESISTANCE, SR_T_KEYVALUE, "shunt", + "Shunt resistance", NULL}, /* Acquisition modes, sample limiting */ {SR_CONF_LIMIT_MSEC, SR_T_UINT64, "limit_time", -- 2.1.4 ------------------------------------------------------------------------------ Dive into the World of Parallel Programming. The Go Parallel Website, sponsored by Intel and developed in partnership with Slashdot Media, is your hub for all things parallel software development, from weekly thought leadership blogs to news, videos, case studies, tutorials and more. Take a look and join the conversation now. http://goparallel.sourceforge.net/ _______________________________________________ sigrok-devel mailing list sigrok-devel@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/sigrok-devel