From cc2d5f8a45807e52d65ca7eb2cbd33c5cc46b19f Mon Sep 17 00:00:00 2001 From: Johan Hedberg Date: Thu, 28 Oct 2021 19:19:01 +0300 Subject: [PATCH] Bluetooth: drivers: h4: Fix uart_fifo_read return value handling Make sure negative error returns from uart_fifo_read() are correctly handled. In the same go, the logic of reading packet headers (ACL/event/ISO) is refactored into its own helper function. This also fixes having an appropriate name for the variable that tracks how many header bytes have already been read (it was called "to_read" and now it's called "bytes_read"). Fixes #39805 Signed-off-by: Johan Hedberg --- drivers/bluetooth/hci/h4.c | 46 ++++++++++++++++++++++++++++---------- 1 file changed, 34 insertions(+), 12 deletions(-) diff --git a/drivers/bluetooth/hci/h4.c b/drivers/bluetooth/hci/h4.c index 18bde92a1d4..aa1465d72d4 100644 --- a/drivers/bluetooth/hci/h4.c +++ b/drivers/bluetooth/hci/h4.c @@ -102,14 +102,26 @@ static inline void h4_get_type(void) } } +static void h4_read_hdr(void) +{ + int bytes_read = rx.hdr_len - rx.remaining; + int ret; + + ret = uart_fifo_read(h4_dev, rx.hdr + bytes_read, rx.remaining); + if (unlikely(ret < 0)) { + BT_ERR("Unable to read from UART (ret %d)", ret); + } else { + rx.remaining -= ret; + } +} + static inline void get_acl_hdr(void) { - struct bt_hci_acl_hdr *hdr = &rx.acl; - int to_read = sizeof(*hdr) - rx.remaining; + h4_read_hdr(); - rx.remaining -= uart_fifo_read(h4_dev, (uint8_t *)hdr + to_read, - rx.remaining); if (!rx.remaining) { + struct bt_hci_acl_hdr *hdr = &rx.acl; + rx.remaining = sys_le16_to_cpu(hdr->len); BT_DBG("Got ACL header. Payload %u bytes", rx.remaining); rx.have_hdr = true; @@ -118,12 +130,11 @@ static inline void get_acl_hdr(void) static inline void get_iso_hdr(void) { - struct bt_hci_iso_hdr *hdr = &rx.iso; - unsigned int to_read = sizeof(*hdr) - rx.remaining; + h4_read_hdr(); - rx.remaining -= uart_fifo_read(h4_dev, (uint8_t *)hdr + to_read, - rx.remaining); if (!rx.remaining) { + struct bt_hci_iso_hdr *hdr = &rx.iso; + rx.remaining = sys_le16_to_cpu(hdr->len); BT_DBG("Got ISO header. Payload %u bytes", rx.remaining); rx.have_hdr = true; @@ -133,10 +144,9 @@ static inline void get_iso_hdr(void) static inline void get_evt_hdr(void) { struct bt_hci_evt_hdr *hdr = &rx.evt; - int to_read = rx.hdr_len - rx.remaining; - rx.remaining -= uart_fifo_read(h4_dev, (uint8_t *)hdr + to_read, - rx.remaining); + h4_read_hdr(); + if (rx.hdr_len == sizeof(*hdr) && rx.remaining < sizeof(*hdr)) { switch (rx.evt.evt) { case BT_HCI_EVT_LE_META_EVENT: @@ -253,8 +263,15 @@ static void rx_thread(void *p1, void *p2, void *p3) static size_t h4_discard(const struct device *uart, size_t len) { uint8_t buf[33]; + int err; - return uart_fifo_read(uart, buf, MIN(len, sizeof(buf))); + err = uart_fifo_read(uart, buf, MIN(len, sizeof(buf))); + if (unlikely(err < 0)) { + BT_ERR("Unable to read from UART (err %d)", err); + return 0; + } + + return err; } static inline void read_payload(void) @@ -291,6 +308,11 @@ static inline void read_payload(void) } read = uart_fifo_read(h4_dev, net_buf_tail(rx.buf), rx.remaining); + if (unlikely(read < 0)) { + BT_ERR("Failed to read UART (err %d)", read); + return; + } + net_buf_add(rx.buf, read); rx.remaining -= read;