Signed-off-by: Bartosz Golaszewski <bgolaszew...@baylibre.com>
---
 include/libsigrok/libsigrok.h |   6 ++
 src/hardware/acme/acme.c      | 130 +++++++++++++++++++++++++++++++++++++++++-
 src/hwdriver.c                |   2 +
 3 files changed, 136 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 4715a14..65b9f29 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;
@@ -269,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;
 }
@@ -401,12 +405,121 @@ 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 written = 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;
+
+               written += snprintf(buf + written,
+                                   sizeof(buf) - written,
+                                   "%s: ", chg->name);
+               if (chgp->prb_type == PROBE_TEMP) {
+                       written += snprintf(buf + written,
+                                           sizeof(buf) - written, "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;
+                       written += snprintf(buf + written,
+                                           sizeof(buf) - written,
+                                           "%u mOhms, ",
+                                           shunt);
+                       g_free(contents);
+               }
+       }
+
+       buf[written - 1] = '\0';
+       *data = g_variant_new_string(buf);
+
+       return 0;
+}
+
+static int set_shunt_values(struct dev_context *devc, const char *shunt_vals)
+{
+       gchar **toks, **shunts, **pos;
+       uint32_t probe, shunt;
+       char path[256];
+       int ret = 0;
+       FILE *fd;
+
+       toks = g_strsplit(shunt_vals, ",", MAX_PROBES);
+       pos = toks;
+       while (*pos) {
+               shunts = g_strsplit(*pos++, "=", 2);
+               if (!shunts[1]) {
+                       g_strfreev(shunts);
+                       ret = -1;
+                       break;
+               }
+
+               probe = strtoul(shunts[0], NULL, 10);
+               shunt = strtoul(shunts[1], NULL, 10);
+               g_strfreev(shunts);
+
+               if (probe > MAX_PROBES) {
+                       sr_err("Invalid probe number");
+                       ret = -1;
+                       break;
+               }
+
+               if (devc->probes[probe - 1] == NULL) {
+                       sr_err("Probe %u not present", probe);
+                       ret = -1;
+                       break;
+               }
+
+               if (devc->probes[probe - 1]->prb_type == PROBE_TEMP) {
+                       sr_err("Unable to set shunt on a temperature probe");
+                       ret = -1;
+                       break;
+               }
+
+               snprintf(path, sizeof(path),
+                        "/sys/class/hwmon/hwmon%u/shunt_resistor",
+                        devc->probes[probe - 1]->hwmon_num);
+
+               fd = fopen(path, "w");
+               if (!fd) {
+                       sr_err("Error setting shunt resistance: %s\n",
+                              strerror(errno));
+                       ret = -1;
+                       break;
+               }
+
+               fprintf(fd, "%u\n", shunt * 1000);
+               fclose(fd);
+       }
+
+       g_strfreev(toks);
+       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;
@@ -425,6 +538,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;
        }
@@ -438,7 +556,9 @@ static int config_set(uint32_t key, GVariant *data,
 {
        struct dev_context *devc;
        uint64_t samplerate;
-       int ret;
+       const char *shunt_vals;
+       gsize shuntlen;
+       int ret, status;
 
        (void)data;
        (void)cg;
@@ -470,6 +590,12 @@ 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:
+               shunt_vals = g_variant_get_string(data, &shuntlen);
+               status = set_shunt_values(devc, shunt_vals);
+               if (status < 0)
+                       ret = SR_ERR_ARG;
+               break;
        default:
                ret = SR_ERR_NA;
        }
diff --git a/src/hwdriver.c b/src/hwdriver.c
index 239592d..7bb7cd8 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_STRING, "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

Reply via email to