diff mbox series

[BlueZ,v6,3/6] adv_monitor: Receive the Device Found/Lost events

Message ID 20211120072449.BlueZ.v6.3.I68039747acc3c63f758278452889d6ed2bfff065@changeid
State Superseded
Headers show
Series [BlueZ,v6,1/6] doc: Introduce the Adv Monitor Device Found/Lost events | expand

Commit Message

Manish Mandlik Nov. 20, 2021, 3:29 p.m. UTC
This patch registers callback functions to receive the Advertisement
Monitor Device Found and Device Lost events. It also disables software
based filtering whenever controller offloading support is available.

Test performed:
- Verified by logs that the MSFT Monitor Device is received from the
  controller and the bluetoothd is notified whenever the controller
  starts/stops monitoring a device.

Reviewed-by: Miao-chen Chou <mcchou@google.com>
---

Changes in v6:
- Removed unused variable 'handle'.

Changes in v5:
- Update the Adv Monitor Device Found event to include fields from the
  existing Device Found event and update the device object.
- Disable the software based filtering whenever controller offloading is
  available.

Changes in v4:
- Add Advertisement Monitor Device Found event.

Changes in v3:
- Fix indentation of the adv_monitor_device_lost_callback() name and
  it's arguments.

Changes in v2:
- Update function name adv_monitor_tracking_callback() to
  adv_monitor_device_lost_callback() as it will receive only Device Lost
  event.

 src/adapter.c     | 47 ++++++++++++++-----------
 src/adapter.h     |  8 +++++
 src/adv_monitor.c | 90 +++++++++++++++++++++++++++++++++++++++++++++++
 src/adv_monitor.h |  2 ++
 4 files changed, 127 insertions(+), 20 deletions(-)
diff mbox series

Patch

diff --git a/src/adapter.c b/src/adapter.c
index d0d38621b..42463a3c1 100644
--- a/src/adapter.c
+++ b/src/adapter.c
@@ -6984,12 +6984,13 @@  static bool device_is_discoverable(struct btd_adapter *adapter,
 	return discoverable;
 }
 
-static void update_found_devices(struct btd_adapter *adapter,
+void btd_adapter_update_found_device(struct btd_adapter *adapter,
 					const bdaddr_t *bdaddr,
 					uint8_t bdaddr_type, int8_t rssi,
 					bool confirm, bool legacy,
 					bool not_connectable,
-					const uint8_t *data, uint8_t data_len)
+					const uint8_t *data, uint8_t data_len,
+					bool monitoring)
 {
 	struct btd_device *dev;
 	struct bt_ad *ad = NULL;
@@ -6999,20 +7000,24 @@  static void update_found_devices(struct btd_adapter *adapter,
 	bool duplicate = false;
 	struct queue *matched_monitors = NULL;
 
-	if (bdaddr_type != BDADDR_BREDR)
-		ad = bt_ad_new_with_data(data_len, data);
+	if (!btd_adv_monitor_offload_supported(adapter->adv_monitor_manager)) {
+		if (bdaddr_type != BDADDR_BREDR)
+			ad = bt_ad_new_with_data(data_len, data);
 
-	/* During the background scanning, update the device only when the data
-	 * match at least one Adv monitor
-	 */
-	if (ad) {
-		matched_monitors = btd_adv_monitor_content_filter(
-					adapter->adv_monitor_manager, ad);
-		bt_ad_unref(ad);
-		ad = NULL;
+		/* During the background scanning, update the device only when
+		 * the data match at least one Adv monitor
+		 */
+		if (ad) {
+			matched_monitors = btd_adv_monitor_content_filter(
+						adapter->adv_monitor_manager,
+						ad);
+			bt_ad_unref(ad);
+			ad = NULL;
+			monitoring = matched_monitors ? true : false;
+		}
 	}
 
-	if (!adapter->discovering && !matched_monitors)
+	if (!adapter->discovering && !monitoring)
 		return;
 
 	memset(&eir_data, 0, sizeof(eir_data));
@@ -7025,7 +7030,7 @@  static void update_found_devices(struct btd_adapter *adapter,
 
 	dev = btd_adapter_find_device(adapter, bdaddr, bdaddr_type);
 	if (!dev) {
-		if (!discoverable && !matched_monitors) {
+		if (!discoverable && !monitoring) {
 			eir_data_free(&eir_data);
 			return;
 		}
@@ -7064,7 +7069,7 @@  static void update_found_devices(struct btd_adapter *adapter,
 	 */
 	if (!btd_device_is_connected(dev) &&
 		(device_is_temporary(dev) && !adapter->discovery_list) &&
-		!matched_monitors) {
+		!monitoring) {
 		eir_data_free(&eir_data);
 		return;
 	}
@@ -7072,7 +7077,7 @@  static void update_found_devices(struct btd_adapter *adapter,
 	/* If there is no matched Adv monitors, don't continue if not
 	 * discoverable or if active discovery filter don't match.
 	 */
-	if (!matched_monitors && (!discoverable ||
+	if (!monitoring && (!discoverable ||
 		(adapter->filtered_discovery && !is_filter_match(
 				adapter->discovery_list, &eir_data, rssi)))) {
 		eir_data_free(&eir_data);
@@ -7202,6 +7207,7 @@  static void device_found_callback(uint16_t index, uint16_t length,
 	bool confirm_name;
 	bool legacy;
 	char addr[18];
+	bool not_connectable;
 
 	if (length < sizeof(*ev)) {
 		btd_error(adapter->dev_id,
@@ -7230,11 +7236,12 @@  static void device_found_callback(uint16_t index, uint16_t length,
 
 	confirm_name = (flags & MGMT_DEV_FOUND_CONFIRM_NAME);
 	legacy = (flags & MGMT_DEV_FOUND_LEGACY_PAIRING);
+	not_connectable = (flags & MGMT_DEV_FOUND_NOT_CONNECTABLE);
 
-	update_found_devices(adapter, &ev->addr.bdaddr, ev->addr.type,
-					ev->rssi, confirm_name, legacy,
-					flags & MGMT_DEV_FOUND_NOT_CONNECTABLE,
-					eir, eir_len);
+	btd_adapter_update_found_device(adapter, &ev->addr.bdaddr,
+					ev->addr.type, ev->rssi, confirm_name,
+					legacy, not_connectable, eir, eir_len,
+					false);
 }
 
 struct agent *adapter_get_agent(struct btd_adapter *adapter)
diff --git a/src/adapter.h b/src/adapter.h
index db3c17f23..cd0d037af 100644
--- a/src/adapter.h
+++ b/src/adapter.h
@@ -87,6 +87,14 @@  struct btd_device *btd_adapter_find_device(struct btd_adapter *adapter,
 struct btd_device *btd_adapter_find_device_by_path(struct btd_adapter *adapter,
 						   const char *path);
 
+void btd_adapter_update_found_device(struct btd_adapter *adapter,
+					const bdaddr_t *bdaddr,
+					uint8_t bdaddr_type, int8_t rssi,
+					bool confirm, bool legacy,
+					bool not_connectable,
+					const uint8_t *data, uint8_t data_len,
+					bool monitored);
+
 const char *adapter_get_path(struct btd_adapter *adapter);
 const bdaddr_t *btd_adapter_get_address(struct btd_adapter *adapter);
 uint8_t btd_adapter_get_address_type(struct btd_adapter *adapter);
diff --git a/src/adv_monitor.c b/src/adv_monitor.c
index a3b33188b..ca8aa976c 100644
--- a/src/adv_monitor.c
+++ b/src/adv_monitor.c
@@ -1531,6 +1531,77 @@  static void adv_monitor_removed_callback(uint16_t index, uint16_t length,
 		ev->monitor_handle);
 }
 
+/* Processes Adv Monitor Device Found event from kernel */
+static void adv_monitor_device_found_callback(uint16_t index, uint16_t length,
+						const void *param,
+						void *user_data)
+{
+	const struct mgmt_ev_adv_monitor_device_found *ev = param;
+	struct btd_adv_monitor_manager *manager = user_data;
+	const uint16_t adapter_id = manager->adapter_id;
+	struct btd_adapter *adapter = manager->adapter;
+	const uint8_t *ad_data = NULL;
+	uint16_t ad_data_len;
+	uint32_t flags;
+	bool confirm_name;
+	bool legacy;
+	char addr[18];
+	bool not_connectable;
+
+	if (length < sizeof(*ev)) {
+		btd_error(adapter_id,
+				"Too short Adv Monitor Device Found event");
+		return;
+	}
+
+	ad_data_len = btohs(ev->ad_data_len);
+	if (length != sizeof(*ev) + ad_data_len) {
+		btd_error(adapter_id,
+				"Wrong size of Adv Monitor Device Found event");
+		return;
+	}
+
+	if (ad_data_len > 0)
+		ad_data = ev->ad_data;
+
+	flags = btohl(ev->flags);
+
+	ba2str(&ev->addr.bdaddr, addr);
+	DBG("hci%u addr %s, rssi %d flags 0x%04x ad_data_len %u",
+			index, addr, ev->rssi, flags, ad_data_len);
+
+	confirm_name = (flags & MGMT_DEV_FOUND_CONFIRM_NAME);
+	legacy = (flags & MGMT_DEV_FOUND_LEGACY_PAIRING);
+	not_connectable = (flags & MGMT_DEV_FOUND_NOT_CONNECTABLE);
+
+	btd_adapter_update_found_device(adapter, &ev->addr.bdaddr,
+					ev->addr.type, ev->rssi, confirm_name,
+					legacy, not_connectable, ad_data,
+					ad_data_len, true);
+}
+
+/* Processes Adv Monitor Device Lost event from kernel */
+static void adv_monitor_device_lost_callback(uint16_t index, uint16_t length,
+						const void *param,
+						void *user_data)
+{
+	struct btd_adv_monitor_manager *manager = user_data;
+	const struct mgmt_ev_adv_monitor_device_lost *ev = param;
+	uint16_t handle = le16_to_cpu(ev->monitor_handle);
+	const uint16_t adapter_id = manager->adapter_id;
+	char addr[18];
+
+	if (length < sizeof(*ev)) {
+		btd_error(adapter_id,
+				"Wrong size of Adv Monitor Device Lost event");
+		return;
+	}
+
+	ba2str(&ev->addr.bdaddr, addr);
+	DBG("Adv Monitor with handle 0x%04x stopped tracking the device %s",
+		handle, addr);
+}
+
 /* Allocates a manager object */
 static struct btd_adv_monitor_manager *manager_new(
 						struct btd_adapter *adapter,
@@ -1555,6 +1626,14 @@  static struct btd_adv_monitor_manager *manager_new(
 			manager->adapter_id, adv_monitor_removed_callback,
 			manager, NULL);
 
+	mgmt_register(manager->mgmt, MGMT_EV_ADV_MONITOR_DEVICE_FOUND,
+			manager->adapter_id, adv_monitor_device_found_callback,
+			manager, NULL);
+
+	mgmt_register(manager->mgmt, MGMT_EV_ADV_MONITOR_DEVICE_LOST,
+			manager->adapter_id, adv_monitor_device_lost_callback,
+			manager, NULL);
+
 	return manager;
 }
 
@@ -1666,6 +1745,17 @@  void btd_adv_monitor_manager_destroy(struct btd_adv_monitor_manager *manager)
 	manager_destroy(manager);
 }
 
+bool btd_adv_monitor_offload_supported(struct btd_adv_monitor_manager *manager)
+{
+	if (!manager) {
+		error("Manager is NULL, get offload support failed");
+		return false;
+	}
+
+	return !!(manager->enabled_features &
+				MGMT_ADV_MONITOR_FEATURE_MASK_OR_PATTERNS);
+}
+
 /* Processes the content matching based pattern(s) of a monitor */
 static void adv_match_per_monitor(void *data, void *user_data)
 {
diff --git a/src/adv_monitor.h b/src/adv_monitor.h
index d9cb9ccbb..bed6572d0 100644
--- a/src/adv_monitor.h
+++ b/src/adv_monitor.h
@@ -27,6 +27,8 @@  struct btd_adv_monitor_manager *btd_adv_monitor_manager_create(
 						struct mgmt *mgmt);
 void btd_adv_monitor_manager_destroy(struct btd_adv_monitor_manager *manager);
 
+bool btd_adv_monitor_offload_supported(struct btd_adv_monitor_manager *manager);
+
 struct queue *btd_adv_monitor_content_filter(
 				struct btd_adv_monitor_manager *manager,
 				struct bt_ad *ad);