I tried using the zketech-ebd-usb USB driver (in the libsigrok project), 
without enabling the load, but each time after quitting sigrok the driver would 
enable the load.
to figure out the issue I revered the protocol.
I documented what I found on the wiki: 
https://sigrok.org/wiki/ZKETECH_EBD-USB#Protocol
it turns out the command that was used to disable the load (sent when stopping 
the acquisition, even if the load was not enabled), actually toggles the load. 
thus it enabled the load when it wasn't at the start of the acquisition.
I fixed this behaviour in the attached patch, but did numerous other 
modifications/upgrades because I found additional features/issues:
- the messages are sent byte per byte with a pause in between since bytes were 
sometimes dropped in my setup else
- the incoming stream is parsed continuously instead of using a fixed length, 
again because I had byte drop in my setup (the messages have a constant 
start/stop)
- I've added the under-voltage threshold (under which the load would stop) as 
configuration
- I've added the D+/D- voltage measurements as two new channels (and has to 
rename the existing to avoid confusion)

note: I am not familiar with the coding style. Feet free to adapt the patch.
>From 9aebfdb9b7f578f187111ed753a1e318798d0117 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?King=20K=C3=A9vin?= <kingke...@cuvoodoo.info>
Date: Sun, 18 Aug 2019 15:20:51 +0200
Subject: [PATCH] zketech-ebd-usb: mutliple fixes and upgrades

- fix load toggling at acquisition stop
- messages are sent byte per byte with a pause in between since bytes were 
sometimes dropped
- incoming stream is parsed continuously instead of using a fixed length (the 
messages have a constant start/stop)
- add under-voltage threshold (under which the load would stop) as configuration
- add D+/D- voltage measurements as two new channels (and has to rename the 
existing to avoid confusion)
---
 src/hardware/zketech-ebd-usb/api.c      |  48 +++-
 src/hardware/zketech-ebd-usb/protocol.c | 336 +++++++++++++++++-------
 src/hardware/zketech-ebd-usb/protocol.h |  13 +-
 3 files changed, 292 insertions(+), 105 deletions(-)

diff --git a/src/hardware/zketech-ebd-usb/api.c 
b/src/hardware/zketech-ebd-usb/api.c
index 3327aff7..7aeb8c8e 100644
--- a/src/hardware/zketech-ebd-usb/api.c
+++ b/src/hardware/zketech-ebd-usb/api.c
@@ -2,6 +2,7 @@
  * This file is part of the libsigrok project.
  *
  * Copyright (C) 2018 Sven Bursch-Osewold <sb_...@bursch.com>
+ * Copyright (C) 2019 King Kévin <kingke...@cuvoodoo.info>
  *
  * This program is free software: you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
@@ -32,6 +33,7 @@ static const uint32_t drvopts[] = {
 static const uint32_t devopts[] = {
        SR_CONF_CONTINUOUS,
        SR_CONF_CURRENT_LIMIT | SR_CONF_GET | SR_CONF_SET | SR_CONF_LIST,
+       SR_CONF_UNDER_VOLTAGE_CONDITION_THRESHOLD | SR_CONF_GET | SR_CONF_SET | 
SR_CONF_LIST,
        SR_CONF_LIMIT_SAMPLES | SR_CONF_GET | SR_CONF_SET,
 };
 
@@ -43,7 +45,7 @@ static GSList *scan(struct sr_dev_driver *di, GSList *options)
        const char *conn, *serialcomm;
        struct sr_config *src;
        struct sr_serial_dev_inst *serial;
-       uint8_t reply[MSG_LEN];
+       uint8_t reply[MSG_MAX_LEN];
 
        conn = NULL;
        serialcomm = NULL;
@@ -76,12 +78,15 @@ static GSList *scan(struct sr_dev_driver *di, GSList 
*options)
        sdi->inst_type = SR_INST_SERIAL;
        sdi->conn = serial;
 
-       sr_channel_new(sdi, 0, SR_CHANNEL_ANALOG, TRUE, "V");
-       sr_channel_new(sdi, 1, SR_CHANNEL_ANALOG, TRUE, "I");
+       sr_channel_new(sdi, 0, SR_CHANNEL_ANALOG, TRUE, "V.VBUS");
+       sr_channel_new(sdi, 1, SR_CHANNEL_ANALOG, TRUE, "I.VBUS");
+       sr_channel_new(sdi, 2, SR_CHANNEL_ANALOG, TRUE, "V.D+");
+       sr_channel_new(sdi, 3, SR_CHANNEL_ANALOG, TRUE, "V.D-");
 
        devc = g_malloc0(sizeof(struct dev_context));
        g_mutex_init(&devc->rw_mutex);
        devc->current_limit = 0;
+       devc->voltage_limit = 0;
        devc->running = FALSE;
        devc->load_activated = FALSE;
        sr_sw_limits_init(&devc->limits);
@@ -89,10 +94,12 @@ static GSList *scan(struct sr_dev_driver *di, GSList 
*options)
 
        /* Starting device. */
        ebd_init(serial, devc);
-       int ret = ebd_read_chars(serial, MSG_LEN, reply);
-       if (ret != MSG_LEN || reply[MSG_FRAME_BEGIN_POS] != MSG_FRAME_BEGIN \
-                       || reply[MSG_FRAME_END_POS] != MSG_FRAME_END) {
-               sr_warn("Invalid message received!");
+       int ret = ebd_read_message(serial, MSG_MAX_LEN, reply);
+       if (ret < 0) {
+               sr_warn("Could not receive message!");
+               ret = SR_ERR;
+       } else if (0 == ret) {
+               sr_warn("No message received!");
                ret = SR_ERR;
        }
        ebd_stop(serial, devc);
@@ -139,6 +146,11 @@ static int config_get(uint32_t key, GVariant **data,
                if (ret == SR_OK)
                        *data = g_variant_new_double(fvalue);
                return ret;
+       case SR_CONF_UNDER_VOLTAGE_CONDITION_THRESHOLD:
+               ret = ebd_get_voltage_limit(sdi, &fvalue);
+               if (ret == SR_OK)
+                       *data = g_variant_new_double(fvalue);
+               return ret;
        default:
                return SR_ERR_NA;
        }
@@ -164,6 +176,11 @@ static int config_set(uint32_t key, GVariant *data,
                if (value < 0.0 || value > 4.0)
                        return SR_ERR_ARG;
                return ebd_set_current_limit(sdi, value);
+       case SR_CONF_UNDER_VOLTAGE_CONDITION_THRESHOLD:
+               value = g_variant_get_double(data);
+               if (value < 0.0 || value > 21.0)
+                       return SR_ERR_ARG;
+               return ebd_set_voltage_limit(sdi, value);
        default:
                return SR_ERR_NA;
        }
@@ -177,7 +194,10 @@ static int config_list(uint32_t key, GVariant **data,
        case SR_CONF_DEVICE_OPTIONS:
                return STD_CONFIG_LIST(key, data, sdi, cg, scanopts, drvopts, 
devopts);
        case SR_CONF_CURRENT_LIMIT:
-               *data = std_gvar_min_max_step(0.0, 4.0, 0.01);
+               *data = std_gvar_min_max_step(0.0, 4.0, 0.001);
+               break;
+       case SR_CONF_UNDER_VOLTAGE_CONDITION_THRESHOLD:
+               *data = std_gvar_min_max_step(0.0, 21.0, 0.01);
                break;
        default:
                return SR_ERR_NA;
@@ -198,8 +218,6 @@ static int dev_acquisition_start(const struct sr_dev_inst 
*sdi)
        std_session_send_df_header(sdi);
 
        ebd_init(serial, devc);
-       if (!ebd_current_is0(devc))
-               ebd_loadstart(serial, devc);
 
        serial_source_add(sdi->session, serial, G_IO_IN, 100,
                ebd_receive_data, (void *)sdi);
@@ -209,7 +227,15 @@ static int dev_acquisition_start(const struct sr_dev_inst 
*sdi)
 
 static int dev_acquisition_stop(struct sr_dev_inst *sdi)
 {
-       ebd_loadstop(sdi->conn, sdi->priv);
+       struct dev_context *devc;
+
+       if (sdi) {
+               devc = sdi->priv;
+               if (devc->load_activated) {
+                       ebd_loadtoggle(sdi->conn, devc);
+               }
+               ebd_stop(sdi->conn, devc);
+       }
 
        return std_serial_dev_acquisition_stop(sdi);
 }
diff --git a/src/hardware/zketech-ebd-usb/protocol.c 
b/src/hardware/zketech-ebd-usb/protocol.c
index 0c99ea50..275fb7ac 100644
--- a/src/hardware/zketech-ebd-usb/protocol.c
+++ b/src/hardware/zketech-ebd-usb/protocol.c
@@ -2,6 +2,7 @@
  * This file is part of the libsigrok project.
  *
  * Copyright (C) 2018 Sven Bursch-Osewold <sb_...@bursch.com>
+ * Copyright (C) 2019 King Kévin <kingke...@cuvoodoo.info>
  *
  * This program is free software: you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
@@ -39,10 +40,13 @@ static int send_cmd(struct sr_serial_dev_inst *serial, 
uint8_t buf[], size_t cou
        int ret;
 
        log_buf("Sending", buf, count);
-       ret = serial_write_blocking(serial, buf, count, 0);
-       if (ret < 0) {
-               sr_err("Error sending command: %d.", ret);
-               return ret;
+       for (size_t byte = 0; byte < count; byte++) {
+               ret = serial_write_blocking(serial, &buf[byte], 1, 0);
+               if (ret < 0) {
+                       sr_err("Error sending command: %d.", ret);
+                       return ret;
+               }
+               g_usleep(10000); // wait between bytes to prevent data loss at 
the receiving side
        }
 
        return (ret == (int)count) ? SR_OK : SR_ERR;
@@ -71,9 +75,9 @@ static int send_cfg(struct sr_serial_dev_inst *serial, struct 
dev_context *devc)
        uint8_t send[] = { 0xfa, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
0x00, 0xf8 };
 
        encode_value(devc->current_limit, &send[2], &send[3], 1000.0);
+       encode_value(devc->voltage_limit, &send[4], &send[5], 100.0);
 
-       send[8] = send[1] ^ send[2] ^ send[3] ^ send[4] ^ send[5] ^ \
-                       send[6] ^ send[7];
+       send[8] = send[1] ^ send[2] ^ send[3] ^ send[4] ^ send[5] ^ send[6] ^ 
send[7];
 
        return send_cmd(serial, send, 10);
 }
@@ -86,8 +90,6 @@ SR_PRIV int ebd_init(struct sr_serial_dev_inst *serial, 
struct dev_context *devc
        (void)devc;
 
        int ret = send_cmd(serial, init, 10);
-       if (ret == SR_OK)
-               devc->running = TRUE;
 
        return ret;
 }
@@ -98,29 +100,31 @@ SR_PRIV int ebd_loadstart(struct sr_serial_dev_inst 
*serial, struct dev_context
        uint8_t start[] = { 0xfa, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
0x01, 0xf8 };
        int ret;
 
+       encode_value(devc->current_limit, &start[2], &start[3], 1000.0);
+       encode_value(devc->voltage_limit, &start[4], &start[5], 100.0);
+
+       start[8] = start[1] ^ start[2] ^ start[3] ^ start[4] ^ start[5] ^ 
start[6] ^ start[7];
+
+       sr_info("Activating load");
        ret = send_cmd(serial, start, 10);
-       sr_dbg("Current limit: %f.", devc->current_limit);
+       sr_dbg("current limit: %.03f", devc->current_limit);
+       sr_dbg("under-voltage threshold: %.02f", devc->voltage_limit);
        if (ebd_current_is0(devc))
                return SR_OK;
 
-       ret = send_cfg(serial, devc);
-       if (ret == SR_OK) {
-               sr_dbg("Load activated.");
-               devc->load_activated = TRUE;
-       }
-
        return ret;
 }
 
-/* Stop the load functionality. */
-SR_PRIV int ebd_loadstop(struct sr_serial_dev_inst *serial, struct dev_context 
*devc)
+/* Toggle the load functionality. */
+SR_PRIV int ebd_loadtoggle(struct sr_serial_dev_inst *serial, struct 
dev_context *devc)
 {
        int ret;
-       uint8_t stop[] = { 0xfa, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
0x02, 0xF8 };
+       uint8_t toggle[] = { 0xfa, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
0x02, 0xF8 };
 
-       ret = send_cmd(serial, stop, 10);
-       if (ret == SR_OK)
-               devc->load_activated = FALSE;
+       (void) devc;
+
+       sr_info("Toggling load");
+       ret = send_cmd(serial, toggle, 10);
 
        return ret;
 }
@@ -134,36 +138,118 @@ SR_PRIV int ebd_stop(struct sr_serial_dev_inst *serial, 
struct dev_context *devc
        (void) devc;
 
        ret = send_cmd(serial, stop, 10);
-       if (ret == SR_OK) {
-               devc->load_activated = FALSE;
-               devc->running= FALSE;
-       }
 
        return ret;
 }
 
-/** Read count bytes from the serial connection. */
-SR_PRIV int ebd_read_chars(struct sr_serial_dev_inst *serial, int count, 
uint8_t *buf)
+/** Receive a complete message
+ *  @param[in] serial Serial port from which to read the packet
+ *  @param[in] length Buffer length
+ *  @param[out] buf Buffer to write packet to
+ *  @return packet length (0 = timeout, -1 = error)
+ */
+SR_PRIV int ebd_read_message(struct sr_serial_dev_inst *serial, int length, 
uint8_t *buf)
 {
-       int ret, received, turns;
-
-       received = 0;
-       turns = 0;
+       // check parameters
+       if (NULL == serial) {
+               sr_err("Serial device to receive packet missing.");
+               return -1;
+       }
+       if (length < 3) {
+               sr_err("Packet buffer not large enough.");
+               return -1;
+       }
+       if (NULL == buf) {
+               sr_err("Packet buffer missing.");
+               return -1;
+       }
 
-       do {
-               ret = serial_read_blocking(serial, buf + received,
-                       count - received, serial_timeout(serial, count));
-               if (ret < 0) {
-                       sr_err("Error %d reading %d bytes.", ret, count);
-                       return ret;
+       int ret;
+       gboolean message_complete = FALSE;
+       int message_length = 0;
+       unsigned int turn = 0;
+       const unsigned int TURNS = 200;
+       buf[message_length] = 0;
+       // try to read data
+       while (!message_complete && turn < TURNS) {
+               // wait for header byte
+               message_length = 0;
+               while (MSG_FRAME_BEGIN != buf[0] && turn < TURNS) {
+                       ret = serial_read_blocking(serial, &buf[0], 1,  
serial_timeout(serial, 1));
+                       if (ret < 0) {
+                               sr_err("Error %d reading byte.", ret);
+                               return ret;
+                       } else if (1 == ret) {
+                               if (MSG_FRAME_BEGIN != buf[message_length]) {
+                                       sr_warn("Not frame begin byte %02x 
received", buf[message_length]);
+                               } else {
+                                       sr_dbg("Message header received: %02x", 
buf[message_length]);
+                                       message_length += ret;
+                               }
+                       }
+                       turn++;
+               }
+               // read until end byte
+               while (MSG_FRAME_END !=  buf[message_length - 1] && 
message_length < length && turn < TURNS) {
+                       ret = serial_read_blocking(serial, 
&buf[message_length], 1,  serial_timeout(serial, 1));
+                       if (ret < 0) {
+                               sr_err("Error %d reading byte.", ret);
+                               return ret;
+                       } else if (1 == ret) {
+                               if (MSG_FRAME_BEGIN == buf[message_length]) {
+                                       sr_warn("Frame begin before end 
received");
+                                       message_length = 1;
+                               } else {
+                                       sr_dbg("Message data received: %02x", 
buf[message_length]);
+                                       message_length += ret;
+                               }
+                       }
+                       turn++;
                }
-               received += ret;
-               turns++;
-       } while ((received < count) && (turns < 100));
+               // verify frame
+               if (turn < TURNS) {
+                       if (MSG_FRAME_END == buf[message_length - 1]) {
+                               message_complete = TRUE;
+                               sr_dbg("Message end received");
+                       } else {
+                               sr_warn("Frame end not received");
+                       }
+               } else {
+                       sr_warn("Invalid data and timeout");
+               }
+       }
 
-       log_buf("Received", buf, received);
+       if (message_complete && message_length > 2) {
+               ret = message_length;
+       } else if (turn >= TURNS) {
+               ret = 0;
+       } else {
+               ret = -1;
+       }
+       return ret;
+}
+
+static void ebd_send_value(const struct sr_dev_inst *sdi, struct sr_channel 
*ch,
+               float value, enum sr_mq mq, enum sr_unit unit, int digits)
+{
+       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;
 
-       return received;
+       sr_analog_init(&analog, &encoding, &meaning, &spec, digits);
+       analog.meaning->channels = g_slist_append(NULL, ch);
+       analog.num_samples = 1;
+       analog.data = &value;
+       analog.meaning->mq = mq;
+       analog.meaning->unit = unit;
+       analog.meaning->mqflags = SR_MQFLAG_DC;
+
+       packet.type = SR_DF_ANALOG;
+       packet.payload = &analog;
+       sr_session_send(sdi, &packet);
+       g_slist_free(analog.meaning->channels);
 }
 
 SR_PRIV int ebd_receive_data(int fd, int revents, void *cb_data)
@@ -176,8 +262,7 @@ SR_PRIV int ebd_receive_data(int fd, int revents, void 
*cb_data)
        struct sr_analog_encoding encoding;
        struct sr_analog_meaning meaning;
        struct sr_analog_spec spec;
-       float voltage, current, current_limit;
-       GSList *l;
+       float voltage, voltage_dp, voltage_dm, current, current_limit, 
voltage_limit;
 
        (void)revents;
        (void)fd;
@@ -189,39 +274,70 @@ SR_PRIV int ebd_receive_data(int fd, int revents, void 
*cb_data)
                return FALSE;
 
        serial = sdi->conn;
+       current_limit = devc->current_limit;
+       voltage_limit = devc->voltage_limit;
 
-       uint8_t reply[MSG_LEN];
-       int ret = ebd_read_chars(serial, MSG_LEN, reply);
+       uint8_t reply[MSG_MAX_LEN];
+       int ret = ebd_read_message(serial, MSG_MAX_LEN, reply);
 
        /* Tests for correct message. */
-       if (ret != MSG_LEN) {
-               sr_err("Message invalid [Len].");
-               return (ret < 0) ? ret : SR_ERR;
+       if (-1 == ret) {
+               sr_err("Can't receive messages");
+               return SR_ERR;
+       } else if (0 == ret) {
+               sr_err("No messages received");
+               devc->running = FALSE;
+               return 0;
+       } else if (ret != 19 || (reply[1] != 0x00 && reply[1] != 0x0a && 
reply[1] != 0x64 && reply[1] != 0x6e)) {
+               sr_info("Not measurement message received");
+               return ret;
        }
 
-       uint8_t xor = reply[1] ^ reply[2] ^ reply[3] ^ reply[4] ^ \
-                     reply[5] ^ reply[6] ^ reply[7] ^ reply[8] ^ \
-                     reply[9] ^ reply[10] ^ reply[11] ^ reply[12] ^ \
-                     reply[13] ^ reply[14] ^ reply[15] ^ reply[16];
+       /* Verify checksum */
+       uint8_t checksum = 0;
+       for (int i = 1; i < ret - 1; i++) {
+               checksum ^= reply[i];
+       }
+       if (0 != checksum) {
+               sr_warn("Invalid checksum");
+               return ret; /* Don't exit on wrong checksum, the device can 
recover */
+       }
 
-       if (reply[MSG_FRAME_BEGIN_POS] != MSG_FRAME_BEGIN || \
-                       reply[MSG_FRAME_END_POS] != MSG_FRAME_END || \
-                       xor != reply[MSG_CHECKSUM_POS]) {
-               sr_err("Message invalid [XOR, BEGIN/END].");
-               return SR_ERR;
+       devc->running = TRUE;
+       if (0x00 == reply[1] || 0x64 == reply[1]) {
+               devc->load_activated = FALSE;
+       } else if (0x0a == reply[1] || 0x6e == reply[1]) {
+               devc->load_activated = TRUE;
        }
 
        /* Calculate values. */
-       sr_dbg("V: %02X %02X A: %02X %02X -- Limit %02X %02X", reply[4],
-               reply[5], reply[2], reply[3], reply[10], reply[11]);
-
-       voltage = decode_value(reply[4], reply[5], 1000.0);
        current = decode_value(reply[2], reply[3], 10000.0);
-       current_limit = decode_value(reply[10], reply[11], 1000.0);
+       voltage = decode_value(reply[4], reply[5], 1000.0);
+       voltage_dp = decode_value(reply[6], reply[7], 1000.0);
+       voltage_dm = decode_value(reply[8], reply[9], 1000.0);
+       if (0x0a == reply[1]) {
+               current_limit = decode_value(reply[10], reply[11], 1000.0);
+               voltage_limit = decode_value(reply[12], reply[13], 100.0);
+       }
 
-       sr_dbg("Voltage %f", voltage);
-       sr_dbg("Current %f", current);
-       sr_dbg("Current limit %f", current_limit);
+       sr_dbg("VBUS current %.04f A", current);
+       sr_dbg("VBUS voltage %.03f V", voltage);
+       sr_dbg("D+ voltage %.03f V", voltage_dp);
+       sr_dbg("D- voltage %.03f V", voltage_dm);
+       if (0x0a == reply[1]) {
+               sr_dbg("Current limit %.03f A", current_limit);
+               sr_dbg("Voltage limit %.03f A", voltage_limit);
+       }
+
+       // update load state
+       if (devc->load_activated && ebd_current_is0(devc)) {
+               ebd_loadtoggle(serial, devc);
+       } else if (!devc->load_activated && !ebd_current_is0(devc)) {
+               ebd_loadstart(serial, devc);
+       } else if (devc->load_activated && (current_limit != 
devc->current_limit || voltage_limit != devc->voltage_limit)) {
+               sr_dbg("Adjusting limit from %.03f A %.03f V to %.03f A %.03f 
V", current_limit, voltage_limit, devc->current_limit, devc->voltage_limit);
+               send_cfg(serial, devc);
+       }
 
        /* Begin frame. */
        packet.type = SR_DF_FRAME_BEGIN;
@@ -234,27 +350,15 @@ SR_PRIV int ebd_receive_data(int fd, int revents, void 
*cb_data)
        packet.payload = &analog;
        analog.num_samples = 1;
 
-       /* Voltage */
-       l = g_slist_copy(sdi->channels);
-       l = g_slist_remove_link(l, g_slist_nth(l, 1));
-       meaning.channels = l;
-       meaning.mq = SR_MQ_VOLTAGE;
-       meaning.mqflags = SR_MQFLAG_DC;
-       meaning.unit = SR_UNIT_VOLT;
-       analog.data = &voltage;
-       sr_session_send(sdi, &packet);
-       g_slist_free(l);
-
-       /* Current */
-       l = g_slist_copy(sdi->channels);
-       l = g_slist_remove_link(l, g_slist_nth(l, 0));
-       meaning.channels = l;
-       meaning.mq = SR_MQ_CURRENT;
-       meaning.mqflags = SR_MQFLAG_DC;
-       meaning.unit = SR_UNIT_AMPERE;
-       analog.data = &current;
-       sr_session_send(sdi, &packet);
-       g_slist_free(l);
+       /* Values */
+       ebd_send_value(sdi, sdi->channels->data, current,
+               SR_MQ_VOLTAGE, SR_UNIT_VOLT, 3);
+       ebd_send_value(sdi, sdi->channels->next->data, voltage,
+               SR_MQ_CURRENT, SR_UNIT_AMPERE, 4);
+       ebd_send_value(sdi, sdi->channels->next->next->data, voltage_dp,
+               SR_MQ_VOLTAGE, SR_UNIT_VOLT, 3);
+       ebd_send_value(sdi, sdi->channels->next->next->next->data, voltage_dm,
+               SR_MQ_VOLTAGE, SR_UNIT_VOLT, 3);
 
        /* End frame. */
        packet.type = SR_DF_FRAME_END;
@@ -304,7 +408,63 @@ SR_PRIV int ebd_set_current_limit(const struct sr_dev_inst 
*sdi, float current)
        if (devc->load_activated) {
                if (ebd_current_is0(devc)) {
                        /* Stop load. */
-                       ret = ebd_loadstop(sdi->conn, devc);
+                       ret = ebd_loadtoggle(sdi->conn, devc);
+               } else {
+                       /* Send new current. */
+                       ret = send_cfg(sdi->conn, devc);
+               }
+       } else {
+               if (ebd_current_is0(devc)) {
+                       /* Nothing to do. */
+                       ret = SR_OK;
+               } else {
+                       /* Start load. */
+                       ret = ebd_loadstart(sdi->conn, devc);
+               }
+       }
+
+       g_mutex_unlock(&devc->rw_mutex);
+
+       return ret;
+}
+
+SR_PRIV int ebd_get_voltage_limit(const struct sr_dev_inst *sdi, float 
*voltage)
+{
+       struct dev_context *devc;
+
+       if (!(devc = sdi->priv))
+               return SR_ERR;
+
+       g_mutex_lock(&devc->rw_mutex);
+       *voltage = devc->voltage_limit;
+       g_mutex_unlock(&devc->rw_mutex);
+
+       return SR_OK;
+}
+
+SR_PRIV int ebd_set_voltage_limit(const struct sr_dev_inst *sdi, float voltage)
+{
+       struct dev_context *devc;
+       int ret;
+
+       if (!(devc = sdi->priv))
+               return SR_ERR;
+
+       g_mutex_lock(&devc->rw_mutex);
+       devc->voltage_limit = voltage;
+
+       if (!devc->running) {
+               sr_dbg("Setting voltage limit later.");
+               g_mutex_unlock(&devc->rw_mutex);
+               return SR_OK;
+       }
+
+       sr_dbg("Setting voltage limit to %fV.", voltage);
+
+       if (devc->load_activated) {
+               if (ebd_current_is0(devc)) {
+                       /* Stop load. */
+                       ret = ebd_loadtoggle(sdi->conn, devc);
                } else {
                        /* Send new current. */
                        ret = send_cfg(sdi->conn, devc);
diff --git a/src/hardware/zketech-ebd-usb/protocol.h 
b/src/hardware/zketech-ebd-usb/protocol.h
index 004ce5fb..a4d62ec3 100644
--- a/src/hardware/zketech-ebd-usb/protocol.h
+++ b/src/hardware/zketech-ebd-usb/protocol.h
@@ -2,6 +2,7 @@
  * This file is part of the libsigrok project.
  *
  * Copyright (C) 2018 Sven Bursch-Osewold <sb_...@bursch.com>
+ * Copyright (C) 2019 King Kévin <kingke...@cuvoodoo.info>
  *
  * This program is free software: you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
@@ -27,34 +28,34 @@
 
 #define LOG_PREFIX "zketech-ebd-usb"
 
-#define MSG_LEN 19
-#define MSG_CHECKSUM_POS 17
+#define MSG_MAX_LEN 19
 #define MSG_FRAME_BEGIN 0xfa
-#define MSG_FRAME_BEGIN_POS 0
 #define MSG_FRAME_END 0xf8
-#define MSG_FRAME_END_POS 18
 
 struct dev_context {
        struct sr_sw_limits limits;
        GMutex rw_mutex;
        float current_limit;
+       float voltage_limit;
        gboolean running;
        gboolean load_activated;
 };
 
 /* Communication via serial. */
-SR_PRIV int ebd_read_chars(struct sr_serial_dev_inst *serial, int count, 
uint8_t *buf);
+SR_PRIV int ebd_read_message(struct sr_serial_dev_inst *serial, int length, 
uint8_t *buf);
 
 /* Commands. */
 SR_PRIV int ebd_init(struct sr_serial_dev_inst *serial, struct dev_context 
*devc);
 SR_PRIV int ebd_loadstart(struct sr_serial_dev_inst *serial, struct 
dev_context *devc);
 SR_PRIV int ebd_receive_data(int fd, int revents, void *cb_data);
 SR_PRIV int ebd_stop(struct sr_serial_dev_inst *serial, struct dev_context 
*devc);
-SR_PRIV int ebd_loadstop(struct sr_serial_dev_inst *serial, struct dev_context 
*devc);
+SR_PRIV int ebd_loadtoggle(struct sr_serial_dev_inst *serial, struct 
dev_context *devc);
 
 /* Configuration. */
 SR_PRIV int ebd_get_current_limit(const struct sr_dev_inst *sdi, float 
*current);
 SR_PRIV int ebd_set_current_limit(const struct sr_dev_inst *sdi, float 
current);
+SR_PRIV int ebd_get_voltage_limit(const struct sr_dev_inst *sdi, float 
*current);
+SR_PRIV int ebd_set_voltage_limit(const struct sr_dev_inst *sdi, float 
current);
 SR_PRIV gboolean ebd_current_is0(struct dev_context *devc);
 
 #endif
-- 
2.22.0

_______________________________________________
sigrok-devel mailing list
sigrok-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/sigrok-devel

Reply via email to