* [RFC v2 1/3] Add HCI commands to enable address resolution in controller
@ 2017-10-09 9:51 Shermin Joy
0 siblings, 0 replies; only message in thread
From: Shermin Joy @ 2017-10-09 9:51 UTC (permalink / raw)
To: linux-bluetooth
Add HCI commands : LE Read Resolving List Size,
LE Add Device to Resolving List, LE Delete Device from Resolving List,
LE Clear Resolving List, LE Set Address Resolution Enable
Signed-off-by: Shermin Joy <shermin.joy@gmail.com>
---
include/net/bluetooth/hci.h | 25 ++++++++++
include/net/bluetooth/hci_core.h | 12 +++++
net/bluetooth/hci_core.c | 20 ++++++++
net/bluetooth/hci_event.c | 98 ++++++++++++++++++++++++++++++++++++++++
net/bluetooth/hci_request.c | 62 +++++++++++++++++++++++++
net/bluetooth/hci_request.h | 8 ++++
6 files changed, 225 insertions(+)
diff --git a/include/net/bluetooth/hci.h b/include/net/bluetooth/hci.h
index fe98f0a..1ef3ae8 100644
--- a/include/net/bluetooth/hci.h
+++ b/include/net/bluetooth/hci.h
@@ -398,6 +398,7 @@ enum {
#define HCI_LE_SLAVE_FEATURES 0x08
#define HCI_LE_PING 0x10
#define HCI_LE_DATA_LEN_EXT 0x20
+#define HCI_LE_LL_PRIVACY 0x40
#define HCI_LE_EXT_SCAN_POLICY 0x80
#define HCI_LE_CHAN_SEL_ALG2 0x40
@@ -1506,6 +1507,30 @@ struct hci_cp_le_set_default_phy {
__u8 rx_phys;
} __packed;
+#define HCI_OP_LE_ADD_TO_RESOLVING_LIST 0x2027
+struct hci_cp_le_add_to_resolving_list {
+ __u8 peer_bdaddr_type;
+ bdaddr_t peer_bdaddr;
+ __u8 peer_irk[16];
+ __u8 local_irk[16];
+} __packed;
+
+#define HCI_OP_LE_DEL_FROM_RESOLVING_LIST 0x2028
+struct hci_cp_le_del_from_resolving_list {
+ __u8 peer_bdaddr_type;
+ bdaddr_t peer_bdaddr;
+} __packed;
+
+#define HCI_OP_LE_CLEAR_RESOLVING_LIST 0x2029
+
+#define HCI_OP_LE_READ_RESOLVING_LIST_SIZE 0x202A
+struct hci_rp_le_read_resolving_list_size {
+ __u8 status;
+ __u8 size;
+} __packed;
+
+#define HCI_OP_LE_SET_ADDR_RESOL_ENABLE 0x202D
+
/* ---- HCI Events ---- */
#define HCI_EV_INQUIRY_COMPLETE 0x01
diff --git a/include/net/bluetooth/hci_core.h b/include/net/bluetooth/hci_core.h
index 95ccc1e..65ba086 100644
--- a/include/net/bluetooth/hci_core.h
+++ b/include/net/bluetooth/hci_core.h
@@ -139,6 +139,13 @@ struct smp_irk {
u8 val[16];
};
+struct hci_irk {
+ struct list_head list;
+ bdaddr_t bdaddr;
+ u8 addr_type;
+ u8 val[16];
+};
+
struct link_key {
struct list_head list;
struct rcu_head rcu;
@@ -221,6 +228,7 @@ struct hci_dev {
__u8 features[HCI_MAX_PAGES][8];
__u8 le_features[8];
__u8 le_white_list_size;
+ __u8 le_resolving_list_size;
__u8 le_states[8];
__u8 commands[64];
__u8 hci_ver;
@@ -259,6 +267,7 @@ struct hci_dev {
__u8 ssp_debug_mode;
__u8 hw_error_code;
__u32 clock;
+ bool le_ll_addr_resolve_enabled;
__u16 devid_source;
__u16 devid_vendor;
@@ -361,6 +370,7 @@ struct hci_dev {
struct list_head mgmt_pending;
struct list_head blacklist;
struct list_head whitelist;
+ struct list_head resolvinglist;
struct list_head uuids;
struct list_head link_keys;
struct list_head long_term_keys;
@@ -1536,6 +1546,8 @@ void hci_le_start_enc(struct hci_conn *conn, __le16 ediv, __le64 rand,
void hci_copy_identity_address(struct hci_dev *hdev, bdaddr_t *bdaddr,
u8 *bdaddr_type);
+void hci_clear_resolving_list(struct hci_dev *hdev);
+
#define SCO_AIRMODE_MASK 0x0003
#define SCO_AIRMODE_CVSD 0x0000
#define SCO_AIRMODE_TRANSP 0x0003
diff --git a/net/bluetooth/hci_core.c b/net/bluetooth/hci_core.c
index 6bc679c..bfeeb18 100644
--- a/net/bluetooth/hci_core.c
+++ b/net/bluetooth/hci_core.c
@@ -731,6 +731,24 @@ static int hci_init3_req(struct hci_request *req, unsigned long opt)
hci_req_add(req, HCI_OP_LE_READ_DEF_DATA_LEN, 0, NULL);
}
+ if (hdev->le_features[0] & HCI_LE_LL_PRIVACY) {
+ if (hdev->commands[34] & 0x40)
+ /* Read LE Resolving List Size */
+ hci_req_add(req,
+ HCI_OP_LE_READ_RESOLVING_LIST_SIZE,
+ 0, NULL);
+ if (hdev->commands[35] & 0x02)
+ /* Enable Address Resolution in Controller */
+ hci_req_add(req,
+ HCI_OP_LE_SET_ADDR_RESOL_ENABLE,
+ 0, NULL);
+ if (hdev->commands[34] & 0x20)
+ /* Clear LE Resolving List */
+ hci_req_add(req,
+ HCI_OP_LE_CLEAR_RESOLVING_LIST,
+ 0, NULL);
+ }
+
hci_set_le_support(req);
}
@@ -3021,6 +3039,7 @@ struct hci_dev *hci_alloc_dev(void)
INIT_LIST_HEAD(&hdev->mgmt_pending);
INIT_LIST_HEAD(&hdev->blacklist);
INIT_LIST_HEAD(&hdev->whitelist);
+ INIT_LIST_HEAD(&hdev->resolvinglist);
INIT_LIST_HEAD(&hdev->uuids);
INIT_LIST_HEAD(&hdev->link_keys);
INIT_LIST_HEAD(&hdev->long_term_keys);
@@ -3221,6 +3240,7 @@ void hci_unregister_dev(struct hci_dev *hdev)
hci_dev_lock(hdev);
hci_bdaddr_list_clear(&hdev->blacklist);
hci_bdaddr_list_clear(&hdev->whitelist);
+ hci_clear_resolving_list(hdev);
hci_uuids_clear(hdev);
hci_link_keys_clear(hdev);
hci_smp_ltks_clear(hdev);
diff --git a/net/bluetooth/hci_event.c b/net/bluetooth/hci_event.c
index 0b4dba0..6252307 100644
--- a/net/bluetooth/hci_event.c
+++ b/net/bluetooth/hci_event.c
@@ -1442,6 +1442,84 @@ static void hci_cc_write_ssp_debug_mode(struct hci_dev *hdev, struct sk_buff *sk
hdev->ssp_debug_mode = *mode;
}
+static void hci_cc_le_read_resolving_list_size(struct hci_dev *hdev,
+ struct sk_buff *skb)
+{
+ struct hci_rp_le_read_resolving_list_size *rp = (void *)skb->data;
+
+ BT_DBG("%s status 0x%2.2x size %u", hdev->name, rp->status, rp->size);
+
+ if (rp->status)
+ return;
+
+ hdev->le_resolving_list_size = rp->size;
+}
+
+static void hci_cc_le_clear_resolving_list(struct hci_dev *hdev,
+ struct sk_buff *skb)
+{
+ __u8 status = *((__u8 *)skb->data);
+
+ BT_DBG("%s status 0x%2.2x", hdev->name, status);
+
+ if (status)
+ return;
+
+ /* Clear all entries in the resolving list.*/
+ hci_clear_resolving_list(hdev);
+}
+
+static void hci_cc_le_add_to_resolving_list(struct hci_dev *hdev,
+ struct sk_buff *skb)
+{
+ struct hci_cp_le_add_to_resolving_list *sent;
+ __u8 status = *((__u8 *)skb->data);
+
+ BT_DBG("%s status 0x%2.2x", hdev->name, status);
+
+ if (status)
+ return;
+
+ sent = hci_sent_cmd_data(hdev, HCI_OP_LE_ADD_TO_RESOLVING_LIST);
+ if (!sent)
+ return;
+
+ hci_update_resolving_list(hdev, sent->peer_bdaddr_type,
+ &sent->peer_bdaddr, sent->peer_irk);
+}
+
+static void hci_cc_le_del_from_resolving_list(struct hci_dev *hdev,
+ struct sk_buff *skb)
+{
+ struct hci_cp_le_del_from_resolving_list *sent;
+ __u8 status = *((__u8 *)skb->data);
+
+ BT_DBG("%s status 0x%2.2x", hdev->name, status);
+
+ if (status)
+ return;
+
+ sent = hci_sent_cmd_data(hdev, HCI_OP_LE_DEL_FROM_RESOLVING_LIST);
+ if (!sent)
+ return;
+
+ hci_delete_from_resolving_list(hdev, sent->peer_bdaddr_type,
+ &sent->peer_bdaddr);
+}
+
+static void hci_cc_le_set_address_resolution_enable(struct hci_dev *hdev,
+ struct sk_buff *skb)
+{
+ __u8 status = *((__u8 *)skb->data);
+
+ BT_DBG("%s status 0x%2.2x", hdev->name, status);
+
+ if (status)
+ return;
+
+ hdev->le_ll_addr_resolve_enabled = true;
+}
+
static void hci_cs_inquiry(struct hci_dev *hdev, __u8 status)
{
BT_DBG("%s status 0x%2.2x", hdev->name, status);
@@ -3039,6 +3117,26 @@ static void hci_cmd_complete_evt(struct hci_dev *hdev, struct sk_buff *skb,
hci_cc_write_ssp_debug_mode(hdev, skb);
break;
+ case HCI_OP_LE_READ_RESOLVING_LIST_SIZE:
+ hci_cc_le_read_resolving_list_size(hdev, skb);
+ break;
+
+ case HCI_OP_LE_CLEAR_RESOLVING_LIST:
+ hci_cc_le_clear_resolving_list(hdev, skb);
+ break;
+
+ case HCI_OP_LE_ADD_TO_RESOLVING_LIST:
+ hci_cc_le_add_to_resolving_list(hdev, skb);
+ break;
+
+ case HCI_OP_LE_DEL_FROM_RESOLVING_LIST:
+ hci_cc_le_del_from_resolving_list(hdev, skb);
+ break;
+
+ case HCI_OP_LE_SET_ADDR_RESOL_ENABLE:
+ hci_cc_le_set_address_resolution_enable(hdev, skb);
+ break;
+
default:
BT_DBG("%s opcode 0x%4.4x", hdev->name, *opcode);
break;
diff --git a/net/bluetooth/hci_request.c b/net/bluetooth/hci_request.c
index b73ac14..8bdc22b 100644
--- a/net/bluetooth/hci_request.c
+++ b/net/bluetooth/hci_request.c
@@ -773,6 +773,68 @@ static u8 update_white_list(struct hci_request *req)
return 0x01;
}
+struct hci_irk *hci_resolving_list_lookup(struct hci_dev *hdev,
+ bdaddr_t *bdaddr, u8 type)
+{
+ struct hci_irk *b;
+
+ list_for_each_entry(b, &hdev->resolvinglist, list) {
+ if (!bacmp(&b->bdaddr, bdaddr) && b->addr_type == type)
+ return b;
+ }
+
+ return NULL;
+}
+
+int hci_update_resolving_list(struct hci_dev *hdev, u8 addr_type,
+ bdaddr_t *bdaddr, u8 irk_val[16])
+{
+ struct hci_irk *irk;
+
+ irk = hci_resolving_list_lookup(hdev, bdaddr, addr_type);
+ if (irk) {
+ /* If present, remove the entry from current position.*/
+ list_del(&irk->list);
+ } else {
+ irk = kzalloc(sizeof(*irk), GFP_KERNEL);
+ if (!irk)
+ return -ENOMEM;
+ bacpy(&irk->bdaddr, bdaddr);
+ irk->addr_type = addr_type;
+ }
+
+ memcpy(irk->val, irk_val, 16);
+
+ /* Add the entry to the end of the list.*/
+ list_add_tail(&irk->list, &hdev->resolvinglist);
+ return 0;
+}
+
+int hci_delete_from_resolving_list(struct hci_dev *hdev, u8 addr_type,
+ bdaddr_t *bdaddr)
+{
+ struct hci_irk *irk;
+
+ irk = hci_resolving_list_lookup(hdev, bdaddr, addr_type);
+ if (!irk)
+ return -ENOENT;
+
+ /* If present, remove the entry from current position.*/
+ list_del(&irk->list);
+
+ return 0;
+}
+
+void hci_clear_resolving_list(struct hci_dev *hdev)
+{
+ struct hci_irk *irk;
+
+ list_for_each_entry(irk, &hdev->resolvinglist, list) {
+ list_del(&irk->list);
+ kfree(irk);
+ }
+}
+
static bool scan_use_rpa(struct hci_dev *hdev)
{
return hci_dev_test_flag(hdev, HCI_PRIVACY);
diff --git a/net/bluetooth/hci_request.h b/net/bluetooth/hci_request.h
index dde77bd..ab4aac6 100644
--- a/net/bluetooth/hci_request.h
+++ b/net/bluetooth/hci_request.h
@@ -66,6 +66,14 @@ struct sk_buff *hci_prepare_cmd(struct hci_dev *hdev, u16 opcode, u32 plen,
void hci_req_add_le_scan_disable(struct hci_request *req);
void hci_req_add_le_passive_scan(struct hci_request *req);
+struct hci_irk *hci_resolving_list_lookup(struct hci_dev *hdev,
+ bdaddr_t *bdaddr, u8 type);
+int hci_update_resolving_list(struct hci_dev *hdev, u8 addr_type,
+ bdaddr_t *bdaddr, u8 irk_val[16]);
+int hci_delete_from_resolving_list(struct hci_dev *hdev, u8 addr_type,
+ bdaddr_t *bdaddr);
+void hci_clear_resolving_list(struct hci_dev *hdev);
+
void hci_req_reenable_advertising(struct hci_dev *hdev);
void __hci_req_enable_advertising(struct hci_request *req);
void __hci_req_disable_advertising(struct hci_request *req);
--
1.9.1
^ permalink raw reply related [flat|nested] only message in thread
only message in thread, other threads:[~2017-10-09 9:51 UTC | newest]
Thread overview: (only message) (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2017-10-09 9:51 [RFC v2 1/3] Add HCI commands to enable address resolution in controller Shermin Joy
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).