This patch delivers DeviceFound/DeviceLost events to apps over D-Bus whenever controller starts/stops tracking a device. Tests performed: - Add a monitor and verify that DeviceFound/DeviceLost events are received whenever controller starts/stops monitoring. - Verify from logs that only one Adv Report is received from the controller when Sampling_Period is set to 0xFF and the DeviceFound/DeviceLost functionality still works as intended. - Verify that DeviceFound/DeviceLost is reported appropriately even when the Active Scanning is in progress. - Verify that the reconnection also works properly with and without any active Advertisement Monitor. Reviewed-by: Miao-chen Chou <mcchou@xxxxxxxxxx> --- Changes in v5: - Add this new patch in series to deliver DeviceFound/Lost to apps src/adv_monitor.c | 103 ++++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 95 insertions(+), 8 deletions(-) diff --git a/src/adv_monitor.c b/src/adv_monitor.c index e5bdfb6ef..1a8397259 100644 --- a/src/adv_monitor.c +++ b/src/adv_monitor.c @@ -174,6 +174,11 @@ struct adv_rssi_filter_info { int8_t rssi; }; +struct monitored_device_info { + uint16_t monitor_handle; /* Kernel Monitor Handle */ + struct btd_device *device; +}; + static void monitor_device_free(void *data); static void adv_monitor_filter_rssi(struct adv_monitor *monitor, struct btd_device *device, int8_t rssi); @@ -1531,6 +1536,39 @@ static void adv_monitor_removed_callback(uint16_t index, uint16_t length, ev->monitor_handle); } +/* Includes found/lost device's object path into the dbus message */ +static void report_device_state_setup(DBusMessageIter *iter, void *user_data) +{ + const char *path = device_get_path(user_data); + + dbus_message_iter_append_basic(iter, DBUS_TYPE_OBJECT_PATH, &path); +} + +/* Invokes DeviceFound on the matched monitor */ +static void notify_device_found_per_monitor(void *data, void *user_data) +{ + struct adv_monitor *monitor = data; + struct monitored_device_info *info = user_data; + + if (monitor->merged_pattern->monitor_handle == info->monitor_handle) { + DBG("Calling DeviceFound() on Adv Monitor of owner %s " + "at path %s", monitor->app->owner, monitor->path); + + g_dbus_proxy_method_call(monitor->proxy, "DeviceFound", + report_device_state_setup, NULL, + info->device, NULL); + } +} + +/* Checks all monitors for match in the app to invoke DeviceFound */ +static void notify_device_found_per_app(void *data, void *user_data) +{ + struct adv_monitor_app *app = data; + + queue_foreach(app->monitors, notify_device_found_per_monitor, + user_data); +} + /* Processes Adv Monitor Device Found event from kernel */ static void adv_monitor_device_found_callback(uint16_t index, uint16_t length, const void *param, @@ -1548,6 +1586,7 @@ static void adv_monitor_device_found_callback(uint16_t index, uint16_t length, bool legacy; char addr[18]; bool not_connectable; + struct monitored_device_info info; if (length < sizeof(*ev)) { btd_error(adapter_id, @@ -1579,6 +1618,49 @@ static void adv_monitor_device_found_callback(uint16_t index, uint16_t length, ev->addr.type, ev->rssi, confirm_name, legacy, not_connectable, ad_data, ad_data_len, true); + + if (handle) { + DBG("Adv Monitor with handle 0x%04x started tracking " + "the device %s", handle, addr); + + info.device = btd_adapter_find_device(adapter, &ev->addr.bdaddr, + ev->addr.type); + if (!info.device) { + btd_error(adapter_id, "Device object not found for %s", + addr); + return; + } + + /* Check for matched monitor in all apps */ + info.monitor_handle = handle; + queue_foreach(manager->apps, notify_device_found_per_app, + &info); + } +} + +/* Invokes DeviceLost on the matched monitor */ +static void notify_device_lost_per_monitor(void *data, void *user_data) +{ + struct adv_monitor *monitor = data; + struct monitored_device_info *info = user_data; + + if (monitor->merged_pattern->monitor_handle == info->monitor_handle) { + DBG("Calling DeviceLost() on Adv Monitor of owner %s " + "at path %s", monitor->app->owner, monitor->path); + + g_dbus_proxy_method_call(monitor->proxy, "DeviceLost", + report_device_state_setup, NULL, + info->device, NULL); + } +} + +/* Checks all monitors for match in the app to invoke DeviceLost */ +static void notify_device_lost_per_app(void *data, void *user_data) +{ + struct adv_monitor_app *app = data; + + queue_foreach(app->monitors, notify_device_lost_per_monitor, + user_data); } /* Processes Adv Monitor Device Lost event from kernel */ @@ -1590,7 +1672,9 @@ static void adv_monitor_device_lost_callback(uint16_t index, uint16_t length, 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; + struct btd_adapter *adapter = manager->adapter; char addr[18]; + struct monitored_device_info info; if (length < sizeof(*ev)) { btd_error(adapter_id, @@ -1601,6 +1685,17 @@ static void adv_monitor_device_lost_callback(uint16_t index, uint16_t length, ba2str(&ev->addr.bdaddr, addr); DBG("Adv Monitor with handle 0x%04x stopped tracking the device %s", handle, addr); + + info.device = btd_adapter_find_device(adapter, &ev->addr.bdaddr, + ev->addr.type); + if (!info.device) { + btd_error(adapter_id, "Device object not found for %s", addr); + return; + } + + /* Check for matched monitor in all apps */ + info.monitor_handle = handle; + queue_foreach(manager->apps, notify_device_lost_per_app, &info); } /* Allocates a manager object */ @@ -1962,14 +2057,6 @@ static struct adv_monitor_device *monitor_device_create( return dev; } -/* Includes found/lost device's object path into the dbus message */ -static void report_device_state_setup(DBusMessageIter *iter, void *user_data) -{ - const char *path = device_get_path(user_data); - - dbus_message_iter_append_basic(iter, DBUS_TYPE_OBJECT_PATH, &path); -} - /* Handles a situation where the device goes offline/out-of-range */ static bool handle_device_lost_timeout(gpointer user_data) { -- 2.34.0.rc1.387.gb447b232ab-goog