diff mbox series

[Bluez,v2,06/10] advertising: Catch tx power selected event and handle it

Message ID 20200918151041.Bluez.v2.6.Ia7689bc6f45cf6b8e13a95cd1da4f96fbfc3ac14@changeid (mailing list archive)
State New, archived
Headers show
Series Bluetooth: Add new MGMT interface for advertising add | expand

Commit Message

Daniel Winkler Sept. 18, 2020, 10:13 p.m. UTC
The new Tx Power Selected MGMT event will alert bluetoothd that an
advertising instance has been assigned a tx power. This is intended to
be used to then update the client of their instance's tx power.

Towards this goal, this patch does the following:
- When adv manager is created, register a handler for tx selected event
- On callback, identify the relevant advertising instance, and call for
  a property set with the new value. If the client exposes this method,
  it will be called with the new value selected by the controller.

To test, I modified the example-advertisement python script to implement
the Set dbus method, and verified that it is called after advertisement
registration on a device with extended advertising.

Reviewed-by: Sonny Sasaka <sonnysasaka@chromium.org>
Reviewed-by: Alain Michaud <alainm@chromium.org>
---

Changes in v2: None

 lib/mgmt.h        |  6 ++++++
 src/advertising.c | 32 ++++++++++++++++++++++++++++++++
 2 files changed, 38 insertions(+)
diff mbox series

Patch

diff --git a/lib/mgmt.h b/lib/mgmt.h
index 9874be004..56f46ce93 100644
--- a/lib/mgmt.h
+++ b/lib/mgmt.h
@@ -1002,6 +1002,12 @@  struct mgmt_ev_controller_resume {
 	uint8_t wake_reason;
 } __packed;
 
+#define MGMT_EV_ADV_TX_POWER_SELECTED	0x002f
+struct mgmt_ev_adv_tx_power_selected {
+	uint8_t	instance;
+	int8_t	tx_power;
+} __packed;
+
 static const char *mgmt_op[] = {
 	"<0x0000>",
 	"Read Version",
diff --git a/src/advertising.c b/src/advertising.c
index cab0b79de..c7deda1ad 100644
--- a/src/advertising.c
+++ b/src/advertising.c
@@ -113,6 +113,17 @@  static bool match_client(const void *a, const void *b)
 	return true;
 }
 
+static bool match_client_by_instance(const void *a, const void *b)
+{
+	const struct btd_adv_client *client = a;
+	const uint8_t *instance = b;
+
+	if (client && client->instance == *instance)
+		return true;
+
+	return false;
+}
+
 static void client_free(void *data)
 {
 	struct btd_adv_client *client = data;
@@ -1681,6 +1692,22 @@  static void read_adv_features_callback(uint8_t status, uint16_t length,
 		remove_advertising(manager, 0);
 }
 
+static void tx_power_selected(uint16_t index, uint16_t length,
+					const void *param, void *user_data)
+{
+	const struct mgmt_ev_adv_tx_power_selected *ev = param;
+	struct btd_adv_client *client;
+	struct btd_adv_manager *manager = user_data;
+	dbus_int16_t tx_power = ev->tx_power;
+
+	client = queue_find(manager->clients, match_client_by_instance,
+			&ev->instance);
+
+	if (client)
+		g_dbus_proxy_set_property_basic(client->proxy, "TxPower",
+				DBUS_TYPE_INT16, &tx_power, NULL, NULL, NULL);
+}
+
 static struct btd_adv_manager *manager_create(struct btd_adapter *adapter,
 						struct mgmt *mgmt)
 {
@@ -1718,6 +1745,11 @@  static struct btd_adv_manager *manager_create(struct btd_adapter *adapter,
 		goto fail;
 	}
 
+	if (manager->extended_add_cmds)
+		mgmt_register(manager->mgmt, MGMT_EV_ADV_TX_POWER_SELECTED,
+			      manager->mgmt_index, tx_power_selected,
+			      manager, NULL);
+
 	return manager;
 
 fail: