This is an automated email from the ASF dual-hosted git repository.

acassis pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/nuttx.git

commit 386dbfa44994e4094132582437d8789fba99f009
Author: zhongzhijie1 <zhongzhij...@xiaomi.com>
AuthorDate: Mon Dec 9 20:28:03 2024 +0800

    Refactored the btuart_rxwork function to improve data reception stability.
    
    Read as much data as possible initially, then process each packet 
individually. Defined the read buffer within the structure and added a rx_len 
variable to indicate the current read offset. After processing each complete 
packet, leftover data is moved to rxbuf[0] and rx_len is reduced by the length 
of the processed packet. The next packet process will start from rxbuf[0] after 
the read ends at new rxbuf[rx_len].
    
    Signed-off-by: zhongzhijie1 <zhongzhij...@xiaomi.com>
---
 drivers/wireless/bluetooth/bt_uart.c | 101 +++++++++++++++--------------------
 drivers/wireless/bluetooth/bt_uart.h |   3 ++
 2 files changed, 47 insertions(+), 57 deletions(-)

diff --git a/drivers/wireless/bluetooth/bt_uart.c 
b/drivers/wireless/bluetooth/bt_uart.c
index 0c6fdb08fe..f5ee4105c9 100644
--- a/drivers/wireless/bluetooth/bt_uart.c
+++ b/drivers/wireless/bluetooth/bt_uart.c
@@ -102,9 +102,7 @@ static ssize_t btuart_read(FAR struct btuart_upperhalf_s 
*upper,
 static void btuart_rxwork(FAR void *arg)
 {
   FAR struct btuart_upperhalf_s *upper;
-  uint8_t data[CONFIG_BLUETOOTH_UART_RXBUFSIZE];
   enum bt_buf_type_e type;
-  unsigned int hdrlen;
   unsigned int pktlen;
   ssize_t nread;
   union
@@ -117,80 +115,69 @@ static void btuart_rxwork(FAR void *arg)
 
   upper = (FAR struct btuart_upperhalf_s *)arg;
 
-  /* Beginning of a new packet.
-   * Read the first byte to get the packet type.
-   */
-
-  while (true)
+  nread = btuart_read(upper, &upper->rxbuf[upper->rxlen],
+                      sizeof(upper->rxbuf) - upper->rxlen,
+                      sizeof(upper->rxbuf) - upper->rxlen);
+  if (nread <= 0)
     {
-      nread = btuart_read(upper, data, H4_HEADER_SIZE, 0);
-      if (nread != H4_HEADER_SIZE)
-        {
-          wlwarn("WARNING: Unable to read H4 packet type: %zd\n", nread);
-          break;
-        }
-
-      if (data[0] == H4_EVT)
-        {
-          hdrlen = sizeof(struct bt_hci_evt_hdr_s);
-        }
-      else if (data[0] == H4_ACL)
-        {
-          hdrlen = sizeof(struct bt_hci_acl_hdr_s);
-        }
-      else
-        {
-          wlerr("ERROR: Unknown H4 type %u\n", data[0]);
-          break;
-        }
+      wlerr("ERROR: btuart_read failed: %zd\n", nread);
+      return;
+    }
 
-      nread = btuart_read(upper, data + H4_HEADER_SIZE,
-                          hdrlen, hdrlen);
-      if (nread != hdrlen)
-        {
-          wlwarn("WARNING: Unable to read H4 packet header: %zd\n", nread);
-          break;
-        }
+  upper->rxlen += (uint16_t)nread;
 
-      hdr = (FAR void *)(data + H4_HEADER_SIZE);
+  while (upper->rxlen)
+    {
+      hdr = (FAR void *)&upper->rxbuf[H4_HEADER_SIZE];
 
-      if (data[0] == H4_EVT)
+      switch (upper->rxbuf[0])
         {
-          pktlen = hdr->evt.len;
+        case H4_EVT:
+          if (upper->rxlen < H4_HEADER_SIZE +
+              sizeof(struct bt_hci_evt_hdr_s))
+            {
+              wlwarn("WARNING: Incomplete HCI event header\n");
+              return;
+            }
+
           type = BT_EVT;
-        }
-      else if (data[0] == H4_ACL)
-        {
-          pktlen = hdr->acl.len;
+          pktlen = H4_HEADER_SIZE +
+                   sizeof(struct bt_hci_evt_hdr_s) + hdr->evt.len;
+          break;
 
-          if (pktlen + H4_HEADER_SIZE + hdrlen >
-              CONFIG_BLUETOOTH_UART_RXBUFSIZE)
+        case H4_ACL:
+          if (upper->rxlen < H4_HEADER_SIZE +
+              sizeof(struct bt_hci_acl_hdr_s))
             {
-              wlwarn("WARNING: H4 packet is too long\n");
-              break;
+              wlwarn("WARNING: Incomplete HCI ACL header\n");
+              return;
             }
 
           type = BT_ACL_IN;
-        }
-      else
-        {
-          wlerr("ERROR: Unknown H4 type %u\n", data[0]);
+          pktlen = H4_HEADER_SIZE +
+                   sizeof(struct bt_hci_acl_hdr_s) + hdr->acl.len;
           break;
+
+        default:
+          wlerr("ERROR: Unknown H4 type %u\n", upper->rxbuf[0]);
+          return;
         }
 
-      nread = btuart_read(upper, data + H4_HEADER_SIZE + hdrlen,
-                          pktlen, pktlen);
-      if (nread != pktlen)
+      if (upper->rxlen < pktlen)
         {
-          wlwarn("WARNING: Unable to read H4 packet: %zd\n", nread);
-          break;
+          wlwarn("WARNING: Incomplete packet: rxlen=%u, pktlen=%u\n",
+                 upper->rxlen, pktlen);
+          return;
         }
 
       /* Pass buffer to the stack */
 
-      BT_DUMP("Received", data, H4_HEADER_SIZE + hdrlen + pktlen);
-      bt_netdev_receive(&upper->dev, type, data + H4_HEADER_SIZE,
-                        hdrlen + pktlen);
+      BT_DUMP("Received", upper->rxbuf, pktlen);
+      bt_netdev_receive(&upper->dev, type, &upper->rxbuf[H4_HEADER_SIZE],
+                        pktlen - H4_HEADER_SIZE);
+
+      upper->rxlen -= pktlen;
+      memmove(upper->rxbuf, upper->rxbuf + pktlen, upper->rxlen);
     }
 }
 
diff --git a/drivers/wireless/bluetooth/bt_uart.h 
b/drivers/wireless/bluetooth/bt_uart.h
index 1392b78f39..02a4b40318 100644
--- a/drivers/wireless/bluetooth/bt_uart.h
+++ b/drivers/wireless/bluetooth/bt_uart.h
@@ -75,6 +75,9 @@ struct btuart_upperhalf_s
 
   FAR const struct btuart_lowerhalf_s *lower;
 
+  uint16_t           rxlen;
+  uint8_t            rxbuf[CONFIG_BLUETOOTH_UART_RXBUFSIZE];
+
   /* Work queue support */
 
   struct work_s work;

Reply via email to