Bluetooth: hci_event: Fix not handling PA Sync Lost event

This handles PA Sync Lost event which previously was assumed to be
handled with BIG Sync Lost but their lifetime are not the same thus why
there are 2 different events to inform when each sync is lost.

Fixes: b2a5f2e1c1 ("Bluetooth: hci_event: Add support for handling LE BIG Sync Lost event")
Signed-off-by: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>
This commit is contained in:
Luiz Augusto von Dentz
2025-11-06 13:05:35 -05:00
parent 41bf23338a
commit 485e0626e5
2 changed files with 40 additions and 14 deletions

View File

@@ -2783,6 +2783,11 @@ struct hci_ev_le_per_adv_report {
__u8 data[];
} __packed;
#define HCI_EV_LE_PA_SYNC_LOST 0x10
struct hci_ev_le_pa_sync_lost {
__le16 handle;
} __packed;
#define LE_PA_DATA_COMPLETE 0x00
#define LE_PA_DATA_MORE_TO_COME 0x01
#define LE_PA_DATA_TRUNCATED 0x02

View File

@@ -5843,6 +5843,29 @@ static void hci_le_enh_conn_complete_evt(struct hci_dev *hdev, void *data,
le16_to_cpu(ev->supervision_timeout));
}
static void hci_le_pa_sync_lost_evt(struct hci_dev *hdev, void *data,
struct sk_buff *skb)
{
struct hci_ev_le_pa_sync_lost *ev = data;
u16 handle = le16_to_cpu(ev->handle);
struct hci_conn *conn;
bt_dev_dbg(hdev, "sync handle 0x%4.4x", handle);
hci_dev_lock(hdev);
/* Delete the pa sync connection */
conn = hci_conn_hash_lookup_pa_sync_handle(hdev, handle);
if (conn) {
clear_bit(HCI_CONN_BIG_SYNC, &conn->flags);
clear_bit(HCI_CONN_PA_SYNC, &conn->flags);
hci_disconn_cfm(conn, HCI_ERROR_REMOTE_USER_TERM);
hci_conn_del(conn);
}
hci_dev_unlock(hdev);
}
static void hci_le_ext_adv_term_evt(struct hci_dev *hdev, void *data,
struct sk_buff *skb)
{
@@ -7046,29 +7069,24 @@ static void hci_le_big_sync_lost_evt(struct hci_dev *hdev, void *data,
struct sk_buff *skb)
{
struct hci_evt_le_big_sync_lost *ev = data;
struct hci_conn *bis, *conn;
bool mgmt_conn;
struct hci_conn *bis;
bool mgmt_conn = false;
bt_dev_dbg(hdev, "big handle 0x%2.2x", ev->handle);
hci_dev_lock(hdev);
/* Delete the pa sync connection */
bis = hci_conn_hash_lookup_pa_sync_big_handle(hdev, ev->handle);
if (bis) {
conn = hci_conn_hash_lookup_pa_sync_handle(hdev,
bis->sync_handle);
if (conn)
hci_conn_del(conn);
}
/* Delete each bis connection */
while ((bis = hci_conn_hash_lookup_big_state(hdev, ev->handle,
BT_CONNECTED,
HCI_ROLE_SLAVE))) {
mgmt_conn = test_and_clear_bit(HCI_CONN_MGMT_CONNECTED, &bis->flags);
mgmt_device_disconnected(hdev, &bis->dst, bis->type, bis->dst_type,
ev->reason, mgmt_conn);
if (!mgmt_conn) {
mgmt_conn = test_and_clear_bit(HCI_CONN_MGMT_CONNECTED,
&bis->flags);
mgmt_device_disconnected(hdev, &bis->dst, bis->type,
bis->dst_type, ev->reason,
mgmt_conn);
}
clear_bit(HCI_CONN_BIG_SYNC, &bis->flags);
hci_disconn_cfm(bis, ev->reason);
@@ -7182,6 +7200,9 @@ static const struct hci_le_ev {
hci_le_per_adv_report_evt,
sizeof(struct hci_ev_le_per_adv_report),
HCI_MAX_EVENT_SIZE),
/* [0x10 = HCI_EV_LE_PA_SYNC_LOST] */
HCI_LE_EV(HCI_EV_LE_PA_SYNC_LOST, hci_le_pa_sync_lost_evt,
sizeof(struct hci_ev_le_pa_sync_lost)),
/* [0x12 = HCI_EV_LE_EXT_ADV_SET_TERM] */
HCI_LE_EV(HCI_EV_LE_EXT_ADV_SET_TERM, hci_le_ext_adv_term_evt,
sizeof(struct hci_evt_le_ext_adv_set_term)),