lkml.org 
[lkml]   [2020]   [Jun]   [15]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
Patch in this message
/
From
Subject[PATCH v5 3/7] Bluetooth: Add handler of MGMT_OP_ADD_ADV_PATTERNS_MONITOR
Date
This adds the request handler of MGMT_OP_ADD_ADV_PATTERNS_MONITOR command.
Note that the controller-based monitoring is not yet in place. This tracks
the content of the monitor without sending HCI traffic, so the request
returns immediately.

The following manual test was performed.
- Issue btmgmt advmon-add with valid and invalid inputs.
- Issue btmgmt advmon-add more the allowed number of monitors.

Signed-off-by: Miao-chen Chou <mcchou@chromium.org>
---

Changes in v5: None
Changes in v4: None
Changes in v3:
- Update the opcode in the mgmt table.
- Convert the endianness of the returned handle.

Changes in v2: None

include/net/bluetooth/hci_core.h | 2 +
net/bluetooth/hci_core.c | 40 +++++++++++++
net/bluetooth/mgmt.c | 100 +++++++++++++++++++++++++++++++
3 files changed, 142 insertions(+)

diff --git a/include/net/bluetooth/hci_core.h b/include/net/bluetooth/hci_core.h
index 431fe0265dcfb..862d94f711bc0 100644
--- a/include/net/bluetooth/hci_core.h
+++ b/include/net/bluetooth/hci_core.h
@@ -1240,6 +1240,8 @@ int hci_remove_adv_instance(struct hci_dev *hdev, u8 instance);
void hci_adv_instances_set_rpa_expired(struct hci_dev *hdev, bool rpa_expired);

void hci_adv_monitors_clear(struct hci_dev *hdev);
+void hci_free_adv_monitor(struct adv_monitor *monitor);
+int hci_add_adv_monitor(struct hci_dev *hdev, struct adv_monitor *monitor);

void hci_event_packet(struct hci_dev *hdev, struct sk_buff *skb);

