aboutsummaryrefslogtreecommitdiffstats
path: root/net/bluetooth
diff options
context:
space:
mode:
authorJohan Hedberg <johan.hedberg@intel.com>2012-01-04 06:31:59 -0500
committerJohan Hedberg <johan.hedberg@intel.com>2012-02-13 10:01:19 -0500
commit561aafbcb2e3f8fee11d3781f866c7b4c4f93a28 (patch)
tree98fc5da4793bd16810a47450afe28e7304bdea8c /net/bluetooth
parent32748db00228b67a5315a91e1a6dd2c54864d87b (diff)
Bluetooth: Add initial mgmt_confirm_name support
This patch adds initial support for mgmt_confirm_name. It adds the necessary tracking of the name state by extending the inquiry cache. The actual name resolving operation (to be done once inquiry is finished) is not yet part of this patch. Signed-off-by: Johan Hedberg <johan.hedberg@intel.com> Acked-by: Marcel Holtmann <marcel@holtmann.org>
Diffstat (limited to 'net/bluetooth')
-rw-r--r--net/bluetooth/hci_core.c58
-rw-r--r--net/bluetooth/hci_event.c51
-rw-r--r--net/bluetooth/hci_sysfs.c2
-rw-r--r--net/bluetooth/mgmt.c51
4 files changed, 141 insertions, 21 deletions
diff --git a/net/bluetooth/hci_core.c b/net/bluetooth/hci_core.c
index feeea4df252..fc09a3cbe20 100644
--- a/net/bluetooth/hci_core.c
+++ b/net/bluetooth/hci_core.c
@@ -357,12 +357,16 @@ struct hci_dev *hci_dev_get(int index)
357/* ---- Inquiry support ---- */ 357/* ---- Inquiry support ---- */
358static void inquiry_cache_flush(struct hci_dev *hdev) 358static void inquiry_cache_flush(struct hci_dev *hdev)
359{ 359{
360 struct inquiry_cache *cache = &hdev->inq_cache;
360 struct inquiry_entry *p, *n; 361 struct inquiry_entry *p, *n;
361 362
362 list_for_each_entry_safe(p, n, &hdev->inq_cache.list, list) { 363 list_for_each_entry_safe(p, n, &cache->all, all) {
363 list_del(&p->list); 364 list_del(&p->all);
364 kfree(p); 365 kfree(p);
365 } 366 }
367
368 INIT_LIST_HEAD(&cache->unknown);
369 INIT_LIST_HEAD(&cache->resolve);
366} 370}
367 371
368struct inquiry_entry *hci_inquiry_cache_lookup(struct hci_dev *hdev, bdaddr_t *bdaddr) 372struct inquiry_entry *hci_inquiry_cache_lookup(struct hci_dev *hdev, bdaddr_t *bdaddr)
@@ -372,7 +376,7 @@ struct inquiry_entry *hci_inquiry_cache_lookup(struct hci_dev *hdev, bdaddr_t *b
372 376
373 BT_DBG("cache %p, %s", cache, batostr(bdaddr)); 377 BT_DBG("cache %p, %s", cache, batostr(bdaddr));
374 378
375 list_for_each_entry(e, &cache->list, list) { 379 list_for_each_entry(e, &cache->all, all) {
376 if (!bacmp(&e->data.bdaddr, bdaddr)) 380 if (!bacmp(&e->data.bdaddr, bdaddr))
377 return e; 381 return e;
378 } 382 }
@@ -380,7 +384,24 @@ struct inquiry_entry *hci_inquiry_cache_lookup(struct hci_dev *hdev, bdaddr_t *b
380 return NULL; 384 return NULL;
381} 385}
382 386
383void hci_inquiry_cache_update(struct hci_dev *hdev, struct inquiry_data *data) 387struct inquiry_entry *hci_inquiry_cache_lookup_unknown(struct hci_dev *hdev,
388 bdaddr_t *bdaddr)
389{
390 struct inquiry_cache *cache = &hdev->inq_cache;
391 struct inquiry_entry *e;
392
393 BT_DBG("cache %p, %s", cache, batostr(bdaddr));
394
395 list_for_each_entry(e, &cache->unknown, list) {
396 if (!bacmp(&e->data.bdaddr, bdaddr))
397 return e;
398 }
399
400 return NULL;
401}
402
403void hci_inquiry_cache_update(struct hci_dev *hdev, struct inquiry_data *data,
404 bool name_known)
384{ 405{
385 struct inquiry_cache *cache = &hdev->inq_cache; 406 struct inquiry_cache *cache = &hdev->inq_cache;
386 struct inquiry_entry *ie; 407 struct inquiry_entry *ie;
@@ -388,13 +409,28 @@ void hci_inquiry_cache_update(struct hci_dev *hdev, struct inquiry_data *data)
388 BT_DBG("cache %p, %s", cache, batostr(&data->bdaddr)); 409 BT_DBG("cache %p, %s", cache, batostr(&data->bdaddr));
389 410
390 ie = hci_inquiry_cache_lookup(hdev, &data->bdaddr); 411 ie = hci_inquiry_cache_lookup(hdev, &data->bdaddr);
391 if (!ie) { 412 if (ie)
392 /* Entry not in the cache. Add new one. */ 413 goto update;
393 ie = kzalloc(sizeof(struct inquiry_entry), GFP_ATOMIC); 414
394 if (!ie) 415 /* Entry not in the cache. Add new one. */
395 return; 416 ie = kzalloc(sizeof(struct inquiry_entry), GFP_ATOMIC);
417 if (!ie)
418 return;
419
420 list_add(&ie->all, &cache->all);
421
422 if (name_known) {
423 ie->name_state = NAME_KNOWN;
424 } else {
425 ie->name_state = NAME_NOT_KNOWN;
426 list_add(&ie->list, &cache->unknown);
427 }
396 428
397 list_add(&ie->list, &cache->list); 429update:
430 if (name_known && ie->name_state != NAME_KNOWN &&
431 ie->name_state != NAME_PENDING) {
432 ie->name_state = NAME_KNOWN;
433 list_del(&ie->list);
398 } 434 }
399 435
400 memcpy(&ie->data, data, sizeof(*data)); 436 memcpy(&ie->data, data, sizeof(*data));
@@ -409,7 +445,7 @@ static int inquiry_cache_dump(struct hci_dev *hdev, int num, __u8 *buf)
409 struct inquiry_entry *e; 445 struct inquiry_entry *e;
410 int copied = 0; 446 int copied = 0;
411 447
412 list_for_each_entry(e, &cache->list, list) { 448 list_for_each_entry(e, &cache->all, all) {
413 struct inquiry_data *data = &e->data; 449 struct inquiry_data *data = &e->data;
414 450
415 if (copied >= num) 451 if (copied >= num)
diff --git a/net/bluetooth/hci_event.c b/net/bluetooth/hci_event.c
index 001307f8105..9302c3c2556 100644
--- a/net/bluetooth/hci_event.c
+++ b/net/bluetooth/hci_event.c
@@ -1533,9 +1533,9 @@ static inline void hci_inquiry_result_evt(struct hci_dev *hdev, struct sk_buff *
1533 data.clock_offset = info->clock_offset; 1533 data.clock_offset = info->clock_offset;
1534 data.rssi = 0x00; 1534 data.rssi = 0x00;
1535 data.ssp_mode = 0x00; 1535 data.ssp_mode = 0x00;
1536 hci_inquiry_cache_update(hdev, &data); 1536 hci_inquiry_cache_update(hdev, &data, false);
1537 mgmt_device_found(hdev, &info->bdaddr, ACL_LINK, 0x00, 1537 mgmt_device_found(hdev, &info->bdaddr, ACL_LINK, 0x00,
1538 info->dev_class, 0, NULL); 1538 info->dev_class, 0, 1, NULL);
1539 } 1539 }
1540 1540
1541 hci_dev_unlock(hdev); 1541 hci_dev_unlock(hdev);
@@ -2572,10 +2572,10 @@ static inline void hci_inquiry_result_with_rssi_evt(struct hci_dev *hdev, struct
2572 data.clock_offset = info->clock_offset; 2572 data.clock_offset = info->clock_offset;
2573 data.rssi = info->rssi; 2573 data.rssi = info->rssi;
2574 data.ssp_mode = 0x00; 2574 data.ssp_mode = 0x00;
2575 hci_inquiry_cache_update(hdev, &data); 2575 hci_inquiry_cache_update(hdev, &data, false);
2576 mgmt_device_found(hdev, &info->bdaddr, ACL_LINK, 0x00, 2576 mgmt_device_found(hdev, &info->bdaddr, ACL_LINK, 0x00,
2577 info->dev_class, info->rssi, 2577 info->dev_class, info->rssi,
2578 NULL); 2578 1, NULL);
2579 } 2579 }
2580 } else { 2580 } else {
2581 struct inquiry_info_with_rssi *info = (void *) (skb->data + 1); 2581 struct inquiry_info_with_rssi *info = (void *) (skb->data + 1);
@@ -2589,10 +2589,10 @@ static inline void hci_inquiry_result_with_rssi_evt(struct hci_dev *hdev, struct
2589 data.clock_offset = info->clock_offset; 2589 data.clock_offset = info->clock_offset;
2590 data.rssi = info->rssi; 2590 data.rssi = info->rssi;
2591 data.ssp_mode = 0x00; 2591 data.ssp_mode = 0x00;
2592 hci_inquiry_cache_update(hdev, &data); 2592 hci_inquiry_cache_update(hdev, &data, false);
2593 mgmt_device_found(hdev, &info->bdaddr, ACL_LINK, 0x00, 2593 mgmt_device_found(hdev, &info->bdaddr, ACL_LINK, 0x00,
2594 info->dev_class, info->rssi, 2594 info->dev_class, info->rssi,
2595 NULL); 2595 1, NULL);
2596 } 2596 }
2597 } 2597 }
2598 2598
@@ -2710,6 +2710,31 @@ static inline void hci_sniff_subrate_evt(struct hci_dev *hdev, struct sk_buff *s
2710 BT_DBG("%s status %d", hdev->name, ev->status); 2710 BT_DBG("%s status %d", hdev->name, ev->status);
2711} 2711}
2712 2712
2713static inline bool eir_has_complete_name(u8 *data, size_t data_len)
2714{
2715 u8 field_len;
2716 size_t parsed;
2717
2718 for (parsed = 0; parsed < data_len - 1; parsed += field_len) {
2719 field_len = data[0];
2720
2721 if (field_len == 0)
2722 break;
2723
2724 parsed += field_len + 1;
2725
2726 if (parsed > data_len)
2727 break;
2728
2729 if (data[1] == EIR_NAME_COMPLETE)
2730 return true;
2731
2732 data += field_len + 1;
2733 }
2734
2735 return false;
2736}
2737
2713static inline void hci_extended_inquiry_result_evt(struct hci_dev *hdev, struct sk_buff *skb) 2738static inline void hci_extended_inquiry_result_evt(struct hci_dev *hdev, struct sk_buff *skb)
2714{ 2739{
2715 struct inquiry_data data; 2740 struct inquiry_data data;
@@ -2724,6 +2749,8 @@ static inline void hci_extended_inquiry_result_evt(struct hci_dev *hdev, struct
2724 hci_dev_lock(hdev); 2749 hci_dev_lock(hdev);
2725 2750
2726 for (; num_rsp; num_rsp--, info++) { 2751 for (; num_rsp; num_rsp--, info++) {
2752 bool name_known;
2753
2727 bacpy(&data.bdaddr, &info->bdaddr); 2754 bacpy(&data.bdaddr, &info->bdaddr);
2728 data.pscan_rep_mode = info->pscan_rep_mode; 2755 data.pscan_rep_mode = info->pscan_rep_mode;
2729 data.pscan_period_mode = info->pscan_period_mode; 2756 data.pscan_period_mode = info->pscan_period_mode;
@@ -2732,9 +2759,17 @@ static inline void hci_extended_inquiry_result_evt(struct hci_dev *hdev, struct
2732 data.clock_offset = info->clock_offset; 2759 data.clock_offset = info->clock_offset;
2733 data.rssi = info->rssi; 2760 data.rssi = info->rssi;
2734 data.ssp_mode = 0x01; 2761 data.ssp_mode = 0x01;
2735 hci_inquiry_cache_update(hdev, &data); 2762
2763 if (test_bit(HCI_MGMT, &hdev->flags))
2764 name_known = eir_has_complete_name(info->data,
2765 sizeof(info->data));
2766 else
2767 name_known = true;
2768
2769 hci_inquiry_cache_update(hdev, &data, name_known);
2736 mgmt_device_found(hdev, &info->bdaddr, ACL_LINK, 0x00, 2770 mgmt_device_found(hdev, &info->bdaddr, ACL_LINK, 0x00,
2737 info->dev_class, info->rssi, info->data); 2771 info->dev_class, info->rssi,
2772 !name_known, info->data);
2738 } 2773 }
2739 2774
2740 hci_dev_unlock(hdev); 2775 hci_dev_unlock(hdev);
diff --git a/net/bluetooth/hci_sysfs.c b/net/bluetooth/hci_sysfs.c
index ed9cceeec7b..3600d78c2f2 100644
--- a/net/bluetooth/hci_sysfs.c
+++ b/net/bluetooth/hci_sysfs.c
@@ -388,7 +388,7 @@ static int inquiry_cache_show(struct seq_file *f, void *p)
388 388
389 hci_dev_lock(hdev); 389 hci_dev_lock(hdev);
390 390
391 list_for_each_entry(e, &cache->list, list) { 391 list_for_each_entry(e, &cache->all, all) {
392 struct inquiry_data *data = &e->data; 392 struct inquiry_data *data = &e->data;
393 seq_printf(f, "%s %d %d %d 0x%.2x%.2x%.2x 0x%.4x %d %d %u\n", 393 seq_printf(f, "%s %d %d %d 0x%.2x%.2x%.2x 0x%.4x %d %d %u\n",
394 batostr(&data->bdaddr), 394 batostr(&data->bdaddr),
diff --git a/net/bluetooth/mgmt.c b/net/bluetooth/mgmt.c
index 851cb19c55b..39775119585 100644
--- a/net/bluetooth/mgmt.c
+++ b/net/bluetooth/mgmt.c
@@ -1967,6 +1967,50 @@ failed:
1967 return err; 1967 return err;
1968} 1968}
1969 1969
1970static int confirm_name(struct sock *sk, u16 index, unsigned char *data,
1971 u16 len)
1972{
1973 struct mgmt_cp_confirm_name *cp = (void *) data;
1974 struct inquiry_entry *e;
1975 struct hci_dev *hdev;
1976 int err;
1977
1978 BT_DBG("hci%u", index);
1979
1980 if (len != sizeof(*cp))
1981 return cmd_status(sk, index, MGMT_OP_CONFIRM_NAME,
1982 MGMT_STATUS_INVALID_PARAMS);
1983
1984 hdev = hci_dev_get(index);
1985 if (!hdev)
1986 return cmd_status(sk, index, MGMT_OP_CONFIRM_NAME,
1987 MGMT_STATUS_INVALID_PARAMS);
1988
1989 hci_dev_lock(hdev);
1990
1991 e = hci_inquiry_cache_lookup_unknown(hdev, &cp->bdaddr);
1992 if (!e) {
1993 err = cmd_status (sk, index, MGMT_OP_CONFIRM_NAME,
1994 MGMT_STATUS_INVALID_PARAMS);
1995 goto failed;
1996 }
1997
1998 if (cp->name_known) {
1999 e->name_state = NAME_KNOWN;
2000 list_del(&e->list);
2001 } else {
2002 e->name_state = NAME_NEEDED;
2003 list_move(&e->list, &hdev->inq_cache.resolve);
2004 }
2005
2006 err = 0;
2007
2008failed:
2009 hci_dev_unlock(hdev);
2010
2011 return err;
2012}
2013
1970static int block_device(struct sock *sk, u16 index, unsigned char *data, 2014static int block_device(struct sock *sk, u16 index, unsigned char *data,
1971 u16 len) 2015 u16 len)
1972{ 2016{
@@ -2215,6 +2259,9 @@ int mgmt_control(struct sock *sk, struct msghdr *msg, size_t msglen)
2215 case MGMT_OP_STOP_DISCOVERY: 2259 case MGMT_OP_STOP_DISCOVERY:
2216 err = stop_discovery(sk, index); 2260 err = stop_discovery(sk, index);
2217 break; 2261 break;
2262 case MGMT_OP_CONFIRM_NAME:
2263 err = confirm_name(sk, index, buf + sizeof(*hdr), len);
2264 break;
2218 case MGMT_OP_BLOCK_DEVICE: 2265 case MGMT_OP_BLOCK_DEVICE:
2219 err = block_device(sk, index, buf + sizeof(*hdr), len); 2266 err = block_device(sk, index, buf + sizeof(*hdr), len);
2220 break; 2267 break;
@@ -2689,7 +2736,8 @@ int mgmt_read_local_oob_data_reply_complete(struct hci_dev *hdev, u8 *hash,
2689} 2736}
2690 2737
2691int mgmt_device_found(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 link_type, 2738int mgmt_device_found(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 link_type,
2692 u8 addr_type, u8 *dev_class, s8 rssi, u8 *eir) 2739 u8 addr_type, u8 *dev_class, s8 rssi,
2740 u8 cfm_name, u8 *eir)
2693{ 2741{
2694 struct mgmt_ev_device_found ev; 2742 struct mgmt_ev_device_found ev;
2695 2743
@@ -2698,6 +2746,7 @@ int mgmt_device_found(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 link_type,
2698 bacpy(&ev.addr.bdaddr, bdaddr); 2746 bacpy(&ev.addr.bdaddr, bdaddr);
2699 ev.addr.type = link_to_mgmt(link_type, addr_type); 2747 ev.addr.type = link_to_mgmt(link_type, addr_type);
2700 ev.rssi = rssi; 2748 ev.rssi = rssi;
2749 ev.confirm_name = cfm_name;
2701 2750
2702 if (eir) 2751 if (eir)
2703 memcpy(ev.eir, eir, sizeof(ev.eir)); 2752 memcpy(ev.eir, eir, sizeof(ev.eir));