[PATCH 4/6] Bluetooth: Emit tx power chosen on ext adv params completion

From: Daniel Winkler
Date: Wed Sep 16 2020 - 16:18:08 EST


Our hci call to set extended advertising parameters returns the actual
tx power selected by the controller. This patch signals a new
TX_POWER_SELECTED mgmt event to alert the caller of the actual tx power
that is being used. This is important because the power selected will
not necessarily match the power requested by the user.

This patch is manually verified by ensuring the tx power selected event
is signalled and caught by bluetoothd.

Reviewed-by: Sonny Sasaka <sonnysasaka@xxxxxxxxxxxx>
Signed-off-by: Daniel Winkler <danielwinkler@xxxxxxxxxx>
---

include/net/bluetooth/hci_core.h | 2 ++
include/net/bluetooth/mgmt.h | 6 ++++++
net/bluetooth/hci_event.c | 4 ++++
net/bluetooth/mgmt.c | 11 +++++++++++
4 files changed, 23 insertions(+)

diff --git a/include/net/bluetooth/hci_core.h b/include/net/bluetooth/hci_core.h
index ab168f46b6d909..667b9d37099dec 100644
--- a/include/net/bluetooth/hci_core.h
+++ b/include/net/bluetooth/hci_core.h
@@ -1781,6 +1781,8 @@ void mgmt_advertising_added(struct sock *sk, struct hci_dev *hdev,
u8 instance);
void mgmt_advertising_removed(struct sock *sk, struct hci_dev *hdev,
u8 instance);
+void mgmt_adv_tx_power_selected(struct hci_dev *hdev, u8 instance,
+ s8 tx_power);
int mgmt_phy_configuration_changed(struct hci_dev *hdev, struct sock *skip);

u8 hci_le_conn_update(struct hci_conn *conn, u16 min, u16 max, u16 latency,
diff --git a/include/net/bluetooth/mgmt.h b/include/net/bluetooth/mgmt.h
index 859f0d3cd6ea38..db64cf4747554c 100644
--- a/include/net/bluetooth/mgmt.h
+++ b/include/net/bluetooth/mgmt.h
@@ -1079,3 +1079,9 @@ struct mgmt_ev_controller_resume {
#define MGMT_WAKE_REASON_NON_BT_WAKE 0x0
#define MGMT_WAKE_REASON_UNEXPECTED 0x1
#define MGMT_WAKE_REASON_REMOTE_WAKE 0x2
+
+#define MGMT_EV_ADV_TX_POWER_SELECTED 0x002f
+struct mgmt_ev_adv_tx_power_selected {
+ __u8 instance;
+ __s8 tx_power;
+} __packed;
diff --git a/net/bluetooth/hci_event.c b/net/bluetooth/hci_event.c
index bd306ba3ade545..9a24fd99d9e08e 100644
--- a/net/bluetooth/hci_event.c
+++ b/net/bluetooth/hci_event.c
@@ -1749,6 +1749,10 @@ static void hci_cc_set_ext_adv_param(struct hci_dev *hdev, struct sk_buff *skb)
}
/* Update adv data as tx power is known now */
hci_req_update_adv_data(hdev, hdev->cur_adv_instance);
+
+ if (cp->handle)
+ mgmt_adv_tx_power_selected(hdev, cp->handle, rp->tx_power);
+
hci_dev_unlock(hdev);
}

diff --git a/net/bluetooth/mgmt.c b/net/bluetooth/mgmt.c
index 717c97affb1554..b9347ff1a1e961 100644
--- a/net/bluetooth/mgmt.c
+++ b/net/bluetooth/mgmt.c
@@ -167,6 +167,7 @@ static const u16 mgmt_events[] = {
MGMT_EV_DEVICE_FLAGS_CHANGED,
MGMT_EV_CONTROLLER_SUSPEND,
MGMT_EV_CONTROLLER_RESUME,
+ MGMT_EV_ADV_TX_POWER_SELECTED,
};

static const u16 mgmt_untrusted_commands[] = {
@@ -1152,6 +1153,16 @@ void mgmt_advertising_removed(struct sock *sk, struct hci_dev *hdev,
mgmt_event(MGMT_EV_ADVERTISING_REMOVED, hdev, &ev, sizeof(ev), sk);
}

+void mgmt_adv_tx_power_selected(struct hci_dev *hdev, u8 instance, s8 tx_power)
+{
+ struct mgmt_ev_adv_tx_power_selected ev;
+
+ ev.instance = instance;
+ ev.tx_power = tx_power;
+
+ mgmt_event(MGMT_EV_ADV_TX_POWER_SELECTED, hdev, &ev, sizeof(ev), NULL);
+}
+
static void cancel_adv_timeout(struct hci_dev *hdev)
{
if (hdev->adv_instance_timeout) {
--
2.28.0.618.gf4bc123cb7-goog