aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJaganath Kanakkassery <jaganath.k.os@gmail.com>2018-07-19 17:09:46 +0530
committerMarcel Holtmann <marcel@holtmann.org>2018-07-30 13:44:53 +0200
commitacf0aeae431a0f1723385cd1cb50177e4cc10edd (patch)
tree4aa5741c3a89a52c6acb6ff41c0ab307128f0c18
parentBluetooth: Implement Set ADV set random address (diff)
downloadlinux-dev-acf0aeae431a0f1723385cd1cb50177e4cc10edd.tar.xz
linux-dev-acf0aeae431a0f1723385cd1cb50177e4cc10edd.zip
Bluetooth: Handle ADv set terminated event
This event comes after connection complete event for incoming connections. Since we now have different random address for each instance, conn resp address is assigned from this event. As of now only connection part is handled as we are not enabling duration or max num of events while starting ext adv. Signed-off-by: Jaganath Kanakkassery <jaganathx.kanakkassery@intel.com> Signed-off-by: Marcel Holtmann <marcel@holtmann.org>
-rw-r--r--include/net/bluetooth/hci.h8
-rw-r--r--net/bluetooth/hci_core.c8
-rw-r--r--net/bluetooth/hci_event.c43
3 files changed, 56 insertions, 3 deletions
diff --git a/include/net/bluetooth/hci.h b/include/net/bluetooth/hci.h
index 8d348d0d3eea..57e3e3675d66 100644
--- a/include/net/bluetooth/hci.h
+++ b/include/net/bluetooth/hci.h
@@ -2155,6 +2155,14 @@ struct hci_ev_le_enh_conn_complete {
__u8 clk_accurancy;
} __packed;
+#define HCI_EV_LE_EXT_ADV_SET_TERM 0x12
+struct hci_evt_le_ext_adv_set_term {
+ __u8 status;
+ __u8 handle;
+ __le16 conn_handle;
+ __u8 num_evts;
+} __packed;
+
/* Internal events generated by Bluetooth stack */
#define HCI_EV_STACK_INTERNAL 0xfd
struct hci_ev_stack_internal {
diff --git a/net/bluetooth/hci_core.c b/net/bluetooth/hci_core.c
index 840e8fd89fa5..79e02d24a215 100644
--- a/net/bluetooth/hci_core.c
+++ b/net/bluetooth/hci_core.c
@@ -712,6 +712,14 @@ static int hci_init3_req(struct hci_request *req, unsigned long opt)
* Complete
*/
+ /* If the controller supports the LE Extended Advertising
+ * command, enable the corresponding event.
+ */
+ if (ext_adv_capable(hdev))
+ events[2] |= 0x02; /* LE Advertising Set
+ * Terminated
+ */
+
hci_req_add(req, HCI_OP_LE_SET_EVENT_MASK, sizeof(events),
events);
diff --git a/net/bluetooth/hci_event.c b/net/bluetooth/hci_event.c
index 392c9d8febd0..754714c8d752 100644
--- a/net/bluetooth/hci_event.c
+++ b/net/bluetooth/hci_event.c
@@ -4798,10 +4798,15 @@ static void le_conn_complete_evt(struct hci_dev *hdev, u8 status,
* the advertising address type.
*/
conn->resp_addr_type = hdev->adv_addr_type;
- if (hdev->adv_addr_type == ADDR_LE_DEV_RANDOM)
- bacpy(&conn->resp_addr, &hdev->random_addr);
- else
+ if (hdev->adv_addr_type == ADDR_LE_DEV_RANDOM) {
+ /* In case of ext adv, resp_addr will be updated in
+ * Adv Terminated event.
+ */
+ if (!ext_adv_capable(hdev))
+ bacpy(&conn->resp_addr, &hdev->random_addr);
+ } else {
bacpy(&conn->resp_addr, &hdev->bdaddr);
+ }
conn->init_addr_type = bdaddr_type;
bacpy(&conn->init_addr, bdaddr);
@@ -4931,6 +4936,34 @@ static void hci_le_enh_conn_complete_evt(struct hci_dev *hdev,
le16_to_cpu(ev->supervision_timeout));
}
+static void hci_le_ext_adv_term_evt(struct hci_dev *hdev, struct sk_buff *skb)
+{
+ struct hci_evt_le_ext_adv_set_term *ev = (void *) skb->data;
+ struct hci_conn *conn;
+
+ BT_DBG("%s status 0x%2.2x", hdev->name, ev->status);
+
+ if (ev->status)
+ return;
+
+ conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->conn_handle));
+ if (conn) {
+ struct adv_info *adv_instance;
+
+ if (hdev->adv_addr_type != ADDR_LE_DEV_RANDOM)
+ return;
+
+ if (!hdev->cur_adv_instance) {
+ bacpy(&conn->resp_addr, &hdev->random_addr);
+ return;
+ }
+
+ adv_instance = hci_find_adv_instance(hdev, hdev->cur_adv_instance);
+ if (adv_instance)
+ bacpy(&conn->resp_addr, &adv_instance->random_addr);
+ }
+}
+
static void hci_le_conn_update_complete_evt(struct hci_dev *hdev,
struct sk_buff *skb)
{
@@ -5578,6 +5611,10 @@ static void hci_le_meta_evt(struct hci_dev *hdev, struct sk_buff *skb)
hci_le_enh_conn_complete_evt(hdev, skb);
break;
+ case HCI_EV_LE_EXT_ADV_SET_TERM:
+ hci_le_ext_adv_term_evt(hdev, skb);
+ break;
+
default:
break;
}