Bluetooth: Controller: Fix missing Broadcast ISO Sync MIC failure
Fix missing implementation to handle Broadcast ISO MIC failure during Broadcast ISO establishment, and during an already established Broadcast ISO sync. Signed-off-by: Vinayak Kariappa Chettimada <vich@nordicsemi.no>
This commit is contained in:
parent
d5da582e00
commit
f05d16dabb
2 changed files with 55 additions and 9 deletions
|
@ -10,6 +10,7 @@
|
||||||
#include <soc.h>
|
#include <soc.h>
|
||||||
#include <zephyr/sys/byteorder.h>
|
#include <zephyr/sys/byteorder.h>
|
||||||
#include <zephyr/sys/util.h>
|
#include <zephyr/sys/util.h>
|
||||||
|
#include <zephyr/bluetooth/hci_types.h>
|
||||||
|
|
||||||
#include "hal/cpu.h"
|
#include "hal/cpu.h"
|
||||||
#include "hal/ccm.h"
|
#include "hal/ccm.h"
|
||||||
|
@ -435,6 +436,7 @@ static void abort_cb(struct lll_prepare_param *prepare_param, void *param)
|
||||||
static void isr_rx_estab(void *param)
|
static void isr_rx_estab(void *param)
|
||||||
{
|
{
|
||||||
struct event_done_extra *e;
|
struct event_done_extra *e;
|
||||||
|
struct lll_sync_iso *lll;
|
||||||
uint8_t trx_done;
|
uint8_t trx_done;
|
||||||
uint8_t crc_ok;
|
uint8_t crc_ok;
|
||||||
|
|
||||||
|
@ -454,6 +456,36 @@ static void isr_rx_estab(void *param)
|
||||||
/* Clear radio rx status and events */
|
/* Clear radio rx status and events */
|
||||||
lll_isr_rx_status_reset();
|
lll_isr_rx_status_reset();
|
||||||
|
|
||||||
|
/* Get reference to LLL context */
|
||||||
|
lll = param;
|
||||||
|
|
||||||
|
/* Check for MIC failures for encrypted Broadcast ISO streams */
|
||||||
|
if (IS_ENABLED(CONFIG_BT_CTLR_BROADCAST_ISO_ENC) && crc_ok && lll->enc) {
|
||||||
|
struct node_rx_pdu *node_rx;
|
||||||
|
struct pdu_bis *pdu;
|
||||||
|
|
||||||
|
/* By design, there shall always be one free node rx available when setting up radio
|
||||||
|
* for new PDU reception.
|
||||||
|
*/
|
||||||
|
node_rx = ull_iso_pdu_rx_alloc_peek(1U);
|
||||||
|
LL_ASSERT(node_rx);
|
||||||
|
|
||||||
|
/* Get reference to received PDU and validate MIC for non-empty PDU */
|
||||||
|
pdu = (void *)node_rx->pdu;
|
||||||
|
if (pdu->len) {
|
||||||
|
bool mic_failure;
|
||||||
|
uint32_t done;
|
||||||
|
|
||||||
|
done = radio_ccm_is_done();
|
||||||
|
LL_ASSERT(done);
|
||||||
|
|
||||||
|
mic_failure = !radio_ccm_mic_is_valid();
|
||||||
|
if (mic_failure) {
|
||||||
|
lll->term_reason = BT_HCI_ERR_TERM_DUE_TO_MIC_FAIL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (IS_ENABLED(CONFIG_BT_CTLR_PROFILE_ISR)) {
|
if (IS_ENABLED(CONFIG_BT_CTLR_PROFILE_ISR)) {
|
||||||
lll_prof_cputime_capture();
|
lll_prof_cputime_capture();
|
||||||
}
|
}
|
||||||
|
@ -463,14 +495,11 @@ static void isr_rx_estab(void *param)
|
||||||
LL_ASSERT(e);
|
LL_ASSERT(e);
|
||||||
|
|
||||||
e->type = EVENT_DONE_EXTRA_TYPE_SYNC_ISO_ESTAB;
|
e->type = EVENT_DONE_EXTRA_TYPE_SYNC_ISO_ESTAB;
|
||||||
e->estab_failed = 0U;
|
e->estab_failed = lll->term_reason ? 1U : 0U;
|
||||||
e->trx_cnt = trx_cnt;
|
e->trx_cnt = trx_cnt;
|
||||||
e->crc_valid = crc_ok;
|
e->crc_valid = crc_ok;
|
||||||
|
|
||||||
if (trx_cnt) {
|
if (trx_cnt) {
|
||||||
struct lll_sync_iso *lll;
|
|
||||||
|
|
||||||
lll = param;
|
|
||||||
e->drift.preamble_to_addr_us = addr_us_get(lll->phy);
|
e->drift.preamble_to_addr_us = addr_us_get(lll->phy);
|
||||||
e->drift.start_to_address_actual_us =
|
e->drift.start_to_address_actual_us =
|
||||||
radio_tmr_aa_get() - radio_tmr_ready_get();
|
radio_tmr_aa_get() - radio_tmr_ready_get();
|
||||||
|
@ -492,7 +521,6 @@ static void isr_rx_estab(void *param)
|
||||||
static void isr_rx(void *param)
|
static void isr_rx(void *param)
|
||||||
{
|
{
|
||||||
struct lll_sync_iso_stream *stream;
|
struct lll_sync_iso_stream *stream;
|
||||||
struct node_rx_pdu *node_rx;
|
|
||||||
struct lll_sync_iso *lll;
|
struct lll_sync_iso *lll;
|
||||||
uint8_t access_addr[4];
|
uint8_t access_addr[4];
|
||||||
uint16_t data_chan_id;
|
uint16_t data_chan_id;
|
||||||
|
@ -562,6 +590,7 @@ static void isr_rx(void *param)
|
||||||
/* Check CRC and generate ISO Data PDU */
|
/* Check CRC and generate ISO Data PDU */
|
||||||
if (crc_ok) {
|
if (crc_ok) {
|
||||||
struct lll_sync_iso_stream *sync_stream;
|
struct lll_sync_iso_stream *sync_stream;
|
||||||
|
struct node_rx_pdu *node_rx;
|
||||||
uint32_t payload_offset;
|
uint32_t payload_offset;
|
||||||
uint16_t payload_index;
|
uint16_t payload_index;
|
||||||
uint16_t stream_handle;
|
uint16_t stream_handle;
|
||||||
|
@ -631,14 +660,18 @@ static void isr_rx(void *param)
|
||||||
|
|
||||||
if (IS_ENABLED(CONFIG_BT_CTLR_BROADCAST_ISO_ENC) &&
|
if (IS_ENABLED(CONFIG_BT_CTLR_BROADCAST_ISO_ENC) &&
|
||||||
lll->enc) {
|
lll->enc) {
|
||||||
uint32_t mic_failure;
|
bool mic_failure;
|
||||||
uint32_t done;
|
uint32_t done;
|
||||||
|
|
||||||
done = radio_ccm_is_done();
|
done = radio_ccm_is_done();
|
||||||
LL_ASSERT(done);
|
LL_ASSERT(done);
|
||||||
|
|
||||||
mic_failure = !radio_ccm_mic_is_valid();
|
mic_failure = !radio_ccm_mic_is_valid();
|
||||||
LL_ASSERT(!mic_failure);
|
if (mic_failure) {
|
||||||
|
lll->term_reason = BT_HCI_ERR_TERM_DUE_TO_MIC_FAIL;
|
||||||
|
|
||||||
|
goto isr_rx_mic_failure;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ull_iso_pdu_rx_alloc();
|
ull_iso_pdu_rx_alloc();
|
||||||
|
@ -893,6 +926,7 @@ isr_rx_find_subevent:
|
||||||
goto isr_rx_next_subevent;
|
goto isr_rx_next_subevent;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
isr_rx_mic_failure:
|
||||||
isr_rx_done(param);
|
isr_rx_done(param);
|
||||||
|
|
||||||
if (IS_ENABLED(CONFIG_BT_CTLR_PROFILE_ISR)) {
|
if (IS_ENABLED(CONFIG_BT_CTLR_PROFILE_ISR)) {
|
||||||
|
@ -972,6 +1006,8 @@ isr_rx_next_subevent:
|
||||||
|
|
||||||
payload_count = lll->payload_count - lll->bn;
|
payload_count = lll->payload_count - lll->bn;
|
||||||
if (bis) {
|
if (bis) {
|
||||||
|
struct node_rx_pdu *node_rx;
|
||||||
|
|
||||||
payload_count += (lll->bn_curr - 1U) +
|
payload_count += (lll->bn_curr - 1U) +
|
||||||
(lll->ptc_curr * lll->pto);
|
(lll->ptc_curr * lll->pto);
|
||||||
|
|
||||||
|
@ -1000,6 +1036,8 @@ isr_rx_next_subevent:
|
||||||
struct pdu_bis *pdu;
|
struct pdu_bis *pdu;
|
||||||
|
|
||||||
if (bis) {
|
if (bis) {
|
||||||
|
struct node_rx_pdu *node_rx;
|
||||||
|
|
||||||
/* By design, there shall always be one free node rx
|
/* By design, there shall always be one free node rx
|
||||||
* available for setting up radio for new PDU reception.
|
* available for setting up radio for new PDU reception.
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -698,9 +698,17 @@ void ull_sync_iso_estab_done(struct node_rx_event_done *done)
|
||||||
rx->hdr.handle = sync_iso_handle_get(sync_iso);
|
rx->hdr.handle = sync_iso_handle_get(sync_iso);
|
||||||
rx->rx_ftr.param = sync_iso;
|
rx->rx_ftr.param = sync_iso;
|
||||||
|
|
||||||
|
/* status value is stored in the PDU member of the node rx */
|
||||||
se = (void *)rx->pdu;
|
se = (void *)rx->pdu;
|
||||||
se->status = done->extra.estab_failed ?
|
if (done->extra.estab_failed) {
|
||||||
BT_HCI_ERR_CONN_FAIL_TO_ESTAB : BT_HCI_ERR_SUCCESS;
|
if (sync_iso->lll.term_reason != BT_HCI_ERR_SUCCESS) {
|
||||||
|
se->status = sync_iso->lll.term_reason;
|
||||||
|
} else {
|
||||||
|
se->status = BT_HCI_ERR_CONN_FAIL_TO_ESTAB;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
se->status = BT_HCI_ERR_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
ll_rx_put_sched(rx->hdr.link, rx);
|
ll_rx_put_sched(rx->hdr.link, rx);
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue