From patchwork Thu Sep 17 07:04:53 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Miao-chen Chou X-Patchwork-Id: 252703 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-12.8 required=3.0 tests=BAYES_00,DKIMWL_WL_HIGH, DKIM_SIGNED,DKIM_VALID,DKIM_VALID_AU,HEADER_FROM_DIFFERENT_DOMAINS, INCLUDES_PATCH, MAILING_LIST_MULTI, SPF_HELO_NONE, SPF_PASS, URIBL_BLOCKED, USER_AGENT_GIT autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 7F8D4C433E2 for ; Thu, 17 Sep 2020 07:07:40 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 381A121D24 for ; Thu, 17 Sep 2020 07:07:40 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=pass (1024-bit key) header.d=chromium.org header.i=@chromium.org header.b="GDdTL9uE" Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1726196AbgIQHH1 (ORCPT ); Thu, 17 Sep 2020 03:07:27 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:46226 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1726218AbgIQHFF (ORCPT ); Thu, 17 Sep 2020 03:05:05 -0400 Received: from mail-pl1-x641.google.com (mail-pl1-x641.google.com [IPv6:2607:f8b0:4864:20::641]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 4FF6AC06174A for ; Thu, 17 Sep 2020 00:05:05 -0700 (PDT) Received: by mail-pl1-x641.google.com with SMTP id y6so623557plt.9 for ; Thu, 17 Sep 2020 00:05:05 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=chromium.org; s=google; h=from:to:cc:subject:date:message-id:mime-version :content-transfer-encoding; bh=sDqXCkXQZ7goM0PwAfEYoxwVPgx97yi616G18CFZ3Sk=; b=GDdTL9uEj3UCNT72uLZaYOKc1PuHKWWfKJuaJnljsb6EE7HvyNfLPe39xIYc/oPXI/ tiY18wyNGhQLmYLCMc2zmZ4KKdBY7A0mVnKejniU2aUZquWH09VwAc2qPmeGV12Q6JkE vWTdcrCZi9sHJSe/T57iCFI9rRBgvCTI2mqpA= X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:mime-version :content-transfer-encoding; bh=sDqXCkXQZ7goM0PwAfEYoxwVPgx97yi616G18CFZ3Sk=; b=qJJ18YpavXGd0LULCm3L8qCMY7QnRR149J7YQ3D15zSKbJaUJK3I9KpH2In/a0qMpz DtHpcg7aMjEBwe3+JStebw2bFVIM/+aGkTKqQaZKFm58xAABqy1ZTCY/pAg/+OmYWUg5 JtVUY9SPAU0s7wdHoHepCTLxBQ6xCDvLYNNqDJqCofKWeYYboek0OM9y8ZwkMv9iRqKd jiAStZOud9xiVTFqE8LFyELZ/x3bjmo4ZTZ9Poxv+14MNSXChZauDSgzzc7FSCKFq7Qv 8ig+sWqu/WgztOe4a2KxEcR93fF8u/RKlAs1qhsOK2APrqs5xWI+2+ipXf9Dr2EXqvaS qikg== X-Gm-Message-State: AOAM530giQtO5NvLRJPeUMbfVzqlEx+JtnptPyXgECStQZLYGXLb+8eC 5v08xjHVey+LL9yYAY3e1dlS8zvBN+B9yA== X-Google-Smtp-Source: ABdhPJwbPMfTJh4txTCdjsrEdkLYb5/0QUliYmgwfoYRCYOq5RA1ZSaJ0rZSkOyhaq4OfNm1RugkgQ== X-Received: by 2002:a17:902:161:b029:d1:9bc8:15f1 with SMTP id 88-20020a1709020161b02900d19bc815f1mr27324878plb.39.1600326304290; Thu, 17 Sep 2020 00:05:04 -0700 (PDT) Received: from mcchou0.mtv.corp.google.com ([2620:15c:202:201:de4a:3eff:fe75:1314]) by smtp.gmail.com with ESMTPSA id y197sm5407372pfc.220.2020.09.17.00.05.03 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Thu, 17 Sep 2020 00:05:03 -0700 (PDT) From: Miao-chen Chou To: Bluetooth Kernel Mailing List Cc: Howard Chung , Alain Michaud , chromeos-bluetooth-upstreaming@chromium.org, Marcel Holtmann , Manish Mandlik , Luiz Augusto von Dentz , Manish Mandlik , Abhishek Pandit-Subedi , Miao-chen Chou Subject: [BlueZ PATCH v3 1/8] adv_monitor: Implement RSSI Filter logic for background scanning Date: Thu, 17 Sep 2020 00:04:53 -0700 Message-Id: <20200917000448.BlueZ.v3.1.I2830b9c1212a64b062201ed9f2b71294f50ad22d@changeid> X-Mailer: git-send-email 2.26.2 MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-bluetooth@vger.kernel.org From: Manish Mandlik This patch implements the RSSI Filter logic for background scanning. This was unit-tested by running tests in unit/test-adv-monitor.c unit/test-adv-monitor.c file. Verified all tests PASS by running: USE="-bluez-next bluez-upstream" FEATURES=test emerge-hatch bluez Reviewed-by: Abhishek Pandit-Subedi Reviewed-by: Alain Michaud Reviewed-by: Miao-chen Chou Reviewed-by: Howard Chung --- Changes in v3: - Fix commit message doc/advertisement-monitor-api.txt | 5 + src/adapter.c | 1 + src/adv_monitor.c | 286 +++++++++++++++++++++++++++++- src/adv_monitor.h | 4 + 4 files changed, 292 insertions(+), 4 deletions(-) diff --git a/doc/advertisement-monitor-api.txt b/doc/advertisement-monitor-api.txt index e09b6fd25..92c8ffc38 100644 --- a/doc/advertisement-monitor-api.txt +++ b/doc/advertisement-monitor-api.txt @@ -70,6 +70,11 @@ Properties string Type [read-only] dBm indicates unset. The valid range of a timer is 1 to 300 seconds while 0 indicates unset. + If the peer device advertising interval is greater than the + HighRSSIThresholdTimer, the device will never be found. Similarly, + if it is greater than LowRSSIThresholdTimer, the device will be + considered as lost. Consider configuring these values accordingly. + array{(uint8, uint8, array{byte})} Patterns [read-only, optional] If Type is set to 0x01, this must exist and has at least diff --git a/src/adapter.c b/src/adapter.c index b2bd8b3f1..415d6e06b 100644 --- a/src/adapter.c +++ b/src/adapter.c @@ -1227,6 +1227,7 @@ void btd_adapter_remove_device(struct btd_adapter *adapter, adapter->connect_list = g_slist_remove(adapter->connect_list, dev); adapter->devices = g_slist_remove(adapter->devices, dev); + btd_adv_monitor_device_remove(adapter->adv_monitor_manager, dev); adapter->discovery_found = g_slist_remove(adapter->discovery_found, dev); diff --git a/src/adv_monitor.c b/src/adv_monitor.c index 737da1c90..7baa5317f 100644 --- a/src/adv_monitor.c +++ b/src/adv_monitor.c @@ -35,6 +35,7 @@ #include "adapter.h" #include "dbus-common.h" +#include "device.h" #include "log.h" #include "src/error.h" #include "src/shared/ad.h" @@ -44,6 +45,8 @@ #include "adv_monitor.h" +static void monitor_device_free(void *data); + #define ADV_MONITOR_INTERFACE "org.bluez.AdvertisementMonitor1" #define ADV_MONITOR_MGR_INTERFACE "org.bluez.AdvertisementMonitorManager1" @@ -104,15 +107,36 @@ struct adv_monitor { enum monitor_state state; /* MONITOR_STATE_* */ - int8_t high_rssi; /* high RSSI threshold */ - uint16_t high_rssi_timeout; /* high RSSI threshold timeout */ - int8_t low_rssi; /* low RSSI threshold */ - uint16_t low_rssi_timeout; /* low RSSI threshold timeout */ + int8_t high_rssi; /* High RSSI threshold */ + uint16_t high_rssi_timeout; /* High RSSI threshold timeout */ + int8_t low_rssi; /* Low RSSI threshold */ + uint16_t low_rssi_timeout; /* Low RSSI threshold timeout */ + struct queue *devices; /* List of adv_monitor_device objects */ enum monitor_type type; /* MONITOR_TYPE_* */ struct queue *patterns; }; +/* Some data like last_seen, timer/timeout values need to be maintained + * per device. struct adv_monitor_device maintains such data. + */ +struct adv_monitor_device { + struct adv_monitor *monitor; + struct btd_device *device; + + time_t high_rssi_first_seen; /* Start time when RSSI climbs above + * the high RSSI threshold + */ + time_t low_rssi_first_seen; /* Start time when RSSI drops below + * the low RSSI threshold + */ + time_t last_seen; /* Time when last Adv was received */ + bool device_found; /* State of the device - lost/found */ + guint device_lost_timer; /* Timer to track if the device goes + * offline/out-of-range + */ +}; + struct app_match_data { const char *owner; const char *path; @@ -159,6 +183,9 @@ static void monitor_free(void *data) g_dbus_proxy_unref(monitor->proxy); g_free(monitor->path); + queue_destroy(monitor->devices, monitor_device_free); + monitor->devices = NULL; + queue_destroy(monitor->patterns, pattern_free); free(monitor); @@ -257,6 +284,7 @@ static struct adv_monitor *monitor_new(struct adv_monitor_app *app, monitor->high_rssi_timeout = ADV_MONITOR_UNSET_TIMER; monitor->low_rssi = ADV_MONITOR_UNSET_RSSI; monitor->low_rssi_timeout = ADV_MONITOR_UNSET_TIMER; + monitor->devices = queue_new(); monitor->type = MONITOR_TYPE_NONE; monitor->patterns = NULL; @@ -932,3 +960,253 @@ void btd_adv_monitor_manager_destroy(struct btd_adv_monitor_manager *manager) manager_destroy(manager); } + +/* Matches a device based on btd_device object */ +static bool monitor_device_match(const void *a, const void *b) +{ + const struct adv_monitor_device *dev = a; + const struct btd_device *device = b; + + if (!dev) + return false; + + if (dev->device != device) + return false; + + return true; +} + +/* Frees a monitor device object */ +static void monitor_device_free(void *data) +{ + struct adv_monitor_device *dev = data; + + if (!dev) + return; + + if (dev->device_lost_timer) { + g_source_remove(dev->device_lost_timer); + dev->device_lost_timer = 0; + } + + dev->monitor = NULL; + dev->device = NULL; + + g_free(dev); +} + +/* Removes a device from monitor->devices list */ +static void remove_device_from_monitor(void *data, void *user_data) +{ + struct adv_monitor *monitor = data; + struct btd_device *device = user_data; + struct adv_monitor_device *dev = NULL; + + if (!monitor) + return; + + dev = queue_remove_if(monitor->devices, monitor_device_match, device); + if (dev) { + DBG("Device removed from the Adv Monitor at path %s", + monitor->path); + monitor_device_free(dev); + } +} + +/* Removes a device from every monitor in an app */ +static void remove_device_from_app(void *data, void *user_data) +{ + struct adv_monitor_app *app = data; + struct btd_device *device = user_data; + + if (!app) + return; + + queue_foreach(app->monitors, remove_device_from_monitor, device); +} + +/* Removes a device from every monitor in all apps */ +void btd_adv_monitor_device_remove(struct btd_adv_monitor_manager *manager, + struct btd_device *device) +{ + if (!manager || !device) + return; + + queue_foreach(manager->apps, remove_device_from_app, device); +} + +/* Creates a device object to track the per-device information */ +static struct adv_monitor_device *monitor_device_create( + struct adv_monitor *monitor, + struct btd_device *device) +{ + struct adv_monitor_device *dev = NULL; + + dev = g_try_malloc0(sizeof(struct adv_monitor_device)); + if (!dev) + return NULL; + + dev->monitor = monitor; + dev->device = device; + + queue_push_tail(monitor->devices, dev); + + 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 gboolean handle_device_lost_timeout(gpointer user_data) +{ + struct adv_monitor_device *dev = user_data; + struct adv_monitor *monitor = dev->monitor; + time_t curr_time = time(NULL); + + DBG("Device Lost timeout triggered for device %p " + "for the Adv Monitor at path %s", dev->device, monitor->path); + + dev->device_lost_timer = 0; + + if (dev->device_found && dev->last_seen) { + /* We were tracking for the Low RSSI filter. Check if there is + * any Adv received after the timeout function is invoked. + * If not, report the Device Lost event. + */ + if (difftime(curr_time, dev->last_seen) >= + monitor->low_rssi_timeout) { + dev->device_found = false; + + 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, dev->device, NULL); + } + } + + return FALSE; +} + +/* Filters an Adv based on its RSSI value */ +static void adv_monitor_filter_rssi(struct adv_monitor *monitor, + struct btd_device *device, int8_t rssi) +{ + struct adv_monitor_device *dev = NULL; + time_t curr_time = time(NULL); + uint16_t adapter_id = monitor->app->manager->adapter_id; + + /* If the RSSI thresholds and timeouts are not specified, report the + * DeviceFound() event without tracking for the RSSI as the Adv has + * already matched the pattern filter. + */ + if (monitor->high_rssi == ADV_MONITOR_UNSET_RSSI && + monitor->low_rssi == ADV_MONITOR_UNSET_RSSI && + monitor->high_rssi_timeout == ADV_MONITOR_UNSET_TIMER && + monitor->low_rssi_timeout == ADV_MONITOR_UNSET_TIMER) { + 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, + device, NULL); + + return; + } + + dev = queue_find(monitor->devices, monitor_device_match, device); + if (!dev) + dev = monitor_device_create(monitor, device); + if (!dev) { + btd_error(adapter_id, "Failed to create Adv Monitor " + "device object."); + return; + } + + if (dev->device_lost_timer) { + g_source_remove(dev->device_lost_timer); + dev->device_lost_timer = 0; + } + + /* Reset the timings of found/lost if a device has been offline for + * longer than the high/low timeouts. + */ + if (dev->last_seen) { + if (difftime(curr_time, dev->last_seen) > + monitor->high_rssi_timeout) { + dev->high_rssi_first_seen = 0; + } + + if (difftime(curr_time, dev->last_seen) > + monitor->low_rssi_timeout) { + dev->low_rssi_first_seen = 0; + } + } + dev->last_seen = curr_time; + + /* Check for the found devices (if the device is not already found) */ + if (!dev->device_found && rssi > monitor->high_rssi) { + if (dev->high_rssi_first_seen) { + if (difftime(curr_time, dev->high_rssi_first_seen) >= + monitor->high_rssi_timeout) { + dev->device_found = true; + + 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, + dev->device, NULL); + } + } else { + dev->high_rssi_first_seen = curr_time; + } + } else { + dev->high_rssi_first_seen = 0; + } + + /* Check for the lost devices (only if the device is already found, as + * it doesn't make any sense to report the Device Lost event if the + * device is not found yet) + */ + if (dev->device_found && rssi < monitor->low_rssi) { + if (dev->low_rssi_first_seen) { + if (difftime(curr_time, dev->low_rssi_first_seen) >= + monitor->low_rssi_timeout) { + dev->device_found = false; + + 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, + dev->device, NULL); + } + } else { + dev->low_rssi_first_seen = curr_time; + } + } else { + dev->low_rssi_first_seen = 0; + } + + /* Setup a timer to track if the device goes offline/out-of-range, only + * if we are tracking for the Low RSSI Threshold. If we are tracking + * the High RSSI Threshold, nothing needs to be done. + */ + if (dev->device_found) { + dev->device_lost_timer = + g_timeout_add_seconds(monitor->low_rssi_timeout, + handle_device_lost_timeout, dev); + } +} diff --git a/src/adv_monitor.h b/src/adv_monitor.h index 69ea348f8..14508e7d1 100644 --- a/src/adv_monitor.h +++ b/src/adv_monitor.h @@ -21,6 +21,7 @@ #define __ADV_MONITOR_H struct mgmt; +struct btd_device; struct btd_adapter; struct btd_adv_monitor_manager; @@ -29,4 +30,7 @@ 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); +void btd_adv_monitor_device_remove(struct btd_adv_monitor_manager *manager, + struct btd_device *device); + #endif /* __ADV_MONITOR_H */ From patchwork Thu Sep 17 07:05:01 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Miao-chen Chou X-Patchwork-Id: 252706 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-12.8 required=3.0 tests=BAYES_00,DKIMWL_WL_HIGH, DKIM_SIGNED,DKIM_VALID,DKIM_VALID_AU,HEADER_FROM_DIFFERENT_DOMAINS, INCLUDES_PATCH, MAILING_LIST_MULTI, SPF_HELO_NONE, SPF_PASS, URIBL_BLOCKED, USER_AGENT_GIT autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 0987CC43461 for ; Thu, 17 Sep 2020 07:06:24 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id BFA0021D7F for ; Thu, 17 Sep 2020 07:06:23 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=pass (1024-bit key) header.d=chromium.org header.i=@chromium.org header.b="S2eLc/rv" Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1726353AbgIQHGN (ORCPT ); Thu, 17 Sep 2020 03:06:13 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:46392 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1726318AbgIQHGE (ORCPT ); Thu, 17 Sep 2020 03:06:04 -0400 Received: from mail-pf1-x443.google.com (mail-pf1-x443.google.com [IPv6:2607:f8b0:4864:20::443]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 09FD6C06174A for ; Thu, 17 Sep 2020 00:06:04 -0700 (PDT) Received: by mail-pf1-x443.google.com with SMTP id z18so644196pfg.0 for ; Thu, 17 Sep 2020 00:06:04 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=chromium.org; s=google; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=u+E1bUX0uVxPcQEsE71u1Ro0+1uBNDa00K7AzDVg6ww=; b=S2eLc/rvaepND8Icr0cBILxS+QGa1uFhTFmd65QO/R5XHGqAutzWOK/X0Gq1ePvGTH sGZxpejzUWulmO7S38fEzqEXU0IYhtJwN6YDVGjFwU2mACSS8kc3rP8g21AaRuoo70aG KW8MUeTXKsKnIdcQBUz4/rLga2cdAN1H+GW5I= X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=u+E1bUX0uVxPcQEsE71u1Ro0+1uBNDa00K7AzDVg6ww=; b=cWmxwTIDTNNtYpji80ylmlaeG/qzEBiSGwLCSdJ2QhytrB0qlzY/GFWpPhjnAzMHJ6 3+YWXn8lTu2FKQeWwuhdEiIvK2HJMSZo+Mw5LEHYqzmIe4w0hA8HM+ioWl7JJTq2JDpB in4sJKxgr0uKtUaeO0dOgC4a0m56uCnNSAhz0E7eaKcpnmWI05r1lZUyYcp7TkJxrTrA tzZbGkpiMBQpPeZNmNBRp0pXqtsWA32vpwTB6HtiMDzz4EgCG2QaMIkoj7UFdmHmwJYu Z/x+fya7cCTyYF5U5PvWHQKInA5R3eGxTiaNCfiyf9wF2TlhOXECC2sQNaAlNJ3psYoe 0Wvw== X-Gm-Message-State: AOAM530/fzpOwv2peLMgrH3dZ0ykz8/M+66CGWNNesLjbxCXeLO2zuvp 5ydsO/Wx5GRKABnVxO+9Wf7pZcIAL2962g== X-Google-Smtp-Source: ABdhPJwxlR1tasWj8I4dTGhLmdFaC+kEF8dazPqIRuKiWZCfyfybzBHPNljq3cdI+ltW5Hocp7ZDZg== X-Received: by 2002:a63:e802:: with SMTP id s2mr21569528pgh.350.1600326363295; Thu, 17 Sep 2020 00:06:03 -0700 (PDT) Received: from mcchou0.mtv.corp.google.com ([2620:15c:202:201:de4a:3eff:fe75:1314]) by smtp.gmail.com with ESMTPSA id y197sm5407372pfc.220.2020.09.17.00.06.02 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Thu, 17 Sep 2020 00:06:02 -0700 (PDT) From: Miao-chen Chou To: Bluetooth Kernel Mailing List Cc: Howard Chung , Alain Michaud , chromeos-bluetooth-upstreaming@chromium.org, Marcel Holtmann , Manish Mandlik , Luiz Augusto von Dentz , Miao-chen Chou Subject: [BlueZ PATCH v3 5/8] adapter: Clear all Adv monitors upon bring-up Date: Thu, 17 Sep 2020 00:05:01 -0700 Message-Id: <20200917000448.BlueZ.v3.5.Id6bfe7838831ae01fddc8605689dd77b51673960@changeid> X-Mailer: git-send-email 2.26.2 In-Reply-To: <20200917000448.BlueZ.v3.1.I2830b9c1212a64b062201ed9f2b71294f50ad22d@changeid> References: <20200917000448.BlueZ.v3.1.I2830b9c1212a64b062201ed9f2b71294f50ad22d@changeid> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-bluetooth@vger.kernel.org This clears all Adv monitors upon daemon bring-up by issuing MGMT_OP_REMOVE_ADV_MONITOR command with monitor_handle 0. The following test was performed: - Add an Adv Monitor using btmgmt, restart bluetoothd and observe the monitor got removed. Reviewed-by: Alain Michaud Reviewed-by: Manish Mandlik Reviewed-by: Howard Chung --- (no changes since v1) src/adapter.c | 39 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 39 insertions(+) diff --git a/src/adapter.c b/src/adapter.c index d33ce7124..191467048 100644 --- a/src/adapter.c +++ b/src/adapter.c @@ -9513,6 +9513,43 @@ failed: btd_adapter_unref(adapter); } +static void reset_adv_monitors_complete(uint8_t status, uint16_t length, + const void *param, void *user_data) +{ + struct mgmt_rp_remove_adv_monitor *rp = param; + + if (status != MGMT_STATUS_SUCCESS) { + error("Failed to reset Adv Monitors: %s (0x%02x)", + mgmt_errstr(status), status); + return; + } + + if (length < sizeof(*rp)) { + error("Wrong size of remove Adv Monitor response for reset " + "all Adv Monitors"); + return; + } + + DBG("Removed all Adv Monitors"); +} + +static void reset_adv_monitors(uint16_t index) +{ + struct mgmt_cp_remove_adv_monitor cp; + + DBG("sending remove Adv Monitor command with handle 0"); + + /* Handle 0 indicates to remove all */ + cp.monitor_handle = 0; + if (mgmt_send(mgmt_master, MGMT_OP_REMOVE_ADV_MONITOR, index, + sizeof(cp), &cp, reset_adv_monitors_complete, NULL, + NULL) > 0) { + return; + } + + error("Failed to reset Adv Monitors"); +} + static void index_added(uint16_t index, uint16_t length, const void *param, void *user_data) { @@ -9527,6 +9564,8 @@ static void index_added(uint16_t index, uint16_t length, const void *param, return; } + reset_adv_monitors(index); + adapter = btd_adapter_new(index); if (!adapter) { btd_error(index, From patchwork Thu Sep 17 07:05:05 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Miao-chen Chou X-Patchwork-Id: 252705 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-12.8 required=3.0 tests=BAYES_00,DKIMWL_WL_HIGH, DKIM_SIGNED,DKIM_VALID,DKIM_VALID_AU,HEADER_FROM_DIFFERENT_DOMAINS, INCLUDES_PATCH, MAILING_LIST_MULTI, SPF_HELO_NONE, SPF_PASS, URIBL_BLOCKED, USER_AGENT_GIT autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 147DFC43461 for ; Thu, 17 Sep 2020 07:06:54 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id CCD4021D41 for ; Thu, 17 Sep 2020 07:06:53 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=pass (1024-bit key) header.d=chromium.org header.i=@chromium.org header.b="FF2N56Pe" Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1726373AbgIQHGr (ORCPT ); Thu, 17 Sep 2020 03:06:47 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:46476 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1726217AbgIQHGe (ORCPT ); Thu, 17 Sep 2020 03:06:34 -0400 Received: from mail-pg1-x543.google.com (mail-pg1-x543.google.com [IPv6:2607:f8b0:4864:20::543]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 4835BC06174A for ; Thu, 17 Sep 2020 00:06:34 -0700 (PDT) Received: by mail-pg1-x543.google.com with SMTP id j34so811692pgi.7 for ; Thu, 17 Sep 2020 00:06:34 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=chromium.org; s=google; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=A+EJCB6WY4TQKa6gHOsgkF94rPPA4eTIhn24gfOv1nI=; b=FF2N56PeIxVmnF0nGltOa7r6EMHha58z7gvoJwo7mWCQvJtkmgIdJkq+qLADDM1zNL QAkRpePyXvdBSBtA/2w8BmSnWeVuG8LpiIGsIOlD1qnMQ/D3exppan5R1XgrfGn59lkb QAgjQERN6iF3VsS8STtpcU9jHBMvnChdsnknI= X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=A+EJCB6WY4TQKa6gHOsgkF94rPPA4eTIhn24gfOv1nI=; b=Hv7RlNibDtSwrSIi/mKFfbWMZ6nN4MriVldrAviWngmS7hRrSaL2VrNUoGI/Sg2EBz ltKoBv/swTNqSkstWhaoTxxIVUt1sb8/o4oFER7/4Yqm7/zeoJQb25U1vFVR2IkSUYBt xazBpoF7CgueukZB6SsEWOKM1wCso0D34/Mi5qE17BBgKSEtRaIVvGG4M75PF9l9RHGY k+5ZtMTWv/Pn+jiWqkcgtq/Sw09h6snxIRMwrnocoGjQWKHcbFNln3r9tEINGjrmgJY9 xthA6WoANhES8cniwEwVreGeiswSo1gwsM25hXbysKFPq7HPu9DB2zG+Xhe3J9yyFAh4 ZPpQ== X-Gm-Message-State: AOAM53204N+y8E9o7P2G3/AwUXrs5hCJJ2WZaFEEDTfuuBLg2WTRk+E8 jUxian+U2fNhLyvpb3MZ1pU92k8/j1iBhA== X-Google-Smtp-Source: ABdhPJxaxXAPMJwgOVtYfC2bOjtHTHJ/6SnYQZuOFUwcNEEaIlNcw06Uj8kP/FClvULzQNUARTCm9w== X-Received: by 2002:a63:30c:: with SMTP id 12mr21539115pgd.66.1600326393586; Thu, 17 Sep 2020 00:06:33 -0700 (PDT) Received: from mcchou0.mtv.corp.google.com ([2620:15c:202:201:de4a:3eff:fe75:1314]) by smtp.gmail.com with ESMTPSA id y197sm5407372pfc.220.2020.09.17.00.06.32 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Thu, 17 Sep 2020 00:06:32 -0700 (PDT) From: Miao-chen Chou To: Bluetooth Kernel Mailing List Cc: Howard Chung , Alain Michaud , chromeos-bluetooth-upstreaming@chromium.org, Marcel Holtmann , Manish Mandlik , Luiz Augusto von Dentz , Miao-chen Chou Subject: [BlueZ PATCH v3 7/8] adv_monitor: Fix return type of RegisterMonitor() method Date: Thu, 17 Sep 2020 00:05:05 -0700 Message-Id: <20200917000448.BlueZ.v3.7.Ic8dbe9115e82704b4c0c860eee27ad897db13237@changeid> X-Mailer: git-send-email 2.26.2 In-Reply-To: <20200917000448.BlueZ.v3.1.I2830b9c1212a64b062201ed9f2b71294f50ad22d@changeid> References: <20200917000448.BlueZ.v3.1.I2830b9c1212a64b062201ed9f2b71294f50ad22d@changeid> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-bluetooth@vger.kernel.org This modifies the D-Bus call return type to be asynchronous for RegisterMonitor() method call. The following test was performed: - Enter bluetoothctl, exit the console and re-enter the console without AlreadyExist error for RegisterMonitor() upon bring-up of the console. Reviewed-by: Howard Chung Reviewed-by: Manish Mandlik --- (no changes since v1) src/adv_monitor.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/adv_monitor.c b/src/adv_monitor.c index deaa1894a..b4fe39eff 100644 --- a/src/adv_monitor.c +++ b/src/adv_monitor.c @@ -758,6 +758,8 @@ static struct adv_monitor_app *app_create(DBusConnection *conn, app->monitors = queue_new(); + app->reg = dbus_message_ref(msg); + g_dbus_client_set_disconnect_watch(app->client, app_disconnect_cb, app); /* Note that any property changes on a monitor object would not affect @@ -769,8 +771,6 @@ static struct adv_monitor_app *app_create(DBusConnection *conn, g_dbus_client_set_ready_watch(app->client, app_ready_cb, app); - app->reg = dbus_message_ref(msg); - return app; } @@ -864,7 +864,7 @@ static DBusMessage *unregister_monitor(DBusConnection *conn, } static const GDBusMethodTable adv_monitor_methods[] = { - { GDBUS_EXPERIMENTAL_METHOD("RegisterMonitor", + { GDBUS_EXPERIMENTAL_ASYNC_METHOD("RegisterMonitor", GDBUS_ARGS({ "application", "o" }), NULL, register_monitor) }, { GDBUS_EXPERIMENTAL_ASYNC_METHOD("UnregisterMonitor", From patchwork Thu Sep 17 07:05:07 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Miao-chen Chou X-Patchwork-Id: 252704 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-12.8 required=3.0 tests=BAYES_00,DKIMWL_WL_HIGH, DKIM_SIGNED,DKIM_VALID,DKIM_VALID_AU,HEADER_FROM_DIFFERENT_DOMAINS, INCLUDES_PATCH, MAILING_LIST_MULTI, SPF_HELO_NONE, SPF_PASS, URIBL_BLOCKED, USER_AGENT_GIT autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 982C4C433E2 for ; Thu, 17 Sep 2020 07:07:14 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 51D8D21D41 for ; Thu, 17 Sep 2020 07:07:14 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=pass (1024-bit key) header.d=chromium.org header.i=@chromium.org header.b="mU3QgRhG" Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1726249AbgIQHHH (ORCPT ); Thu, 17 Sep 2020 03:07:07 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:46518 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1726375AbgIQHGu (ORCPT ); Thu, 17 Sep 2020 03:06:50 -0400 Received: from mail-pg1-x535.google.com (mail-pg1-x535.google.com [IPv6:2607:f8b0:4864:20::535]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id F1420C06174A for ; Thu, 17 Sep 2020 00:06:49 -0700 (PDT) Received: by mail-pg1-x535.google.com with SMTP id 7so802003pgm.11 for ; Thu, 17 Sep 2020 00:06:49 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=chromium.org; s=google; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=NdeK9jrlbDmnJ07T/Z6f3zn8nKeo+Ri2ioiOM8etDYk=; b=mU3QgRhGh7VqA72Z6FfXfRR7d3d3ExVV0jY6g5UZusp0tHnOdhxE5fyJYI7L7KD9R8 E301OSe2P+uI6uH0+c8j8VHoxsHJ/O2RZXIVh/H7Rx/3+vNOgZaGBG9+6m56a23qrWCY nkPVmJIv9i+uaf+HQhZCt8dAy8oQGZlaYlop8= X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=NdeK9jrlbDmnJ07T/Z6f3zn8nKeo+Ri2ioiOM8etDYk=; b=Lk+l2q/lHNglyfS0bVJs1swXHqolfj/FuIljFt1xZ2ONeF4JLuI4y8r2+mIOBiqw6L HxSrhf6AAZ6+4plaaGrCjPO5lef5x8oqNjfAnPGzcCf58EJx56ZxhZphkmcIj2YG1qlH Hmz8C+Ge1Es9u63s5V+JTpVOThZWBJAIf1YiW65fi0p63ba+IKyOiZHpBd39ni3m6qbS S/LFJiqbygXrvJGripLaadhzfpzrz8qOblPc91TML208Hx8seMjMOVwuzqZCUzAdwP9J TQeSgzN4DuJFDzhWJGtsnJx+pmWdxoLb1KmCw3VeWGUse4y8nlVB24IUl5GOjiW5oxNi yvyg== X-Gm-Message-State: AOAM531Q9smGIcfsFfucJtQoYFI+JM9FglATAVr8q3Bvulo6gYTLmoAy k1nbNmSx9phpNiINHxbw7Ez2ez8tiiZQFA== X-Google-Smtp-Source: ABdhPJzCj2mdX7DUBKZmn2Ro004df9GNjfmoXTF3DbYgKPRK8nr4eipKPKT2AJ5krVgf+EirCaqD0w== X-Received: by 2002:a63:4404:: with SMTP id r4mr19954616pga.29.1600326409123; Thu, 17 Sep 2020 00:06:49 -0700 (PDT) Received: from mcchou0.mtv.corp.google.com ([2620:15c:202:201:de4a:3eff:fe75:1314]) by smtp.gmail.com with ESMTPSA id y197sm5407372pfc.220.2020.09.17.00.06.48 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Thu, 17 Sep 2020 00:06:48 -0700 (PDT) From: Miao-chen Chou To: Bluetooth Kernel Mailing List Cc: Howard Chung , Alain Michaud , chromeos-bluetooth-upstreaming@chromium.org, Marcel Holtmann , Manish Mandlik , Luiz Augusto von Dentz Subject: [BlueZ PATCH v3 8/8] adv_monitor: Issue Remove Adv Monitor mgmt call Date: Thu, 17 Sep 2020 00:05:07 -0700 Message-Id: <20200917000448.BlueZ.v3.8.Ifda683c92ff520bf58ac37c02dc40b8d9598d1b0@changeid> X-Mailer: git-send-email 2.26.2 In-Reply-To: <20200917000448.BlueZ.v3.1.I2830b9c1212a64b062201ed9f2b71294f50ad22d@changeid> References: <20200917000448.BlueZ.v3.1.I2830b9c1212a64b062201ed9f2b71294f50ad22d@changeid> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-bluetooth@vger.kernel.org From: Alain Michaud This calls Remove Adv Monitor command to kernel and handles the callback during a monitor removal initiated by a D-Bus client. This also registers callback for getting notified on Adv Monitor Removed event, so that the Adv monitor manager can invalidate the monitor by calling Release() on its proxy. The following tests were performed. - In bluetoothctl console, add a monitor and remove the monitor by its index and verify the removal in both the output of btmgmt and syslog. - In bluetoothctl console, add a monitor, remove the monitor via btmgmt and verify the removal in syslog. Reviewed-by: Howard Chung --- Changes in v3: - Fix const qualifier of a pointer src/adv_monitor.c | 128 +++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 120 insertions(+), 8 deletions(-) diff --git a/src/adv_monitor.c b/src/adv_monitor.c index b4fe39eff..27da30b51 100644 --- a/src/adv_monitor.c +++ b/src/adv_monitor.c @@ -88,6 +88,7 @@ enum monitor_state { MONITOR_STATE_FAILED, /* Failed to be init'ed */ MONITOR_STATE_INITED, /* Init'ed but not yet sent to kernel */ MONITOR_STATE_HONORED, /* Accepted by kernel */ + MONITOR_STATE_REMOVING, /* Removing from kernel */ }; struct btd_adv_monitor_pattern { @@ -103,6 +104,7 @@ struct adv_monitor { char *path; enum monitor_state state; /* MONITOR_STATE_* */ + uint16_t monitor_handle; /* Kernel Monitor Handle */ int8_t high_rssi; /* High RSSI threshold */ uint16_t high_rssi_timeout; /* High RSSI threshold timeout */ @@ -631,6 +633,7 @@ static void add_adv_patterns_monitor_cb(uint8_t status, uint16_t length, return; } + monitor->monitor_handle = le16_to_cpu(rp->monitor_handle); monitor->state = MONITOR_STATE_HONORED; DBG("Calling Activate() on Adv Monitor of owner %s at path %s", @@ -639,8 +642,7 @@ static void add_adv_patterns_monitor_cb(uint8_t status, uint16_t length, g_dbus_proxy_method_call(monitor->proxy, "Activate", NULL, NULL, NULL, NULL); - DBG("Adv Monitor with handle:0x%04x added", - le16_to_cpu(rp->monitor_handle)); + DBG("Adv monitor with handle:0x%04x added", monitor->monitor_handle); } static void monitor_copy_patterns(void *data, void *user_data) @@ -714,20 +716,77 @@ done: free(cp); } +/* Handles the callback of Remove Adv Monitor command */ +static void remove_adv_monitor_cb(uint8_t status, uint16_t length, + const void *param, void *user_data) +{ + struct adv_monitor *monitor = user_data; + const struct mgmt_rp_remove_adv_monitor *rp = param; + uint16_t adapter_id = monitor->app->manager->adapter_id; + + if (status != MGMT_STATUS_SUCCESS || !param) { + btd_error(adapter_id, "Failed to Remove Adv Monitor with " + "status 0x%02x", status); + goto done; + } + + if (length < sizeof(*rp)) { + btd_error(adapter_id, "Wrong size of Remove Adv Monitor " + "response"); + goto done; + } + +done: + queue_remove(monitor->app->monitors, monitor); + + DBG("Adv Monitor removed with handle:0x%04x, path %s", + monitor->monitor_handle, monitor->path); + + monitor_free(monitor); +} + + /* Handles the removal of an Adv Monitor D-Bus proxy */ static void monitor_proxy_removed_cb(GDBusProxy *proxy, void *user_data) { struct adv_monitor *monitor; + struct mgmt_cp_remove_adv_monitor cp; struct adv_monitor_app *app = user_data; + uint16_t adapter_id = app->manager->adapter_id; - monitor = queue_remove_if(app->monitors, monitor_match, proxy); - if (monitor) { - DBG("Adv Monitor removed for the object at path %s", - monitor->path); + monitor = queue_find(app->monitors, monitor_match, proxy); - /* The object was gone, so we don't need to call Release() */ - monitor_free(monitor); + /* A monitor removed event from kernel can remove a monitor and notify + * the app on Release() where this callback can be invoked, so we + * simply skip here. + */ + if (!monitor) + return; + + if (monitor->state != MONITOR_STATE_HONORED) + goto done; + + monitor->state = MONITOR_STATE_REMOVING; + + cp.monitor_handle = cpu_to_le16(monitor->monitor_handle); + + if (!mgmt_send(app->manager->mgmt, MGMT_OP_REMOVE_ADV_MONITOR, + adapter_id, sizeof(cp), &cp, remove_adv_monitor_cb, + monitor, NULL)) { + btd_error(adapter_id, "Unable to send Remove Advt Monitor " + "command"); + goto done; } + + return; + +done: + queue_remove(app->monitors, monitor); + + DBG("Adv Monitor removed in state %02x with path %s", monitor->state, + monitor->path); + + monitor_free(monitor); } /* Creates an app object, initiates it and sets D-Bus event handlers */ @@ -936,6 +995,55 @@ static const GDBusPropertyTable adv_monitor_properties[] = { { } }; +/* Matches a monitor based on its handle */ +static bool removed_monitor_match(const void *data, const void *user_data) +{ + const struct adv_monitor *monitor = data; + const struct mgmt_ev_adv_monitor_removed *ev = user_data; + + return monitor->monitor_handle == ev->monitor_handle; +} + +/* Remove the matched monitor and reports the removal to the app */ +static void app_remove_monitor(void *data, void *user_data) +{ + struct adv_monitor_app *app = data; + struct adv_monitor *monitor; + + monitor = queue_find(app->monitors, removed_monitor_match, user_data); + if (monitor) { + if (monitor->state == MONITOR_STATE_HONORED) + monitor_release(monitor, NULL); + + queue_remove(app->monitors, monitor); + + DBG("Adv Monitor at path %s removed", monitor->path); + + monitor_free(monitor); + } +} + +/* Processes Adv Monitor removed event from kernel */ +static void adv_monitor_removed_callback(uint16_t index, uint16_t length, + const void *param, void *user_data) +{ + const uint16_t adapter_id = manager->adapter_id; + struct btd_adv_monitor_manager *manager = user_data; + const struct mgmt_ev_adv_monitor_removed *ev = param; + + if (length < sizeof(*ev)) { + btd_error(adapter_id, "Wrong size of Adv Monitor Removed " + "event"); + return; + } + + /* Traverse the apps to find the monitor */ + queue_foreach(manager->apps, app_remove_monitor, ev); + + DBG("Adv Monitor removed event with handle 0x%04x processed", + ev->monitor_handle); +} + /* Allocates a manager object */ static struct btd_adv_monitor_manager *manager_new( struct btd_adapter *adapter, @@ -955,6 +1063,10 @@ static struct btd_adv_monitor_manager *manager_new( manager->adapter_id = btd_adapter_get_index(adapter); manager->apps = queue_new(); + mgmt_register(manager->mgmt, MGMT_EV_ADV_MONITOR_REMOVED, + manager->adapter_id, adv_monitor_removed_callback, + manager, NULL); + return manager; }