diff options
| author | Johan Hedberg <johan.hedberg@intel.com> | 2012-09-06 11:39:26 -0400 |
|---|---|---|
| committer | Gustavo Padovan <gustavo.padovan@collabora.co.uk> | 2012-09-18 21:27:29 -0400 |
| commit | 92a25256f142d55e25f9959441cea6ddeabae57e (patch) | |
| tree | eb276a7076d59e7d29f14139b3993d441c3ea0fd /net/bluetooth | |
| parent | 5ad777958621524b48d1bdf4aaf3b26a363d4553 (diff) | |
Bluetooth: mgmt: Implement support for passkey notification
This patch adds support for Secure Simple Pairing with devices that have
KeyboardOnly as their IO capability. Such devices will cause a passkey
notification on our side and optionally also keypress notifications.
Without this patch some keyboards cannot be paired using the mgmt
interface.
Signed-off-by: Johan Hedberg <johan.hedberg@intel.com>
Cc: stable@vger.kernel.org
Acked-by: Marcel Holtmann <marcel@holtmann.org>
Signed-off-by: Gustavo Padovan <gustavo.padovan@collabora.co.uk>
Diffstat (limited to 'net/bluetooth')
| -rw-r--r-- | net/bluetooth/hci_event.c | 67 | ||||
| -rw-r--r-- | net/bluetooth/mgmt.c | 17 |
2 files changed, 84 insertions, 0 deletions
diff --git a/net/bluetooth/hci_event.c b/net/bluetooth/hci_event.c index 48d730228c2f..ccca88fc6195 100644 --- a/net/bluetooth/hci_event.c +++ b/net/bluetooth/hci_event.c | |||
| @@ -3263,6 +3263,65 @@ static void hci_user_passkey_request_evt(struct hci_dev *hdev, | |||
| 3263 | mgmt_user_passkey_request(hdev, &ev->bdaddr, ACL_LINK, 0); | 3263 | mgmt_user_passkey_request(hdev, &ev->bdaddr, ACL_LINK, 0); |
| 3264 | } | 3264 | } |
| 3265 | 3265 | ||
| 3266 | static void hci_user_passkey_notify_evt(struct hci_dev *hdev, | ||
| 3267 | struct sk_buff *skb) | ||
| 3268 | { | ||
| 3269 | struct hci_ev_user_passkey_notify *ev = (void *) skb->data; | ||
| 3270 | struct hci_conn *conn; | ||
| 3271 | |||
| 3272 | BT_DBG("%s", hdev->name); | ||
| 3273 | |||
| 3274 | conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr); | ||
| 3275 | if (!conn) | ||
| 3276 | return; | ||
| 3277 | |||
| 3278 | conn->passkey_notify = __le32_to_cpu(ev->passkey); | ||
| 3279 | conn->passkey_entered = 0; | ||
| 3280 | |||
| 3281 | if (test_bit(HCI_MGMT, &hdev->dev_flags)) | ||
| 3282 | mgmt_user_passkey_notify(hdev, &conn->dst, conn->type, | ||
| 3283 | conn->dst_type, conn->passkey_notify, | ||
| 3284 | conn->passkey_entered); | ||
| 3285 | } | ||
| 3286 | |||
| 3287 | static void hci_keypress_notify_evt(struct hci_dev *hdev, struct sk_buff *skb) | ||
| 3288 | { | ||
| 3289 | struct hci_ev_keypress_notify *ev = (void *) skb->data; | ||
| 3290 | struct hci_conn *conn; | ||
| 3291 | |||
| 3292 | BT_DBG("%s", hdev->name); | ||
| 3293 | |||
| 3294 | conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr); | ||
| 3295 | if (!conn) | ||
| 3296 | return; | ||
| 3297 | |||
| 3298 | switch (ev->type) { | ||
| 3299 | case HCI_KEYPRESS_STARTED: | ||
| 3300 | conn->passkey_entered = 0; | ||
| 3301 | return; | ||
| 3302 | |||
| 3303 | case HCI_KEYPRESS_ENTERED: | ||
| 3304 | conn->passkey_entered++; | ||
| 3305 | break; | ||
| 3306 | |||
| 3307 | case HCI_KEYPRESS_ERASED: | ||
| 3308 | conn->passkey_entered--; | ||
| 3309 | break; | ||
| 3310 | |||
| 3311 | case HCI_KEYPRESS_CLEARED: | ||
| 3312 | conn->passkey_entered = 0; | ||
| 3313 | break; | ||
| 3314 | |||
| 3315 | case HCI_KEYPRESS_COMPLETED: | ||
| 3316 | return; | ||
| 3317 | } | ||
| 3318 | |||
| 3319 | if (test_bit(HCI_MGMT, &hdev->dev_flags)) | ||
| 3320 | mgmt_user_passkey_notify(hdev, &conn->dst, conn->type, | ||
| 3321 | conn->dst_type, conn->passkey_notify, | ||
| 3322 | conn->passkey_entered); | ||
| 3323 | } | ||
| 3324 | |||
| 3266 | static void hci_simple_pair_complete_evt(struct hci_dev *hdev, | 3325 | static void hci_simple_pair_complete_evt(struct hci_dev *hdev, |
| 3267 | struct sk_buff *skb) | 3326 | struct sk_buff *skb) |
| 3268 | { | 3327 | { |
| @@ -3627,6 +3686,14 @@ void hci_event_packet(struct hci_dev *hdev, struct sk_buff *skb) | |||
| 3627 | hci_user_passkey_request_evt(hdev, skb); | 3686 | hci_user_passkey_request_evt(hdev, skb); |
| 3628 | break; | 3687 | break; |
| 3629 | 3688 | ||
| 3689 | case HCI_EV_USER_PASSKEY_NOTIFY: | ||
| 3690 | hci_user_passkey_notify_evt(hdev, skb); | ||
| 3691 | break; | ||
| 3692 | |||
| 3693 | case HCI_EV_KEYPRESS_NOTIFY: | ||
| 3694 | hci_keypress_notify_evt(hdev, skb); | ||
| 3695 | break; | ||
| 3696 | |||
| 3630 | case HCI_EV_SIMPLE_PAIR_COMPLETE: | 3697 | case HCI_EV_SIMPLE_PAIR_COMPLETE: |
| 3631 | hci_simple_pair_complete_evt(hdev, skb); | 3698 | hci_simple_pair_complete_evt(hdev, skb); |
| 3632 | break; | 3699 | break; |
diff --git a/net/bluetooth/mgmt.c b/net/bluetooth/mgmt.c index 05d4b83a0189..8e1ab59a9cef 100644 --- a/net/bluetooth/mgmt.c +++ b/net/bluetooth/mgmt.c | |||
| @@ -99,6 +99,7 @@ static const u16 mgmt_events[] = { | |||
| 99 | MGMT_EV_DEVICE_BLOCKED, | 99 | MGMT_EV_DEVICE_BLOCKED, |
| 100 | MGMT_EV_DEVICE_UNBLOCKED, | 100 | MGMT_EV_DEVICE_UNBLOCKED, |
| 101 | MGMT_EV_DEVICE_UNPAIRED, | 101 | MGMT_EV_DEVICE_UNPAIRED, |
| 102 | MGMT_EV_PASSKEY_NOTIFY, | ||
| 102 | }; | 103 | }; |
| 103 | 104 | ||
| 104 | /* | 105 | /* |
| @@ -3276,6 +3277,22 @@ int mgmt_user_passkey_neg_reply_complete(struct hci_dev *hdev, bdaddr_t *bdaddr, | |||
| 3276 | MGMT_OP_USER_PASSKEY_NEG_REPLY); | 3277 | MGMT_OP_USER_PASSKEY_NEG_REPLY); |
| 3277 | } | 3278 | } |
| 3278 | 3279 | ||
| 3280 | int mgmt_user_passkey_notify(struct hci_dev *hdev, bdaddr_t *bdaddr, | ||
| 3281 | u8 link_type, u8 addr_type, u32 passkey, | ||
| 3282 | u8 entered) | ||
| 3283 | { | ||
| 3284 | struct mgmt_ev_passkey_notify ev; | ||
| 3285 | |||
| 3286 | BT_DBG("%s", hdev->name); | ||
| 3287 | |||
| 3288 | bacpy(&ev.addr.bdaddr, bdaddr); | ||
| 3289 | ev.addr.type = link_to_bdaddr(link_type, addr_type); | ||
| 3290 | ev.passkey = __cpu_to_le32(passkey); | ||
| 3291 | ev.entered = entered; | ||
| 3292 | |||
| 3293 | return mgmt_event(MGMT_EV_PASSKEY_NOTIFY, hdev, &ev, sizeof(ev), NULL); | ||
| 3294 | } | ||
| 3295 | |||
| 3279 | int mgmt_auth_failed(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 link_type, | 3296 | int mgmt_auth_failed(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 link_type, |
| 3280 | u8 addr_type, u8 status) | 3297 | u8 addr_type, u8 status) |
| 3281 | { | 3298 | { |
