From patchwork Thu Dec 16 12:49:54 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Manish Mandlik X-Patchwork-Id: 12680985 X-Patchwork-Delegate: kuba@kernel.org Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 1B15DC4332F for ; Thu, 16 Dec 2021 12:50:04 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S236947AbhLPMuC (ORCPT ); Thu, 16 Dec 2021 07:50:02 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:47736 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S234245AbhLPMuC (ORCPT ); Thu, 16 Dec 2021 07:50:02 -0500 Received: from mail-yb1-xb4a.google.com (mail-yb1-xb4a.google.com [IPv6:2607:f8b0:4864:20::b4a]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id C8914C061574 for ; Thu, 16 Dec 2021 04:50:01 -0800 (PST) Received: by mail-yb1-xb4a.google.com with SMTP id e131-20020a25d389000000b005fb5e6eb757so49396121ybf.22 for ; Thu, 16 Dec 2021 04:50:01 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20210112; h=date:message-id:mime-version:subject:from:to:cc; bh=OYe0X5Z+39vgIcBBkai30ctoKVlHHKDrTKntAV/6gvE=; b=Vl3sYzpqAwU82wJDrYCE5h/TokhiDADcrgd9aF5HL7gVg3nuo9DVNYh8YkS1ZMJ8Ql R+HQMhz2b0sW4hHVdTUTd3Yndb0SNBhLbBYF9uiivsVHmMvHOs0Mw9mcapYlUGVqKYhb +ZMoJafXYD3bnO6qdlx0BUzv5MmBeJrBQXvtPkNKQhhVQu9p0kh5FIOOQBdgEzcN3cJd /lVQ32O7QR+GeOX/Py2kxQAQBFIQwwQkNVS20LBINSePohZAYz+3B1isZIDHtIe7ewF/ GThNuCvAJh2v9Fiy/MNMhaSNA+AHZlPw0/zGivXVzg2FfYIryy+RLdCci0lHJDVlYtfn R+rg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=x-gm-message-state:date:message-id:mime-version:subject:from:to:cc; bh=OYe0X5Z+39vgIcBBkai30ctoKVlHHKDrTKntAV/6gvE=; b=JX5LA15Hf+ZkRxd3jHkzEl51/04IYsWK5KV2P/sg2AZ6hZZq5bDM2elc7EzcdHB6gC KIUYgLkJ+v6zQKlWNqIYktYM30JeVZg0UQgWhG2MVbUTuYcokAZWhl10xqBQIoIBUe9e IJjxH4lKZ0FbmMZRfmJdC+jfA5z1BfHQt78w0ZCPGNCiczl5AV1uHsKdxvkZVcB06JyE CldpvxWyHVccV9V4NE1SRtD4BQnSriQMvihHNBxD9Nticiz76B4MEM37MppO8MQNBBMg X/ouhURwb7/oiyIqyKir74vDG66qGYHwrGXL00gzikD7OYApsMuO1RPTWMSuj/vv5RMW OiFQ== X-Gm-Message-State: AOAM532RTTKUz4DSnKRVtuVNqSzNdDwlsw2VShLfVvy1/cAlYm2l6NMo ozQM8R2Ft2kYrfpf+CEtypv5ljNG1FKMGQ== X-Google-Smtp-Source: ABdhPJws2q8VMhv19+PsC7/kIw2UIk2tic+egzZT5bj+wH1nPfB7/uW9Z6bDjRvMy5/qMZFeGfXJawTBbbuQmw== X-Received: from mmandlik.mtv.corp.google.com ([2620:15c:202:201:bfe1:d4f7:bb68:8aa6]) (user=mmandlik job=sendgmr) by 2002:a25:6d04:: with SMTP id i4mr13837902ybc.757.1639659000972; Thu, 16 Dec 2021 04:50:00 -0800 (PST) Date: Thu, 16 Dec 2021 04:49:54 -0800 Message-Id: <20211216044839.v9.1.Ic0a40b84dee3825302890aaea690e73165c71820@changeid> Mime-Version: 1.0 X-Mailer: git-send-email 2.34.1.173.g76aa8bc2d0-goog Subject: [PATCH v9 1/3] bluetooth: msft: Handle MSFT Monitor Device Event From: Manish Mandlik To: marcel@holtmann.org, luiz.dentz@gmail.com Cc: chromeos-bluetooth-upstreaming@chromium.org, linux-bluetooth@vger.kernel.org, Manish Mandlik , Miao-chen Chou , "David S. Miller" , Jakub Kicinski , Johan Hedberg , linux-kernel@vger.kernel.org, netdev@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: netdev@vger.kernel.org X-Patchwork-Delegate: kuba@kernel.org Whenever the controller starts/stops monitoring a bt device, it sends MSFT Monitor Device event. Add handler to read this vendor event. Test performed: - Verified by logs that the MSFT Monitor Device event is received from the controller whenever it starts/stops monitoring a device. Signed-off-by: Manish Mandlik Reviewed-by: Miao-chen Chou Reported-by: kernel test robot Reported-by: Dan Carpenter --- Hello Bt-Maintainers, As mentioned in the bluez patch series [1], we need to capture the 'MSFT Monitor Device' event from the controller and pass on the necessary information to the bluetoothd. This is required to further optimize the power consumption by avoiding handling of RSSI thresholds and timeouts in the user space and let the controller do the RSSI tracking. This patch series adds support to read the MSFT vendor event HCI_VS_MSFT_LE_Monitor_Device_Event and introduces new MGMT events MGMT_EV_ADV_MONITOR_DEVICE_FOUND and MGMT_EV_ADV_MONITOR_DEVICE_LOST to indicate that the controller has started/stopped tracking a particular device. Please let me know what you think about this or if you have any further questions. [1] https://patchwork.kernel.org/project/bluetooth/list/?series=583423 Thanks, Manish. Changes in v9: - Fix compiler error. Changes in v8: - Fix use-after-free in msft_le_cancel_monitor_advertisement_cb(). - Use skb_pull_data() instead of skb_pull(). Changes in v6: - Fix compiler warning bt_dev_err() missing argument. Changes in v5: - Split v4 into two patches. - Buffer controller Device Found event and maintain the device tracking state in the kernel. Changes in v4: - Add Advertisement Monitor Device Found event and update addr type. Changes in v3: - Discard changes to the Device Found event and notify bluetoothd only when the controller stops monitoring the device via new Device Lost event. Changes in v2: - Instead of creating a new 'Device Tracking' event, add a flag 'Device Tracked' in the existing 'Device Found' event and add a new 'Device Lost' event to indicate that the controller has stopped tracking that device. include/net/bluetooth/hci_core.h | 11 +++ net/bluetooth/hci_core.c | 1 + net/bluetooth/msft.c | 150 +++++++++++++++++++++++++++++-- 3 files changed, 154 insertions(+), 8 deletions(-) diff --git a/include/net/bluetooth/hci_core.h b/include/net/bluetooth/hci_core.h index 4d69dcfebd63..c2a8b1163c30 100644 --- a/include/net/bluetooth/hci_core.h +++ b/include/net/bluetooth/hci_core.h @@ -258,6 +258,15 @@ struct adv_info { #define HCI_ADV_TX_POWER_NO_PREFERENCE 0x7F +struct monitored_device { + struct list_head list; + + bdaddr_t bdaddr; + __u8 addr_type; + __u16 handle; + bool notified; +}; + struct adv_pattern { struct list_head list; __u8 ad_type; @@ -590,6 +599,8 @@ struct hci_dev { struct delayed_work interleave_scan; + struct list_head monitored_devices; + #if IS_ENABLED(CONFIG_BT_LEDS) struct led_trigger *power_led; #endif diff --git a/net/bluetooth/hci_core.c b/net/bluetooth/hci_core.c index 38063bf1fdc5..c67e6d40c97d 100644 --- a/net/bluetooth/hci_core.c +++ b/net/bluetooth/hci_core.c @@ -2503,6 +2503,7 @@ struct hci_dev *hci_alloc_dev_priv(int sizeof_priv) INIT_LIST_HEAD(&hdev->conn_hash.list); INIT_LIST_HEAD(&hdev->adv_instances); INIT_LIST_HEAD(&hdev->blocked_keys); + INIT_LIST_HEAD(&hdev->monitored_devices); INIT_LIST_HEAD(&hdev->local_codecs); INIT_WORK(&hdev->rx_work, hci_rx_work); diff --git a/net/bluetooth/msft.c b/net/bluetooth/msft.c index 6a943634b31a..a2e1cfb5d5d0 100644 --- a/net/bluetooth/msft.c +++ b/net/bluetooth/msft.c @@ -80,6 +80,14 @@ struct msft_rp_le_set_advertisement_filter_enable { __u8 sub_opcode; } __packed; +#define MSFT_EV_LE_MONITOR_DEVICE 0x02 +struct msft_ev_le_monitor_device { + __u8 addr_type; + bdaddr_t bdaddr; + __u8 monitor_handle; + __u8 monitor_state; +} __packed; + struct msft_monitor_advertisement_handle_data { __u8 msft_handle; __u16 mgmt_handle; @@ -266,6 +274,7 @@ static void msft_le_cancel_monitor_advertisement_cb(struct hci_dev *hdev, struct msft_data *msft = hdev->msft_data; int err; bool pending; + struct monitored_device *dev, *tmp; if (status) goto done; @@ -294,6 +303,15 @@ static void msft_le_cancel_monitor_advertisement_cb(struct hci_dev *hdev, if (monitor && !msft->suspending) hci_free_adv_monitor(hdev, monitor); + /* Clear any monitored devices by this Adv Monitor */ + list_for_each_entry_safe(dev, tmp, &hdev->monitored_devices, + list) { + if (dev->handle == handle_data->mgmt_handle) { + list_del(&dev->list); + kfree(dev); + } + } + list_del(&handle_data->list); kfree(handle_data); } @@ -538,6 +556,7 @@ void msft_do_close(struct hci_dev *hdev) struct msft_data *msft = hdev->msft_data; struct msft_monitor_advertisement_handle_data *handle_data, *tmp; struct adv_monitor *monitor; + struct monitored_device *dev, *tmp_dev; if (!msft) return; @@ -557,6 +576,16 @@ void msft_do_close(struct hci_dev *hdev) list_del(&handle_data->list); kfree(handle_data); } + + hci_dev_lock(hdev); + + /* Clear any devices that are being monitored */ + list_for_each_entry_safe(dev, tmp_dev, &hdev->monitored_devices, list) { + list_del(&dev->list); + kfree(dev); + } + + hci_dev_unlock(hdev); } void msft_register(struct hci_dev *hdev) @@ -590,10 +619,103 @@ void msft_unregister(struct hci_dev *hdev) kfree(msft); } +/* This function requires the caller holds hdev->lock */ +static void msft_device_found(struct hci_dev *hdev, bdaddr_t *bdaddr, + __u8 addr_type, __u16 mgmt_handle) +{ + struct monitored_device *dev; + + dev = kmalloc(sizeof(*dev), GFP_KERNEL); + if (!dev) { + bt_dev_err(hdev, "MSFT vendor event %u: no memory", + MSFT_EV_LE_MONITOR_DEVICE); + return; + } + + bacpy(&dev->bdaddr, bdaddr); + dev->addr_type = addr_type; + dev->handle = mgmt_handle; + dev->notified = false; + + INIT_LIST_HEAD(&dev->list); + list_add(&dev->list, &hdev->monitored_devices); +} + +/* This function requires the caller holds hdev->lock */ +static void msft_device_lost(struct hci_dev *hdev, bdaddr_t *bdaddr, + __u8 addr_type, __u16 mgmt_handle) +{ + struct monitored_device *dev, *tmp; + + list_for_each_entry_safe(dev, tmp, &hdev->monitored_devices, list) { + if (dev->handle == mgmt_handle) { + list_del(&dev->list); + kfree(dev); + + break; + } + } +} + +static void *msft_skb_pull(struct hci_dev *hdev, struct sk_buff *skb, + u8 ev, size_t len) +{ + void *data; + + data = skb_pull_data(skb, len); + if (!data) + bt_dev_err(hdev, "Malformed MSFT vendor event: 0x%02x", ev); + + return data; +} + +/* This function requires the caller holds hdev->lock */ +static void msft_monitor_device_evt(struct hci_dev *hdev, struct sk_buff *skb) +{ + struct msft_ev_le_monitor_device *ev; + struct msft_monitor_advertisement_handle_data *handle_data; + u8 addr_type; + + ev = msft_skb_pull(hdev, skb, MSFT_EV_LE_MONITOR_DEVICE, sizeof(*ev)); + if (!ev) + return; + + bt_dev_dbg(hdev, + "MSFT vendor event 0x%02x: handle 0x%04x state %d addr %pMR", + MSFT_EV_LE_MONITOR_DEVICE, ev->monitor_handle, + ev->monitor_state, &ev->bdaddr); + + handle_data = msft_find_handle_data(hdev, ev->monitor_handle, false); + + switch (ev->addr_type) { + case ADDR_LE_DEV_PUBLIC: + addr_type = BDADDR_LE_PUBLIC; + break; + + case ADDR_LE_DEV_RANDOM: + addr_type = BDADDR_LE_RANDOM; + break; + + default: + bt_dev_err(hdev, + "MSFT vendor event 0x%02x: unknown addr type 0x%02x", + MSFT_EV_LE_MONITOR_DEVICE, ev->addr_type); + return; + } + + if (ev->monitor_state) + msft_device_found(hdev, &ev->bdaddr, addr_type, + handle_data->mgmt_handle); + else + msft_device_lost(hdev, &ev->bdaddr, addr_type, + handle_data->mgmt_handle); +} + void msft_vendor_evt(struct hci_dev *hdev, void *data, struct sk_buff *skb) { struct msft_data *msft = hdev->msft_data; - u8 event; + u8 *evt_prefix; + u8 *evt; if (!msft) return; @@ -602,13 +724,12 @@ void msft_vendor_evt(struct hci_dev *hdev, void *data, struct sk_buff *skb) * matches, and otherwise just return. */ if (msft->evt_prefix_len > 0) { - if (skb->len < msft->evt_prefix_len) + evt_prefix = msft_skb_pull(hdev, skb, 0, msft->evt_prefix_len); + if (!evt_prefix) return; - if (memcmp(skb->data, msft->evt_prefix, msft->evt_prefix_len)) + if (memcmp(evt_prefix, msft->evt_prefix, msft->evt_prefix_len)) return; - - skb_pull(skb, msft->evt_prefix_len); } /* Every event starts at least with an event code and the rest of @@ -617,10 +738,23 @@ void msft_vendor_evt(struct hci_dev *hdev, void *data, struct sk_buff *skb) if (skb->len < 1) return; - event = *skb->data; - skb_pull(skb, 1); + hci_dev_lock(hdev); + + evt = msft_skb_pull(hdev, skb, 0, sizeof(*evt)); + if (!evt) + return; + + switch (*evt) { + case MSFT_EV_LE_MONITOR_DEVICE: + msft_monitor_device_evt(hdev, skb); + break; - bt_dev_dbg(hdev, "MSFT vendor event %u", event); + default: + bt_dev_dbg(hdev, "MSFT vendor event 0x%02x", *evt); + break; + } + + hci_dev_unlock(hdev); } __u64 msft_get_features(struct hci_dev *hdev) From patchwork Thu Dec 16 12:49:55 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Manish Mandlik X-Patchwork-Id: 12680987 X-Patchwork-Delegate: kuba@kernel.org Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id C60C1C433EF for ; Thu, 16 Dec 2021 12:50:08 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S236956AbhLPMuH (ORCPT ); Thu, 16 Dec 2021 07:50:07 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:47750 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S234267AbhLPMuE (ORCPT ); Thu, 16 Dec 2021 07:50:04 -0500 Received: from mail-yb1-xb49.google.com (mail-yb1-xb49.google.com [IPv6:2607:f8b0:4864:20::b49]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 178A4C061574 for ; Thu, 16 Dec 2021 04:50:04 -0800 (PST) Received: by mail-yb1-xb49.google.com with SMTP id b15-20020a25ae8f000000b005c20f367790so49521108ybj.2 for ; Thu, 16 Dec 2021 04:50:04 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20210112; h=date:in-reply-to:message-id:mime-version:references:subject:from:to :cc; bh=4E46wH3yvcuVYAB7a18vEgINbxOyjE1Nt6ME7Foq9JU=; b=m7uC2w8pfP0RNfizHcNxfi3qgcR4Gm7ltAtaF8eUGGeXSl8bLOElBzOqEyrzKT/+WM wIeEAKcbk7D+ZvsIA85HutMcEpRffcYWZC7GL5bgrUGWtqRKSDyPpmFii7djkuVtmt1A oHTafZQ0l+m7LBRX14Di/8iURQZz8AZlDs3hBBcQUPGKxAEHKADqNtKLYqDnGwNc4dbQ PtqNcgvf0wTS4/iGXkXNaROB1F4fY8bBv3e99VXViAJ3wZFVviMahA5A7TB3iDEExqzN mbP4r7my9C6Rtlutcbb/hksX9/EIq2gAgeb7VwJMQH7ve6j1E2VP9dAHdr9pbYcSqcnl XK1Q== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=x-gm-message-state:date:in-reply-to:message-id:mime-version :references:subject:from:to:cc; bh=4E46wH3yvcuVYAB7a18vEgINbxOyjE1Nt6ME7Foq9JU=; b=RminvMLWrWbFVHYceIU56DR5pcokUobN+4r6Ri9ZldkR8Q8LuutmVftqrpdZOHiq9c tw50UH+rQnLmMXQuUhkr2VfkIbwbdOfUcZfcqg6hab+fBauBokUMOpqoZEZtvDs5GTW3 e5cB8UF3hNUr04VqTgRbevJy5M+kzs8dBepRQzNmrBdVfZ+zfmq0CCM+Dv7cPsiLjp5Y iwujzWdUtsDlXf32PxXcqhv7FR7FbPOguejfPhPI537atj4ad2vxk00mxEQQYdpiR5pD 8D8DbuHvEkf0fmgqMIqxjx8yzcDnZ/5XgTCb+7btHF/N0V2XOzeuIK5Nd9vo5nD9Bgi4 FPEQ== X-Gm-Message-State: AOAM53121W6AlTa20lhneTpNAo81N7G4jRJFZ6xYWf5O0U7nYj9SW0X9 zpnXP5WcMy0LTqSdJzaOp9YHbTrQJLLAqQ== X-Google-Smtp-Source: ABdhPJyS/SwSK7zhuZYNsgo5Gcbdjn6HjsXhhVX+fbFa4ysZEu2I7EVbH3ljSmWRiNYjJVL6jDyDLI4RKyL6DQ== X-Received: from mmandlik.mtv.corp.google.com ([2620:15c:202:201:bfe1:d4f7:bb68:8aa6]) (user=mmandlik job=sendgmr) by 2002:a25:287:: with SMTP id 129mr13756470ybc.524.1639659003289; Thu, 16 Dec 2021 04:50:03 -0800 (PST) Date: Thu, 16 Dec 2021 04:49:55 -0800 In-Reply-To: <20211216044839.v9.1.Ic0a40b84dee3825302890aaea690e73165c71820@changeid> Message-Id: <20211216044839.v9.2.I9eda306e4c542010535dc49b5488946af592795e@changeid> Mime-Version: 1.0 References: <20211216044839.v9.1.Ic0a40b84dee3825302890aaea690e73165c71820@changeid> X-Mailer: git-send-email 2.34.1.173.g76aa8bc2d0-goog Subject: [PATCH v9 2/3] bluetooth: mgmt: Add MGMT Adv Monitor Device Found/Lost events From: Manish Mandlik To: marcel@holtmann.org, luiz.dentz@gmail.com Cc: chromeos-bluetooth-upstreaming@chromium.org, linux-bluetooth@vger.kernel.org, Manish Mandlik , Miao-chen Chou , "David S. Miller" , Jakub Kicinski , Johan Hedberg , linux-kernel@vger.kernel.org, netdev@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: netdev@vger.kernel.org X-Patchwork-Delegate: kuba@kernel.org This patch introduces two new MGMT events for notifying the bluetoothd whenever the controller starts/stops monitoring a device. 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. Signed-off-by: Manish Mandlik Reviewed-by: Miao-chen Chou --- (no changes since v8) Changes in v8: - Refactor mgmt_adv_monitor_device_found() to make use of skb_put/skb_put_data. Changes in v7: - Refactor mgmt_device_found() to fix stack frame size limit Changes in v6: - Fix compiler warning for mgmt_adv_monitor_device_found(). Changes in v5: - New patch in the series. Split previous patch into two. - Update the Device Found logic to send existing Device Found event or Adv Monitor Device Found event depending on the active scanning state. include/net/bluetooth/hci_core.h | 3 + include/net/bluetooth/mgmt.h | 16 +++++ net/bluetooth/mgmt.c | 115 +++++++++++++++++++++++++++++-- net/bluetooth/msft.c | 15 +++- 4 files changed, 143 insertions(+), 6 deletions(-) diff --git a/include/net/bluetooth/hci_core.h b/include/net/bluetooth/hci_core.h index c2a8b1163c30..290b8a1ac0f9 100644 --- a/include/net/bluetooth/hci_core.h +++ b/include/net/bluetooth/hci_core.h @@ -600,6 +600,7 @@ struct hci_dev { struct delayed_work interleave_scan; struct list_head monitored_devices; + bool advmon_pend_notify; #if IS_ENABLED(CONFIG_BT_LEDS) struct led_trigger *power_led; @@ -1852,6 +1853,8 @@ void mgmt_adv_monitor_removed(struct hci_dev *hdev, u16 handle); int mgmt_phy_configuration_changed(struct hci_dev *hdev, struct sock *skip); int mgmt_add_adv_patterns_monitor_complete(struct hci_dev *hdev, u8 status); int mgmt_remove_adv_monitor_complete(struct hci_dev *hdev, u8 status); +void mgmt_adv_monitor_device_lost(struct hci_dev *hdev, u16 handle, + bdaddr_t *bdaddr, u8 addr_type); u8 hci_le_conn_update(struct hci_conn *conn, u16 min, u16 max, u16 latency, u16 to_multiplier); diff --git a/include/net/bluetooth/mgmt.h b/include/net/bluetooth/mgmt.h index 107b25deae68..99266f7aebdc 100644 --- a/include/net/bluetooth/mgmt.h +++ b/include/net/bluetooth/mgmt.h @@ -1104,3 +1104,19 @@ struct mgmt_ev_controller_resume { #define MGMT_WAKE_REASON_NON_BT_WAKE 0x0 #define MGMT_WAKE_REASON_UNEXPECTED 0x1 #define MGMT_WAKE_REASON_REMOTE_WAKE 0x2 + +#define MGMT_EV_ADV_MONITOR_DEVICE_FOUND 0x002f +struct mgmt_ev_adv_monitor_device_found { + __le16 monitor_handle; + struct mgmt_addr_info addr; + __s8 rssi; + __le32 flags; + __le16 eir_len; + __u8 eir[0]; +} __packed; + +#define MGMT_EV_ADV_MONITOR_DEVICE_LOST 0x0030 +struct mgmt_ev_adv_monitor_device_lost { + __le16 monitor_handle; + struct mgmt_addr_info addr; +} __packed; diff --git a/net/bluetooth/mgmt.c b/net/bluetooth/mgmt.c index e931e417d3e1..c65247b5896c 100644 --- a/net/bluetooth/mgmt.c +++ b/net/bluetooth/mgmt.c @@ -174,6 +174,8 @@ static const u16 mgmt_events[] = { MGMT_EV_ADV_MONITOR_REMOVED, MGMT_EV_CONTROLLER_SUSPEND, MGMT_EV_CONTROLLER_RESUME, + MGMT_EV_ADV_MONITOR_DEVICE_FOUND, + MGMT_EV_ADV_MONITOR_DEVICE_LOST, }; static const u16 mgmt_untrusted_commands[] = { @@ -9562,12 +9564,116 @@ static bool is_filter_match(struct hci_dev *hdev, s8 rssi, u8 *eir, return true; } +void mgmt_adv_monitor_device_lost(struct hci_dev *hdev, u16 handle, + bdaddr_t *bdaddr, u8 addr_type) +{ + struct mgmt_ev_adv_monitor_device_lost ev; + + ev.monitor_handle = cpu_to_le16(handle); + bacpy(&ev.addr.bdaddr, bdaddr); + ev.addr.type = addr_type; + + mgmt_event(MGMT_EV_ADV_MONITOR_DEVICE_LOST, hdev, &ev, sizeof(ev), + NULL); +} + +static void mgmt_adv_monitor_device_found(struct hci_dev *hdev, + bdaddr_t *bdaddr, bool report_device, + struct sk_buff *skb, + struct sock *skip_sk) +{ + struct sk_buff *advmon_skb; + size_t advmon_skb_len; + __le16 *monitor_handle; + struct monitored_device *dev, *tmp; + bool matched = false; + bool notify = false; + + /* We have received the Advertisement Report because: + * 1. the kernel has initiated active discovery + * 2. if not, we have pend_le_reports > 0 in which case we are doing + * passive scanning + * 3. if none of the above is true, we have one or more active + * Advertisement Monitor + * + * For case 1 and 2, report all advertisements via MGMT_EV_DEVICE_FOUND + * and report ONLY one advertisement per device for the matched Monitor + * via MGMT_EV_ADV_MONITOR_DEVICE_FOUND event. + * + * For case 3, since we are not active scanning and all advertisements + * received are due to a matched Advertisement Monitor, report all + * advertisements ONLY via MGMT_EV_ADV_MONITOR_DEVICE_FOUND event. + */ + if (report_device && !hdev->advmon_pend_notify) { + mgmt_event_skb(skb, skip_sk); + return; + } + + advmon_skb_len = (sizeof(struct mgmt_ev_adv_monitor_device_found) - + sizeof(struct mgmt_ev_device_found)) + skb->len; + advmon_skb = mgmt_alloc_skb(hdev, MGMT_EV_ADV_MONITOR_DEVICE_FOUND, + advmon_skb_len); + if (!advmon_skb) { + if (report_device) + mgmt_event_skb(skb, skip_sk); + else + kfree_skb(skb); + return; + } + + /* ADV_MONITOR_DEVICE_FOUND is similar to DEVICE_FOUND event except + * that it also has 'monitor_handle'. Make a copy of DEVICE_FOUND and + * store monitor_handle of the matched monitor. + */ + monitor_handle = skb_put(advmon_skb, sizeof(*monitor_handle)); + skb_put_data(advmon_skb, skb->data, skb->len); + + hdev->advmon_pend_notify = false; + + list_for_each_entry_safe(dev, tmp, &hdev->monitored_devices, list) { + if (!bacmp(&dev->bdaddr, bdaddr)) { + matched = true; + + if (!dev->notified) { + *monitor_handle = cpu_to_le16(dev->handle); + notify = true; + dev->notified = true; + } + } + + if (!dev->notified) + hdev->advmon_pend_notify = true; + } + + if (!report_device && + ((matched && !notify) || !msft_monitor_supported(hdev))) { + /* Handle 0 indicates that we are not active scanning and this + * is a subsequent advertisement report for an already matched + * Advertisement Monitor or the controller offloading support + * is not available. + */ + *monitor_handle = 0; + notify = true; + } + + if (report_device) + mgmt_event_skb(skb, skip_sk); + else + kfree_skb(skb); + + if (notify) + mgmt_event_skb(advmon_skb, skip_sk); + else + kfree_skb(advmon_skb); +} + void mgmt_device_found(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 link_type, u8 addr_type, u8 *dev_class, s8 rssi, u32 flags, u8 *eir, u16 eir_len, u8 *scan_rsp, u8 scan_rsp_len) { struct sk_buff *skb; struct mgmt_ev_device_found *ev; + bool report_device = hci_discovery_active(hdev); /* Don't send events for a non-kernel initiated discovery. With * LE one exception is if we have pend_le_reports > 0 in which @@ -9576,11 +9682,10 @@ void mgmt_device_found(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 link_type, if (!hci_discovery_active(hdev)) { if (link_type == ACL_LINK) return; - if (link_type == LE_LINK && - list_empty(&hdev->pend_le_reports) && - !hci_is_adv_monitoring(hdev)) { + if (link_type == LE_LINK && !list_empty(&hdev->pend_le_reports)) + report_device = true; + else if (!hci_is_adv_monitoring(hdev)) return; - } } if (hdev->discovery.result_filtering) { @@ -9645,7 +9750,7 @@ void mgmt_device_found(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 link_type, ev->eir_len = cpu_to_le16(eir_len + scan_rsp_len); - mgmt_event_skb(skb, NULL); + mgmt_adv_monitor_device_found(hdev, bdaddr, report_device, skb, NULL); } void mgmt_remote_name(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 link_type, diff --git a/net/bluetooth/msft.c b/net/bluetooth/msft.c index a2e1cfb5d5d0..d507faa9626a 100644 --- a/net/bluetooth/msft.c +++ b/net/bluetooth/msft.c @@ -579,8 +579,16 @@ void msft_do_close(struct hci_dev *hdev) hci_dev_lock(hdev); - /* Clear any devices that are being monitored */ + /* Clear any devices that are being monitored and notify device lost */ + + hdev->advmon_pend_notify = false; + list_for_each_entry_safe(dev, tmp_dev, &hdev->monitored_devices, list) { + if (dev->notified) + mgmt_adv_monitor_device_lost(hdev, dev->handle, + &dev->bdaddr, + dev->addr_type); + list_del(&dev->list); kfree(dev); } @@ -639,6 +647,7 @@ static void msft_device_found(struct hci_dev *hdev, bdaddr_t *bdaddr, INIT_LIST_HEAD(&dev->list); list_add(&dev->list, &hdev->monitored_devices); + hdev->advmon_pend_notify = true; } /* This function requires the caller holds hdev->lock */ @@ -649,6 +658,10 @@ static void msft_device_lost(struct hci_dev *hdev, bdaddr_t *bdaddr, list_for_each_entry_safe(dev, tmp, &hdev->monitored_devices, list) { if (dev->handle == mgmt_handle) { + if (dev->notified) + mgmt_adv_monitor_device_lost(hdev, mgmt_handle, + bdaddr, addr_type); + list_del(&dev->list); kfree(dev); From patchwork Thu Dec 16 12:49:56 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Manish Mandlik X-Patchwork-Id: 12680989 X-Patchwork-Delegate: kuba@kernel.org Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 7A41BC433EF for ; Thu, 16 Dec 2021 12:50:12 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S236984AbhLPMuK (ORCPT ); Thu, 16 Dec 2021 07:50:10 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:47778 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S236971AbhLPMuH (ORCPT ); Thu, 16 Dec 2021 07:50:07 -0500 Received: from mail-yb1-xb4a.google.com (mail-yb1-xb4a.google.com [IPv6:2607:f8b0:4864:20::b4a]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id CC91FC06173E for ; Thu, 16 Dec 2021 04:50:06 -0800 (PST) Received: by mail-yb1-xb4a.google.com with SMTP id r18-20020a25ac52000000b005c9047c420bso49573876ybd.4 for ; Thu, 16 Dec 2021 04:50:06 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20210112; h=date:in-reply-to:message-id:mime-version:references:subject:from:to :cc; bh=S1nY8qFye4VS7aI2Ex7vC+CRaOMsD5vumGdm2AeuvSo=; b=eaQA7mpwTk0w1lXjaNNBuByro3X9DWSPaEGaCBrG2HEoWuHYnCO5SmYbRZ8Kxy0fQE pkmO6NEQoTw1x9Z90TmxH9X6b+IlZf7qfOhS39tNwU5Rr2php84TMasxONNrr7GMQzss VqNfTMoX5e3ZusQuLQU5VQ54SUFbLp0wPrWQW4FOCKEN866ij5pIEz260r6XGcin+wGI eaQqy0bjo4uTKh1k4DvFa7FFtRUU0GU6y6qRzhu1wrSkCEU5GtCBYk6583AVq6IjC3Gl q6E6Vc2n6AFCnH7KQkMVEGD0K5f4+kXf0lmaJxtnZersQrT7BLqL2VjsOFaI9o4NL64n pDVg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=x-gm-message-state:date:in-reply-to:message-id:mime-version :references:subject:from:to:cc; bh=S1nY8qFye4VS7aI2Ex7vC+CRaOMsD5vumGdm2AeuvSo=; b=kG+mTi2ZZCfXky7eA7pCdodmkwU32coAcJ1d2z57Y0f4oLbJWetJbuFSEqFN5wuYe5 MCCRI9REpSPKDhpzMM3g5EHAy3UdN2R33niJpXM8w2AY5UUnQ1NB4Uusij2Nx/EUMIZs oGgVH3io8mE7Lp+VXGuXFJsLyW8FaAan+sHxKeBNfhjd4NQuSVoVTvKk1uHCSSgiC2a7 hnBlbv5AH45Giy+V+bsdc8YdYREeO8Ybu+Y33yHXewzIhrIuaRRtIkgAnvALMzmaWeBq OVyXqydlTF8V2t0s7SI/TD3BIfajn4nf9V+AYVGOGceerLl8ErvDmN33Lm3rnEMjkZBN oH2g== X-Gm-Message-State: AOAM530eDgJZUntAMnIzYXEghK2JZ9gkLUOLH9gKExRLlX4qJqp5Cl5+ SQTgItwb+2ze8sQd8UQyFZ2cNupzZE0jvw== X-Google-Smtp-Source: ABdhPJzXci8bvwLqg5dOpNylp6qY3iTOWvjUI2Myi0SZDl+iOaJlDImmnRQk1rWVBvDLJuGK5qJ5tyqiNUkQlw== X-Received: from mmandlik.mtv.corp.google.com ([2620:15c:202:201:bfe1:d4f7:bb68:8aa6]) (user=mmandlik job=sendgmr) by 2002:a05:6902:154c:: with SMTP id r12mr13928990ybu.374.1639659005967; Thu, 16 Dec 2021 04:50:05 -0800 (PST) Date: Thu, 16 Dec 2021 04:49:56 -0800 In-Reply-To: <20211216044839.v9.1.Ic0a40b84dee3825302890aaea690e73165c71820@changeid> Message-Id: <20211216044839.v9.3.If37d23d1dd8b765d8a6c8eca71ac1c29df591565@changeid> Mime-Version: 1.0 References: <20211216044839.v9.1.Ic0a40b84dee3825302890aaea690e73165c71820@changeid> X-Mailer: git-send-email 2.34.1.173.g76aa8bc2d0-goog Subject: [PATCH v9 3/3] bluetooth: mgmt: Fix sizeof in mgmt_device_found() From: Manish Mandlik To: marcel@holtmann.org, luiz.dentz@gmail.com Cc: chromeos-bluetooth-upstreaming@chromium.org, linux-bluetooth@vger.kernel.org, Manish Mandlik , "David S. Miller" , Jakub Kicinski , Johan Hedberg , linux-kernel@vger.kernel.org, netdev@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: netdev@vger.kernel.org X-Patchwork-Delegate: kuba@kernel.org Use correct sizeof() parameter while allocating skb. Signed-off-by: Manish Mandlik --- (no changes since v8) Changes in v8: - New patch in the series. net/bluetooth/mgmt.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/net/bluetooth/mgmt.c b/net/bluetooth/mgmt.c index c65247b5896c..5fd29bd399f1 100644 --- a/net/bluetooth/mgmt.c +++ b/net/bluetooth/mgmt.c @@ -9709,7 +9709,7 @@ void mgmt_device_found(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 link_type, /* Allocate skb. The 5 extra bytes are for the potential CoD field */ skb = mgmt_alloc_skb(hdev, MGMT_EV_DEVICE_FOUND, - sizeof(ev) + eir_len + scan_rsp_len + 5); + sizeof(*ev) + eir_len + scan_rsp_len + 5); if (!skb) return;