Commit 485e0626 authored by Luiz Augusto von Dentz's avatar Luiz Augusto von Dentz
Browse files

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: b2a5f2e1 ("Bluetooth: hci_event: Add support for handling LE BIG Sync Lost event")
Signed-off-by: default avatarLuiz Augusto von Dentz <luiz.von.dentz@intel.com>
parent 41bf2333
Loading
Loading
Loading
Loading
+5 −0
Original line number Diff line number Diff line
@@ -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
+35 −14
Original line number Diff line number Diff line
@@ -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)),