Allow to remotely cut the power at ACME probe level. The key
argument should stand for probe ID, value should be the desired
power state - either 'on' or 'off'.

Signed-off-by: Bartosz Golaszewski <bgolaszew...@baylibre.com>
---
 src/hardware/baylibre-acme/api.c      | 62 +++++++++++++++++++++++++++--------
 src/hardware/baylibre-acme/protocol.c | 58 ++++++++++++++++++++++++++++++++
 src/hardware/baylibre-acme/protocol.h |  3 ++
 3 files changed, 109 insertions(+), 14 deletions(-)

diff --git a/src/hardware/baylibre-acme/api.c b/src/hardware/baylibre-acme/api.c
index 02bac08..cceb98c 100644
--- a/src/hardware/baylibre-acme/api.c
+++ b/src/hardware/baylibre-acme/api.c
@@ -28,6 +28,7 @@ static const uint32_t devopts[] = {
        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,
+       SR_CONF_PROBE_POWER | SR_CONF_GET | SR_CONF_SET,
 };
 
 #define MAX_SAMPLE_RATE                500 /* In Hz */
@@ -190,6 +191,9 @@ static int config_get(uint32_t key, GVariant **data,
                if (status < 0)
                        ret = status;
                break;
+       case SR_CONF_PROBE_POWER:
+               bl_acme_read_power_states(sdi, data);
+               break;
        default:
                return SR_ERR_NA;
        }
@@ -197,6 +201,26 @@ static int config_get(uint32_t key, GVariant **data,
        return ret;
 }
 
+static int parse_keyval(GVariant *variant, const char **key, const char **val)
+{
+       GVariantIter iter_arr, iter_pair;
+       GVariant *keyval, *key_var, *val_var = NULL;
+
+       g_variant_iter_init(&iter_arr, variant);
+       keyval = g_variant_iter_next_value(&iter_arr);
+       g_variant_iter_init(&iter_pair, keyval);
+       key_var = g_variant_iter_next_value(&iter_pair);
+       if (key_var)
+               val_var = g_variant_iter_next_value(&iter_pair);
+       if (!val_var)
+               return -1;
+
+       *key = g_variant_get_string(key_var, NULL);
+       *val = g_variant_get_string(val_var, NULL);
+
+       return 0;
+}
+
 static int config_set(uint32_t key, GVariant *data,
                      const struct sr_dev_inst *sdi,
                      const struct sr_channel_group *cg)
