diff mbox series

[Bluez,01/10] advertising: Detect if extended advertising mgmt commands are supported

Message ID 20200916162155.Bluez.1.I50d9faa25e9da6e71d77c83c7d47a5b135e88799@changeid
State New
Headers show
Series [Bluez,01/10] advertising: Detect if extended advertising mgmt commands are supported | expand

Commit Message

Daniel Winkler Sept. 16, 2020, 11:25 p.m. UTC
We need to know if kernel supports the new MGMT interface. To do so, we
call MGMT_OP_READ_COMMANDS when our manager is created and check if the
new commands are available. This will then be used to route our requests
for new advertisements.

The change is tested by manually verifying that the correct MGMT
commands are used when the feature is and is not available in kernel.

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

 src/advertising.c | 54 +++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 54 insertions(+)

Comments

Luiz Augusto von Dentz Sept. 16, 2020, 11:44 p.m. UTC | #1
Hi Daniel,

On Wed, Sep 16, 2020 at 4:25 PM Daniel Winkler <danielwinkler@google.com> wrote:
>

> We need to know if kernel supports the new MGMT interface. To do so, we

> call MGMT_OP_READ_COMMANDS when our manager is created and check if the

> new commands are available. This will then be used to route our requests

> for new advertisements.

>

> The change is tested by manually verifying that the correct MGMT

> commands are used when the feature is and is not available in kernel.

>

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

> ---

>

>  src/advertising.c | 54 +++++++++++++++++++++++++++++++++++++++++++++++

>  1 file changed, 54 insertions(+)

>

> diff --git a/src/advertising.c b/src/advertising.c

> index e5f25948d..172a83907 100644

> --- a/src/advertising.c

> +++ b/src/advertising.c

> @@ -57,6 +57,7 @@ struct btd_adv_manager {

>         uint8_t max_ads;

>         uint32_t supported_flags;

>         unsigned int instance_bitmap;

> +       bool extended_add_cmds;

>  };

>

>  #define AD_TYPE_BROADCAST 0

> @@ -1407,6 +1408,51 @@ static void read_adv_features_callback(uint8_t status, uint16_t length,

>                 remove_advertising(manager, 0);

>  }

>

> +static void read_commands_complete(uint8_t status, uint16_t length,

> +                                  const void *param, void *user_data)

> +{

> +       struct btd_adv_manager *manager = user_data;

> +       const struct mgmt_rp_read_commands *rp = param;

> +       uint16_t num_commands, num_events;

> +       size_t expected_len;

> +       int i;

> +

> +       if (status != MGMT_STATUS_SUCCESS) {

> +               error("Failed to read supported commands: %s (0x%02x)",

> +                                               mgmt_errstr(status), status);

> +               return;

> +       }

> +

> +       if (length < sizeof(*rp)) {

> +               error("Wrong size of read commands response");

> +               return;

> +       }

> +

> +       num_commands = btohs(rp->num_commands);

> +       num_events = btohs(rp->num_events);

> +

> +       expected_len = sizeof(*rp) + num_commands * sizeof(uint16_t) +

> +                                               num_events * sizeof(uint16_t);

> +

> +       if (length < expected_len) {

> +               error("Too small reply for supported commands: (%u != %zu)",

> +                                                       length, expected_len);

> +               return;

> +       }

> +

> +       for (i = 0; i < num_commands; i++) {

> +               uint16_t op = get_le16(rp->opcodes + i);

> +

> +               switch (op) {

> +               case MGMT_OP_ADD_EXT_ADV_PARAMS:

> +                       manager->extended_add_cmds = true;

> +                       break;

> +               default:

> +                       break;

> +               }

> +       }

> +}


I wouldn't duplicate the handling of MGMT_OP_READ_COMMANDS, so I would
move this to adapter.c and instead use btd_has_kernel_features in
advertising.c

>  static struct btd_adv_manager *manager_create(struct btd_adapter *adapter,

>                                                 struct mgmt *mgmt)

