Bluetooth: controller: Parameter check for ISO sync recv qualification

Add HCI input parameter validation according to spec for passing
qualification tests.

- Conditional compile of LE Set PA Receive Enable feature
- Store BIGinfo encryption state and number of streams
- Do not report BIGinfo if phy is invalid or unsupported
- Return disallowed ll_read_iso_tx_sync uses sync recever handle
- Validate BIS indices in ll_big_sync_create

Signed-off-by: Morten Priess <mtpr@oticon.com>
This commit is contained in:
Morten Priess 2024-03-11 15:19:18 +01:00 committed by David Leach
commit 6f374d850a
6 changed files with 62 additions and 7 deletions

View file

@ -887,8 +887,10 @@ static void read_supported_commands(struct net_buf *buf, struct net_buf **evt)
*/
rp->commands[38] |= BIT(3) | BIT(4) | BIT(5) | BIT(6);
#endif /* CONFIG_BT_CTLR_SYNC_PERIODIC_ADV_LIST */
#if defined(CONFIG_BT_CTLR_SYNC_PERIODIC)
/* LE Set PA Receive Enable */
rp->commands[40] |= BIT(5);
#endif /* CONFIG_BT_CTLR_SYNC_PERIODIC */
#if defined(CONFIG_BT_CTLR_SYNC_ISO)
/* LE BIG Create Sync, LE BIG Terminate Sync */
rp->commands[43] |= BIT(0) | BIT(1);
@ -7749,6 +7751,7 @@ no_ext_hdr:
struct bt_hci_evt_le_biginfo_adv_report *sep;
struct pdu_big_info *bi;
uint8_t bi_size;
uint8_t phy;
/* FIXME: Parse and find the BIGInfo */
if (acad[PDU_ADV_DATA_HEADER_TYPE_OFFSET] != BT_DATA_BIG_INFO) {
@ -7758,6 +7761,14 @@ no_ext_hdr:
bi_size = acad[PDU_ADV_DATA_HEADER_LEN_OFFSET];
bi = (void *)&acad[PDU_ADV_DATA_HEADER_DATA_OFFSET];
/* Do not report if phy is invalid or unsupported */
phy = (bi->chm_phy[4] >> 5);
if ((phy > EXT_ADV_AUX_PHY_LE_CODED) ||
(!IS_ENABLED(CONFIG_BT_CTLR_PHY_CODED) &&
(phy == EXT_ADV_AUX_PHY_LE_CODED))) {
return;
}
/* Allocate new event buffer if periodic advertising report was
* constructed with the caller supplied buffer.
*/

View file

@ -189,6 +189,9 @@ uint8_t ll_read_iso_tx_sync(uint16_t handle, uint16_t *seq,
}
return BT_HCI_ERR_SUCCESS;
} else if (IS_SYNC_ISO_HANDLE(handle)) {
return BT_HCI_ERR_CMD_DISALLOWED;
}
return BT_HCI_ERR_UNKNOWN_CONN_ID;

View file