@@ -204,10 +228,9 @@ static int config_set(uint32_t key, GVariant *data,
        struct dev_context *devc;
        uint64_t samplerate;
        int ret, status;
-       GVariantIter iter_arr, iter_pair;
-       GVariant *keyval, *probe_var, *shunt_var = NULL;
-       const char *probe_str, *shunt_str;
-       unsigned int probe, shunt;
+       const char *probe_str, *shunt_str, *pws_str;
+       unsigned probe, shunt;
+       gboolean power_state;
 
        (void)cg;
 
@@ -240,30 +263,41 @@ static int config_set(uint32_t key, GVariant *data,
                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) {
+               status = parse_keyval(data, &probe_str, &shunt_str);
+               if (status < 0) {
                        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 = bl_acme_set_shunt(devc, probe, shunt);
                if (status < 0) {
-                       ret = status;
+                       ret = SR_ERR_ARG;
                        break;
                }
 
                sr_dbg("Shunt resistance for probe %u set to %u", probe, shunt);
                break;
+       case SR_CONF_PROBE_POWER:
+               status = parse_keyval(data, &probe_str, &pws_str);
+               if (status < 0) {
+                       sr_err("Invalid value");
+                       ret = SR_ERR_ARG;
+                       break;
+               }
+
+               probe = strtoul(probe_str, NULL, 10);
+               power_state = g_strcmp0(pws_str, "on") == 0 ? TRUE : FALSE;
+               status = bl_acme_set_power_state(probe, power_state);
+               if (status < 0) {
+                       ret = SR_ERR_ARG;
+                       break;
+               }
+
+               sr_dbg("Probe %u power-%s", probe, power_state ? "on" : "off");
+               break;
        default:
                ret = SR_ERR_NA;
        }
diff --git a/src/hardware/baylibre-acme/protocol.c 
b/src/hardware/baylibre-acme/protocol.c
index a3211a6..b8ceff0 100644
--- a/src/hardware/baylibre-acme/protocol.c
+++ b/src/hardware/baylibre-acme/protocol.c
@@ -22,6 +22,7 @@
 #include <fcntl.h> /* open(), etc... */
 #include <glib/gstdio.h>
 #include "protocol.h"
+#include "gpio.h"
 
 struct channel_group_priv {
        int probe_type;
@@ -41,6 +42,14 @@ static const uint8_t temp_i2c_addrs[] = {
        0x0, 0x0, 0x0, 0x0, 0x4c, 0x49, 0x4f, 0x4b,
 };
 
+static const uint32_t pws_gpios[] = {
+       486, 498, 502, 482, 478, 506, 510, 474
+};
+
+static const uint32_t pws_info_gpios[] = {
+       487, 499, 503, 483, 479, 507, 511, 475,
+};
+
 #define MOHM_TO_UOHM(x) ((x) * 1000)
 #define UOHM_TO_MOHM(x) ((x) / 1000)
 
@@ -351,6 +360,55 @@ SR_PRIV int bl_acme_set_shunt(const struct dev_context 
*devc,
        return SR_OK;
 }
 
+SR_PRIV int bl_acme_set_power_state(unsigned probe, gboolean state)
+{
+       int has_pws;
+       unsigned index;
+
+       if (probe == 0 || probe > MAX_PROBES) {
+               sr_err("Invalid probe number: %u", probe);
+               return -1;
+       }
+
+       index = probe - 1;
+       has_pws = sr_gpio_getval_export(pws_info_gpios[index]);
+       if (!has_pws) {
+               sr_err("Probe %d doesn't have a power switch", probe);
+               return -1;
+       }
+
+       return sr_gpio_setval_export(pws_gpios[index], state ? 1 : 0);
+}
+
+SR_PRIV void bl_acme_read_power_states(const struct sr_dev_inst *sdi,
+                                      GVariant **data)
+{
+       struct dev_context *devc;
+       unsigned in = 0;
+       gchar buf[512];
+       int i;
+
+       devc = sdi->priv;
+
+       for (i = 0; i < MAX_PROBES; i++) {
+               if (devc->probes[i] == NULL) {
+                       continue;
+               }
+               in += snprintf(buf + in, sizeof(buf) - in, "Probe_%d: ", i + 1);
+               if (devc->probes[i]->probe_type == PROBE_TEMP ||
+                   sr_gpio_getval_export(pws_info_gpios[i]) == 0) {
+                       in += snprintf(buf + in, sizeof(buf) - in, "N/A, ");
+               } else {
+                       in += snprintf(buf + in, sizeof(buf) - in, "%s, ",
+                               sr_gpio_getval_export(pws_gpios[i]) == 1 ?
+                                                               "ON" : "OFF");
+               }
+       }
+
+       buf[in - 2] = '\0';
+       *data = g_variant_new_string(buf);
+}
+
 static int channel_to_mq(struct sr_channel *ch)
 {
        struct channel_priv *chp;
diff --git a/src/hardware/baylibre-acme/protocol.h 
b/src/hardware/baylibre-acme/protocol.h
index 642d0ee..bf938b4 100644
--- a/src/hardware/baylibre-acme/protocol.h
+++ b/src/hardware/baylibre-acme/protocol.h
@@ -88,6 +88,9 @@ SR_PRIV int bl_acme_read_shunt_values(const struct 
sr_dev_inst *sdi,
                                      GVariant **data);
 SR_PRIV int bl_acme_set_shunt(const struct dev_context *devc,
                              unsigned int probe, unsigned int shunt);
+SR_PRIV int bl_acme_set_power_state(unsigned probe, gboolean state);
+SR_PRIV void bl_acme_read_power_states(const struct sr_dev_inst *sdi,
+                                      GVariant **data);
 
 SR_PRIV int bl_acme_receive_data(int fd, int revents, void *cb_data);
 
-- 
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