This is the list of pending patches and fixes merged together. Please
review that the set and functionality is correct and working as
expected.
In v2 the Reviewed-by tags have been added.
Abhishek Pandit-Subedi (4):
Bluetooth: Add bdaddr_list_with_flags for classic whitelist
Bluetooth: Replace wakeable list with flag
Bluetooth: Replace wakeable in hci_conn_params
Bluetooth: Add get/set device flags mgmt op
Manish Mandlik (1):
Bluetooth: Terminate the link if pairing is cancelled
Marcel Holtmann (2):
Bluetooth: mgmt: Add commands for runtime configuration
Bluetooth: mgmt: Use command complete on success for set system config
Miao-chen Chou (7):
Bluetooth: Add definitions for advertisement monitor features
Bluetooth: Add handler of MGMT_OP_READ_ADV_MONITOR_FEATURES
Bluetooth: Add handler of MGMT_OP_ADD_ADV_PATTERNS_MONITOR
Bluetooth: Add handler of MGMT_OP_REMOVE_ADV_MONITOR
Bluetooth: Notify adv monitor added event
Bluetooth: Notify adv monitor removed event
Bluetooth: Update background scan and report device based on
advertisement monitors
include/net/bluetooth/hci_core.h | 73 +++++-
include/net/bluetooth/mgmt.h | 77 +++++++
net/bluetooth/hci_conn.c | 11 +-
net/bluetooth/hci_core.c | 153 ++++++++++++-
net/bluetooth/hci_event.c | 13 +-
net/bluetooth/hci_request.c | 32 ++-
net/bluetooth/l2cap_core.c | 6 +-
net/bluetooth/mgmt.c | 382 ++++++++++++++++++++++++++++++-
net/bluetooth/mgmt_config.c | 23 +-
net/bluetooth/mgmt_config.h | 6 +
net/bluetooth/msft.c | 7 +
net/bluetooth/msft.h | 9 +
12 files changed, 755 insertions(+), 37 deletions(-)
--
2.26.2
The command status reply is only for failure. When completing set system
config command, the reply has to be command complete.
Signed-off-by: Marcel Holtmann <[email protected]>
Reviewed-by: Alain Michaud <[email protected]>
---
net/bluetooth/mgmt_config.c | 5 ++---
1 file changed, 2 insertions(+), 3 deletions(-)
diff --git a/net/bluetooth/mgmt_config.c b/net/bluetooth/mgmt_config.c
index 8e7ad2a51dbb..8d01a8ff85e9 100644
--- a/net/bluetooth/mgmt_config.c
+++ b/net/bluetooth/mgmt_config.c
@@ -247,9 +247,8 @@ int set_def_system_config(struct sock *sk, struct hci_dev *hdev, void *data,
buffer += exp_len;
}
- return mgmt_cmd_status(sk, hdev->id,
- MGMT_OP_SET_DEF_SYSTEM_CONFIG,
- MGMT_STATUS_SUCCESS);
+ return mgmt_cmd_complete(sk, hdev->id,
+ MGMT_OP_SET_DEF_SYSTEM_CONFIG, 0, NULL, 0);
}
int read_def_runtime_config(struct sock *sk, struct hci_dev *hdev, void *data,
--
2.26.2
From: Miao-chen Chou <[email protected]>
This adds the request handler of MGMT_OP_REMOVE_ADV_MONITOR command.
Note that the controller-based monitoring is not yet in place. This
removes the internal monitor(s) without sending HCI traffic, so the
request returns immediately.
The following test was performed.
- Issue btmgmt advmon-remove with valid and invalid handles.
Signed-off-by: Miao-chen Chou <[email protected]>
Signed-off-by: Marcel Holtmann <[email protected]>
---
include/net/bluetooth/hci_core.h | 1 +
net/bluetooth/hci_core.c | 31 ++++++++++++++++++++++++++++
net/bluetooth/mgmt.c | 35 ++++++++++++++++++++++++++++++++
3 files changed, 67 insertions(+)
diff --git a/include/net/bluetooth/hci_core.h b/include/net/bluetooth/hci_core.h
index 13fad419ae7d..c54f9295892e 100644
--- a/include/net/bluetooth/hci_core.h
+++ b/include/net/bluetooth/hci_core.h
@@ -1283,6 +1283,7 @@ 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);
+int hci_remove_adv_monitor(struct hci_dev *hdev, u16 handle);
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 ce481fab349d..59132b3e2cde 100644
--- a/net/bluetooth/hci_core.c
+++ b/net/bluetooth/hci_core.c
@@ -3041,6 +3041,37 @@ int hci_add_adv_monitor(struct hci_dev *hdev, struct adv_monitor *monitor)
return 0;
}
+static int free_adv_monitor(int id, void *ptr, void *data)
+{
+ struct hci_dev *hdev = data;
+ struct adv_monitor *monitor = ptr;
+
+ idr_remove(&hdev->adv_monitors_idr, monitor->handle);
+ hci_free_adv_monitor(monitor);
+
+ return 0;
+}
+
+/* This function requires the caller holds hdev->lock */
+int hci_remove_adv_monitor(struct hci_dev *hdev, u16 handle)
+{
+ struct adv_monitor *monitor;
+
+ if (handle) {
+ monitor = idr_find(&hdev->adv_monitors_idr, handle);
+ if (!monitor)
+ return -ENOENT;
+
+ idr_remove(&hdev->adv_monitors_idr, monitor->handle);
+ hci_free_adv_monitor(monitor);
+ } else {
+ /* Remove all monitors if handle is 0. */
+ idr_for_each(&hdev->adv_monitors_idr, &free_adv_monitor, hdev);
+ }
+
+ 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 1eca36e51706..cff24fde72d2 100644
--- a/net/bluetooth/mgmt.c
+++ b/net/bluetooth/mgmt.c
@@ -121,6 +121,7 @@ static const u16 mgmt_commands[] = {
MGMT_OP_SET_DEVICE_FLAGS,
MGMT_OP_READ_ADV_MONITOR_FEATURES,
MGMT_OP_ADD_ADV_PATTERNS_MONITOR,
+ MGMT_OP_REMOVE_ADV_MONITOR,
};
static const u16 mgmt_events[] = {
@@ -4118,6 +4119,39 @@ static int add_adv_patterns_monitor(struct sock *sk, struct hci_dev *hdev,
return err;
}
+static int remove_adv_monitor(struct sock *sk, struct hci_dev *hdev,
+ void *data, u16 len)
+{
+ struct mgmt_cp_remove_adv_monitor *cp = data;
+ struct mgmt_rp_remove_adv_monitor rp;
+ u16 handle;
+ int err;
+
+ BT_DBG("request for %s", hdev->name);
+
+ hci_dev_lock(hdev);
+
+ handle = __le16_to_cpu(cp->monitor_handle);
+
+ err = hci_remove_adv_monitor(hdev, handle);
+ if (err == -ENOENT) {
+ err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_REMOVE_ADV_MONITOR,
+ MGMT_STATUS_INVALID_INDEX);
+ goto unlock;
+ }
+
+ hci_dev_unlock(hdev);
+
+ rp.monitor_handle = cp->monitor_handle;
+
+ return mgmt_cmd_complete(sk, hdev->id, MGMT_OP_REMOVE_ADV_MONITOR,
+ MGMT_STATUS_SUCCESS, &rp, sizeof(rp));
+
+unlock:
+ hci_dev_unlock(hdev);
+ return err;
+}
+
static void read_local_oob_data_complete(struct hci_dev *hdev, u8 status,
u16 opcode, struct sk_buff *skb)
{
@@ -7589,6 +7623,7 @@ static const struct hci_mgmt_handler mgmt_handlers[] = {
{ read_adv_mon_features, MGMT_READ_ADV_MONITOR_FEATURES_SIZE },
{ add_adv_patterns_monitor,MGMT_ADD_ADV_PATTERNS_MONITOR_SIZE,
HCI_MGMT_VAR_LEN },
+ { remove_adv_monitor, MGMT_REMOVE_ADV_MONITOR_SIZE },
};
void mgmt_index_added(struct hci_dev *hdev)
--
2.26.2
From: Manish Mandlik <[email protected]>
If user decides to cancel the ongoing pairing process (e.g. by clicking
the cancel button on pairing/passkey window), abort any ongoing pairing
and then terminate the link if it was created because of the pair
device action.
Signed-off-by: Manish Mandlik <[email protected]>
Signed-off-by: Marcel Holtmann <[email protected]>
---
include/net/bluetooth/hci_core.h | 14 ++++++++++++--
net/bluetooth/hci_conn.c | 11 ++++++++---
net/bluetooth/l2cap_core.c | 6 ++++--
net/bluetooth/mgmt.c | 22 ++++++++++++++++++----
4 files changed, 42 insertions(+), 11 deletions(-)
diff --git a/include/net/bluetooth/hci_core.h b/include/net/bluetooth/hci_core.h
index 524057598ffd..77d29341b064 100644
--- a/include/net/bluetooth/hci_core.h
+++ b/include/net/bluetooth/hci_core.h
@@ -564,6 +564,12 @@ struct hci_dev {
#define HCI_PHY_HANDLE(handle) (handle & 0xff)
+enum conn_reasons {
+ CONN_REASON_PAIR_DEVICE,
+ CONN_REASON_L2CAP_CHAN,
+ CONN_REASON_SCO_CONNECT,
+};
+
struct hci_conn {
struct list_head list;
@@ -615,6 +621,8 @@ struct hci_conn {
__s8 max_tx_power;
unsigned long flags;
+ enum conn_reasons conn_reason;
+
__u32 clock;
__u16 clock_accuracy;
@@ -1040,12 +1048,14 @@ struct hci_chan *hci_chan_lookup_handle(struct hci_dev *hdev, __u16 handle);
struct hci_conn *hci_connect_le_scan(struct hci_dev *hdev, bdaddr_t *dst,
u8 dst_type, u8 sec_level,
- u16 conn_timeout);
+ u16 conn_timeout,
+ enum conn_reasons conn_reason);
struct hci_conn *hci_connect_le(struct hci_dev *hdev, bdaddr_t *dst,
u8 dst_type, u8 sec_level, u16 conn_timeout,
u8 role, bdaddr_t *direct_rpa);
struct hci_conn *hci_connect_acl(struct hci_dev *hdev, bdaddr_t *dst,
- u8 sec_level, u8 auth_type);
+ u8 sec_level, u8 auth_type,
+ enum conn_reasons conn_reason);
struct hci_conn *hci_connect_sco(struct hci_dev *hdev, int type, bdaddr_t *dst,
__u16 setting);
int hci_conn_check_link_mode(struct hci_conn *conn);
diff --git a/net/bluetooth/hci_conn.c b/net/bluetooth/hci_conn.c
index 9bdffc4e79b0..47f3a45d7dcb 100644
--- a/net/bluetooth/hci_conn.c
+++ b/net/bluetooth/hci_conn.c
@@ -1174,7 +1174,8 @@ static int hci_explicit_conn_params_set(struct hci_dev *hdev,
/* This function requires the caller holds hdev->lock */
struct hci_conn *hci_connect_le_scan(struct hci_dev *hdev, bdaddr_t *dst,
u8 dst_type, u8 sec_level,
- u16 conn_timeout)
+ u16 conn_timeout,
+ enum conn_reasons conn_reason)
{
struct hci_conn *conn;
@@ -1219,6 +1220,7 @@ struct hci_conn *hci_connect_le_scan(struct hci_dev *hdev, bdaddr_t *dst,
conn->sec_level = BT_SECURITY_LOW;
conn->pending_sec_level = sec_level;
conn->conn_timeout = conn_timeout;
+ conn->conn_reason = conn_reason;
hci_update_background_scan(hdev);
@@ -1228,7 +1230,8 @@ struct hci_conn *hci_connect_le_scan(struct hci_dev *hdev, bdaddr_t *dst,
}
struct hci_conn *hci_connect_acl(struct hci_dev *hdev, bdaddr_t *dst,
- u8 sec_level, u8 auth_type)
+ u8 sec_level, u8 auth_type,
+ enum conn_reasons conn_reason)
{
struct hci_conn *acl;
@@ -1248,6 +1251,7 @@ struct hci_conn *hci_connect_acl(struct hci_dev *hdev, bdaddr_t *dst,
hci_conn_hold(acl);
+ acl->conn_reason = conn_reason;
if (acl->state == BT_OPEN || acl->state == BT_CLOSED) {
acl->sec_level = BT_SECURITY_LOW;
acl->pending_sec_level = sec_level;
@@ -1264,7 +1268,8 @@ struct hci_conn *hci_connect_sco(struct hci_dev *hdev, int type, bdaddr_t *dst,
struct hci_conn *acl;
struct hci_conn *sco;
- acl = hci_connect_acl(hdev, dst, BT_SECURITY_LOW, HCI_AT_NO_BONDING);
+ acl = hci_connect_acl(hdev, dst, BT_SECURITY_LOW, HCI_AT_NO_BONDING,
+ CONN_REASON_SCO_CONNECT);
if (IS_ERR(acl))
return acl;
diff --git a/net/bluetooth/l2cap_core.c b/net/bluetooth/l2cap_core.c
index fe913a5c754a..35d2bc569a2d 100644
--- a/net/bluetooth/l2cap_core.c
+++ b/net/bluetooth/l2cap_core.c
@@ -7893,11 +7893,13 @@ int l2cap_chan_connect(struct l2cap_chan *chan, __le16 psm, u16 cid,
else
hcon = hci_connect_le_scan(hdev, dst, dst_type,
chan->sec_level,
- HCI_LE_CONN_TIMEOUT);
+ HCI_LE_CONN_TIMEOUT,
+ CONN_REASON_L2CAP_CHAN);
} else {
u8 auth_type = l2cap_get_auth_type(chan);
- hcon = hci_connect_acl(hdev, dst, chan->sec_level, auth_type);
+ hcon = hci_connect_acl(hdev, dst, chan->sec_level, auth_type,
+ CONN_REASON_L2CAP_CHAN);
}
if (IS_ERR(hcon)) {
diff --git a/net/bluetooth/mgmt.c b/net/bluetooth/mgmt.c
index ec66160a673c..2a732cab1dc9 100644
--- a/net/bluetooth/mgmt.c
+++ b/net/bluetooth/mgmt.c
@@ -2931,7 +2931,7 @@ static int pair_device(struct sock *sk, struct hci_dev *hdev, void *data,
if (cp->addr.type == BDADDR_BREDR) {
conn = hci_connect_acl(hdev, &cp->addr.bdaddr, sec_level,
- auth_type);
+ auth_type, CONN_REASON_PAIR_DEVICE);
} else {
u8 addr_type = le_addr_type(cp->addr.type);
struct hci_conn_params *p;
@@ -2950,9 +2950,9 @@ static int pair_device(struct sock *sk, struct hci_dev *hdev, void *data,
if (p->auto_connect == HCI_AUTO_CONN_EXPLICIT)
p->auto_connect = HCI_AUTO_CONN_DISABLED;
- conn = hci_connect_le_scan(hdev, &cp->addr.bdaddr,
- addr_type, sec_level,
- HCI_LE_CONN_TIMEOUT);
+ conn = hci_connect_le_scan(hdev, &cp->addr.bdaddr, addr_type,
+ sec_level, HCI_LE_CONN_TIMEOUT,
+ CONN_REASON_PAIR_DEVICE);
}
if (IS_ERR(conn)) {
@@ -3053,6 +3053,20 @@ static int cancel_pair_device(struct sock *sk, struct hci_dev *hdev, void *data,
err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_CANCEL_PAIR_DEVICE, 0,
addr, sizeof(*addr));
+
+ /* Since user doesn't want to proceed with the connection, abort any
+ * ongoing pairing and then terminate the link if it was created
+ * because of the pair device action.
+ */
+ if (addr->type == BDADDR_BREDR)
+ hci_remove_link_key(hdev, &addr->bdaddr);
+ else
+ smp_cancel_and_remove_pairing(hdev, &addr->bdaddr,
+ le_addr_type(addr->type));
+
+ if (conn->conn_reason == CONN_REASON_PAIR_DEVICE)
+ hci_abort_conn(conn, HCI_ERROR_REMOTE_USER_TERM);
+
unlock:
hci_dev_unlock(hdev);
return err;
--
2.26.2
From: Miao-chen Chou <[email protected]>
This adds the request handler of MGMT_OP_READ_ADV_MONITOR_FEATURES
command. Since the controller-based monitoring is not yet in place, this
report only the supported features but not the enabled features.
The following test was performed.
- Issuing btmgmt advmon-features.
Signed-off-by: Miao-chen Chou <[email protected]>
Signed-off-by: Marcel Holtmann <[email protected]>
---
include/net/bluetooth/hci_core.h | 24 ++++++++++++++++
net/bluetooth/hci_core.c | 10 ++++++-
net/bluetooth/mgmt.c | 48 ++++++++++++++++++++++++++++++++
net/bluetooth/msft.c | 7 +++++
net/bluetooth/msft.h | 9 ++++++
5 files changed, 97 insertions(+), 1 deletion(-)
diff --git a/include/net/bluetooth/hci_core.h b/include/net/bluetooth/hci_core.h
index 6f88e5d81bd2..4e9d51087674 100644
--- a/include/net/bluetooth/hci_core.h
+++ b/include/net/bluetooth/hci_core.h
@@ -25,6 +25,7 @@
#ifndef __HCI_CORE_H
#define __HCI_CORE_H
+#include <linux/idr.h>
#include <linux/leds.h>
#include <linux/rculist.h>
@@ -237,6 +238,24 @@ struct adv_info {
#define HCI_MAX_ADV_INSTANCES 5
#define HCI_DEFAULT_ADV_DURATION 2
+struct adv_pattern {
+ struct list_head list;
+ __u8 ad_type;
+ __u8 offset;
+ __u8 length;
+ __u8 value[HCI_MAX_AD_LENGTH];
+};
+
+struct adv_monitor {
+ struct list_head patterns;
+ bool active;
+ __u16 handle;
+};
+
+#define HCI_MIN_ADV_MONITOR_HANDLE 1
+#define HCI_MAX_ADV_MONITOR_NUM_HANDLES 32
+#define HCI_MAX_ADV_MONITOR_NUM_PATTERNS 16
+
#define HCI_MAX_SHORT_NAME_LENGTH 10
/* Min encryption key size to match with SMP */
@@ -511,6 +530,9 @@ struct hci_dev {
__u16 adv_instance_timeout;
struct delayed_work adv_instance_expire;
+ struct idr adv_monitors_idr;
+ unsigned int adv_monitors_cnt;
+
__u8 irk[16];
__u32 rpa_timeout;
struct delayed_work rpa_expired;
@@ -1258,6 +1280,8 @@ int hci_add_adv_instance(struct hci_dev *hdev, u8 instance, u32 flags,
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_event_packet(struct hci_dev *hdev, struct sk_buff *skb);
void hci_init_sysfs(struct hci_dev *hdev);
diff --git a/net/bluetooth/hci_core.c b/net/bluetooth/hci_core.c
index 8e01afb2ee8c..53aec32a5850 100644
--- a/net/bluetooth/hci_core.c
+++ b/net/bluetooth/hci_core.c
@@ -26,7 +26,6 @@
/* Bluetooth HCI core. */
#include <linux/export.h>
-#include <linux/idr.h>
#include <linux/rfkill.h>
#include <linux/debugfs.h>
#include <linux/crypto.h>
@@ -2996,6 +2995,12 @@ int hci_add_adv_instance(struct hci_dev *hdev, u8 instance, u32 flags,
return 0;
}
+/* This function requires the caller holds hdev->lock */
+void hci_adv_monitors_clear(struct hci_dev *hdev)
+{
+ idr_destroy(&hdev->adv_monitors_idr);
+}
+
struct bdaddr_list *hci_bdaddr_list_lookup(struct list_head *bdaddr_list,
bdaddr_t *bdaddr, u8 type)
{
@@ -3646,6 +3651,8 @@ int hci_register_dev(struct hci_dev *hdev)
queue_work(hdev->req_workqueue, &hdev->power_on);
+ idr_init(&hdev->adv_monitors_idr);
+
return id;
err_wqueue:
@@ -3716,6 +3723,7 @@ void hci_unregister_dev(struct hci_dev *hdev)
hci_smp_irks_clear(hdev);
hci_remote_oob_data_clear(hdev);
hci_adv_instances_clear(hdev);
+ hci_adv_monitors_clear(hdev);
hci_bdaddr_list_clear(&hdev->le_white_list);
hci_bdaddr_list_clear(&hdev->le_resolv_list);
hci_conn_params_clear_all(hdev);
diff --git a/net/bluetooth/mgmt.c b/net/bluetooth/mgmt.c
index e409ff48e8e6..8aec7fbe9a38 100644
--- a/net/bluetooth/mgmt.c
+++ b/net/bluetooth/mgmt.c
@@ -37,6 +37,7 @@
#include "smp.h"
#include "mgmt_util.h"
#include "mgmt_config.h"
+#include "msft.h"
#define MGMT_VERSION 1
#define MGMT_REVISION 17
@@ -118,6 +119,7 @@ static const u16 mgmt_commands[] = {
MGMT_OP_SET_DEF_RUNTIME_CONFIG,
MGMT_OP_GET_DEVICE_FLAGS,
MGMT_OP_SET_DEVICE_FLAGS,
+ MGMT_OP_READ_ADV_MONITOR_FEATURES,
};
static const u16 mgmt_events[] = {
@@ -3973,6 +3975,51 @@ static int set_device_flags(struct sock *sk, struct hci_dev *hdev, void *data,
&cp->addr, sizeof(cp->addr));
}
+static int read_adv_mon_features(struct sock *sk, struct hci_dev *hdev,
+ void *data, u16 len)
+{
+ struct adv_monitor *monitor = NULL;
+ struct mgmt_rp_read_adv_monitor_features *rp = NULL;
+ int handle;
+ size_t rp_size = 0;
+ __u32 supported = 0;
+ __u16 num_handles = 0;
+ __u16 handles[HCI_MAX_ADV_MONITOR_NUM_HANDLES];
+
+ BT_DBG("request for %s", hdev->name);
+
+ hci_dev_lock(hdev);
+
+ if (msft_get_features(hdev) & MSFT_FEATURE_MASK_LE_ADV_MONITOR)
+ supported |= MGMT_ADV_MONITOR_FEATURE_MASK_OR_PATTERNS;
+
+ idr_for_each_entry(&hdev->adv_monitors_idr, monitor, handle) {
+ handles[num_handles++] = monitor->handle;
+ }
+
+ hci_dev_unlock(hdev);
+
+ rp_size = sizeof(*rp) + (num_handles * sizeof(u16));
+ rp = kmalloc(rp_size, GFP_KERNEL);
+ if (!rp)
+ return -ENOMEM;
+
+ /* Once controller-based monitoring is in place, the enabled_features
+ * should reflect the use.
+ */
+ rp->supported_features = cpu_to_le32(supported);
+ rp->enabled_features = 0;
+ rp->max_num_handles = cpu_to_le16(HCI_MAX_ADV_MONITOR_NUM_HANDLES);
+ rp->max_num_patterns = HCI_MAX_ADV_MONITOR_NUM_PATTERNS;
+ rp->num_handles = cpu_to_le16(num_handles);
+ if (num_handles)
+ memcpy(&rp->handles, &handles, (num_handles * sizeof(u16)));
+
+ return mgmt_cmd_complete(sk, hdev->id,
+ MGMT_OP_READ_ADV_MONITOR_FEATURES,
+ MGMT_STATUS_SUCCESS, rp, rp_size);
+}
+
static void read_local_oob_data_complete(struct hci_dev *hdev, u8 status,
u16 opcode, struct sk_buff *skb)
{
@@ -7441,6 +7488,7 @@ static const struct hci_mgmt_handler mgmt_handlers[] = {
HCI_MGMT_VAR_LEN },
{ get_device_flags, MGMT_GET_DEVICE_FLAGS_SIZE },
{ set_device_flags, MGMT_SET_DEVICE_FLAGS_SIZE },
+ { read_adv_mon_features, MGMT_READ_ADV_MONITOR_FEATURES_SIZE },
};
void mgmt_index_added(struct hci_dev *hdev)
diff --git a/net/bluetooth/msft.c b/net/bluetooth/msft.c
index d6c4e6b5ae77..8579bfeb2836 100644
--- a/net/bluetooth/msft.c
+++ b/net/bluetooth/msft.c
@@ -139,3 +139,10 @@ void msft_vendor_evt(struct hci_dev *hdev, struct sk_buff *skb)
bt_dev_dbg(hdev, "MSFT vendor event %u", event);
}
+
+__u64 msft_get_features(struct hci_dev *hdev)
+{
+ struct msft_data *msft = hdev->msft_data;
+
+ return msft ? msft->features : 0;
+}
diff --git a/net/bluetooth/msft.h b/net/bluetooth/msft.h
index 5aa9130e1f8a..e9c478e890b8 100644
--- a/net/bluetooth/msft.h
+++ b/net/bluetooth/msft.h
@@ -3,16 +3,25 @@
* Copyright (C) 2020 Google Corporation
*/
+#define MSFT_FEATURE_MASK_BREDR_RSSI_MONITOR BIT(0)
+#define MSFT_FEATURE_MASK_LE_CONN_RSSI_MONITOR BIT(1)
+#define MSFT_FEATURE_MASK_LE_ADV_RSSI_MONITOR BIT(2)
+#define MSFT_FEATURE_MASK_LE_ADV_MONITOR BIT(3)
+#define MSFT_FEATURE_MASK_CURVE_VALIDITY BIT(4)
+#define MSFT_FEATURE_MASK_CONCURRENT_ADV_MONITOR BIT(5)
+
#if IS_ENABLED(CONFIG_BT_MSFTEXT)
void msft_do_open(struct hci_dev *hdev);
void msft_do_close(struct hci_dev *hdev);
void msft_vendor_evt(struct hci_dev *hdev, struct sk_buff *skb);
+__u64 msft_get_features(struct hci_dev *hdev);
#else
static inline void msft_do_open(struct hci_dev *hdev) {}
static inline void msft_do_close(struct hci_dev *hdev) {}
static inline void msft_vendor_evt(struct hci_dev *hdev, struct sk_buff *skb) {}
+static inline __u64 msft_get_features(struct hci_dev *hdev) { return 0; }
#endif
--
2.26.2
From: Abhishek Pandit-Subedi <[email protected]>
Add the get device flags and set device flags mgmt ops and the device
flags changed event. Their behavior is described in detail in
mgmt-api.txt in bluez.
Sample btmon trace when a HID device is added (trimmed to 75 chars):
@ MGMT Command: Unknown (0x0050) plen 11 {0x0001} [hci0] 18:06:14.98
90 c5 13 cd f3 cd 02 01 00 00 00 ...........
@ MGMT Event: Unknown (0x002a) plen 15 {0x0004} [hci0] 18:06:14.98
90 c5 13 cd f3 cd 02 01 00 00 00 01 00 00 00 ...............
@ MGMT Event: Unknown (0x002a) plen 15 {0x0003} [hci0] 18:06:14.98
90 c5 13 cd f3 cd 02 01 00 00 00 01 00 00 00 ...............
@ MGMT Event: Unknown (0x002a) plen 15 {0x0002} [hci0] 18:06:14.98
90 c5 13 cd f3 cd 02 01 00 00 00 01 00 00 00 ...............
@ MGMT Event: Command Compl.. (0x0001) plen 10 {0x0001} [hci0] 18:06:14.98
Unknown (0x0050) plen 7
Status: Success (0x00)
90 c5 13 cd f3 cd 02 .......
@ MGMT Command: Add Device (0x0033) plen 8 {0x0001} [hci0] 18:06:14.98
LE Address: CD:F3:CD:13:C5:90 (Static)
Action: Auto-connect remote device (0x02)
@ MGMT Event: Device Added (0x001a) plen 8 {0x0004} [hci0] 18:06:14.98
LE Address: CD:F3:CD:13:C5:90 (Static)
Action: Auto-connect remote device (0x02)
@ MGMT Event: Device Added (0x001a) plen 8 {0x0003} [hci0] 18:06:14.98
LE Address: CD:F3:CD:13:C5:90 (Static)
Action: Auto-connect remote device (0x02)
@ MGMT Event: Device Added (0x001a) plen 8 {0x0002} [hci0] 18:06:14.98
LE Address: CD:F3:CD:13:C5:90 (Static)
Action: Auto-connect remote device (0x02)
@ MGMT Event: Unknown (0x002a) plen 15 {0x0004} [hci0] 18:06:14.98
90 c5 13 cd f3 cd 02 01 00 00 00 01 00 00 00 ...............
@ MGMT Event: Unknown (0x002a) plen 15 {0x0003} [hci0] 18:06:14.98
90 c5 13 cd f3 cd 02 01 00 00 00 01 00 00 00 ...............
@ MGMT Event: Unknown (0x002a) plen 15 {0x0002} [hci0] 18:06:14.98
90 c5 13 cd f3 cd 02 01 00 00 00 01 00 00 00 ...............
@ MGMT Event: Unknown (0x002a) plen 15 {0x0001} [hci0] 18:06:14.98
90 c5 13 cd f3 cd 02 01 00 00 00 01 00 00 00 ...............
Signed-off-by: Abhishek Pandit-Subedi <[email protected]>
Reviewed-by: Alain Michaud <[email protected]>
Signed-off-by: Marcel Holtmann <[email protected]>
---
include/net/bluetooth/mgmt.h | 28 ++++++++
net/bluetooth/mgmt.c | 128 +++++++++++++++++++++++++++++++++++
2 files changed, 156 insertions(+)
diff --git a/include/net/bluetooth/mgmt.h b/include/net/bluetooth/mgmt.h
index e515288f328f..8e47b0c5fe52 100644
--- a/include/net/bluetooth/mgmt.h
+++ b/include/net/bluetooth/mgmt.h
@@ -720,6 +720,27 @@ struct mgmt_rp_set_exp_feature {
#define MGMT_OP_SET_DEF_RUNTIME_CONFIG 0x004e
#define MGMT_SET_DEF_RUNTIME_CONFIG_SIZE 0
+#define MGMT_OP_GET_DEVICE_FLAGS 0x004F
+#define MGMT_GET_DEVICE_FLAGS_SIZE 7
+struct mgmt_cp_get_device_flags {
+ struct mgmt_addr_info addr;
+} __packed;
+struct mgmt_rp_get_device_flags {
+ struct mgmt_addr_info addr;
+ __le32 supported_flags;
+ __le32 current_flags;
+} __packed;
+
+#define MGMT_OP_SET_DEVICE_FLAGS 0x0050
+#define MGMT_SET_DEVICE_FLAGS_SIZE 11
+struct mgmt_cp_set_device_flags {
+ struct mgmt_addr_info addr;
+ __le32 current_flags;
+} __packed;
+struct mgmt_rp_set_device_flags {
+ struct mgmt_addr_info addr;
+} __packed;
+
#define MGMT_EV_CMD_COMPLETE 0x0001
struct mgmt_ev_cmd_complete {
__le16 opcode;
@@ -951,3 +972,10 @@ struct mgmt_ev_exp_feature_changed {
__u8 uuid[16];
__le32 flags;
} __packed;
+
+#define MGMT_EV_DEVICE_FLAGS_CHANGED 0x002a
+struct mgmt_ev_device_flags_changed {
+ struct mgmt_addr_info addr;
+ __le32 supported_flags;
+ __le32 current_flags;
+} __packed;
diff --git a/net/bluetooth/mgmt.c b/net/bluetooth/mgmt.c
index d0d0fa832c8a..e409ff48e8e6 100644
--- a/net/bluetooth/mgmt.c
+++ b/net/bluetooth/mgmt.c
@@ -116,6 +116,8 @@ static const u16 mgmt_commands[] = {
MGMT_OP_SET_DEF_SYSTEM_CONFIG,
MGMT_OP_READ_DEF_RUNTIME_CONFIG,
MGMT_OP_SET_DEF_RUNTIME_CONFIG,
+ MGMT_OP_GET_DEVICE_FLAGS,
+ MGMT_OP_SET_DEVICE_FLAGS,
};
static const u16 mgmt_events[] = {
@@ -156,6 +158,7 @@ static const u16 mgmt_events[] = {
MGMT_EV_EXT_INFO_CHANGED,
MGMT_EV_PHY_CONFIGURATION_CHANGED,
MGMT_EV_EXP_FEATURE_CHANGED,
+ MGMT_EV_DEVICE_FLAGS_CHANGED,
};
static const u16 mgmt_untrusted_commands[] = {
@@ -3856,6 +3859,120 @@ static int set_exp_feature(struct sock *sk, struct hci_dev *hdev,
MGMT_STATUS_NOT_SUPPORTED);
}
+#define SUPPORTED_DEVICE_FLAGS() ((1U << HCI_CONN_FLAG_MAX) - 1)
+
+static int get_device_flags(struct sock *sk, struct hci_dev *hdev, void *data,
+ u16 data_len)
+{
+ struct mgmt_cp_get_device_flags *cp = data;
+ struct mgmt_rp_get_device_flags rp;
+ struct bdaddr_list_with_flags *br_params;
+ struct hci_conn_params *params;
+ u32 supported_flags = SUPPORTED_DEVICE_FLAGS();
+ u32 current_flags = 0;
+ u8 status = MGMT_STATUS_INVALID_PARAMS;
+
+ bt_dev_dbg(hdev, "Get device flags %pMR (type 0x%x)\n",
+ &cp->addr.bdaddr, cp->addr.type);
+
+ if (cp->addr.type == BDADDR_BREDR) {
+ br_params = hci_bdaddr_list_lookup_with_flags(&hdev->whitelist,
+ &cp->addr.bdaddr,
+ cp->addr.type);
+ if (!br_params)
+ goto done;
+
+ current_flags = br_params->current_flags;
+ } else {
+ params = hci_conn_params_lookup(hdev, &cp->addr.bdaddr,
+ le_addr_type(cp->addr.type));
+
+ if (!params)
+ goto done;
+
+ current_flags = params->current_flags;
+ }
+
+ bacpy(&rp.addr.bdaddr, &cp->addr.bdaddr);
+ rp.addr.type = cp->addr.type;
+ rp.supported_flags = cpu_to_le32(supported_flags);
+ rp.current_flags = cpu_to_le32(current_flags);
+
+ status = MGMT_STATUS_SUCCESS;
+
+done:
+ return mgmt_cmd_complete(sk, hdev->id, MGMT_OP_GET_DEVICE_FLAGS, status,
+ &rp, sizeof(rp));
+}
+
+static void device_flags_changed(struct sock *sk, struct hci_dev *hdev,
+ bdaddr_t *bdaddr, u8 bdaddr_type,
+ u32 supported_flags, u32 current_flags)
+{
+ struct mgmt_ev_device_flags_changed ev;
+
+ bacpy(&ev.addr.bdaddr, bdaddr);
+ ev.addr.type = bdaddr_type;
+ ev.supported_flags = cpu_to_le32(supported_flags);
+ ev.current_flags = cpu_to_le32(current_flags);
+
+ mgmt_event(MGMT_EV_DEVICE_FLAGS_CHANGED, hdev, &ev, sizeof(ev), sk);
+}
+
+static int set_device_flags(struct sock *sk, struct hci_dev *hdev, void *data,
+ u16 len)
+{
+ struct mgmt_cp_set_device_flags *cp = data;
+ struct bdaddr_list_with_flags *br_params;
+ struct hci_conn_params *params;
+ u8 status = MGMT_STATUS_INVALID_PARAMS;
+ u32 supported_flags = SUPPORTED_DEVICE_FLAGS();
+ u32 current_flags = __le32_to_cpu(cp->current_flags);
+
+ bt_dev_dbg(hdev, "Set device flags %pMR (type 0x%x) = 0x%x",
+ &cp->addr.bdaddr, cp->addr.type,
+ __le32_to_cpu(current_flags));
+
+ if ((supported_flags | current_flags) != supported_flags) {
+ bt_dev_warn(hdev, "Bad flag given (0x%x) vs supported (0x%0x)",
+ current_flags, supported_flags);
+ goto done;
+ }
+
+ if (cp->addr.type == BDADDR_BREDR) {
+ br_params = hci_bdaddr_list_lookup_with_flags(&hdev->whitelist,
+ &cp->addr.bdaddr,
+ cp->addr.type);
+
+ if (br_params) {
+ br_params->current_flags = current_flags;
+ status = MGMT_STATUS_SUCCESS;
+ } else {
+ bt_dev_warn(hdev, "No such BR/EDR device %pMR (0x%x)",
+ &cp->addr.bdaddr, cp->addr.type);
+ }
+ } else {
+ params = hci_conn_params_lookup(hdev, &cp->addr.bdaddr,
+ le_addr_type(cp->addr.type));
+ if (params) {
+ params->current_flags = current_flags;
+ status = MGMT_STATUS_SUCCESS;
+ } else {
+ bt_dev_warn(hdev, "No such LE device %pMR (0x%x)",
+ &cp->addr.bdaddr,
+ le_addr_type(cp->addr.type));
+ }
+ }
+
+done:
+ if (status == MGMT_STATUS_SUCCESS)
+ device_flags_changed(sk, hdev, &cp->addr.bdaddr, cp->addr.type,
+ supported_flags, current_flags);
+
+ return mgmt_cmd_complete(sk, hdev->id, MGMT_OP_SET_DEVICE_FLAGS, status,
+ &cp->addr, sizeof(cp->addr));
+}
+
static void read_local_oob_data_complete(struct hci_dev *hdev, u8 status,
u16 opcode, struct sk_buff *skb)
{
@@ -5973,7 +6090,9 @@ static int add_device(struct sock *sk, struct hci_dev *hdev,
{
struct mgmt_cp_add_device *cp = data;
u8 auto_conn, addr_type;
+ struct hci_conn_params *params;
int err;
+ u32 current_flags = 0;
bt_dev_dbg(hdev, "sock %p", sk);
@@ -6041,12 +6160,19 @@ static int add_device(struct sock *sk, struct hci_dev *hdev,
MGMT_STATUS_FAILED, &cp->addr,
sizeof(cp->addr));
goto unlock;
+ } else {
+ params = hci_conn_params_lookup(hdev, &cp->addr.bdaddr,
+ addr_type);
+ if (params)
+ current_flags = params->current_flags;
}
hci_update_background_scan(hdev);
added:
device_added(sk, hdev, &cp->addr.bdaddr, cp->addr.type, cp->action);
+ device_flags_changed(NULL, hdev, &cp->addr.bdaddr, cp->addr.type,
+ SUPPORTED_DEVICE_FLAGS(), current_flags);
err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_ADD_DEVICE,
MGMT_STATUS_SUCCESS, &cp->addr,
@@ -7313,6 +7439,8 @@ static const struct hci_mgmt_handler mgmt_handlers[] = {
HCI_MGMT_UNTRUSTED },
{ set_def_runtime_config, MGMT_SET_DEF_RUNTIME_CONFIG_SIZE,
HCI_MGMT_VAR_LEN },
+ { get_device_flags, MGMT_GET_DEVICE_FLAGS_SIZE },
+ { set_device_flags, MGMT_SET_DEVICE_FLAGS_SIZE },
};
void mgmt_index_added(struct hci_dev *hdev)
--
2.26.2
Hi Marcel,
This looks good to me. Thanks for removing
HCI_MGMT_DEVICE_FLAGS_EVENTS -- I misunderstood what it was for.
Abhishek
On Wed, Jun 17, 2020 at 7:39 AM Marcel Holtmann <[email protected]> wrote:
>
> From: Abhishek Pandit-Subedi <[email protected]>
>
> Add the get device flags and set device flags mgmt ops and the device
> flags changed event. Their behavior is described in detail in
> mgmt-api.txt in bluez.
>
> Sample btmon trace when a HID device is added (trimmed to 75 chars):
>
> @ MGMT Command: Unknown (0x0050) plen 11 {0x0001} [hci0] 18:06:14.98
> 90 c5 13 cd f3 cd 02 01 00 00 00 ...........
> @ MGMT Event: Unknown (0x002a) plen 15 {0x0004} [hci0] 18:06:14.98
> 90 c5 13 cd f3 cd 02 01 00 00 00 01 00 00 00 ...............
> @ MGMT Event: Unknown (0x002a) plen 15 {0x0003} [hci0] 18:06:14.98
> 90 c5 13 cd f3 cd 02 01 00 00 00 01 00 00 00 ...............
> @ MGMT Event: Unknown (0x002a) plen 15 {0x0002} [hci0] 18:06:14.98
> 90 c5 13 cd f3 cd 02 01 00 00 00 01 00 00 00 ...............
> @ MGMT Event: Command Compl.. (0x0001) plen 10 {0x0001} [hci0] 18:06:14.98
> Unknown (0x0050) plen 7
> Status: Success (0x00)
> 90 c5 13 cd f3 cd 02 .......
> @ MGMT Command: Add Device (0x0033) plen 8 {0x0001} [hci0] 18:06:14.98
> LE Address: CD:F3:CD:13:C5:90 (Static)
> Action: Auto-connect remote device (0x02)
> @ MGMT Event: Device Added (0x001a) plen 8 {0x0004} [hci0] 18:06:14.98
> LE Address: CD:F3:CD:13:C5:90 (Static)
> Action: Auto-connect remote device (0x02)
> @ MGMT Event: Device Added (0x001a) plen 8 {0x0003} [hci0] 18:06:14.98
> LE Address: CD:F3:CD:13:C5:90 (Static)
> Action: Auto-connect remote device (0x02)
> @ MGMT Event: Device Added (0x001a) plen 8 {0x0002} [hci0] 18:06:14.98
> LE Address: CD:F3:CD:13:C5:90 (Static)
> Action: Auto-connect remote device (0x02)
> @ MGMT Event: Unknown (0x002a) plen 15 {0x0004} [hci0] 18:06:14.98
> 90 c5 13 cd f3 cd 02 01 00 00 00 01 00 00 00 ...............
> @ MGMT Event: Unknown (0x002a) plen 15 {0x0003} [hci0] 18:06:14.98
> 90 c5 13 cd f3 cd 02 01 00 00 00 01 00 00 00 ...............
> @ MGMT Event: Unknown (0x002a) plen 15 {0x0002} [hci0] 18:06:14.98
> 90 c5 13 cd f3 cd 02 01 00 00 00 01 00 00 00 ...............
> @ MGMT Event: Unknown (0x002a) plen 15 {0x0001} [hci0] 18:06:14.98
> 90 c5 13 cd f3 cd 02 01 00 00 00 01 00 00 00 ...............
>
> Signed-off-by: Abhishek Pandit-Subedi <[email protected]>
> Reviewed-by: Alain Michaud <[email protected]>
> Signed-off-by: Marcel Holtmann <[email protected]>
> ---
> include/net/bluetooth/mgmt.h | 28 ++++++++
> net/bluetooth/mgmt.c | 128 +++++++++++++++++++++++++++++++++++
> 2 files changed, 156 insertions(+)
>
> diff --git a/include/net/bluetooth/mgmt.h b/include/net/bluetooth/mgmt.h
> index e515288f328f..8e47b0c5fe52 100644
> --- a/include/net/bluetooth/mgmt.h
> +++ b/include/net/bluetooth/mgmt.h
> @@ -720,6 +720,27 @@ struct mgmt_rp_set_exp_feature {
> #define MGMT_OP_SET_DEF_RUNTIME_CONFIG 0x004e
> #define MGMT_SET_DEF_RUNTIME_CONFIG_SIZE 0
>
> +#define MGMT_OP_GET_DEVICE_FLAGS 0x004F
> +#define MGMT_GET_DEVICE_FLAGS_SIZE 7
> +struct mgmt_cp_get_device_flags {
> + struct mgmt_addr_info addr;
> +} __packed;
> +struct mgmt_rp_get_device_flags {
> + struct mgmt_addr_info addr;
> + __le32 supported_flags;
> + __le32 current_flags;
> +} __packed;
> +
> +#define MGMT_OP_SET_DEVICE_FLAGS 0x0050
> +#define MGMT_SET_DEVICE_FLAGS_SIZE 11
> +struct mgmt_cp_set_device_flags {
> + struct mgmt_addr_info addr;
> + __le32 current_flags;
> +} __packed;
> +struct mgmt_rp_set_device_flags {
> + struct mgmt_addr_info addr;
> +} __packed;
> +
> #define MGMT_EV_CMD_COMPLETE 0x0001
> struct mgmt_ev_cmd_complete {
> __le16 opcode;
> @@ -951,3 +972,10 @@ struct mgmt_ev_exp_feature_changed {
> __u8 uuid[16];
> __le32 flags;
> } __packed;
> +
> +#define MGMT_EV_DEVICE_FLAGS_CHANGED 0x002a
> +struct mgmt_ev_device_flags_changed {
> + struct mgmt_addr_info addr;
> + __le32 supported_flags;
> + __le32 current_flags;
> +} __packed;
> diff --git a/net/bluetooth/mgmt.c b/net/bluetooth/mgmt.c
> index d0d0fa832c8a..e409ff48e8e6 100644
> --- a/net/bluetooth/mgmt.c
> +++ b/net/bluetooth/mgmt.c
> @@ -116,6 +116,8 @@ static const u16 mgmt_commands[] = {
> MGMT_OP_SET_DEF_SYSTEM_CONFIG,
> MGMT_OP_READ_DEF_RUNTIME_CONFIG,
> MGMT_OP_SET_DEF_RUNTIME_CONFIG,
> + MGMT_OP_GET_DEVICE_FLAGS,
> + MGMT_OP_SET_DEVICE_FLAGS,
> };
>
> static const u16 mgmt_events[] = {
> @@ -156,6 +158,7 @@ static const u16 mgmt_events[] = {
> MGMT_EV_EXT_INFO_CHANGED,
> MGMT_EV_PHY_CONFIGURATION_CHANGED,
> MGMT_EV_EXP_FEATURE_CHANGED,
> + MGMT_EV_DEVICE_FLAGS_CHANGED,
> };
>
> static const u16 mgmt_untrusted_commands[] = {
> @@ -3856,6 +3859,120 @@ static int set_exp_feature(struct sock *sk, struct hci_dev *hdev,
> MGMT_STATUS_NOT_SUPPORTED);
> }
>
> +#define SUPPORTED_DEVICE_FLAGS() ((1U << HCI_CONN_FLAG_MAX) - 1)
> +
> +static int get_device_flags(struct sock *sk, struct hci_dev *hdev, void *data,
> + u16 data_len)
> +{
> + struct mgmt_cp_get_device_flags *cp = data;
> + struct mgmt_rp_get_device_flags rp;
> + struct bdaddr_list_with_flags *br_params;
> + struct hci_conn_params *params;
> + u32 supported_flags = SUPPORTED_DEVICE_FLAGS();
> + u32 current_flags = 0;
> + u8 status = MGMT_STATUS_INVALID_PARAMS;
> +
> + bt_dev_dbg(hdev, "Get device flags %pMR (type 0x%x)\n",
> + &cp->addr.bdaddr, cp->addr.type);
> +
> + if (cp->addr.type == BDADDR_BREDR) {
> + br_params = hci_bdaddr_list_lookup_with_flags(&hdev->whitelist,
> + &cp->addr.bdaddr,
> + cp->addr.type);
> + if (!br_params)
> + goto done;
> +
> + current_flags = br_params->current_flags;
> + } else {
> + params = hci_conn_params_lookup(hdev, &cp->addr.bdaddr,
> + le_addr_type(cp->addr.type));
> +
> + if (!params)
> + goto done;
> +
> + current_flags = params->current_flags;
> + }
> +
> + bacpy(&rp.addr.bdaddr, &cp->addr.bdaddr);
> + rp.addr.type = cp->addr.type;
> + rp.supported_flags = cpu_to_le32(supported_flags);
> + rp.current_flags = cpu_to_le32(current_flags);
> +
> + status = MGMT_STATUS_SUCCESS;
> +
> +done:
> + return mgmt_cmd_complete(sk, hdev->id, MGMT_OP_GET_DEVICE_FLAGS, status,
> + &rp, sizeof(rp));
> +}
> +
> +static void device_flags_changed(struct sock *sk, struct hci_dev *hdev,
> + bdaddr_t *bdaddr, u8 bdaddr_type,
> + u32 supported_flags, u32 current_flags)
> +{
> + struct mgmt_ev_device_flags_changed ev;
> +
> + bacpy(&ev.addr.bdaddr, bdaddr);
> + ev.addr.type = bdaddr_type;
> + ev.supported_flags = cpu_to_le32(supported_flags);
> + ev.current_flags = cpu_to_le32(current_flags);
> +
> + mgmt_event(MGMT_EV_DEVICE_FLAGS_CHANGED, hdev, &ev, sizeof(ev), sk);
> +}
> +
> +static int set_device_flags(struct sock *sk, struct hci_dev *hdev, void *data,
> + u16 len)
> +{
> + struct mgmt_cp_set_device_flags *cp = data;
> + struct bdaddr_list_with_flags *br_params;
> + struct hci_conn_params *params;
> + u8 status = MGMT_STATUS_INVALID_PARAMS;
> + u32 supported_flags = SUPPORTED_DEVICE_FLAGS();
> + u32 current_flags = __le32_to_cpu(cp->current_flags);
> +
> + bt_dev_dbg(hdev, "Set device flags %pMR (type 0x%x) = 0x%x",
> + &cp->addr.bdaddr, cp->addr.type,
> + __le32_to_cpu(current_flags));
> +
> + if ((supported_flags | current_flags) != supported_flags) {
> + bt_dev_warn(hdev, "Bad flag given (0x%x) vs supported (0x%0x)",
> + current_flags, supported_flags);
> + goto done;
> + }
> +
> + if (cp->addr.type == BDADDR_BREDR) {
> + br_params = hci_bdaddr_list_lookup_with_flags(&hdev->whitelist,
> + &cp->addr.bdaddr,
> + cp->addr.type);
> +
> + if (br_params) {
> + br_params->current_flags = current_flags;
> + status = MGMT_STATUS_SUCCESS;
> + } else {
> + bt_dev_warn(hdev, "No such BR/EDR device %pMR (0x%x)",
> + &cp->addr.bdaddr, cp->addr.type);
> + }
> + } else {
> + params = hci_conn_params_lookup(hdev, &cp->addr.bdaddr,
> + le_addr_type(cp->addr.type));
> + if (params) {
> + params->current_flags = current_flags;
> + status = MGMT_STATUS_SUCCESS;
> + } else {
> + bt_dev_warn(hdev, "No such LE device %pMR (0x%x)",
> + &cp->addr.bdaddr,
> + le_addr_type(cp->addr.type));
> + }
> + }
> +
> +done:
> + if (status == MGMT_STATUS_SUCCESS)
> + device_flags_changed(sk, hdev, &cp->addr.bdaddr, cp->addr.type,
> + supported_flags, current_flags);
> +
> + return mgmt_cmd_complete(sk, hdev->id, MGMT_OP_SET_DEVICE_FLAGS, status,
> + &cp->addr, sizeof(cp->addr));
> +}
> +
> static void read_local_oob_data_complete(struct hci_dev *hdev, u8 status,
> u16 opcode, struct sk_buff *skb)
> {
> @@ -5973,7 +6090,9 @@ static int add_device(struct sock *sk, struct hci_dev *hdev,
> {
> struct mgmt_cp_add_device *cp = data;
> u8 auto_conn, addr_type;
> + struct hci_conn_params *params;
> int err;
> + u32 current_flags = 0;
>
> bt_dev_dbg(hdev, "sock %p", sk);
>
> @@ -6041,12 +6160,19 @@ static int add_device(struct sock *sk, struct hci_dev *hdev,
> MGMT_STATUS_FAILED, &cp->addr,
> sizeof(cp->addr));
> goto unlock;
> + } else {
> + params = hci_conn_params_lookup(hdev, &cp->addr.bdaddr,
> + addr_type);
> + if (params)
> + current_flags = params->current_flags;
> }
>
> hci_update_background_scan(hdev);
>
> added:
> device_added(sk, hdev, &cp->addr.bdaddr, cp->addr.type, cp->action);
> + device_flags_changed(NULL, hdev, &cp->addr.bdaddr, cp->addr.type,
> + SUPPORTED_DEVICE_FLAGS(), current_flags);
>
> err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_ADD_DEVICE,
> MGMT_STATUS_SUCCESS, &cp->addr,
> @@ -7313,6 +7439,8 @@ static const struct hci_mgmt_handler mgmt_handlers[] = {
> HCI_MGMT_UNTRUSTED },
> { set_def_runtime_config, MGMT_SET_DEF_RUNTIME_CONFIG_SIZE,
> HCI_MGMT_VAR_LEN },
> + { get_device_flags, MGMT_GET_DEVICE_FLAGS_SIZE },
> + { set_device_flags, MGMT_SET_DEVICE_FLAGS_SIZE },
> };
>
> void mgmt_index_added(struct hci_dev *hdev)
> --
> 2.26.2
>
Hi Marcel,
On Wed, Jun 17, 2020, Marcel Holtmann wrote:
> This is the list of pending patches and fixes merged together. Please
> review that the set and functionality is correct and working as
> expected.
>
> In v2 the Reviewed-by tags have been added.
>
> Abhishek Pandit-Subedi (4):
> Bluetooth: Add bdaddr_list_with_flags for classic whitelist
> Bluetooth: Replace wakeable list with flag
> Bluetooth: Replace wakeable in hci_conn_params
> Bluetooth: Add get/set device flags mgmt op
>
> Manish Mandlik (1):
> Bluetooth: Terminate the link if pairing is cancelled
>
> Marcel Holtmann (2):
> Bluetooth: mgmt: Add commands for runtime configuration
> Bluetooth: mgmt: Use command complete on success for set system config
>
> Miao-chen Chou (7):
> Bluetooth: Add definitions for advertisement monitor features
> Bluetooth: Add handler of MGMT_OP_READ_ADV_MONITOR_FEATURES
> Bluetooth: Add handler of MGMT_OP_ADD_ADV_PATTERNS_MONITOR
> Bluetooth: Add handler of MGMT_OP_REMOVE_ADV_MONITOR
> Bluetooth: Notify adv monitor added event
> Bluetooth: Notify adv monitor removed event
> Bluetooth: Update background scan and report device based on
> advertisement monitors
>
> include/net/bluetooth/hci_core.h | 73 +++++-
> include/net/bluetooth/mgmt.h | 77 +++++++
> net/bluetooth/hci_conn.c | 11 +-
> net/bluetooth/hci_core.c | 153 ++++++++++++-
> net/bluetooth/hci_event.c | 13 +-
> net/bluetooth/hci_request.c | 32 ++-
> net/bluetooth/l2cap_core.c | 6 +-
> net/bluetooth/mgmt.c | 382 ++++++++++++++++++++++++++++++-
> net/bluetooth/mgmt_config.c | 23 +-
> net/bluetooth/mgmt_config.h | 6 +
> net/bluetooth/msft.c | 7 +
> net/bluetooth/msft.h | 9 +
> 12 files changed, 755 insertions(+), 37 deletions(-)
All patches in this set have been applied to bluetooth-next. Thanks.
Johan