>  {

> @@ -1426,6 +1472,7 @@ static struct btd_adv_manager *manager_create(struct btd_adapter *adapter,

>         manager->mgmt_index = btd_adapter_get_index(adapter);

>         manager->clients = queue_new();

>         manager->supported_flags = MGMT_ADV_FLAG_LOCAL_NAME;

> +       manager->extended_add_cmds = false;

>

>         if (!g_dbus_register_interface(btd_get_dbus_connection(),

>                                         adapter_get_path(manager->adapter),

> @@ -1442,6 +1489,13 @@ static struct btd_adv_manager *manager_create(struct btd_adapter *adapter,

>                 goto fail;

>         }

>

> +       /* Determine if kernel supports extended advertising add command. We

> +        * don't care if this request fails, as we will fall back to legacy

> +        * add_advertising by default

> +        */

> +       mgmt_send(manager->mgmt, MGMT_OP_READ_COMMANDS, MGMT_INDEX_NONE, 0,

> +                 NULL, read_commands_complete, manager, NULL);

> +

>         return manager;

>

>  fail:

> --

> 2.28.0.618.gf4bc123cb7-goog

>



-- 
Luiz Augusto von Dentz
diff mbox series

Patch

diff --git a/src/advertising.c b/src/advertising.c
index e5f25948d..172a83907 100644
--- a/src/advertising.c
+++ b/src/advertising.c
@@ -57,6 +57,7 @@  struct btd_adv_manager {
 	uint8_t max_ads;
 	uint32_t supported_flags;
 	unsigned int instance_bitmap;
+	bool extended_add_cmds;
 };
 
 #define AD_TYPE_BROADCAST 0
@@ -1407,6 +1408,51 @@  static void read_adv_features_callback(uint8_t status, uint16_t length,
 		remove_advertising(manager, 0);
 }
 
+static void read_commands_complete(uint8_t status, uint16_t length,
+				   const void *param, void *user_data)
+{
+	struct btd_adv_manager *manager = user_data;
+	const struct mgmt_rp_read_commands *rp = param;
+	uint16_t num_commands, num_events;
+	size_t expected_len;
+	int i;
+
+	if (status != MGMT_STATUS_SUCCESS) {
+		error("Failed to read supported commands: %s (0x%02x)",
+						mgmt_errstr(status), status);
+		return;
+	}
+
+	if (length < sizeof(*rp)) {
+		error("Wrong size of read commands response");
+		return;
+	}
+
+	num_commands = btohs(rp->num_commands);
+	num_events = btohs(rp->num_events);
+
+	expected_len = sizeof(*rp) + num_commands * sizeof(uint16_t) +
+						num_events * sizeof(uint16_t);
+
+	if (length < expected_len) {
+		error("Too small reply for supported commands: (%u != %zu)",
+							length, expected_len);
+		return;
+	}
+
+	for (i = 0; i < num_commands; i++) {
+		uint16_t op = get_le16(rp->opcodes + i);
+
+		switch (op) {
+		case MGMT_OP_ADD_EXT_ADV_PARAMS:
+			manager->extended_add_cmds = true;
+			break;
+		default:
+			break;
+		}
+	}
+}
+
 static struct btd_adv_manager *manager_create(struct btd_adapter *adapter,
 						struct mgmt *mgmt)
 {
@@ -1426,6 +1472,7 @@  static struct btd_adv_manager *manager_create(struct btd_adapter *adapter,
 	manager->mgmt_index = btd_adapter_get_index(adapter);
 	manager->clients = queue_new();
 	manager->supported_flags = MGMT_ADV_FLAG_LOCAL_NAME;
+	manager->extended_add_cmds = false;
 
 	if (!g_dbus_register_interface(btd_get_dbus_connection(),
 					adapter_get_path(manager->adapter),
@@ -1442,6 +1489,13 @@  static struct btd_adv_manager *manager_create(struct btd_adapter *adapter,
 		goto fail;
 	}
 
+	/* Determine if kernel supports extended advertising add command. We
+	 * don't care if this request fails, as we will fall back to legacy
+	 * add_advertising by default
+	 */
+	mgmt_send(manager->mgmt, MGMT_OP_READ_COMMANDS, MGMT_INDEX_NONE, 0,
+		  NULL, read_commands_complete, manager, NULL);
+
 	return manager;
 
 fail: