From b8d1180bf6d8a685ce4e592150357a0a21a70532 Mon Sep 17 00:00:00 2001 From: Tian Zeng Date: Wed, 22 Jun 2022 04:03:15 -0400 Subject: [PATCH] Apollo3: Properly accumulate full ACL packet before sending to BLE controller (#1276) There was a bug in the Ambiq Apollo3 ACL data transfer logic in which each data chunk in an mbuf was sent individually to the controller instead of aggregating them together. This caused issues with parts of the bluetooth stack such as BLE SMP. Also deals with cleaning up pointers, making them 1 byte pointers where possible for simplification. --- .../transport/apollo3/src/apollo3_ble_hci.c | 57 ++++++++----------- 1 file changed, 24 insertions(+), 33 deletions(-) diff --git a/nimble/transport/apollo3/src/apollo3_ble_hci.c b/nimble/transport/apollo3/src/apollo3_ble_hci.c index 34b6266dd..2ed3012e9 100644 --- a/nimble/transport/apollo3/src/apollo3_ble_hci.c +++ b/nimble/transport/apollo3/src/apollo3_ble_hci.c @@ -235,28 +235,9 @@ apollo3_update_wake(void) * The payload is placed into a queue and the controller is turned on. When it is ready * an interrupt will fire to handle sending a message */ -static uint8_t -apollo3_hci_write(uint8_t type, uint16_t len, uint8_t *data) +static int +apollo3_hci_write(hci_drv_write_t *write_buf) { - uint8_t *write_ptr; - hci_drv_write_t write_buf; - - /* comparison compensates for the type byte at index 0. */ - if (len > (MYNEWT_VAL(BLE_TRANSPORT_APOLLO3_MAX_TX_PACKET)-1)) { - return 0; - } - - /* Set all of the fields in the hci write structure. */ - write_buf.len = len + 1; - - write_ptr = (uint8_t *) write_buf.data; - - *write_ptr++ = type; - - for (uint32_t i = 0; i < len; i++) { - write_ptr[i] = data[i]; - } - /* Wake up the BLE controller. */ apollo3_update_wake(); @@ -265,7 +246,10 @@ apollo3_hci_write(uint8_t type, uint16_t len, uint8_t *data) os_time_delay(1); } - am_hal_ble_blocking_hci_write(ble_handle, AM_HAL_BLE_RAW, write_buf.data, write_buf.len); + if (AM_HAL_STATUS_SUCCESS != + am_hal_ble_blocking_hci_write(ble_handle, AM_HAL_BLE_RAW, write_buf->data, write_buf->len)) { + return -1; + } return 0; } @@ -273,17 +257,18 @@ apollo3_hci_write(uint8_t type, uint16_t len, uint8_t *data) static int apollo3_ble_hci_acl_tx(struct os_mbuf *om) { - struct os_mbuf *x; int rc = 0; + hci_drv_write_t write_buf; + uint8_t *ptr = (uint8_t *)write_buf.data; - x = om; - while (x) { - rc = apollo3_hci_write(HCI_H4_ACL, x->om_len, x->om_data); - if (rc < 0) { - break; - } - x = SLIST_NEXT(x, om_next); - } + *ptr = HCI_H4_ACL; + ptr++; + write_buf.len = 1; + + os_mbuf_copydata(om, 0, OS_MBUF_PKTLEN(om), ptr); + write_buf.len += OS_MBUF_PKTLEN(om); + + rc = apollo3_hci_write(&write_buf); os_mbuf_free_chain(om); @@ -327,9 +312,15 @@ ble_transport_to_ll_cmd_impl(void *buf) { int rc; uint8_t *cmd = buf; - int len = HCI_CMD_HDR_LEN + cmd[2]; + hci_drv_write_t write_buf; + uint8_t *ptr = (uint8_t *)write_buf.data; - rc = apollo3_hci_write(HCI_H4_CMD, len, cmd); + *ptr = HCI_H4_CMD; + ptr++; + write_buf.len = HCI_CMD_HDR_LEN + cmd[2] + 1; + memcpy(ptr, cmd, write_buf.len - 1); + + rc = apollo3_hci_write(&write_buf); ble_transport_free(cmd);