@@ -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)
@@ -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);
@@ -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)
{
@@ -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);
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(-)