summaryrefslogtreecommitdiffstats
path: root/net/bluetooth/hci_event.c
diff options
context:
space:
mode:
authorJohan Hedberg <johan.hedberg@intel.com>2012-01-04 15:44:20 +0200
committerJohan Hedberg <johan.hedberg@intel.com>2012-02-13 17:01:20 +0200
commit30dc78e1a2bcbe2a0fca7aa44dfded4bb0db6148 (patch)
treee84a8d690192e75d14212d690e772575eebf68e8 /net/bluetooth/hci_event.c
parentff9ef5787046c3fd20cf9f7ca1cd70260c1eedb9 (diff)
downloadtalos-obmc-linux-30dc78e1a2bcbe2a0fca7aa44dfded4bb0db6148.tar.gz
talos-obmc-linux-30dc78e1a2bcbe2a0fca7aa44dfded4bb0db6148.zip
Bluetooth: Add name resolving support for mgmt based discovery
This patch adds the necessary logic to perform name lookups after inquiry completes. This is done by checking for entries in the resolve list after each inquiry complete and remote name complete HCI event. Signed-off-by: Johan Hedberg <johan.hedberg@intel.com> Acked-by: Marcel Holtmann <marcel@holtmann.org>
Diffstat (limited to 'net/bluetooth/hci_event.c')
-rw-r--r--net/bluetooth/hci_event.c81
1 files changed, 77 insertions, 4 deletions
diff --git a/net/bluetooth/hci_event.c b/net/bluetooth/hci_event.c
index 43d69569a0d5..089dff80ccb0 100644
--- a/net/bluetooth/hci_event.c
+++ b/net/bluetooth/hci_event.c
@@ -1119,7 +1119,7 @@ static inline void hci_cs_inquiry(struct hci_dev *hdev, __u8 status)
set_bit(HCI_INQUIRY, &hdev->flags);
hci_dev_lock(hdev);
- hci_discovery_set_state(hdev, DISCOVERY_ACTIVE);
+ hci_discovery_set_state(hdev, DISCOVERY_INQUIRY);
hci_dev_unlock(hdev);
}
@@ -1271,6 +1271,50 @@ static int hci_outgoing_auth_needed(struct hci_dev *hdev,
return 1;
}
+static inline int hci_resolve_name(struct hci_dev *hdev, struct inquiry_entry *e)
+{
+ struct hci_cp_remote_name_req cp;
+
+ memset(&cp, 0, sizeof(cp));
+
+ bacpy(&cp.bdaddr, &e->data.bdaddr);
+ cp.pscan_rep_mode = e->data.pscan_rep_mode;
+ cp.pscan_mode = e->data.pscan_mode;
+ cp.clock_offset = e->data.clock_offset;
+
+ return hci_send_cmd(hdev, HCI_OP_REMOTE_NAME_REQ, sizeof(cp), &cp);
+}
+
+static void hci_resolve_next_name(struct hci_dev *hdev, bdaddr_t *bdaddr)
+{
+ struct discovery_state *discov = &hdev->discovery;
+ struct inquiry_entry *e;
+
+ if (discov->state == DISCOVERY_STOPPING)
+ goto discov_complete;
+
+ if (discov->state != DISCOVERY_RESOLVING)
+ return;
+
+ e = hci_inquiry_cache_lookup_resolve(hdev, bdaddr, NAME_PENDING);
+ if (e) {
+ e->name_state = NAME_KNOWN;
+ list_del(&e->list);
+ }
+
+ if (list_empty(&discov->resolve))
+ goto discov_complete;
+
+ e = hci_inquiry_cache_lookup_resolve(hdev, BDADDR_ANY, NAME_NEEDED);
+ if (hci_resolve_name(hdev, e) == 0) {
+ e->name_state = NAME_PENDING;
+ return;
+ }
+
+discov_complete:
+ hci_discovery_set_state(hdev, DISCOVERY_STOPPED);
+}
+
static void hci_cs_remote_name_req(struct hci_dev *hdev, __u8 status)
{
struct hci_cp_remote_name_req *cp;
@@ -1289,6 +1333,9 @@ static void hci_cs_remote_name_req(struct hci_dev *hdev, __u8 status)
hci_dev_lock(hdev);
+ if (test_bit(HCI_MGMT, &hdev->flags))
+ hci_resolve_next_name(hdev, &cp->bdaddr);
+
conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &cp->bdaddr);
if (!conn)
goto unlock;
@@ -1496,6 +1543,8 @@ static void hci_cs_le_start_enc(struct hci_dev *hdev, u8 status)
static inline void hci_inquiry_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
{
__u8 status = *((__u8 *) skb->data);
+ struct discovery_state *discov = &hdev->discovery;
+ struct inquiry_entry *e;
BT_DBG("%s status %d", hdev->name, status);
@@ -1506,8 +1555,28 @@ static inline void hci_inquiry_complete_evt(struct hci_dev *hdev, struct sk_buff
if (!test_and_clear_bit(HCI_INQUIRY, &hdev->flags))
return;
+ if (!test_bit(HCI_MGMT, &hdev->flags))
+ return;
+
hci_dev_lock(hdev);
- hci_discovery_set_state(hdev, DISCOVERY_STOPPED);
+
+ if (discov->state != DISCOVERY_INQUIRY)
+ goto unlock;
+
+ if (list_empty(&discov->resolve)) {
+ hci_discovery_set_state(hdev, DISCOVERY_STOPPED);
+ goto unlock;
+ }
+
+ e = hci_inquiry_cache_lookup_resolve(hdev, BDADDR_ANY, NAME_NEEDED);
+ if (e && hci_resolve_name(hdev, e) == 0) {
+ e->name_state = NAME_PENDING;
+ hci_discovery_set_state(hdev, DISCOVERY_RESOLVING);
+ } else {
+ hci_discovery_set_state(hdev, DISCOVERY_STOPPED);
+ }
+
+unlock:
hci_dev_unlock(hdev);
}
@@ -1807,8 +1876,12 @@ static inline void hci_remote_name_evt(struct hci_dev *hdev, struct sk_buff *skb
hci_dev_lock(hdev);
- if (ev->status == 0 && test_bit(HCI_MGMT, &hdev->flags))
- mgmt_remote_name(hdev, &ev->bdaddr, ev->name);
+ if (test_bit(HCI_MGMT, &hdev->flags)) {
+ if (ev->status == 0)
+ mgmt_remote_name(hdev, &ev->bdaddr, ev->name);
+
+ hci_resolve_next_name(hdev, &ev->bdaddr);
+ }
conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
if (!conn)
OpenPOWER on IntegriCloud