Bluetooth: controller: Allow any valid ISO sync receiver BIG handle

The BIG handle for an ISO sync receiver is provided by the host. The
valid range is [0x00..0xEF], and this requires the controller to allow
non-consecutive handle numbering. This means that even if only one sync
set is supported, a BIG handle of ex. value 2 must be supported.

As the code uses indexing and range checking directly by handle, this
needs to be changed. Introducing the handle index, which sequnces the
handles such that index = 0 is always the "first handle", regardless
of value.

Signed-off-by: Morten Priess <mtpr@oticon.com>
This commit is contained in:
Morten Priess 2024-03-11 14:41:21 +01:00 committed by Anas Nashif
commit 06870146e6
4 changed files with 50 additions and 24 deletions

View file

@ -90,7 +90,7 @@ int lll_sync_iso_reset(void);
void lll_sync_iso_create_prepare(void *param);
void lll_sync_iso_prepare(void *param);
extern uint8_t ull_sync_iso_lll_handle_get(struct lll_sync_iso *lll);
extern uint8_t ull_sync_iso_lll_index_get(struct lll_sync_iso *lll);
extern struct lll_sync_iso_stream *ull_sync_iso_lll_stream_get(uint16_t handle);
extern void ll_iso_rx_put(memq_link_t *link, void *rx);
extern void ll_rx_sched(void);

View file

@ -375,7 +375,7 @@ static int prepare_cb_common(struct lll_prepare_param *p)
uint32_t overhead;
overhead = lll_preempt_calc(ull, (TICKER_ID_SCAN_SYNC_ISO_BASE +
ull_sync_iso_lll_handle_get(lll)), ticks_at_event);
ull_sync_iso_lll_index_get(lll)), ticks_at_event);
/* check if preempt to start has changed */
if (overhead) {
LL_ASSERT_OVERHEAD(overhead);

View file

@ -52,7 +52,9 @@
static int init_reset(void);
static struct ll_sync_iso_set *sync_iso_get(uint8_t handle);
static struct ll_sync_iso_set *sync_iso_alloc(uint8_t handle);
static uint8_t sync_iso_handle_get(struct ll_sync_iso_set *sync);
static uint8_t sync_iso_handle_to_index(uint8_t handle);
static struct stream *sync_iso_stream_acquire(void);
static uint16_t sync_iso_stream_handle_get(struct lll_sync_iso_stream *stream);
static void timeout_cleanup(struct ll_sync_iso_set *sync_iso);
@ -89,23 +91,23 @@ uint8_t ll_big_sync_create(uint8_t big_handle, uint16_t sync_handle,
int8_t last_index;
sync = ull_sync_is_enabled_get(sync_handle);
if (!sync || sync->iso.sync_iso) {
if (!sync) {
return BT_HCI_ERR_UNKNOWN_ADV_IDENTIFIER;
}
if (sync->iso.sync_iso) {
return BT_HCI_ERR_CMD_DISALLOWED;
}
sync_iso = sync_iso_get(big_handle);
if (!sync_iso) {
/* Host requested more than supported number of ISO Synchronized
* Receivers.
* Or probably HCI handles where not translated to zero-indexed
* controller handles?
*/
return BT_HCI_ERR_MEM_CAPACITY_EXCEEDED;
if (sync_iso) {
/* BIG handle already in use */
return BT_HCI_ERR_CMD_DISALLOWED;
}
/* Check if this ISO already is associated with a Periodic Sync */
if (sync_iso->sync) {
return BT_HCI_ERR_CMD_DISALLOWED;
sync_iso = sync_iso_alloc(big_handle);
if (!sync_iso) {
return BT_HCI_ERR_INSUFFICIENT_RESOURCES;
}
/* TODO: Check remaining parameters */
@ -269,7 +271,8 @@ uint8_t ll_big_sync_terminate(uint8_t big_handle, void **rx)
}
err = ull_ticker_stop_with_mark((TICKER_ID_SCAN_SYNC_ISO_BASE +
big_handle), sync_iso, &sync_iso->lll);
sync_iso_handle_to_index(big_handle)),
sync_iso, &sync_iso->lll);
LL_ASSERT_INFO2(err == 0 || err == -EALREADY, big_handle, err);
if (err) {
return BT_HCI_ERR_CMD_DISALLOWED;
@ -307,9 +310,9 @@ int ull_sync_iso_reset(void)
return 0;
}
uint8_t ull_sync_iso_lll_handle_get(struct lll_sync_iso *lll)
uint8_t ull_sync_iso_lll_index_get(struct lll_sync_iso *lll)
{
return sync_iso_handle_get(HDR_LLL2ULL(lll));
return ARRAY_INDEX(ll_sync_iso, HDR_LLL2ULL(lll));
}
struct ll_sync_iso_set *ull_sync_iso_by_stream_get(uint16_t handle)
@ -630,7 +633,8 @@ void ull_sync_iso_setup(struct ll_sync_iso_set *sync_iso,
handle = sync_iso_handle_get(sync_iso);
ret = ticker_start(TICKER_INSTANCE_ID_CTLR, TICKER_USER_ID_ULL_HIGH,
(TICKER_ID_SCAN_SYNC_ISO_BASE + handle),
(TICKER_ID_SCAN_SYNC_ISO_BASE +
sync_iso_handle_to_index(handle)),
ftr->ticks_anchor - ticks_slot_offset,
HAL_TICKER_US_TO_TICKS(sync_iso_offset_us),
HAL_TICKER_US_TO_TICKS(interval_us),
@ -762,7 +766,7 @@ void ull_sync_iso_done(struct node_rx_event_done *done)
ticker_status = ticker_update(TICKER_INSTANCE_ID_CTLR,
TICKER_USER_ID_ULL_HIGH,
(TICKER_ID_SCAN_SYNC_ISO_BASE +
handle),
sync_iso_handle_to_index(handle)),
ticks_drift_plus,
ticks_drift_minus, 0U, 0U,
lazy, force,
@ -796,7 +800,8 @@ void ull_sync_iso_done_terminate(struct node_rx_event_done *done)
/* Stop Sync ISO Ticker */
handle = sync_iso_handle_get(sync_iso);
ret = ticker_stop(TICKER_INSTANCE_ID_CTLR, TICKER_USER_ID_ULL_HIGH,
(TICKER_ID_SCAN_SYNC_ISO_BASE + handle),
(TICKER_ID_SCAN_SYNC_ISO_BASE +
sync_iso_handle_to_index(handle)),
ticker_stop_op_cb, (void *)sync_iso);
LL_ASSERT((ret == TICKER_STATUS_SUCCESS) ||
(ret == TICKER_STATUS_BUSY));
@ -846,16 +851,35 @@ static int init_reset(void)
static struct ll_sync_iso_set *sync_iso_get(uint8_t handle)
{
if (handle >= CONFIG_BT_CTLR_SCAN_SYNC_ISO_SET) {
return NULL;
for (uint8_t idx = 0; idx < CONFIG_BT_CTLR_SCAN_SYNC_ISO_SET; idx++) {
if (ll_sync_iso[idx].sync && ll_sync_iso[idx].big_handle == handle) {
return &ll_sync_iso[idx];
}
}
return &ll_sync_iso[handle];
return NULL;
}
static struct ll_sync_iso_set *sync_iso_alloc(uint8_t handle)
{
for (uint8_t idx = 0; idx < CONFIG_BT_CTLR_SCAN_SYNC_ISO_SET; idx++) {
if (!ll_sync_iso[idx].sync) {
ll_sync_iso[idx].big_handle = handle;
return &ll_sync_iso[idx];
}
}
return NULL;
}
static uint8_t sync_iso_handle_get(struct ll_sync_iso_set *sync)
{
return mem_index_get(sync, ll_sync_iso, sizeof(*sync));
return sync->big_handle;
}
static uint8_t sync_iso_handle_to_index(uint8_t handle)
{
return ARRAY_INDEX(ll_sync_iso, sync_iso_get(handle));
}
static struct stream *sync_iso_stream_acquire(void)
@ -890,7 +914,8 @@ static void timeout_cleanup(struct ll_sync_iso_set *sync_iso)
/* Stop Sync ISO Ticker */
handle = sync_iso_handle_get(sync_iso);
ret = ticker_stop(TICKER_INSTANCE_ID_CTLR, TICKER_USER_ID_ULL_HIGH,
(TICKER_ID_SCAN_SYNC_ISO_BASE + handle),
(TICKER_ID_SCAN_SYNC_ISO_BASE +
sync_iso_handle_to_index(handle)),
ticker_stop_op_cb, (void *)sync_iso);
LL_ASSERT((ret == TICKER_STATUS_SUCCESS) ||
(ret == TICKER_STATUS_BUSY));

View file

@ -115,6 +115,7 @@ struct ll_sync_iso_set {
uint16_t timeout;
uint16_t volatile timeout_reload; /* Non-zero when sync established */
uint16_t timeout_expire; /* timeout countdown */
uint8_t big_handle;
/* Encryption */
uint8_t gltk[16];