Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

Bluetooth: hci_event: Add support for handling LE BIG Sync Lost event

When the BIS source stops, the controller sends an LE BIG Sync Lost
event (subevent 0x1E). Currently, this event is not handled, causing
the BIS stream to remain active in BlueZ and preventing recovery.

Signed-off-by: Yang Li <yang.li@amlogic.com>
Signed-off-by: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>

authored by

Yang Li and committed by
Luiz Augusto von Dentz
b2a5f2e1 45b54f00

+49 -4
+6
include/net/bluetooth/hci.h
··· 2851 2851 __le16 bis[]; 2852 2852 } __packed; 2853 2853 2854 + #define HCI_EVT_LE_BIG_SYNC_LOST 0x1e 2855 + struct hci_evt_le_big_sync_lost { 2856 + __u8 handle; 2857 + __u8 reason; 2858 + } __packed; 2859 + 2854 2860 #define HCI_EVT_LE_BIG_INFO_ADV_REPORT 0x22 2855 2861 struct hci_evt_le_big_info_adv_report { 2856 2862 __le16 sync_handle;
+3 -2
include/net/bluetooth/hci_core.h
··· 1346 1346 } 1347 1347 1348 1348 static inline struct hci_conn * 1349 - hci_conn_hash_lookup_big_state(struct hci_dev *hdev, __u8 handle, __u16 state) 1349 + hci_conn_hash_lookup_big_state(struct hci_dev *hdev, __u8 handle, __u16 state, 1350 + __u8 role) 1350 1351 { 1351 1352 struct hci_conn_hash *h = &hdev->conn_hash; 1352 1353 struct hci_conn *c; ··· 1355 1354 rcu_read_lock(); 1356 1355 1357 1356 list_for_each_entry_rcu(c, &h->list, list) { 1358 - if (c->type != BIS_LINK || c->state != state) 1357 + if (c->type != BIS_LINK || c->state != state || c->role != role) 1359 1358 continue; 1360 1359 1361 1360 if (handle == c->iso_qos.bcast.big) {
+2 -1
net/bluetooth/hci_conn.c
··· 2146 2146 struct hci_link *link; 2147 2147 2148 2148 /* Look for any BIS that is open for rebinding */ 2149 - conn = hci_conn_hash_lookup_big_state(hdev, qos->bcast.big, BT_OPEN); 2149 + conn = hci_conn_hash_lookup_big_state(hdev, qos->bcast.big, BT_OPEN, 2150 + HCI_ROLE_MASTER); 2150 2151 if (conn) { 2151 2152 memcpy(qos, &conn->iso_qos, sizeof(*qos)); 2152 2153 conn->state = BT_CONNECTED;
+38 -1
net/bluetooth/hci_event.c
··· 6876 6876 6877 6877 /* Connect all BISes that are bound to the BIG */ 6878 6878 while ((conn = hci_conn_hash_lookup_big_state(hdev, ev->handle, 6879 - BT_BOUND))) { 6879 + BT_BOUND, 6880 + HCI_ROLE_MASTER))) { 6880 6881 if (ev->status) { 6881 6882 hci_connect_cfm(conn, ev->status); 6882 6883 hci_conn_del(conn); ··· 6990 6989 } 6991 6990 6992 6991 unlock: 6992 + hci_dev_unlock(hdev); 6993 + } 6994 + 6995 + static void hci_le_big_sync_lost_evt(struct hci_dev *hdev, void *data, 6996 + struct sk_buff *skb) 6997 + { 6998 + struct hci_evt_le_big_sync_lost *ev = data; 6999 + struct hci_conn *bis, *conn; 7000 + 7001 + bt_dev_dbg(hdev, "big handle 0x%2.2x", ev->handle); 7002 + 7003 + hci_dev_lock(hdev); 7004 + 7005 + /* Delete the pa sync connection */ 7006 + bis = hci_conn_hash_lookup_pa_sync_big_handle(hdev, ev->handle); 7007 + if (bis) { 7008 + conn = hci_conn_hash_lookup_pa_sync_handle(hdev, 7009 + bis->sync_handle); 7010 + if (conn) 7011 + hci_conn_del(conn); 7012 + } 7013 + 7014 + /* Delete each bis connection */ 7015 + while ((bis = hci_conn_hash_lookup_big_state(hdev, ev->handle, 7016 + BT_CONNECTED, 7017 + HCI_ROLE_SLAVE))) { 7018 + clear_bit(HCI_CONN_BIG_SYNC, &bis->flags); 7019 + hci_disconn_cfm(bis, ev->reason); 7020 + hci_conn_del(bis); 7021 + } 7022 + 6993 7023 hci_dev_unlock(hdev); 6994 7024 } 6995 7025 ··· 7146 7114 HCI_LE_EV_VL(HCI_EVT_LE_BIG_SYNC_ESTABLISHED, 7147 7115 hci_le_big_sync_established_evt, 7148 7116 sizeof(struct hci_evt_le_big_sync_estabilished), 7117 + HCI_MAX_EVENT_SIZE), 7118 + /* [0x1e = HCI_EVT_LE_BIG_SYNC_LOST] */ 7119 + HCI_LE_EV_VL(HCI_EVT_LE_BIG_SYNC_LOST, 7120 + hci_le_big_sync_lost_evt, 7121 + sizeof(struct hci_evt_le_big_sync_lost), 7149 7122 HCI_MAX_EVENT_SIZE), 7150 7123 /* [0x22 = HCI_EVT_LE_BIG_INFO_ADV_REPORT] */ 7151 7124 HCI_LE_EV_VL(HCI_EVT_LE_BIG_INFO_ADV_REPORT,