Bluetooth: host: Add handling of failures in per sync established evt

Handling of HCI_LE_Periodic_Advertising_Sync_Established didn't
have implemented handling of possible failures of periodic
advertising synchronization.
There are two situations definded by BT 5.3 Core spec:
- There is no AUX_SYNC_IND pdu within 6 periodic advertising events.
  If that happens, status of the command is set to (0x3E) Connection
  Failed To Be Established / Synchronization Timeout.
- Periodic advertising has wrong CTE type while periodic advertising
  list is not used to determine the advertiser to listen.
  In this case status of the command is set to (0x1A) Unsupported
  Remote Feature.

The commit provides missing functionality.
In case of error, the periodic advertising will be deleted and
application will be notified by call to terminated callback.
The callback data were extended by err member. It provides
information why periodic advertising was terminated.

Signed-off-by: Piotr Pryga <piotr.pryga@nordicsemi.no>
This commit is contained in:
Piotr Pryga 2021-11-09 22:45:59 +01:00 committed by Johan Hedberg
commit ea1340acd3
2 changed files with 16 additions and 3 deletions

View file

@ -1153,6 +1153,9 @@ struct bt_le_per_adv_sync_term_info {
/** Advertiser SID */ /** Advertiser SID */
uint8_t sid; uint8_t sid;
/** Cause of periodic advertising termination */
uint8_t reason;
}; };
struct bt_le_per_adv_sync_recv_info { struct bt_le_per_adv_sync_recv_info {

View file

@ -686,6 +686,7 @@ void bt_hci_le_per_adv_sync_established(struct net_buf *buf)
struct bt_le_per_adv_sync_synced_info sync_info; struct bt_le_per_adv_sync_synced_info sync_info;
struct bt_le_per_adv_sync *pending_per_adv_sync; struct bt_le_per_adv_sync *pending_per_adv_sync;
struct bt_le_per_adv_sync_cb *listener; struct bt_le_per_adv_sync_cb *listener;
bool unexpected_evt;
int err; int err;
pending_per_adv_sync = get_pending_per_adv_sync(); pending_per_adv_sync = get_pending_per_adv_sync();
@ -716,22 +717,29 @@ void bt_hci_le_per_adv_sync_established(struct net_buf *buf)
BT_PER_ADV_SYNC_SYNCING_USE_LIST) && BT_PER_ADV_SYNC_SYNCING_USE_LIST) &&
((pending_per_adv_sync->sid != evt->sid) || ((pending_per_adv_sync->sid != evt->sid) ||
bt_addr_le_cmp(&pending_per_adv_sync->addr, &evt->adv_addr)))) { bt_addr_le_cmp(&pending_per_adv_sync->addr, &evt->adv_addr)))) {
struct bt_le_per_adv_sync_term_info term_info;
BT_ERR("Unexpected per adv sync established event"); BT_ERR("Unexpected per adv sync established event");
/* Request terminate of pending periodic advertising in controller */
per_adv_sync_terminate(sys_le16_to_cpu(evt->handle)); per_adv_sync_terminate(sys_le16_to_cpu(evt->handle));
unexpected_evt = true;
} else {
unexpected_evt = false;
}
if (unexpected_evt || evt->status != BT_HCI_ERR_SUCCESS) {
if (pending_per_adv_sync) { if (pending_per_adv_sync) {
struct bt_le_per_adv_sync_term_info term_info;
/* Terminate the pending PA sync and notify app */ /* Terminate the pending PA sync and notify app */
term_info.addr = &pending_per_adv_sync->addr; term_info.addr = &pending_per_adv_sync->addr;
term_info.sid = pending_per_adv_sync->sid; term_info.sid = pending_per_adv_sync->sid;
term_info.reason = unexpected_evt ? BT_HCI_ERR_UNSPECIFIED : evt->status;
/* Deleting before callback, so the caller will be able /* Deleting before callback, so the caller will be able
* to restart sync in the callback. * to restart sync in the callback.
*/ */
per_adv_sync_delete(pending_per_adv_sync); per_adv_sync_delete(pending_per_adv_sync);
SYS_SLIST_FOR_EACH_CONTAINER(&pa_sync_cbs, SYS_SLIST_FOR_EACH_CONTAINER(&pa_sync_cbs,
listener, listener,
node) { node) {
@ -787,6 +795,8 @@ void bt_hci_le_per_adv_sync_lost(struct net_buf *buf)
term_info.addr = &per_adv_sync->addr; term_info.addr = &per_adv_sync->addr;
term_info.sid = per_adv_sync->sid; term_info.sid = per_adv_sync->sid;
/* There is no status in the per. adv. sync lost event */
term_info.reason = BT_HCI_ERR_UNSPECIFIED;
/* Deleting before callback, so the caller will be able to restart /* Deleting before callback, so the caller will be able to restart
* sync in the callback * sync in the callback