aboutsummaryrefslogtreecommitdiffstats
path: root/net
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 /net
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>
Diffstat (limited to 'net')
-rw-r--r--net/bluetooth/hci_conn.c14
-rw-r--r--net/bluetooth/hci_event.c43
2 files changed, 52 insertions, 5 deletions
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;