Skip to content

Commit

Permalink
[Bluetooth] Track status of remote Simple Pairing mode
Browse files Browse the repository at this point in the history
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>
  • Loading branch information
Marcel Holtmann committed Jul 14, 2008
1 parent 333140b commit 41a9621
Show file tree
Hide file tree
Showing 4 changed files with 60 additions and 5 deletions.
6 changes: 6 additions & 0 deletions include/net/bluetooth/hci.h
Original file line number Diff line number Diff line change
Expand Up @@ -816,6 +816,12 @@ struct hci_ev_simple_pair_complete {
bdaddr_t bdaddr;
} __attribute__ ((packed));

#define HCI_EV_REMOTE_HOST_FEATURES 0x3d
struct hci_ev_remote_host_features {
bdaddr_t bdaddr;
__u8 features[8];
} __attribute__ ((packed));

/* Internal events generated by Bluetooth stack */
#define HCI_EV_STACK_INTERNAL 0xfd
struct hci_ev_stack_internal {
Expand Down
2 changes: 2 additions & 0 deletions include/net/bluetooth/hci_core.h
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ struct inquiry_data {
__u8 dev_class[3];
__le16 clock_offset;
__s8 rssi;
__u8 ssp_mode;
};

struct inquiry_entry {
Expand Down Expand Up @@ -162,6 +163,7 @@ struct hci_conn {
__u8 attempt;
__u8 dev_class[3];
__u8 features[8];
__u8 ssp_mode;
__u16 interval;
__u16 pkt_type;
__u16 link_policy;
Expand Down
14 changes: 9 additions & 5 deletions net/bluetooth/hci_conn.c
Original file line number Diff line number Diff line change
Expand Up @@ -71,12 +71,16 @@ void hci_acl_connect(struct hci_conn *conn)
bacpy(&cp.bdaddr, &conn->dst);
cp.pscan_rep_mode = 0x02;

if ((ie = hci_inquiry_cache_lookup(hdev, &conn->dst)) &&
inquiry_entry_age(ie) <= INQUIRY_ENTRY_AGE_MAX) {
cp.pscan_rep_mode = ie->data.pscan_rep_mode;
cp.pscan_mode = ie->data.pscan_mode;
cp.clock_offset = ie->data.clock_offset | cpu_to_le16(0x8000);
if ((ie = hci_inquiry_cache_lookup(hdev, &conn->dst))) {
if (inquiry_entry_age(ie) <= INQUIRY_ENTRY_AGE_MAX) {
cp.pscan_rep_mode = ie->data.pscan_rep_mode;
cp.pscan_mode = ie->data.pscan_mode;
cp.clock_offset = ie->data.clock_offset |
cpu_to_le16(0x8000);
}

memcpy(conn->dev_class, ie->data.dev_class, 3);
conn->ssp_mode = ie->data.ssp_mode;
}

cp.pkt_type = cpu_to_le16(conn->pkt_type);
Expand Down
43 changes: 43 additions & 0 deletions net/bluetooth/hci_event.c
Original file line number Diff line number Diff line change
Expand Up @@ -736,6 +736,7 @@ static inline void hci_inquiry_result_evt(struct hci_dev *hdev, struct sk_buff *
memcpy(data.dev_class, info->dev_class, 3);
data.clock_offset = info->clock_offset;
data.rssi = 0x00;
data.ssp_mode = 0x00;
info++;
hci_inquiry_cache_update(hdev, &data);
}
Expand Down Expand Up @@ -1390,6 +1391,7 @@ static inline void hci_inquiry_result_with_rssi_evt(struct hci_dev *hdev, struct
memcpy(data.dev_class, info->dev_class, 3);
data.clock_offset = info->clock_offset;
data.rssi = info->rssi;
data.ssp_mode = 0x00;
info++;
hci_inquiry_cache_update(hdev, &data);
}
Expand All @@ -1404,6 +1406,7 @@ static inline void hci_inquiry_result_with_rssi_evt(struct hci_dev *hdev, struct
memcpy(data.dev_class, info->dev_class, 3);
data.clock_offset = info->clock_offset;
data.rssi = info->rssi;
data.ssp_mode = 0x00;
info++;
hci_inquiry_cache_update(hdev, &data);
}
Expand All @@ -1414,7 +1417,27 @@ static inline void hci_inquiry_result_with_rssi_evt(struct hci_dev *hdev, struct

static inline void hci_remote_ext_features_evt(struct hci_dev *hdev, struct sk_buff *skb)
{
struct hci_ev_remote_ext_features *ev = (void *) skb->data;
struct hci_conn *conn;

BT_DBG("%s", hdev->name);

if (ev->status || ev->page != 0x01)
return;

hci_dev_lock(hdev);

conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
if (conn) {
struct inquiry_entry *ie;

if ((ie = hci_inquiry_cache_lookup(hdev, &conn->dst)))
ie->data.ssp_mode = (ev->features[0] & 0x01);

conn->ssp_mode = (ev->features[0] & 0x01);
}

hci_dev_unlock(hdev);
}

static inline void hci_sync_conn_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
Expand Down Expand Up @@ -1494,6 +1517,7 @@ static inline void hci_extended_inquiry_result_evt(struct hci_dev *hdev, struct
memcpy(data.dev_class, info->dev_class, 3);
data.clock_offset = info->clock_offset;
data.rssi = info->rssi;
data.ssp_mode = 0x01;
info++;
hci_inquiry_cache_update(hdev, &data);
}
Expand Down Expand Up @@ -1533,6 +1557,21 @@ static inline void hci_simple_pair_complete_evt(struct hci_dev *hdev, struct sk_
hci_dev_unlock(hdev);
}

static inline void hci_remote_host_features_evt(struct hci_dev *hdev, struct sk_buff *skb)
{
struct hci_ev_remote_host_features *ev = (void *) skb->data;
struct inquiry_entry *ie;

BT_DBG("%s", hdev->name);

hci_dev_lock(hdev);

if ((ie = hci_inquiry_cache_lookup(hdev, &ev->bdaddr)))
ie->data.ssp_mode = (ev->features[0] & 0x01);

hci_dev_unlock(hdev);
}

void hci_event_packet(struct hci_dev *hdev, struct sk_buff *skb)
{
struct hci_event_hdr *hdr = (void *) skb->data;
Expand Down Expand Up @@ -1665,6 +1704,10 @@ void hci_event_packet(struct hci_dev *hdev, struct sk_buff *skb)
hci_simple_pair_complete_evt(hdev, skb);
break;

case HCI_EV_REMOTE_HOST_FEATURES:
hci_remote_host_features_evt(hdev, skb);
break;

default:
BT_DBG("%s event 0x%x", hdev->name, event);
break;
Expand Down

0 comments on commit 41a9621

Please sign in to comment.