diff --git a/net/bluetooth/hci_core.c b/net/bluetooth/hci_core.c
index bfcf00e4dfa92..fdbb58eb2fb22 100644
--- a/net/bluetooth/hci_core.c
+++ b/net/bluetooth/hci_core.c
@@ -2998,9 +2998,49 @@ int hci_add_adv_instance(struct hci_dev *hdev, u8 instance, u32 flags,
/* This function requires the caller holds hdev->lock */
void hci_adv_monitors_clear(struct hci_dev *hdev)
{
+ struct adv_monitor *monitor;
+ int handle;
+
+ idr_for_each_entry(&hdev->adv_monitors_idr, monitor, handle)
+ hci_free_adv_monitor(monitor);
+
idr_destroy(&hdev->adv_monitors_idr);
}

+void hci_free_adv_monitor(struct adv_monitor *monitor)
+{
+ struct adv_pattern *pattern;
+ struct adv_pattern *tmp;
+
+ if (!monitor)
+ return;
+
+ list_for_each_entry_safe(pattern, tmp, &monitor->patterns, list)
+ kfree(pattern);
+
+ kfree(monitor);
+}
+
+/* This function requires the caller holds hdev->lock */
+int hci_add_adv_monitor(struct hci_dev *hdev, struct adv_monitor *monitor)
+{
+ int min, max, handle;
+
+ if (!monitor)
+ return -EINVAL;
+
+ min = HCI_MIN_ADV_MONITOR_HANDLE;
+ max = HCI_MIN_ADV_MONITOR_HANDLE + HCI_MAX_ADV_MONITOR_NUM_HANDLES;
+ handle = idr_alloc(&hdev->adv_monitors_idr, monitor, min, max,
+ GFP_KERNEL);
+ if (handle < 0)
+ return handle;
+
+ hdev->adv_monitors_cnt++;
+ monitor->handle = handle;
+ return 0;
+}
+
struct bdaddr_list *hci_bdaddr_list_lookup(struct list_head *bdaddr_list,
bdaddr_t *bdaddr, u8 type)
{
diff --git a/net/bluetooth/mgmt.c b/net/bluetooth/mgmt.c
index 63536d6332d45..8e0d4ccf81f15 100644
--- a/net/bluetooth/mgmt.c
+++ b/net/bluetooth/mgmt.c
@@ -113,6 +113,7 @@ static const u16 mgmt_commands[] = {
MGMT_OP_READ_EXP_FEATURES_INFO,
MGMT_OP_SET_EXP_FEATURE,
MGMT_OP_READ_ADV_MONITOR_FEATURES,
+ MGMT_OP_ADD_ADV_PATTERNS_MONITOR,
};

static const u16 mgmt_events[] = {
@@ -3896,6 +3897,103 @@ static int read_adv_monitor_features(struct sock *sk, struct hci_dev *hdev,
MGMT_STATUS_SUCCESS, rp, rp_size);
}

+static int add_adv_patterns_monitor(struct sock *sk, struct hci_dev *hdev,
+ void *data, u16 len)
+{
+ struct mgmt_cp_add_adv_patterns_monitor *cp = data;
+ struct mgmt_rp_add_adv_patterns_monitor rp;
+ struct adv_monitor *m = NULL;
+ struct adv_pattern *p = NULL;
+ __u8 cp_ofst = 0, cp_len = 0;
+ unsigned int mp_cnt = 0;
+ int err, i;
+
+ BT_DBG("request for %s", hdev->name);
+
+ if (len <= sizeof(*cp) || cp->pattern_count == 0) {
+ err = mgmt_cmd_status(sk, hdev->id,
+ MGMT_OP_ADD_ADV_PATTERNS_MONITOR,
+ MGMT_STATUS_INVALID_PARAMS);
+ goto failed;
+ }
+
+ m = kmalloc(sizeof(*m), GFP_KERNEL);
+ if (!m) {
+ err = -ENOMEM;
+ goto failed;
+ }
+
+ INIT_LIST_HEAD(&m->patterns);
+ m->active = false;
+
+ for (i = 0; i < cp->pattern_count; i++) {
+ if (++mp_cnt > HCI_MAX_ADV_MONITOR_NUM_PATTERNS) {
+ err = mgmt_cmd_status(sk, hdev->id,
+ MGMT_OP_ADD_ADV_PATTERNS_MONITOR,
+ MGMT_STATUS_INVALID_PARAMS);
+ goto failed;
+ }
+
+ cp_ofst = cp->patterns[i].offset;
+ cp_len = cp->patterns[i].length;
+ if (cp_ofst >= HCI_MAX_AD_LENGTH ||
+ cp_len > HCI_MAX_AD_LENGTH ||
+ (cp_ofst + cp_len) > HCI_MAX_AD_LENGTH) {
+ err = mgmt_cmd_status(sk, hdev->id,
+ MGMT_OP_ADD_ADV_PATTERNS_MONITOR,
+ MGMT_STATUS_INVALID_PARAMS);
+ goto failed;
+ }
+
+ p = kmalloc(sizeof(*p), GFP_KERNEL);
+ if (!p) {
+ err = -ENOMEM;
+ goto failed;
+ }
+
+ p->ad_type = cp->patterns[i].ad_type;
+ p->offset = cp->patterns[i].offset;
+ p->length = cp->patterns[i].length;
+ memcpy(p->value, cp->patterns[i].value, p->length);
+
+ INIT_LIST_HEAD(&p->list);
+ list_add(&p->list, &m->patterns);
+ }
+
+ if (mp_cnt != cp->pattern_count) {
+ err = mgmt_cmd_status(sk, hdev->id,
+ MGMT_OP_ADD_ADV_PATTERNS_MONITOR,
+ MGMT_STATUS_INVALID_PARAMS);
+ goto failed;
+ }
+
+ hci_dev_lock(hdev);
+
+ err = hci_add_adv_monitor(hdev, m);
+ if (err) {
+ if (err == -ENOSPC) {
+ mgmt_cmd_status(sk, hdev->id,
+ MGMT_OP_ADD_ADV_PATTERNS_MONITOR,
+ MGMT_STATUS_NO_RESOURCES);
+ }
+ goto unlock;
+ }
+
+ hci_dev_unlock(hdev);
+
+ rp.monitor_handle = cpu_to_le16(m->handle);
+
+ return mgmt_cmd_complete(sk, hdev->id, MGMT_OP_ADD_ADV_PATTERNS_MONITOR,
+ MGMT_STATUS_SUCCESS, &rp, sizeof(rp));
+
+unlock:
+ hci_dev_unlock(hdev);
+
+failed:
+ hci_free_adv_monitor(m);
+ return err;
+}
+
static void read_local_oob_data_complete(struct hci_dev *hdev, u8 status,
u16 opcode, struct sk_buff *skb)
{
@@ -7351,6 +7449,8 @@ static const struct hci_mgmt_handler mgmt_handlers[] = {
{ NULL }, // 0x004F
{ NULL }, // 0x0050
{ read_adv_monitor_features, MGMT_READ_ADV_MONITOR_FEATURES_SIZE },
+ { add_adv_patterns_monitor, MGMT_ADD_ADV_PATTERNS_MONITOR_SIZE,
+ HCI_MGMT_VAR_LEN },
};

void mgmt_index_added(struct hci_dev *hdev)
--
2.26.2
\
 
 \ /
  Last update: 2020-06-16 02:26    [W:0.761 / U:0.520 seconds]
©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site