Received: by 2002:a05:6a10:9e8c:0:0:0:0 with SMTP id y12csp740613pxx; Wed, 28 Oct 2020 16:09:46 -0700 (PDT) X-Google-Smtp-Source: ABdhPJw2WD9BjjshTv4a6yW3V6bEpsTgR81GxHlcVFW+jqCwV9sUYMn8/TG8fw8KINsL7DLPK0O1 X-Received: by 2002:a17:906:f0ce:: with SMTP id dk14mr1379924ejb.539.1603926586428; Wed, 28 Oct 2020 16:09:46 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1603926586; cv=none; d=google.com; s=arc-20160816; b=tBOMTUPZ+gpeFB/L8R0h/z3vCLL9DgR96s3lD415AHMJj8kuC/JGg9ZAFZG8glFakA u6wK6e6EJWFwZBFljdB4PYSMcdwm5YWXgGwCsIGMK6RHpwwBGtHuo1yn4U3Puk7CT/qi VRZRhSrz8ugrxaAJYKDwD07T9ZaPWH5O4JwA3ywaCdLt5OzNzk5w3U+GmWtH/vQYivEw T6WfGGSgFqVnfw2QStT/z/hZAUYCDpUaIU7IZu44cBmrBI9z/PO/522zm3j8rql1kFML xeogg8CdZR5oklNlL4okDfsu+7KkFh0zEixQQuAxVmI3ppWpoBFFdZ4mY8PV49CeGgTT h8VQ== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:content-transfer-encoding:mime-version :references:in-reply-to:message-id:date:subject:cc:to:from :dkim-signature; bh=RYshsJ2zM56tgOKjlW4AxLdnwjqh8QbCbfXq9IQfVhM=; b=AnS6UloN5VFukLpurvDgO3rpkWp2tZjPMbu9Xl1CtZYrmCSne00IsL2yr9JMw4qtuZ B8rtIQZy8W4SIgwE8fu9nMu7DYhpVnYvzFAlX2GRtounaKxeg608b9sFs8CTfLP74noD vlSVtHigtlLGR8L8ip1Zds0SvQEfbU8Ooo/mZSprMcb4uHVsYqZcSge1NLjKXWyVs9an osNhwLpENXCFggycf81iiCHU6+8eqV5PQAnarUf2CR1XNHDPFFuurBZfA3bfnaU6BoK1 upHVWjHcnHJJtyGe/6jralk1zd2wI2i29C4W88BVJo1Ow+H35YstP9ftxOwkQrB8KOi3 5YEQ== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@chromium.org header.s=google header.b=aA+Kyiq4; spf=pass (google.com: domain of linux-bluetooth-owner@vger.kernel.org designates 23.128.96.18 as permitted sender) smtp.mailfrom=linux-bluetooth-owner@vger.kernel.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=chromium.org Return-Path: Received: from vger.kernel.org (vger.kernel.org. [23.128.96.18]) by mx.google.com with ESMTP id f11si620370edj.402.2020.10.28.16.09.22; Wed, 28 Oct 2020 16:09:46 -0700 (PDT) Received-SPF: pass (google.com: domain of linux-bluetooth-owner@vger.kernel.org designates 23.128.96.18 as permitted sender) client-ip=23.128.96.18; Authentication-Results: mx.google.com; dkim=pass header.i=@chromium.org header.s=google header.b=aA+Kyiq4; spf=pass (google.com: domain of linux-bluetooth-owner@vger.kernel.org designates 23.128.96.18 as permitted sender) smtp.mailfrom=linux-bluetooth-owner@vger.kernel.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=chromium.org Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1727337AbgJ1XI3 (ORCPT + 99 others); Wed, 28 Oct 2020 19:08:29 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:33860 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1725789AbgJ1XIQ (ORCPT ); Wed, 28 Oct 2020 19:08:16 -0400 Received: from mail-pg1-x52f.google.com (mail-pg1-x52f.google.com [IPv6:2607:f8b0:4864:20::52f]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id BC151C0613CF for ; Wed, 28 Oct 2020 16:08:15 -0700 (PDT) Received: by mail-pg1-x52f.google.com with SMTP id s22so753333pga.9 for ; Wed, 28 Oct 2020 16:08:15 -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=RYshsJ2zM56tgOKjlW4AxLdnwjqh8QbCbfXq9IQfVhM=; b=aA+Kyiq4n+ngWsa0DmYfAazPchL0lxGKb9DBaj9Z2F2TYNN06U68wnP8Ve/9KRCVJU 8Pd4vzRiv0XwT1g19RAL37OpyFro4OCHuyE4EPvOm/f3PmxdEC4e4THXa0CaNclB2Uu5 +NNjYOUT9+zjt9UhEiOSOpmOngOOXwGt6NuyQ= 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=RYshsJ2zM56tgOKjlW4AxLdnwjqh8QbCbfXq9IQfVhM=; b=ejlrvoMxJQ6RsJXDFu155TnrN4wRgGmNTQh35U8tMfGcZ92YPenGebmXxGnR68Lokz IcuH3iQkmosLZ5FLa6Awd//JQCiH2KNDvSIm1KOpAOU1JHc5gzS5op/AjK38JBZjBf3b lscyN7kAK1HQghynvhTB/iiM/Y/ISX38NOtKS0ujZ3GnVa2AS7fUcXai9wxqCabnf+vx 8QjIX/nnc72itWEf9KFrEMWkaRM7YQcHYXYykXustokLzfhTBMeH8XBS6YMBfo6I4w1+ yekUL2m6cWE0PqVgtuxSoCTp8kTIyIVUcPgIjOa2LzvfO9WOZAt/ifjPGbEWn4nIBy2e R6/A== X-Gm-Message-State: AOAM530idw6kwMxRWmQ7XS4kfRCsurV8+QbWYwFESM7qkPamfDxhwQ85 8AHd64ngP53GTNuuXBNGB41+Y4hwuNtfkQ== X-Received: by 2002:a17:90a:8b16:: with SMTP id y22mr1203432pjn.46.1603926494984; Wed, 28 Oct 2020 16:08:14 -0700 (PDT) Received: from mcchou0.mtv.corp.google.com ([2620:15c:202:201:de4a:3eff:fe75:1314]) by smtp.gmail.com with ESMTPSA id y137sm644134pfc.77.2020.10.28.16.08.13 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Wed, 28 Oct 2020 16:08:14 -0700 (PDT) From: Miao-chen Chou To: Bluetooth Kernel Mailing List Cc: Alain Michaud , Manish Mandlik , Luiz Augusto von Dentz , Howard Chung , chromeos-bluetooth-upstreaming@chromium.org, Marcel Holtmann Subject: [BlueZ PATCH v7 7/7] adv_monitor: Issue Remove Adv Monitor mgmt call Date: Wed, 28 Oct 2020 16:05:38 -0700 Message-Id: <20201028160433.BlueZ.v7.7.Ifda683c92ff520bf58ac37c02dc40b8d9598d1b0@changeid> X-Mailer: git-send-email 2.26.2 In-Reply-To: <20201028160433.BlueZ.v7.1.I2830b9c1212a64b062201ed9f2b71294f50ad22d@changeid> References: <20201028160433.BlueZ.v7.1.I2830b9c1212a64b062201ed9f2b71294f50ad22d@changeid> MIME-Version: 1.0 Content-Transfer-Encoding: 8bit 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 Reviewed-by: Alain Michaud --- Changes in v7: - Rename MONITOR_STATE_HONORED to MONITOR_STATE_ACTIVE Changes in v4: - Fix build error Changes in v3: - Fix const qualifier of a pointer src/adv_monitor.c | 132 +++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 124 insertions(+), 8 deletions(-) diff --git a/src/adv_monitor.c b/src/adv_monitor.c index dbc3b2a92..c786015c8 100644 --- a/src/adv_monitor.c +++ b/src/adv_monitor.c @@ -79,6 +79,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_ACTIVE, /* Accepted by kernel */ + MONITOR_STATE_REMOVING, /* Removing from kernel */ }; struct adv_monitor { @@ -87,6 +88,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 */ @@ -567,6 +569,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_ACTIVE; DBG("Calling Activate() on Adv Monitor of owner %s at path %s", @@ -575,8 +578,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) @@ -650,20 +652,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_ACTIVE) + 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 */ @@ -872,6 +931,59 @@ 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 uint16_t *handle = user_data; + const struct adv_monitor *monitor = data; + + if (!data || !handle) + return false; + + return monitor->monitor_handle == *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_ACTIVE) + 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) +{ + struct btd_adv_monitor_manager *manager = user_data; + const struct mgmt_ev_adv_monitor_removed *ev = param; + uint16_t handle = ev->monitor_handle; + const uint16_t adapter_id = manager->adapter_id; + + 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, &handle); + + 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, @@ -891,6 +1003,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; } -- 2.26.2