]> sigrok.org Git - libsigrok.git/commitdiff
rdtech-tc: grab receive data in larger chunks
authorGerhard Sittig <redacted>
Thu, 16 Mar 2023 03:28:50 +0000 (04:28 +0100)
committerGerhard Sittig <redacted>
Thu, 16 Mar 2023 13:29:30 +0000 (14:29 +0100)
The previous implementation used to read each of the 192 bytes in
individual calls into the serial layer. This implementation grabs
receive data in larger chunks, and accepts data to be in flight
between main loop callbacks.

USB CDC appears to reliably deliver 64 byte chunks (unsurprisingly).
BLE communication is yet to get tested, isn't operational with current
mainline BT support because MTU exchange is not implemented.

(Re-)synchronization to the stream of packets after hiccups remains
an option which this implementation does not provide, neither did
the previous implementation.

src/hardware/rdtech-tc/protocol.c

index 9b5270db5dd0201737f71f1a2fabca38ea64e1af..f2a439e4dacbcbbe0c1975ea562d1f6cdf9496ee 100644 (file)
@@ -163,12 +163,26 @@ SR_PRIV int rdtech_tc_poll(const struct sr_dev_inst *sdi, gboolean force)
        struct sr_serial_dev_inst *serial;
        int len;
 
+       /*
+        * Don't send the request while receive data is being accumulated.
+        */
        devc = sdi->priv;
+       if (!force && devc->buflen)
+               return SR_OK;
+
+       /*
+        * Send the request when the transmit interval was reached. Or
+        * when the caller forced the transmission.
+        */
        now = g_get_monotonic_time() / 1000;
        elapsed = now - devc->cmd_sent_at;
        if (!force && elapsed < POLL_PERIOD_MS)
                return SR_OK;
 
+       /*
+        * Transmit another measurement request. Only advance the
+        * interval after successful transmission.
+        */
        serial = sdi->conn;
        len = serial_write_blocking(serial,
                poll_cmd, strlen(poll_cmd), WRITE_TO_MS);
@@ -191,8 +205,8 @@ static int handle_poll_data(struct sr_dev_inst *sdi)
 
        devc = sdi->priv;
        sr_spew("Received poll packet (len: %zu).", devc->buflen);
-       if (devc->buflen != TC_POLL_LEN) {
-               sr_err("Unexpected poll packet length: %zu", devc->buflen);
+       if (devc->buflen < TC_POLL_LEN) {
+               sr_err("Insufficient poll packet length: %zu", devc->buflen);
                return SR_ERR_DATA;
        }
 
@@ -220,13 +234,16 @@ static int handle_poll_data(struct sr_dev_inst *sdi)
 static int recv_poll_data(struct sr_dev_inst *sdi, struct sr_serial_dev_inst *serial)
 {
        struct dev_context *devc;
+       size_t space;
        int len;
        int ret;
 
-       /* Serial data arrived. */
+       /* Receive data became available. Drain the transport layer. */
        devc = sdi->priv;
        while (devc->buflen < TC_POLL_LEN) {
-               len = serial_read_nonblocking(serial, devc->buf + devc->buflen, 1);
+               space = sizeof(devc->buf) - devc->buflen;
+               len = serial_read_nonblocking(serial,
+                       &devc->buf[devc->buflen], space);
                if (len < 0)
                        return SR_ERR_IO;
                if (len == 0)
@@ -234,12 +251,20 @@ static int recv_poll_data(struct sr_dev_inst *sdi, struct sr_serial_dev_inst *se
                devc->buflen += len;
        }
 
-       if (devc->buflen == TC_POLL_LEN) {
+       /*
+        * TODO Want to (re-)synchronize to the packet stream? The
+        * 'pac1' string literal would be a perfect match for that.
+        */
+
+       /* Process packets when their reception has completed. */
+       while (devc->buflen >= TC_POLL_LEN) {
                ret = handle_poll_data(sdi);
                if (ret != SR_OK)
                        return ret;
+               devc->buflen -= TC_POLL_LEN;
+               if (devc->buflen)
+                       memmove(&devc->buf[0], &devc->buf[TC_POLL_LEN], devc->buflen);
        }
-       devc->buflen = 0;
 
        return SR_OK;
 }