Bluetooth: Store advertising handle so it can be re-enabled

This stores the advertising handle/instance into hci_conn so it is
accessible when re-enabling the advertising once disconnected.

Signed-off-by: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>
Signed-off-by: Marcel Holtmann <marcel@holtmann.org>
This commit is contained in:
Luiz Augusto von Dentz 2021-08-11 16:20:16 -07:00 committed by Marcel Holtmann
parent cafae4cd62
commit 7087c4f694
2 changed files with 30 additions and 16 deletions

View File

@ -629,6 +629,7 @@ struct hci_conn {
__u8 init_addr_type;
bdaddr_t resp_addr;
__u8 resp_addr_type;
__u8 adv_instance;
__u16 handle;
__u16 state;
__u8 mode;

View File

@ -2348,19 +2348,20 @@ static void hci_cs_disconnect(struct hci_dev *hdev, u8 status)
conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(cp->handle));
if (conn) {
u8 type = conn->type;
mgmt_disconnect_failed(hdev, &conn->dst, conn->type,
conn->dst_type, status);
if (conn->type == LE_LINK) {
hdev->cur_adv_instance = conn->adv_instance;
hci_req_reenable_advertising(hdev);
}
/* If the disconnection failed for any reason, the upper layer
* does not retry to disconnect in current implementation.
* Hence, we need to do some basic cleanup here and re-enable
* advertising if necessary.
*/
hci_conn_del(conn);
if (type == LE_LINK)
hci_req_reenable_advertising(hdev);
}
hci_dev_unlock(hdev);
@ -2886,7 +2887,6 @@ static void hci_disconn_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
struct hci_conn_params *params;
struct hci_conn *conn;
bool mgmt_connected;
u8 type;
BT_DBG("%s status 0x%2.2x", hdev->name, ev->status);
@ -2941,10 +2941,7 @@ static void hci_disconn_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
}
}
type = conn->type;
hci_disconn_cfm(conn, ev->reason);
hci_conn_del(conn);
/* The suspend notifier is waiting for all devices to disconnect so
* clear the bit from pending tasks and inform the wait queue.
@ -2964,8 +2961,12 @@ static void hci_disconn_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
* or until a connection is created or until the Advertising
* is timed out due to Directed Advertising."
*/
if (type == LE_LINK)
if (conn->type == LE_LINK) {
hdev->cur_adv_instance = conn->adv_instance;
hci_req_reenable_advertising(hdev);
}
hci_conn_del(conn);
unlock:
hci_dev_unlock(hdev);
@ -5323,6 +5324,13 @@ static void le_conn_complete_evt(struct hci_dev *hdev, u8 status,
conn->handle = handle;
conn->state = BT_CONFIG;
/* Store current advertising instance as connection advertising instance
* when sotfware rotation is in use so it can be re-enabled when
* disconnected.
*/
if (!ext_adv_capable(hdev))
conn->adv_instance = hdev->cur_adv_instance;
conn->le_conn_interval = interval;
conn->le_conn_latency = latency;
conn->le_supv_timeout = supervision_timeout;
@ -5406,13 +5414,13 @@ static void hci_le_ext_adv_term_evt(struct hci_dev *hdev, struct sk_buff *skb)
{
struct hci_evt_le_ext_adv_set_term *ev = (void *) skb->data;
struct hci_conn *conn;
struct adv_info *adv;
BT_DBG("%s status 0x%2.2x", hdev->name, ev->status);
if (ev->status) {
struct adv_info *adv;
adv = hci_find_adv_instance(hdev, ev->handle);
adv = hci_find_adv_instance(hdev, ev->handle);
if (ev->status) {
if (!adv)
return;
@ -5423,9 +5431,15 @@ static void hci_le_ext_adv_term_evt(struct hci_dev *hdev, struct sk_buff *skb)
return;
}
if (adv)
adv->enabled = false;
conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->conn_handle));
if (conn) {
struct adv_info *adv_instance;
/* Store handle in the connection so the correct advertising
* instance can be re-enabled when disconnected.
*/
conn->adv_instance = ev->handle;
if (hdev->adv_addr_type != ADDR_LE_DEV_RANDOM ||
bacmp(&conn->resp_addr, BDADDR_ANY))
@ -5436,9 +5450,8 @@ static void hci_le_ext_adv_term_evt(struct hci_dev *hdev, struct sk_buff *skb)
return;
}
adv_instance = hci_find_adv_instance(hdev, ev->handle);
if (adv_instance)
bacpy(&conn->resp_addr, &adv_instance->random_addr);
if (adv)
bacpy(&conn->resp_addr, &adv->random_addr);
}
}