aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMarcel Holtmann <marcel@holtmann.org>2008-07-14 14:13:48 -0400
committerMarcel Holtmann <marcel@holtmann.org>2008-07-14 14:13:48 -0400
commit41a96212b3b7b3cd59e8e8d33e6dabf0e21d9778 (patch)
tree3ba680af5e3f984d7b32a25c4d71685a54541a8f
parent333140b57fa7867bc92e5ee879b6ac4ef5e1d867 (diff)
[Bluetooth] Track status of remote Simple Pairing mode
The Simple Pairing process can only be used if both sides have the support enabled in the host stack. The current Bluetooth specification has three ways to detect this support. If an Extended Inquiry Result has been sent during inquiry then it is safe to assume that Simple Pairing is enabled. It is not allowed to enable Extended Inquiry without Simple Pairing. During the remote name request phase a notification with the remote host supported features will be sent to indicate Simple Pairing support. Also the second page of the remote extended features can indicate support for Simple Pairing. For all three cases the value of remote Simple Pairing mode is stored in the inquiry cache for later use. Signed-off-by: Marcel Holtmann <marcel@holtmann.org>
-rw-r--r--include/net/bluetooth/hci.h6
-rw-r--r--include/net/bluetooth/hci_core.h2
-rw-r--r--net/bluetooth/hci_conn.c14
-rw-r--r--net/bluetooth/hci_event.c43
4 files changed, 60 insertions, 5 deletions
diff --git a/include/net/bluetooth/hci.h b/include/net/bluetooth/hci.h
index 6d0c04a81fc7..5ac0a18db63c 100644
--- a/include/net/bluetooth/hci.h
+++ b/include/net/bluetooth/hci.h
@@ -816,6 +816,12 @@ struct hci_ev_simple_pair_complete {
816 bdaddr_t bdaddr; 816 bdaddr_t bdaddr;
817} __attribute__ ((packed)); 817} __attribute__ ((packed));
818 818
819#define HCI_EV_REMOTE_HOST_FEATURES 0x3d
820struct hci_ev_remote_host_features {
821 bdaddr_t bdaddr;
822 __u8 features[8];
823} __attribute__ ((packed));
824
819/* Internal events generated by Bluetooth stack */ 825/* Internal events generated by Bluetooth stack */
820#define HCI_EV_STACK_INTERNAL 0xfd 826#define HCI_EV_STACK_INTERNAL 0xfd
821struct hci_ev_stack_internal { 827struct hci_ev_stack_internal {
diff --git a/include/net/bluetooth/hci_core.h b/include/net/bluetooth/hci_core.h
index b85754e29a78..f73cc2945700 100644
--- a/include/net/bluetooth/hci_core.h
+++ b/include/net/bluetooth/hci_core.h
@@ -40,6 +40,7 @@ struct inquiry_data {
40 __u8 dev_class[3]; 40 __u8 dev_class[3];
41 __le16 clock_offset; 41 __le16 clock_offset;
42 __s8 rssi; 42 __s8 rssi;
43 __u8 ssp_mode;
43}; 44};
44 45
45struct inquiry_entry { 46struct inquiry_entry {
@@ -162,6 +163,7 @@ struct hci_conn {
162 __u8 attempt; 163 __u8 attempt;
163 __u8 dev_class[3]; 164 __u8 dev_class[3];
164 __u8 features[8]; 165 __u8 features[8];
166 __u8 ssp_mode;
165 __u16 interval; 167 __u16 interval;
166 __u16 pkt_type; 168 __u16 pkt_type;
167 __u16 link_policy; 169 __u16 link_policy;
diff --git a/net/bluetooth/hci_conn.c b/net/bluetooth/hci_conn.c
index 6175ce841e9e..41351ba692e9 100644
--- a/net/bluetooth/hci_conn.c
+++ b/net/bluetooth/hci_conn.c
@@ -71,12 +71,16 @@ void hci_acl_connect(struct hci_conn *conn)
71 bacpy(&cp.bdaddr, &conn->dst); 71 bacpy(&cp.bdaddr, &conn->dst);
72 cp.pscan_rep_mode = 0x02; 72 cp.pscan_rep_mode = 0x02;
73 73
74 if ((ie = hci_inquiry_cache_lookup(hdev, &conn->dst)) && 74 if ((ie = hci_inquiry_cache_lookup(hdev, &conn->dst))) {
75 inquiry_entry_age(ie) <= INQUIRY_ENTRY_AGE_MAX) { 75 if (inquiry_entry_age(ie) <= INQUIRY_ENTRY_AGE_MAX) {
76 cp.pscan_rep_mode = ie->data.pscan_rep_mode; 76 cp.pscan_rep_mode = ie->data.pscan_rep_mode;
77 cp.pscan_mode = ie->data.pscan_mode; 77 cp.pscan_mode = ie->data.pscan_mode;
78 cp.clock_offset = ie->data.clock_offset | cpu_to_le16(0x8000); 78 cp.clock_offset = ie->data.clock_offset |
79 cpu_to_le16(0x8000);
80 }
81
79 memcpy(conn->dev_class, ie->data.dev_class, 3); 82 memcpy(conn->dev_class, ie->data.dev_class, 3);
83 conn->ssp_mode = ie->data.ssp_mode;
80 } 84 }
81 85
82 cp.pkt_type = cpu_to_le16(conn->pkt_type); 86 cp.pkt_type = cpu_to_le16(conn->pkt_type);
diff --git a/net/bluetooth/hci_event.c b/net/bluetooth/hci_event.c
index 6077a651aac6..c8fda7dc2986 100644
--- a/net/bluetooth/hci_event.c
+++ b/net/bluetooth/hci_event.c
@@ -736,6 +736,7 @@ static inline void hci_inquiry_result_evt(struct hci_dev *hdev, struct sk_buff *
736 memcpy(data.dev_class, info->dev_class, 3); 736 memcpy(data.dev_class, info->dev_class, 3);
737 data.clock_offset = info->clock_offset; 737 data.clock_offset = info->clock_offset;
738 data.rssi = 0x00; 738 data.rssi = 0x00;
739 data.ssp_mode = 0x00;
739 info++; 740 info++;
740 hci_inquiry_cache_update(hdev, &data); 741 hci_inquiry_cache_update(hdev, &data);
741 } 742 }
@@ -1390,6 +1391,7 @@ static inline void hci_inquiry_result_with_rssi_evt(struct hci_dev *hdev, struct
1390 memcpy(data.dev_class, info->dev_class, 3); 1391 memcpy(data.dev_class, info->dev_class, 3);
1391 data.clock_offset = info->clock_offset; 1392 data.clock_offset = info->clock_offset;
1392 data.rssi = info->rssi; 1393 data.rssi = info->rssi;
1394 data.ssp_mode = 0x00;
1393 info++; 1395 info++;
1394 hci_inquiry_cache_update(hdev, &data); 1396 hci_inquiry_cache_update(hdev, &data);
1395 } 1397 }
@@ -1404,6 +1406,7 @@ static inline void hci_inquiry_result_with_rssi_evt(struct hci_dev *hdev, struct
1404 memcpy(data.dev_class, info->dev_class, 3); 1406 memcpy(data.dev_class, info->dev_class, 3);
1405 data.clock_offset = info->clock_offset; 1407 data.clock_offset = info->clock_offset;
1406 data.rssi = info->rssi; 1408 data.rssi = info->rssi;
1409 data.ssp_mode = 0x00;
1407 info++; 1410 info++;
1408 hci_inquiry_cache_update(hdev, &data); 1411 hci_inquiry_cache_update(hdev, &data);
1409 } 1412 }
@@ -1414,7 +1417,27 @@ static inline void hci_inquiry_result_with_rssi_evt(struct hci_dev *hdev, struct
1414 1417
1415static inline void hci_remote_ext_features_evt(struct hci_dev *hdev, struct sk_buff *skb) 1418static inline void hci_remote_ext_features_evt(struct hci_dev *hdev, struct sk_buff *skb)
1416{ 1419{
1420 struct hci_ev_remote_ext_features *ev = (void *) skb->data;
1421 struct hci_conn *conn;
1422
1417 BT_DBG("%s", hdev->name); 1423 BT_DBG("%s", hdev->name);
1424
1425 if (ev->status || ev->page != 0x01)
1426 return;
1427
1428 hci_dev_lock(hdev);
1429
1430 conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
1431 if (conn) {
1432 struct inquiry_entry *ie;
1433
1434 if ((ie = hci_inquiry_cache_lookup(hdev, &conn->dst)))
1435 ie->data.ssp_mode = (ev->features[0] & 0x01);
1436
1437 conn->ssp_mode = (ev->features[0] & 0x01);
1438 }
1439
1440 hci_dev_unlock(hdev);
1418} 1441}
1419 1442
1420static inline void hci_sync_conn_complete_evt(struct hci_dev *hdev, struct sk_buff *skb) 1443static inline void hci_sync_conn_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
@@ -1494,6 +1517,7 @@ static inline void hci_extended_inquiry_result_evt(struct hci_dev *hdev, struct
1494 memcpy(data.dev_class, info->dev_class, 3); 1517 memcpy(data.dev_class, info->dev_class, 3);
1495 data.clock_offset = info->clock_offset; 1518 data.clock_offset = info->clock_offset;
1496 data.rssi = info->rssi; 1519 data.rssi = info->rssi;
1520 data.ssp_mode = 0x01;
1497 info++; 1521 info++;
1498 hci_inquiry_cache_update(hdev, &data); 1522 hci_inquiry_cache_update(hdev, &data);
1499 } 1523 }
@@ -1533,6 +1557,21 @@ static inline void hci_simple_pair_complete_evt(struct hci_dev *hdev, struct sk_
1533 hci_dev_unlock(hdev); 1557 hci_dev_unlock(hdev);
1534} 1558}
1535 1559
1560static inline void hci_remote_host_features_evt(struct hci_dev *hdev, struct sk_buff *skb)
1561{
1562 struct hci_ev_remote_host_features *ev = (void *) skb->data;
1563 struct inquiry_entry *ie;
1564
1565 BT_DBG("%s", hdev->name);
1566
1567 hci_dev_lock(hdev);
1568
1569 if ((ie = hci_inquiry_cache_lookup(hdev, &ev->bdaddr)))
1570 ie->data.ssp_mode = (ev->features[0] & 0x01);
1571
1572 hci_dev_unlock(hdev);
1573}
1574
1536void hci_event_packet(struct hci_dev *hdev, struct sk_buff *skb) 1575void hci_event_packet(struct hci_dev *hdev, struct sk_buff *skb)
1537{ 1576{
1538 struct hci_event_hdr *hdr = (void *) skb->data; 1577 struct hci_event_hdr *hdr = (void *) skb->data;
@@ -1665,6 +1704,10 @@ void hci_event_packet(struct hci_dev *hdev, struct sk_buff *skb)
1665 hci_simple_pair_complete_evt(hdev, skb); 1704 hci_simple_pair_complete_evt(hdev, skb);
1666 break; 1705 break;
1667 1706
1707 case HCI_EV_REMOTE_HOST_FEATURES:
1708 hci_remote_host_features_evt(hdev, skb);
1709 break;
1710
1668 default: 1711 default:
1669 BT_DBG("%s event 0x%x", hdev->name, event); 1712 BT_DBG("%s event 0x%x", hdev->name, event);
1670 break; 1713 break;