]> sigrok.org Git - libsigrok.git/blobdiff - src/hardware/rdtech-um/protocol.c
rdtech-um: tone down and extend diagnostics messages
[libsigrok.git] / src / hardware / rdtech-um / protocol.c
index 54416f6c1456f6a477ce3356a8e6ffacbe58e13e..e4e4c6055101bb42a60008aa47668042969708c1 100644 (file)
  */
 
 #include <config.h>
-#include <stdlib.h>
-#include <math.h>
-#include <string.h>
+
 #include <glib.h>
 #include <libsigrok/libsigrok.h>
+#include <math.h>
+#include <stdlib.h>
+#include <string.h>
+
 #include "libsigrok-internal.h"
 #include "protocol.h"
 
@@ -56,42 +58,54 @@ static const struct binary_analog_channel rdtech_um25c_channels[] = {
        ALL_ZERO,
 };
 
-static int poll_csum_fff1(char buf[], int len)
+static gboolean csum_ok_fff1(const uint8_t *buf, size_t len)
 {
+       uint16_t csum_recv;
+
        if (len != UM_POLL_LEN)
-               return 0;
-       else
-               return RB16(&buf[len - 2]) == 0xFFF1;
+               return FALSE;
+
+       csum_recv = read_u16be(&buf[len - sizeof(uint16_t)]);
+       if (csum_recv != 0xfff1)
+               return FALSE;
+
+       return TRUE;
 }
 