@ -454,10 +454,27 @@ void ull_scan_aux_setup(memq_link_t *link, struct node_rx_hdr *rx)
/* Periodic Advertising Channel Map Indication */
ull_sync_chm_update(rx->handle, ptr, acad_len);
#if defined(CONFIG_BT_CTLR_SYNC_ISO)
struct ll_sync_set *sync_set;
struct pdu_big_info *bi;
uint8_t bi_size;
sync_set = HDR_LLL2ULL(sync_lll);
/* Provide encryption information for BIG sync creation */
bi_size = ptr[PDU_ADV_DATA_HEADER_LEN_OFFSET] -
PDU_ADV_DATA_HEADER_TYPE_SIZE;
sync_set->enc = (bi_size == PDU_BIG_INFO_ENCRYPTED_SIZE);
/* Store number of BISes in the BIG */
bi = (void *)&ptr[PDU_ADV_DATA_HEADER_DATA_OFFSET];
sync_set->num_bis = PDU_BIG_INFO_NUM_BIS_GET(bi);
/* Broadcast ISO synchronize */
if (IS_ENABLED(CONFIG_BT_CTLR_SYNC_ISO) && sync_iso) {
if (sync_iso) {
ull_sync_iso_setup(sync_iso, rx, ptr, acad_len);
}
#endif /* CONFIG_BT_CTLR_SYNC_ISO */
}
/* Do not ULL schedule auxiliary PDU reception if no aux pointer

View file

@ -201,6 +201,10 @@ uint8_t ll_sync_create(uint8_t options, uint8_t sid, uint8_t adv_addr_type,
sync->skip = skip;
sync->is_stop = 0U;
#if defined(CONFIG_BT_CTLR_SYNC_ISO)
sync->enc = 0U;
#endif /* CONFIG_BT_CTLR_SYNC_ISO */
/* NOTE: Use timeout not zero to represent sync context used for sync
* create.
*/
@ -1492,7 +1496,6 @@ static struct pdu_cte_info *pdu_cte_info_get(struct pdu_adv *pdu)
{
struct pdu_adv_com_ext_adv *com_hdr;
struct pdu_adv_ext_hdr *hdr;
uint8_t *dptr;
com_hdr = &pdu->adv_ext_ind;
hdr = &com_hdr->ext_hdr;
@ -1501,9 +1504,6 @@ static struct pdu_cte_info *pdu_cte_info_get(struct pdu_adv *pdu)
return NULL;
}
/* Skip flags in extended advertising header */
dptr = hdr->data;
/* Make sure there are no fields that are not allowd for AUX_SYNC_IND and AUX_CHAIN_IND */
LL_ASSERT(!hdr->adv_addr);
LL_ASSERT(!hdr->tgt_addr);

View file

@ -86,6 +86,7 @@ uint8_t ll_big_sync_create(uint8_t big_handle, uint16_t sync_handle,
struct node_rx_hdr *node_rx;
struct ll_sync_set *sync;
struct lll_sync_iso *lll;
int8_t last_index;
sync = ull_sync_is_enabled_get(sync_handle);
if (!sync || sync->iso.sync_iso) {
@ -107,11 +108,29 @@ uint8_t ll_big_sync_create(uint8_t big_handle, uint16_t sync_handle,
return BT_HCI_ERR_CMD_DISALLOWED;
}
/* TODO: Check parameters */
/* TODO: Check remaining parameters */
/* Check BIS indices */
last_index = -1;
for (uint8_t i = 0U; i < num_bis; i++) {
/* Stream index must be in valid range and in ascending order */
if (!IN_RANGE(bis[i], 0x01, 0x1F) || (bis[i] <= last_index)) {
return BT_HCI_ERR_INVALID_PARAM;
} else if (bis[i] > sync->num_bis) {
return BT_HCI_ERR_UNSUPP_FEATURE_PARAM_VAL;
}
last_index = bis[i];
}
/* Check if requested encryption matches */
if (encryption != sync->enc) {
return BT_HCI_ERR_ENC_MODE_NOT_ACCEPTABLE;
}
/* Check if free BISes available */
if (mem_free_count_get(stream_free) < num_bis) {
return BT_HCI_ERR_MEM_CAPACITY_EXCEEDED;
return BT_HCI_ERR_INSUFFICIENT_RESOURCES;
}
link_sync_estab = ll_rx_link_alloc();

View file

@ -57,6 +57,11 @@ struct ll_sync_set {
uint8_t is_stop:1; /* sync terminate or cancel requested */
uint8_t sync_expire:3; /* countdown of 6 before fail to establish */
#if defined(CONFIG_BT_CTLR_SYNC_ISO)
uint8_t enc : 1;
uint8_t num_bis : 5;
#endif /* CONFIG_BT_CTLR_SYNC_ISO */
#if defined(CONFIG_BT_CTLR_CHECK_SAME_PEER_SYNC)
uint8_t sid;
#endif /* CONFIG_BT_CTLR_CHECK_SAME_PEER_SYNC */