-static int poll_csum_um34c(char buf[], int len)
+static gboolean csum_ok_um34c(const uint8_t *buf, size_t len)
 {
        static const int positions[] = {
                1, 3, 7, 9, 15, 17, 19, 23, 31, 39, 41, 45, 49, 53,
                55, 57, 59, 63, 67, 69, 73, 79, 83, 89, 97, 99, 109,
                111, 113, 119, 121, 127,
        };
-       unsigned int i;
-       uint8_t csum = 0;
+
+       size_t i;
+       uint8_t csum_calc, csum_recv;
 
        if (len != UM_POLL_LEN)
-               return 0;
+               return FALSE;
 
+       csum_calc = 0;
        for (i = 0; i < ARRAY_SIZE(positions); i++)
-               csum ^= buf[positions[i]];
+               csum_calc ^= buf[positions[i]];
+       csum_recv = read_u8(&buf[len - sizeof(uint8_t)]);
+       if (csum_recv != csum_calc)
+               return FALSE;
 
-       return csum == (uint8_t)buf[len - 1];
+       return TRUE;
 }
 
 static const struct rdtech_um_profile um_profiles[] = {
-       { "UM24C", RDTECH_UM24C, rdtech_default_channels, &poll_csum_fff1, },
-       { "UM25C", RDTECH_UM25C, rdtech_um25c_channels, &poll_csum_fff1, },
-       { "UM34C", RDTECH_UM34C, rdtech_default_channels, &poll_csum_um34c, },
+       { "UM24C", RDTECH_UM24C, rdtech_default_channels, csum_ok_fff1, },
+       { "UM25C", RDTECH_UM25C, rdtech_um25c_channels, csum_ok_fff1, },
+       { "UM34C", RDTECH_UM34C, rdtech_default_channels, csum_ok_um34c, },
 };
 
 static const struct rdtech_um_profile *find_profile(uint16_t id)
 {
        unsigned int i;
+
        for (i = 0; i < ARRAY_SIZE(um_profiles); i++) {
                if (um_profiles[i].model_id == id)
                        return &um_profiles[i];
@@ -102,10 +116,12 @@ static const struct rdtech_um_profile *find_profile(uint16_t id)
 SR_PRIV const struct rdtech_um_profile *rdtech_um_probe(struct sr_serial_dev_inst *serial)
 {
        const struct rdtech_um_profile *p;
-       static const uint8_t request = UM_CMD_POLL;
-       char buf[RDTECH_UM_BUFSIZE];
+       uint8_t request;
+       uint8_t buf[RDTECH_UM_BUFSIZE];
        int len;
+       uint16_t model_id;
 
+       request = UM_CMD_POLL;
        if (serial_write_blocking(serial, &request, sizeof(request),
                        SERIAL_WRITE_TIMEOUT_MS) < 0) {
                sr_err("Unable to send probe request.");
@@ -118,46 +134,58 @@ SR_PRIV const struct rdtech_um_profile *rdtech_um_probe(struct sr_serial_dev_ins
                return NULL;
        }
 
-       p = find_profile(RB16(&buf[0]));
+       model_id = read_u16be(&buf[0]);
+       p = find_profile(model_id);
        if (!p) {
-               sr_err("Unrecognized UM device (0x%.4" PRIx16 ")!", RB16(&buf[0]));
+               sr_err("Unrecognized UM device (0x%.4" PRIx16 ").", model_id);
                return NULL;
        }
 
-       if (!p->poll_csum(buf, len)) {
-               sr_err("Probe response contains illegal checksum or end marker.\n");
+       if (!p->csum_ok(buf, len)) {
+               sr_err("Probe response fails checksum verification.");
                return NULL;
        }
 
        return p;
 }
 
-SR_PRIV int rdtech_um_poll(const struct sr_dev_inst *sdi)
+SR_PRIV int rdtech_um_poll(const struct sr_dev_inst *sdi, gboolean force)
 {
-       struct dev_context *devc = sdi->priv;
-       struct sr_serial_dev_inst *serial = sdi->conn;
-       static const uint8_t request = UM_CMD_POLL;
+       struct dev_context *devc;
+       int64_t now, elapsed;
+       struct sr_serial_dev_inst *serial;
+       uint8_t request;
+
+       /* Check for expired intervals or forced requests. */
+       devc = sdi->priv;
+       now = g_get_monotonic_time() / 1000;
+       elapsed = now - devc->cmd_sent_at;
+       if (!force && elapsed < UM_POLL_PERIOD_MS)
+               return SR_OK;
 
+       /* Send another poll request. Update interval only on success. */
+       serial = sdi->conn;
+       request = UM_CMD_POLL;
        if (serial_write_blocking(serial, &request, sizeof(request),
                        SERIAL_WRITE_TIMEOUT_MS) < 0) {
                sr_err("Unable to send poll request.");
                return SR_ERR;
        }
-
-       devc->cmd_sent_at = g_get_monotonic_time() / 1000;
+       devc->cmd_sent_at = now;
 
        return SR_OK;
 }
 
 static void handle_poll_data(const struct sr_dev_inst *sdi)
 {
-       struct dev_context *devc = sdi->priv;
+       struct dev_context *devc;
        int i;
        GSList *ch;
 
-       sr_spew("Received poll packet (len: %d).", devc->buflen);
+       devc = sdi->priv;
+       sr_spew("Received poll packet (len: %zu).", devc->buflen);
        if (devc->buflen != UM_POLL_LEN) {
-               sr_err("Unexpected poll packet length: %i", devc->buflen);
+               sr_err("Unexpected poll packet length: %zu", devc->buflen);
                return;
        }
 
@@ -172,17 +200,18 @@ static void handle_poll_data(const struct sr_dev_inst *sdi)
 
 static void recv_poll_data(struct sr_dev_inst *sdi, struct sr_serial_dev_inst *serial)
 {
-       struct dev_context *devc = sdi->priv;
-       const struct rdtech_um_profile *p = devc->profile;
+       struct dev_context *devc;
+       const struct rdtech_um_profile *p;
        int len;
 
        /* Serial data arrived. */
+       devc = sdi->priv;
+       p = devc->profile;
        while (devc->buflen < UM_POLL_LEN) {
                len = serial_read_nonblocking(serial, devc->buf + devc->buflen, 1);
                if (len < 1)
                        return;
-
-               devc->buflen++;
+               devc->buflen += len;
 
                /* Check if the poll model ID matches the profile. */
                if (devc->buflen == 2 && RB16(devc->buf) != p->model_id) {
@@ -194,11 +223,12 @@ static void recv_poll_data(struct sr_dev_inst *sdi, struct sr_serial_dev_inst *s
                }
        }
 
-       if (devc->buflen == UM_POLL_LEN && p->poll_csum(devc->buf, devc->buflen))
-               handle_poll_data(sdi);
+       if (devc->buflen != UM_POLL_LEN)
+               sr_warn("Skipping packet, unexpected receive length.");
+       else if (!p->csum_ok(devc->buf, devc->buflen))
+               sr_warn("Skipping packet, checksum verification failed.");
        else
-               sr_warn("Skipping packet with illegal checksum / end marker.");
-
+               handle_poll_data(sdi);
        devc->buflen = 0;
 }
 
@@ -207,7 +237,6 @@ SR_PRIV int rdtech_um_receive_data(int fd, int revents, void *cb_data)
        struct sr_dev_inst *sdi;
        struct dev_context *devc;
        struct sr_serial_dev_inst *serial;
-       int64_t now, elapsed;
 
        (void)fd;
 
@@ -226,11 +255,7 @@ SR_PRIV int rdtech_um_receive_data(int fd, int revents, void *cb_data)
                return TRUE;
        }
 
-       now = g_get_monotonic_time() / 1000;
-       elapsed = now - devc->cmd_sent_at;
-
-       if (elapsed > UM_POLL_PERIOD_MS)
-               rdtech_um_poll(sdi);
+       (void)rdtech_um_poll(sdi, FALSE);
 
        return TRUE;
 }