blob: 78f1af52ed818186d14c288bdea08c15b76b7948 [file] [log] [blame]
YOSHIFUJI Hideaki8e87d142007-02-09 23:24:33 +09001/*
Linus Torvalds1da177e2005-04-16 15:20:36 -07002 BlueZ - Bluetooth protocol stack for Linux
Ron Shaffer2d0a0342010-05-28 11:53:46 -04003 Copyright (c) 2000-2001, 2010, Code Aurora Forum. All rights reserved.
Linus Torvalds1da177e2005-04-16 15:20:36 -07004
5 Written 2000,2001 by Maxim Krasnyansky <maxk@qualcomm.com>
6
7 This program is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License version 2 as
9 published by the Free Software Foundation;
10
11 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
12 OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
13 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF THIRD PARTY RIGHTS.
14 IN NO EVENT SHALL THE COPYRIGHT HOLDER(S) AND AUTHOR(S) BE LIABLE FOR ANY
YOSHIFUJI Hideaki8e87d142007-02-09 23:24:33 +090015 CLAIM, OR ANY SPECIAL INDIRECT OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES
16 WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
17 ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
Linus Torvalds1da177e2005-04-16 15:20:36 -070018 OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
19
YOSHIFUJI Hideaki8e87d142007-02-09 23:24:33 +090020 ALL LIABILITY, INCLUDING LIABILITY FOR INFRINGEMENT OF ANY PATENTS,
21 COPYRIGHTS, TRADEMARKS OR OTHER RIGHTS, RELATING TO USE OF THIS
Linus Torvalds1da177e2005-04-16 15:20:36 -070022 SOFTWARE IS DISCLAIMED.
23*/
24
25/* Bluetooth HCI event handling. */
26
Gustavo Padovan8c520a52012-05-23 04:04:22 -030027#include <linux/export.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070028#include <asm/unaligned.h>
29
30#include <net/bluetooth/bluetooth.h>
31#include <net/bluetooth/hci_core.h>
Mikel Astizf0d6a0e2012-08-09 09:52:30 +020032#include <net/bluetooth/mgmt.h>
Andrei Emeltchenko8e2a0d92012-09-27 17:26:08 +030033#include <net/bluetooth/a2mp.h>
Andrei Emeltchenko903e4542012-09-27 17:26:09 +030034#include <net/bluetooth/amp.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070035
Linus Torvalds1da177e2005-04-16 15:20:36 -070036/* Handle HCI Event packets */
37
Marcel Holtmanna9de9242007-10-20 13:33:56 +020038static void hci_cc_inquiry_cancel(struct hci_dev *hdev, struct sk_buff *skb)
Linus Torvalds1da177e2005-04-16 15:20:36 -070039{
Marcel Holtmanna9de9242007-10-20 13:33:56 +020040 __u8 status = *((__u8 *) skb->data);
Linus Torvalds1da177e2005-04-16 15:20:36 -070041
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +030042 BT_DBG("%s status 0x%2.2x", hdev->name, status);
Linus Torvalds1da177e2005-04-16 15:20:36 -070043
Andre Guedese6d465c2011-11-09 17:14:26 -030044 if (status) {
45 hci_dev_lock(hdev);
46 mgmt_stop_discovery_failed(hdev, status);
47 hci_dev_unlock(hdev);
Marcel Holtmanna9de9242007-10-20 13:33:56 +020048 return;
Andre Guedese6d465c2011-11-09 17:14:26 -030049 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070050
Andre Guedes89352e72011-11-04 14:16:53 -030051 clear_bit(HCI_INQUIRY, &hdev->flags);
52
Johan Hedberg56e5cb82011-11-08 20:40:16 +020053 hci_dev_lock(hdev);
Johan Hedbergff9ef572012-01-04 14:23:45 +020054 hci_discovery_set_state(hdev, DISCOVERY_STOPPED);
Johan Hedberg56e5cb82011-11-08 20:40:16 +020055 hci_dev_unlock(hdev);
Marcel Holtmann6bd57412006-11-18 22:14:22 +010056
Johan Hedberg23bb5762010-12-21 23:01:27 +020057 hci_req_complete(hdev, HCI_OP_INQUIRY_CANCEL, status);
Marcel Holtmann6bd57412006-11-18 22:14:22 +010058
Marcel Holtmanna9de9242007-10-20 13:33:56 +020059 hci_conn_check_pending(hdev);
Linus Torvalds1da177e2005-04-16 15:20:36 -070060}
61
Andre Guedes4d934832012-03-21 00:03:35 -030062static void hci_cc_periodic_inq(struct hci_dev *hdev, struct sk_buff *skb)
63{
64 __u8 status = *((__u8 *) skb->data);
65
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +030066 BT_DBG("%s status 0x%2.2x", hdev->name, status);
Andre Guedesae854a72012-03-21 00:03:36 -030067
68 if (status)
69 return;
70
71 set_bit(HCI_PERIODIC_INQ, &hdev->dev_flags);
Andre Guedes4d934832012-03-21 00:03:35 -030072}
73
Marcel Holtmanna9de9242007-10-20 13:33:56 +020074static void hci_cc_exit_periodic_inq(struct hci_dev *hdev, struct sk_buff *skb)
Linus Torvalds1da177e2005-04-16 15:20:36 -070075{
Marcel Holtmanna9de9242007-10-20 13:33:56 +020076 __u8 status = *((__u8 *) skb->data);
77
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +030078 BT_DBG("%s status 0x%2.2x", hdev->name, status);
Marcel Holtmanna9de9242007-10-20 13:33:56 +020079
80 if (status)
81 return;
82
Andre Guedesae854a72012-03-21 00:03:36 -030083 clear_bit(HCI_PERIODIC_INQ, &hdev->dev_flags);
84
Marcel Holtmanna9de9242007-10-20 13:33:56 +020085 hci_conn_check_pending(hdev);
86}
87
Gustavo Padovan807deac2012-05-17 00:36:24 -030088static void hci_cc_remote_name_req_cancel(struct hci_dev *hdev,
89 struct sk_buff *skb)
Marcel Holtmanna9de9242007-10-20 13:33:56 +020090{
91 BT_DBG("%s", hdev->name);
92}
93
94static void hci_cc_role_discovery(struct hci_dev *hdev, struct sk_buff *skb)
95{
96 struct hci_rp_role_discovery *rp = (void *) skb->data;
Linus Torvalds1da177e2005-04-16 15:20:36 -070097 struct hci_conn *conn;
Linus Torvalds1da177e2005-04-16 15:20:36 -070098
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +030099 BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700100
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200101 if (rp->status)
102 return;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700103
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200104 hci_dev_lock(hdev);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700105
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200106 conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(rp->handle));
107 if (conn) {
108 if (rp->role)
109 conn->link_mode &= ~HCI_LM_MASTER;
110 else
111 conn->link_mode |= HCI_LM_MASTER;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700112 }
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200113
114 hci_dev_unlock(hdev);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700115}
116
Marcel Holtmanne4e8e372008-07-14 20:13:47 +0200117static void hci_cc_read_link_policy(struct hci_dev *hdev, struct sk_buff *skb)
118{
119 struct hci_rp_read_link_policy *rp = (void *) skb->data;
120 struct hci_conn *conn;
121
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +0300122 BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
Marcel Holtmanne4e8e372008-07-14 20:13:47 +0200123
124 if (rp->status)
125 return;
126
127 hci_dev_lock(hdev);
128
129 conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(rp->handle));
130 if (conn)
131 conn->link_policy = __le16_to_cpu(rp->policy);
132
133 hci_dev_unlock(hdev);
134}
135
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200136static void hci_cc_write_link_policy(struct hci_dev *hdev, struct sk_buff *skb)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700137{
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200138 struct hci_rp_write_link_policy *rp = (void *) skb->data;
139 struct hci_conn *conn;
140 void *sent;
141
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +0300142 BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200143
144 if (rp->status)
145 return;
146
147 sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_LINK_POLICY);
148 if (!sent)
149 return;
150
151 hci_dev_lock(hdev);
152
153 conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(rp->handle));
Marcel Holtmanne4e8e372008-07-14 20:13:47 +0200154 if (conn)
Harvey Harrison83985312008-05-02 16:25:46 -0700155 conn->link_policy = get_unaligned_le16(sent + 2);
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200156
157 hci_dev_unlock(hdev);
158}
159
Gustavo Padovan807deac2012-05-17 00:36:24 -0300160static void hci_cc_read_def_link_policy(struct hci_dev *hdev,
161 struct sk_buff *skb)
Marcel Holtmanne4e8e372008-07-14 20:13:47 +0200162{
163 struct hci_rp_read_def_link_policy *rp = (void *) skb->data;
164
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +0300165 BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
Marcel Holtmanne4e8e372008-07-14 20:13:47 +0200166
167 if (rp->status)
168 return;
169
170 hdev->link_policy = __le16_to_cpu(rp->policy);
171}
172
Gustavo Padovan807deac2012-05-17 00:36:24 -0300173static void hci_cc_write_def_link_policy(struct hci_dev *hdev,
174 struct sk_buff *skb)
Marcel Holtmanne4e8e372008-07-14 20:13:47 +0200175{
176 __u8 status = *((__u8 *) skb->data);
177 void *sent;
178
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +0300179 BT_DBG("%s status 0x%2.2x", hdev->name, status);
Marcel Holtmanne4e8e372008-07-14 20:13:47 +0200180
181 sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_DEF_LINK_POLICY);
182 if (!sent)
183 return;
184
185 if (!status)
186 hdev->link_policy = get_unaligned_le16(sent);
187
Johan Hedberg23bb5762010-12-21 23:01:27 +0200188 hci_req_complete(hdev, HCI_OP_WRITE_DEF_LINK_POLICY, status);
Marcel Holtmanne4e8e372008-07-14 20:13:47 +0200189}
190
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200191static void hci_cc_reset(struct hci_dev *hdev, struct sk_buff *skb)
192{
193 __u8 status = *((__u8 *) skb->data);
194
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +0300195 BT_DBG("%s status 0x%2.2x", hdev->name, status);
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200196
Gustavo F. Padovan10572132011-03-16 15:36:29 -0300197 clear_bit(HCI_RESET, &hdev->flags);
198
Johan Hedberg23bb5762010-12-21 23:01:27 +0200199 hci_req_complete(hdev, HCI_OP_RESET, status);
Andre Guedesd23264a2011-11-25 20:53:38 -0300200
Johan Hedberga297e972012-02-21 17:55:47 +0200201 /* Reset all non-persistent flags */
Andre Guedesae854a72012-03-21 00:03:36 -0300202 hdev->dev_flags &= ~(BIT(HCI_LE_SCAN) | BIT(HCI_PENDING_CLASS) |
203 BIT(HCI_PERIODIC_INQ));
Andre Guedes69775ff2012-02-23 16:50:05 +0200204
205 hdev->discovery.state = DISCOVERY_STOPPED;
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200206}
207
208static void hci_cc_write_local_name(struct hci_dev *hdev, struct sk_buff *skb)
209{
210 __u8 status = *((__u8 *) skb->data);
211 void *sent;
212
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +0300213 BT_DBG("%s status 0x%2.2x", hdev->name, status);
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200214
215 sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_LOCAL_NAME);
216 if (!sent)
217 return;
218
Johan Hedberg56e5cb82011-11-08 20:40:16 +0200219 hci_dev_lock(hdev);
220
Johan Hedbergf51d5b22012-02-22 18:17:32 +0200221 if (test_bit(HCI_MGMT, &hdev->dev_flags))
222 mgmt_set_local_name_complete(hdev, sent, status);
Johan Hedberg28cc7bd2012-02-22 21:06:55 +0200223 else if (!status)
224 memcpy(hdev->dev_name, sent, HCI_MAX_NAME_LENGTH);
Johan Hedbergf51d5b22012-02-22 18:17:32 +0200225
Johan Hedberg56e5cb82011-11-08 20:40:16 +0200226 hci_dev_unlock(hdev);
Johan Hedberg3159d382012-02-24 13:47:56 +0200227
228 hci_req_complete(hdev, HCI_OP_WRITE_LOCAL_NAME, status);
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200229}
230
231static void hci_cc_read_local_name(struct hci_dev *hdev, struct sk_buff *skb)
232{
233 struct hci_rp_read_local_name *rp = (void *) skb->data;
234
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +0300235 BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200236
237 if (rp->status)
238 return;
239
Johan Hedbergdb99b5f2012-02-22 20:14:22 +0200240 if (test_bit(HCI_SETUP, &hdev->dev_flags))
241 memcpy(hdev->dev_name, rp->name, HCI_MAX_NAME_LENGTH);
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200242}
243
244static void hci_cc_write_auth_enable(struct hci_dev *hdev, struct sk_buff *skb)
245{
246 __u8 status = *((__u8 *) skb->data);
247 void *sent;
248
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +0300249 BT_DBG("%s status 0x%2.2x", hdev->name, status);
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200250
251 sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_AUTH_ENABLE);
252 if (!sent)
253 return;
254
255 if (!status) {
256 __u8 param = *((__u8 *) sent);
257
258 if (param == AUTH_ENABLED)
259 set_bit(HCI_AUTH, &hdev->flags);
260 else
261 clear_bit(HCI_AUTH, &hdev->flags);
262 }
263
Johan Hedberg33ef95e2012-02-16 23:56:27 +0200264 if (test_bit(HCI_MGMT, &hdev->dev_flags))
265 mgmt_auth_enable_complete(hdev, status);
266
Johan Hedberg23bb5762010-12-21 23:01:27 +0200267 hci_req_complete(hdev, HCI_OP_WRITE_AUTH_ENABLE, status);
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200268}
269
270static void hci_cc_write_encrypt_mode(struct hci_dev *hdev, struct sk_buff *skb)
271{
272 __u8 status = *((__u8 *) skb->data);
273 void *sent;
274
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +0300275 BT_DBG("%s status 0x%2.2x", hdev->name, status);
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200276
277 sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_ENCRYPT_MODE);
278 if (!sent)
279 return;
280
281 if (!status) {
282 __u8 param = *((__u8 *) sent);
283
284 if (param)
285 set_bit(HCI_ENCRYPT, &hdev->flags);
286 else
287 clear_bit(HCI_ENCRYPT, &hdev->flags);
288 }
289
Johan Hedberg23bb5762010-12-21 23:01:27 +0200290 hci_req_complete(hdev, HCI_OP_WRITE_ENCRYPT_MODE, status);
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200291}
292
293static void hci_cc_write_scan_enable(struct hci_dev *hdev, struct sk_buff *skb)
294{
Johan Hedberg36f7fc72011-11-04 00:17:45 +0200295 __u8 param, status = *((__u8 *) skb->data);
296 int old_pscan, old_iscan;
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200297 void *sent;
298
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +0300299 BT_DBG("%s status 0x%2.2x", hdev->name, status);
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200300
301 sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_SCAN_ENABLE);
302 if (!sent)
303 return;
304
Johan Hedberg36f7fc72011-11-04 00:17:45 +0200305 param = *((__u8 *) sent);
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200306
Johan Hedberg56e5cb82011-11-08 20:40:16 +0200307 hci_dev_lock(hdev);
308
Mikel Astizfa1bd912012-08-09 09:52:29 +0200309 if (status) {
Johan Hedberg744cf192011-11-08 20:40:14 +0200310 mgmt_write_scan_failed(hdev, param, status);
Johan Hedberg2d7cee52011-11-07 22:16:03 +0200311 hdev->discov_timeout = 0;
312 goto done;
313 }
314
Johan Hedberg36f7fc72011-11-04 00:17:45 +0200315 old_pscan = test_and_clear_bit(HCI_PSCAN, &hdev->flags);
316 old_iscan = test_and_clear_bit(HCI_ISCAN, &hdev->flags);
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200317
Johan Hedberg36f7fc72011-11-04 00:17:45 +0200318 if (param & SCAN_INQUIRY) {
319 set_bit(HCI_ISCAN, &hdev->flags);
320 if (!old_iscan)
Johan Hedberg744cf192011-11-08 20:40:14 +0200321 mgmt_discoverable(hdev, 1);
Johan Hedberg16ab91a2011-11-07 22:16:02 +0200322 if (hdev->discov_timeout > 0) {
323 int to = msecs_to_jiffies(hdev->discov_timeout * 1000);
324 queue_delayed_work(hdev->workqueue, &hdev->discov_off,
Gustavo Padovan807deac2012-05-17 00:36:24 -0300325 to);
Johan Hedberg16ab91a2011-11-07 22:16:02 +0200326 }
Johan Hedberg36f7fc72011-11-04 00:17:45 +0200327 } else if (old_iscan)
Johan Hedberg744cf192011-11-08 20:40:14 +0200328 mgmt_discoverable(hdev, 0);
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200329
Johan Hedberg36f7fc72011-11-04 00:17:45 +0200330 if (param & SCAN_PAGE) {
331 set_bit(HCI_PSCAN, &hdev->flags);
332 if (!old_pscan)
Johan Hedberg744cf192011-11-08 20:40:14 +0200333 mgmt_connectable(hdev, 1);
Johan Hedberg36f7fc72011-11-04 00:17:45 +0200334 } else if (old_pscan)
Johan Hedberg744cf192011-11-08 20:40:14 +0200335 mgmt_connectable(hdev, 0);
Johan Hedberg36f7fc72011-11-04 00:17:45 +0200336
337done:
Johan Hedberg56e5cb82011-11-08 20:40:16 +0200338 hci_dev_unlock(hdev);
Johan Hedberg23bb5762010-12-21 23:01:27 +0200339 hci_req_complete(hdev, HCI_OP_WRITE_SCAN_ENABLE, status);
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200340}
341
342static void hci_cc_read_class_of_dev(struct hci_dev *hdev, struct sk_buff *skb)
343{
344 struct hci_rp_read_class_of_dev *rp = (void *) skb->data;
345
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +0300346 BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200347
348 if (rp->status)
349 return;
350
351 memcpy(hdev->dev_class, rp->dev_class, 3);
352
353 BT_DBG("%s class 0x%.2x%.2x%.2x", hdev->name,
Gustavo Padovan807deac2012-05-17 00:36:24 -0300354 hdev->dev_class[2], hdev->dev_class[1], hdev->dev_class[0]);
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200355}
356
357static void hci_cc_write_class_of_dev(struct hci_dev *hdev, struct sk_buff *skb)
358{
359 __u8 status = *((__u8 *) skb->data);
360 void *sent;
361
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +0300362 BT_DBG("%s status 0x%2.2x", hdev->name, status);
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200363
364 sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_CLASS_OF_DEV);
365 if (!sent)
366 return;
367
Marcel Holtmann7f9a9032012-02-22 18:38:01 +0100368 hci_dev_lock(hdev);
369
370 if (status == 0)
371 memcpy(hdev->dev_class, sent, 3);
372
373 if (test_bit(HCI_MGMT, &hdev->dev_flags))
374 mgmt_set_class_of_dev_complete(hdev, sent, status);
375
376 hci_dev_unlock(hdev);
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200377}
378
379static void hci_cc_read_voice_setting(struct hci_dev *hdev, struct sk_buff *skb)
380{
381 struct hci_rp_read_voice_setting *rp = (void *) skb->data;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700382 __u16 setting;
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200383
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +0300384 BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200385
386 if (rp->status)
387 return;
388
389 setting = __le16_to_cpu(rp->voice_setting);
390
Marcel Holtmannf383f272008-07-14 20:13:47 +0200391 if (hdev->voice_setting == setting)
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200392 return;
393
394 hdev->voice_setting = setting;
395
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +0300396 BT_DBG("%s voice setting 0x%4.4x", hdev->name, setting);
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200397
Gustavo F. Padovan3c547112011-12-14 22:58:44 -0200398 if (hdev->notify)
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200399 hdev->notify(hdev, HCI_NOTIFY_VOICE_SETTING);
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200400}
401
Gustavo Padovan8fc9ced2012-05-23 04:04:21 -0300402static void hci_cc_write_voice_setting(struct hci_dev *hdev,
403 struct sk_buff *skb)
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200404{
405 __u8 status = *((__u8 *) skb->data);
Marcel Holtmannf383f272008-07-14 20:13:47 +0200406 __u16 setting;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700407 void *sent;
408
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +0300409 BT_DBG("%s status 0x%2.2x", hdev->name, status);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700410
Marcel Holtmannf383f272008-07-14 20:13:47 +0200411 if (status)
412 return;
413
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200414 sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_VOICE_SETTING);
415 if (!sent)
416 return;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700417
Marcel Holtmannf383f272008-07-14 20:13:47 +0200418 setting = get_unaligned_le16(sent);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700419
Marcel Holtmannf383f272008-07-14 20:13:47 +0200420 if (hdev->voice_setting == setting)
421 return;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700422
Marcel Holtmannf383f272008-07-14 20:13:47 +0200423 hdev->voice_setting = setting;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700424
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +0300425 BT_DBG("%s voice setting 0x%4.4x", hdev->name, setting);
Marcel Holtmannf383f272008-07-14 20:13:47 +0200426
Gustavo F. Padovan3c547112011-12-14 22:58:44 -0200427 if (hdev->notify)
Marcel Holtmannf383f272008-07-14 20:13:47 +0200428 hdev->notify(hdev, HCI_NOTIFY_VOICE_SETTING);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700429}
430
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200431static void hci_cc_host_buffer_size(struct hci_dev *hdev, struct sk_buff *skb)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700432{
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200433 __u8 status = *((__u8 *) skb->data);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700434
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +0300435 BT_DBG("%s status 0x%2.2x", hdev->name, status);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700436
Johan Hedberg23bb5762010-12-21 23:01:27 +0200437 hci_req_complete(hdev, HCI_OP_HOST_BUFFER_SIZE, status);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700438}
439
Marcel Holtmann333140b2008-07-14 20:13:48 +0200440static void hci_cc_write_ssp_mode(struct hci_dev *hdev, struct sk_buff *skb)
441{
442 __u8 status = *((__u8 *) skb->data);
443 void *sent;
444
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +0300445 BT_DBG("%s status 0x%2.2x", hdev->name, status);
Marcel Holtmann333140b2008-07-14 20:13:48 +0200446
Marcel Holtmann333140b2008-07-14 20:13:48 +0200447 sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_SSP_MODE);
448 if (!sent)
449 return;
450
Johan Hedberged2c4ee2012-02-17 00:56:28 +0200451 if (test_bit(HCI_MGMT, &hdev->dev_flags))
Johan Hedbergc0ecddc2012-02-22 12:38:31 +0200452 mgmt_ssp_enable_complete(hdev, *((u8 *) sent), status);
453 else if (!status) {
454 if (*((u8 *) sent))
455 set_bit(HCI_SSP_ENABLED, &hdev->dev_flags);
456 else
457 clear_bit(HCI_SSP_ENABLED, &hdev->dev_flags);
458 }
Marcel Holtmann333140b2008-07-14 20:13:48 +0200459}
460
Johan Hedbergd5859e22011-01-25 01:19:58 +0200461static u8 hci_get_inquiry_mode(struct hci_dev *hdev)
462{
463 if (hdev->features[6] & LMP_EXT_INQ)
464 return 2;
465
466 if (hdev->features[3] & LMP_RSSI_INQ)
467 return 1;
468
469 if (hdev->manufacturer == 11 && hdev->hci_rev == 0x00 &&
Gustavo Padovan807deac2012-05-17 00:36:24 -0300470 hdev->lmp_subver == 0x0757)
Johan Hedbergd5859e22011-01-25 01:19:58 +0200471 return 1;
472
473 if (hdev->manufacturer == 15) {
474 if (hdev->hci_rev == 0x03 && hdev->lmp_subver == 0x6963)
475 return 1;
476 if (hdev->hci_rev == 0x09 && hdev->lmp_subver == 0x6963)
477 return 1;
478 if (hdev->hci_rev == 0x00 && hdev->lmp_subver == 0x6965)
479 return 1;
480 }
481
482 if (hdev->manufacturer == 31 && hdev->hci_rev == 0x2005 &&
Gustavo Padovan807deac2012-05-17 00:36:24 -0300483 hdev->lmp_subver == 0x1805)
Johan Hedbergd5859e22011-01-25 01:19:58 +0200484 return 1;
485
486 return 0;
487}
488
489static void hci_setup_inquiry_mode(struct hci_dev *hdev)
490{
491 u8 mode;
492
493 mode = hci_get_inquiry_mode(hdev);
494
495 hci_send_cmd(hdev, HCI_OP_WRITE_INQUIRY_MODE, 1, &mode);
496}
497
498static void hci_setup_event_mask(struct hci_dev *hdev)
499{
500 /* The second byte is 0xff instead of 0x9f (two reserved bits
501 * disabled) since a Broadcom 1.2 dongle doesn't respond to the
502 * command otherwise */
503 u8 events[8] = { 0xff, 0xff, 0xfb, 0xff, 0x00, 0x00, 0x00, 0x00 };
504
Ville Tervo6de6c182011-05-27 11:16:21 +0300505 /* CSR 1.1 dongles does not accept any bitfield so don't try to set
506 * any event mask for pre 1.2 devices */
Andrei Emeltchenko5a13b092011-12-01 14:33:28 +0200507 if (hdev->hci_ver < BLUETOOTH_VER_1_2)
Ville Tervo6de6c182011-05-27 11:16:21 +0300508 return;
509
Johan Hedberge1171e82012-10-19 20:57:45 +0300510 if (lmp_bredr_capable(hdev)) {
511 events[4] |= 0x01; /* Flow Specification Complete */
512 events[4] |= 0x02; /* Inquiry Result with RSSI */
513 events[4] |= 0x04; /* Read Remote Extended Features Complete */
514 events[5] |= 0x08; /* Synchronous Connection Complete */
515 events[5] |= 0x10; /* Synchronous Connection Changed */
516 }
Johan Hedbergd5859e22011-01-25 01:19:58 +0200517
518 if (hdev->features[3] & LMP_RSSI_INQ)
Johan Hedberga24299e2012-04-26 09:47:46 +0300519 events[4] |= 0x02; /* Inquiry Result with RSSI */
Johan Hedbergd5859e22011-01-25 01:19:58 +0200520
Andre Guedes999dcd12012-07-24 15:03:52 -0300521 if (lmp_sniffsubr_capable(hdev))
Johan Hedbergd5859e22011-01-25 01:19:58 +0200522 events[5] |= 0x20; /* Sniff Subrating */
523
524 if (hdev->features[5] & LMP_PAUSE_ENC)
525 events[5] |= 0x80; /* Encryption Key Refresh Complete */
526
527 if (hdev->features[6] & LMP_EXT_INQ)
528 events[5] |= 0x40; /* Extended Inquiry Result */
529
Andre Guedesc58e8102012-07-24 15:03:53 -0300530 if (lmp_no_flush_capable(hdev))
Johan Hedbergd5859e22011-01-25 01:19:58 +0200531 events[7] |= 0x01; /* Enhanced Flush Complete */
532
533 if (hdev->features[7] & LMP_LSTO)
534 events[6] |= 0x80; /* Link Supervision Timeout Changed */
535
Andre Guedes9a1a1992012-07-24 15:03:48 -0300536 if (lmp_ssp_capable(hdev)) {
Johan Hedbergd5859e22011-01-25 01:19:58 +0200537 events[6] |= 0x01; /* IO Capability Request */
538 events[6] |= 0x02; /* IO Capability Response */
539 events[6] |= 0x04; /* User Confirmation Request */
540 events[6] |= 0x08; /* User Passkey Request */
541 events[6] |= 0x10; /* Remote OOB Data Request */
542 events[6] |= 0x20; /* Simple Pairing Complete */
543 events[7] |= 0x04; /* User Passkey Notification */
544 events[7] |= 0x08; /* Keypress Notification */
545 events[7] |= 0x10; /* Remote Host Supported
546 * Features Notification */
547 }
548
Andre Guedesc383ddc2012-07-24 15:03:47 -0300549 if (lmp_le_capable(hdev))
Johan Hedbergd5859e22011-01-25 01:19:58 +0200550 events[7] |= 0x20; /* LE Meta-Event */
551
552 hci_send_cmd(hdev, HCI_OP_SET_EVENT_MASK, sizeof(events), events);
Johan Hedberge36b04c2012-10-19 20:57:47 +0300553
554 if (lmp_le_capable(hdev)) {
555 memset(events, 0, sizeof(events));
556 events[0] = 0x1f;
557 hci_send_cmd(hdev, HCI_OP_LE_SET_EVENT_MASK,
558 sizeof(events), events);
559 }
Johan Hedbergd5859e22011-01-25 01:19:58 +0200560}
561
Johan Hedberge1171e82012-10-19 20:57:45 +0300562static void bredr_init(struct hci_dev *hdev)
563{
564 struct hci_cp_delete_stored_link_key cp;
565 __le16 param;
566 __u8 flt_type;
567
568 /* Read Buffer Size (ACL mtu, max pkt, etc.) */
569 hci_send_cmd(hdev, HCI_OP_READ_BUFFER_SIZE, 0, NULL);
570
571 /* Read Class of Device */
572 hci_send_cmd(hdev, HCI_OP_READ_CLASS_OF_DEV, 0, NULL);
573
574 /* Read Local Name */
575 hci_send_cmd(hdev, HCI_OP_READ_LOCAL_NAME, 0, NULL);
576
577 /* Read Voice Setting */
578 hci_send_cmd(hdev, HCI_OP_READ_VOICE_SETTING, 0, NULL);
579
580 /* Clear Event Filters */
581 flt_type = HCI_FLT_CLEAR_ALL;
582 hci_send_cmd(hdev, HCI_OP_SET_EVENT_FLT, 1, &flt_type);
583
584 /* Connection accept timeout ~20 secs */
585 param = __constant_cpu_to_le16(0x7d00);
586 hci_send_cmd(hdev, HCI_OP_WRITE_CA_TIMEOUT, 2, &param);
587
588 bacpy(&cp.bdaddr, BDADDR_ANY);
589 cp.delete_all = 1;
590 hci_send_cmd(hdev, HCI_OP_DELETE_STORED_LINK_KEY, sizeof(cp), &cp);
591}
592
593static void le_init(struct hci_dev *hdev)
594{
595 /* Read LE Buffer Size */
596 hci_send_cmd(hdev, HCI_OP_LE_READ_BUFFER_SIZE, 0, NULL);
597}
598
Johan Hedbergd5859e22011-01-25 01:19:58 +0200599static void hci_setup(struct hci_dev *hdev)
600{
Andrei Emeltchenkoe61ef4992011-12-19 16:31:27 +0200601 if (hdev->dev_type != HCI_BREDR)
602 return;
603
Johan Hedberge1171e82012-10-19 20:57:45 +0300604 /* Read BD Address */
605 hci_send_cmd(hdev, HCI_OP_READ_BD_ADDR, 0, NULL);
606
607 if (lmp_bredr_capable(hdev))
608 bredr_init(hdev);
609
610 if (lmp_le_capable(hdev))
611 le_init(hdev);
612
Johan Hedbergd5859e22011-01-25 01:19:58 +0200613 hci_setup_event_mask(hdev);
614
Andrei Emeltchenkod095c1e2011-12-01 14:33:27 +0200615 if (hdev->hci_ver > BLUETOOTH_VER_1_1)
Johan Hedbergd5859e22011-01-25 01:19:58 +0200616 hci_send_cmd(hdev, HCI_OP_READ_LOCAL_COMMANDS, 0, NULL);
617
Gustavo Padovan6d3c7302012-05-24 03:36:37 -0300618 if (lmp_ssp_capable(hdev)) {
Johan Hedberg54d04db2012-02-22 15:47:48 +0200619 if (test_bit(HCI_SSP_ENABLED, &hdev->dev_flags)) {
620 u8 mode = 0x01;
621 hci_send_cmd(hdev, HCI_OP_WRITE_SSP_MODE,
Gustavo F. Padovan04124682012-03-08 01:25:00 -0300622 sizeof(mode), &mode);
Johan Hedberg54d04db2012-02-22 15:47:48 +0200623 } else {
624 struct hci_cp_write_eir cp;
625
626 memset(hdev->eir, 0, sizeof(hdev->eir));
627 memset(&cp, 0, sizeof(cp));
628
629 hci_send_cmd(hdev, HCI_OP_WRITE_EIR, sizeof(cp), &cp);
630 }
Johan Hedbergd5859e22011-01-25 01:19:58 +0200631 }
632
633 if (hdev->features[3] & LMP_RSSI_INQ)
634 hci_setup_inquiry_mode(hdev);
635
636 if (hdev->features[7] & LMP_INQ_TX_PWR)
637 hci_send_cmd(hdev, HCI_OP_READ_INQ_RSP_TX_POWER, 0, NULL);
Andre Guedes971e3a42011-06-30 19:20:52 -0300638
639 if (hdev->features[7] & LMP_EXTFEATURES) {
640 struct hci_cp_read_local_ext_features cp;
641
642 cp.page = 0x01;
Gustavo F. Padovan04124682012-03-08 01:25:00 -0300643 hci_send_cmd(hdev, HCI_OP_READ_LOCAL_EXT_FEATURES, sizeof(cp),
644 &cp);
Andre Guedes971e3a42011-06-30 19:20:52 -0300645 }
Andre Guedese6100a22011-06-30 19:20:54 -0300646
Johan Hedberg47990ea2012-02-22 11:58:37 +0200647 if (test_bit(HCI_LINK_SECURITY, &hdev->dev_flags)) {
648 u8 enable = 1;
Gustavo F. Padovan04124682012-03-08 01:25:00 -0300649 hci_send_cmd(hdev, HCI_OP_WRITE_AUTH_ENABLE, sizeof(enable),
650 &enable);
Johan Hedberg47990ea2012-02-22 11:58:37 +0200651 }
Johan Hedbergd5859e22011-01-25 01:19:58 +0200652}
653
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200654static void hci_cc_read_local_version(struct hci_dev *hdev, struct sk_buff *skb)
655{
656 struct hci_rp_read_local_version *rp = (void *) skb->data;
657
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +0300658 BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200659
660 if (rp->status)
Andrei Emeltchenko28b8df72012-02-24 12:45:44 +0200661 goto done;
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200662
663 hdev->hci_ver = rp->hci_ver;
Marcel Holtmanne4e8e372008-07-14 20:13:47 +0200664 hdev->hci_rev = __le16_to_cpu(rp->hci_rev);
Johan Hedbergd5859e22011-01-25 01:19:58 +0200665 hdev->lmp_ver = rp->lmp_ver;
Marcel Holtmanne4e8e372008-07-14 20:13:47 +0200666 hdev->manufacturer = __le16_to_cpu(rp->manufacturer);
Johan Hedbergd5859e22011-01-25 01:19:58 +0200667 hdev->lmp_subver = __le16_to_cpu(rp->lmp_subver);
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200668
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +0300669 BT_DBG("%s manufacturer 0x%4.4x hci ver %d:%d", hdev->name,
Gustavo Padovan807deac2012-05-17 00:36:24 -0300670 hdev->manufacturer, hdev->hci_ver, hdev->hci_rev);
Johan Hedbergd5859e22011-01-25 01:19:58 +0200671
672 if (test_bit(HCI_INIT, &hdev->flags))
673 hci_setup(hdev);
Andrei Emeltchenko28b8df72012-02-24 12:45:44 +0200674
675done:
676 hci_req_complete(hdev, HCI_OP_READ_LOCAL_VERSION, rp->status);
Johan Hedbergd5859e22011-01-25 01:19:58 +0200677}
678
679static void hci_setup_link_policy(struct hci_dev *hdev)
680{
Andrei Emeltchenko035100c2012-03-12 15:59:32 +0200681 struct hci_cp_write_def_link_policy cp;
Johan Hedbergd5859e22011-01-25 01:19:58 +0200682 u16 link_policy = 0;
683
Andre Guedes9f92ebf2012-07-24 15:03:50 -0300684 if (lmp_rswitch_capable(hdev))
Johan Hedbergd5859e22011-01-25 01:19:58 +0200685 link_policy |= HCI_LP_RSWITCH;
686 if (hdev->features[0] & LMP_HOLD)
687 link_policy |= HCI_LP_HOLD;
Andre Guedes6eded102012-07-24 15:03:51 -0300688 if (lmp_sniff_capable(hdev))
Johan Hedbergd5859e22011-01-25 01:19:58 +0200689 link_policy |= HCI_LP_SNIFF;
690 if (hdev->features[1] & LMP_PARK)
691 link_policy |= HCI_LP_PARK;
692
Andrei Emeltchenko035100c2012-03-12 15:59:32 +0200693 cp.policy = cpu_to_le16(link_policy);
694 hci_send_cmd(hdev, HCI_OP_WRITE_DEF_LINK_POLICY, sizeof(cp), &cp);
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200695}
696
Gustavo Padovan8fc9ced2012-05-23 04:04:21 -0300697static void hci_cc_read_local_commands(struct hci_dev *hdev,
698 struct sk_buff *skb)
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200699{
700 struct hci_rp_read_local_commands *rp = (void *) skb->data;
701
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +0300702 BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200703
704 if (rp->status)
Johan Hedbergd5859e22011-01-25 01:19:58 +0200705 goto done;
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200706
707 memcpy(hdev->commands, rp->commands, sizeof(hdev->commands));
Johan Hedbergd5859e22011-01-25 01:19:58 +0200708
709 if (test_bit(HCI_INIT, &hdev->flags) && (hdev->commands[5] & 0x10))
710 hci_setup_link_policy(hdev);
711
712done:
713 hci_req_complete(hdev, HCI_OP_READ_LOCAL_COMMANDS, rp->status);
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200714}
715
Gustavo Padovan8fc9ced2012-05-23 04:04:21 -0300716static void hci_cc_read_local_features(struct hci_dev *hdev,
717 struct sk_buff *skb)
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200718{
719 struct hci_rp_read_local_features *rp = (void *) skb->data;
720
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +0300721 BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200722
723 if (rp->status)
724 return;
725
726 memcpy(hdev->features, rp->features, 8);
727
728 /* Adjust default settings according to features
729 * supported by device. */
730
731 if (hdev->features[0] & LMP_3SLOT)
732 hdev->pkt_type |= (HCI_DM3 | HCI_DH3);
733
734 if (hdev->features[0] & LMP_5SLOT)
735 hdev->pkt_type |= (HCI_DM5 | HCI_DH5);
736
737 if (hdev->features[1] & LMP_HV2) {
738 hdev->pkt_type |= (HCI_HV2);
739 hdev->esco_type |= (ESCO_HV2);
740 }
741
742 if (hdev->features[1] & LMP_HV3) {
743 hdev->pkt_type |= (HCI_HV3);
744 hdev->esco_type |= (ESCO_HV3);
745 }
746
Andre Guedes45db810f2012-07-24 15:03:49 -0300747 if (lmp_esco_capable(hdev))
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200748 hdev->esco_type |= (ESCO_EV3);
749
750 if (hdev->features[4] & LMP_EV4)
751 hdev->esco_type |= (ESCO_EV4);
752
753 if (hdev->features[4] & LMP_EV5)
754 hdev->esco_type |= (ESCO_EV5);
755
Marcel Holtmannefc76882009-02-06 09:13:37 +0100756 if (hdev->features[5] & LMP_EDR_ESCO_2M)
757 hdev->esco_type |= (ESCO_2EV3);
758
759 if (hdev->features[5] & LMP_EDR_ESCO_3M)
760 hdev->esco_type |= (ESCO_3EV3);
761
762 if (hdev->features[5] & LMP_EDR_3S_ESCO)
763 hdev->esco_type |= (ESCO_2EV5 | ESCO_3EV5);
764
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200765 BT_DBG("%s features 0x%.2x%.2x%.2x%.2x%.2x%.2x%.2x%.2x", hdev->name,
Gustavo Padovan807deac2012-05-17 00:36:24 -0300766 hdev->features[0], hdev->features[1],
767 hdev->features[2], hdev->features[3],
768 hdev->features[4], hdev->features[5],
769 hdev->features[6], hdev->features[7]);
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200770}
771
Johan Hedberg8f984df2012-02-28 01:07:22 +0200772static void hci_set_le_support(struct hci_dev *hdev)
773{
774 struct hci_cp_write_le_host_supported cp;
775
776 memset(&cp, 0, sizeof(cp));
777
Marcel Holtmann9d428202012-05-03 07:12:31 +0200778 if (test_bit(HCI_LE_ENABLED, &hdev->dev_flags)) {
Johan Hedberg8f984df2012-02-28 01:07:22 +0200779 cp.le = 1;
780 cp.simul = !!(hdev->features[6] & LMP_SIMUL_LE_BR);
781 }
782
783 if (cp.le != !!(hdev->host_features[0] & LMP_HOST_LE))
Gustavo F. Padovan04124682012-03-08 01:25:00 -0300784 hci_send_cmd(hdev, HCI_OP_WRITE_LE_HOST_SUPPORTED, sizeof(cp),
785 &cp);
Johan Hedberg8f984df2012-02-28 01:07:22 +0200786}
787
Andre Guedes971e3a42011-06-30 19:20:52 -0300788static void hci_cc_read_local_ext_features(struct hci_dev *hdev,
Gustavo Padovan807deac2012-05-17 00:36:24 -0300789 struct sk_buff *skb)
Andre Guedes971e3a42011-06-30 19:20:52 -0300790{
791 struct hci_rp_read_local_ext_features *rp = (void *) skb->data;
792
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +0300793 BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
Andre Guedes971e3a42011-06-30 19:20:52 -0300794
795 if (rp->status)
Johan Hedberg8f984df2012-02-28 01:07:22 +0200796 goto done;
Andre Guedes971e3a42011-06-30 19:20:52 -0300797
Andre Guedesb5b32b62011-12-30 10:34:04 -0300798 switch (rp->page) {
799 case 0:
800 memcpy(hdev->features, rp->features, 8);
801 break;
802 case 1:
803 memcpy(hdev->host_features, rp->features, 8);
804 break;
805 }
Andre Guedes971e3a42011-06-30 19:20:52 -0300806
Andre Guedesc383ddc2012-07-24 15:03:47 -0300807 if (test_bit(HCI_INIT, &hdev->flags) && lmp_le_capable(hdev))
Johan Hedberg8f984df2012-02-28 01:07:22 +0200808 hci_set_le_support(hdev);
809
810done:
Andre Guedes971e3a42011-06-30 19:20:52 -0300811 hci_req_complete(hdev, HCI_OP_READ_LOCAL_EXT_FEATURES, rp->status);
812}
813
Andrei Emeltchenko1e89cff2011-11-24 14:52:02 +0200814static void hci_cc_read_flow_control_mode(struct hci_dev *hdev,
Gustavo Padovan807deac2012-05-17 00:36:24 -0300815 struct sk_buff *skb)
Andrei Emeltchenko1e89cff2011-11-24 14:52:02 +0200816{
817 struct hci_rp_read_flow_control_mode *rp = (void *) skb->data;
818
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +0300819 BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
Andrei Emeltchenko1e89cff2011-11-24 14:52:02 +0200820
821 if (rp->status)
822 return;
823
824 hdev->flow_ctl_mode = rp->mode;
825
826 hci_req_complete(hdev, HCI_OP_READ_FLOW_CONTROL_MODE, rp->status);
827}
828
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200829static void hci_cc_read_buffer_size(struct hci_dev *hdev, struct sk_buff *skb)
830{
831 struct hci_rp_read_buffer_size *rp = (void *) skb->data;
832
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +0300833 BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200834
835 if (rp->status)
836 return;
837
838 hdev->acl_mtu = __le16_to_cpu(rp->acl_mtu);
839 hdev->sco_mtu = rp->sco_mtu;
840 hdev->acl_pkts = __le16_to_cpu(rp->acl_max_pkt);
841 hdev->sco_pkts = __le16_to_cpu(rp->sco_max_pkt);
842
843 if (test_bit(HCI_QUIRK_FIXUP_BUFFER_SIZE, &hdev->quirks)) {
844 hdev->sco_mtu = 64;
845 hdev->sco_pkts = 8;
846 }
847
848 hdev->acl_cnt = hdev->acl_pkts;
849 hdev->sco_cnt = hdev->sco_pkts;
850
Gustavo Padovan807deac2012-05-17 00:36:24 -0300851 BT_DBG("%s acl mtu %d:%d sco mtu %d:%d", hdev->name, hdev->acl_mtu,
852 hdev->acl_pkts, hdev->sco_mtu, hdev->sco_pkts);
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200853}
854
855static void hci_cc_read_bd_addr(struct hci_dev *hdev, struct sk_buff *skb)
856{
857 struct hci_rp_read_bd_addr *rp = (void *) skb->data;
858
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +0300859 BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200860
861 if (!rp->status)
862 bacpy(&hdev->bdaddr, &rp->bdaddr);
863
Johan Hedberg23bb5762010-12-21 23:01:27 +0200864 hci_req_complete(hdev, HCI_OP_READ_BD_ADDR, rp->status);
865}
866
Andrei Emeltchenko350ee4c2011-12-07 15:56:51 +0200867static void hci_cc_read_data_block_size(struct hci_dev *hdev,
Gustavo Padovan807deac2012-05-17 00:36:24 -0300868 struct sk_buff *skb)
Andrei Emeltchenko350ee4c2011-12-07 15:56:51 +0200869{
870 struct hci_rp_read_data_block_size *rp = (void *) skb->data;
871
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +0300872 BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
Andrei Emeltchenko350ee4c2011-12-07 15:56:51 +0200873
874 if (rp->status)
875 return;
876
877 hdev->block_mtu = __le16_to_cpu(rp->max_acl_len);
878 hdev->block_len = __le16_to_cpu(rp->block_len);
879 hdev->num_blocks = __le16_to_cpu(rp->num_blocks);
880
881 hdev->block_cnt = hdev->num_blocks;
882
883 BT_DBG("%s blk mtu %d cnt %d len %d", hdev->name, hdev->block_mtu,
Gustavo Padovan807deac2012-05-17 00:36:24 -0300884 hdev->block_cnt, hdev->block_len);
Andrei Emeltchenko350ee4c2011-12-07 15:56:51 +0200885
886 hci_req_complete(hdev, HCI_OP_READ_DATA_BLOCK_SIZE, rp->status);
887}
888
Johan Hedberg23bb5762010-12-21 23:01:27 +0200889static void hci_cc_write_ca_timeout(struct hci_dev *hdev, struct sk_buff *skb)
890{
891 __u8 status = *((__u8 *) skb->data);
892
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +0300893 BT_DBG("%s status 0x%2.2x", hdev->name, status);
Johan Hedberg23bb5762010-12-21 23:01:27 +0200894
895 hci_req_complete(hdev, HCI_OP_WRITE_CA_TIMEOUT, status);
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200896}
897
Andrei Emeltchenko928abaa2011-10-12 10:53:57 +0300898static void hci_cc_read_local_amp_info(struct hci_dev *hdev,
Gustavo Padovan807deac2012-05-17 00:36:24 -0300899 struct sk_buff *skb)
Andrei Emeltchenko928abaa2011-10-12 10:53:57 +0300900{
901 struct hci_rp_read_local_amp_info *rp = (void *) skb->data;
902
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +0300903 BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
Andrei Emeltchenko928abaa2011-10-12 10:53:57 +0300904
905 if (rp->status)
Andrei Emeltchenko8e2a0d92012-09-27 17:26:08 +0300906 goto a2mp_rsp;
Andrei Emeltchenko928abaa2011-10-12 10:53:57 +0300907
908 hdev->amp_status = rp->amp_status;
909 hdev->amp_total_bw = __le32_to_cpu(rp->total_bw);
910 hdev->amp_max_bw = __le32_to_cpu(rp->max_bw);
911 hdev->amp_min_latency = __le32_to_cpu(rp->min_latency);
912 hdev->amp_max_pdu = __le32_to_cpu(rp->max_pdu);
913 hdev->amp_type = rp->amp_type;
914 hdev->amp_pal_cap = __le16_to_cpu(rp->pal_cap);
915 hdev->amp_assoc_size = __le16_to_cpu(rp->max_assoc_size);
916 hdev->amp_be_flush_to = __le32_to_cpu(rp->be_flush_to);
917 hdev->amp_max_flush_to = __le32_to_cpu(rp->max_flush_to);
918
919 hci_req_complete(hdev, HCI_OP_READ_LOCAL_AMP_INFO, rp->status);
Andrei Emeltchenko8e2a0d92012-09-27 17:26:08 +0300920
921a2mp_rsp:
922 a2mp_send_getinfo_rsp(hdev);
Andrei Emeltchenko928abaa2011-10-12 10:53:57 +0300923}
924
Andrei Emeltchenko903e4542012-09-27 17:26:09 +0300925static void hci_cc_read_local_amp_assoc(struct hci_dev *hdev,
926 struct sk_buff *skb)
927{
928 struct hci_rp_read_local_amp_assoc *rp = (void *) skb->data;
929 struct amp_assoc *assoc = &hdev->loc_assoc;
930 size_t rem_len, frag_len;
931
932 BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
933
934 if (rp->status)
935 goto a2mp_rsp;
936
937 frag_len = skb->len - sizeof(*rp);
938 rem_len = __le16_to_cpu(rp->rem_len);
939
940 if (rem_len > frag_len) {
Andrei Emeltchenko2e430be32012-09-28 14:44:23 +0300941 BT_DBG("frag_len %zu rem_len %zu", frag_len, rem_len);
Andrei Emeltchenko903e4542012-09-27 17:26:09 +0300942
943 memcpy(assoc->data + assoc->offset, rp->frag, frag_len);
944 assoc->offset += frag_len;
945
946 /* Read other fragments */
947 amp_read_loc_assoc_frag(hdev, rp->phy_handle);
948
949 return;
950 }
951
952 memcpy(assoc->data + assoc->offset, rp->frag, rem_len);
953 assoc->len = assoc->offset + rem_len;
954 assoc->offset = 0;
955
956a2mp_rsp:
957 /* Send A2MP Rsp when all fragments are received */
958 a2mp_send_getampassoc_rsp(hdev, rp->status);
Andrei Emeltchenko9495b2e2012-09-27 17:26:22 +0300959 a2mp_send_create_phy_link_req(hdev, rp->status);
Andrei Emeltchenko903e4542012-09-27 17:26:09 +0300960}
961
Johan Hedbergb0916ea2011-01-10 13:44:55 +0200962static void hci_cc_delete_stored_link_key(struct hci_dev *hdev,
Gustavo Padovan807deac2012-05-17 00:36:24 -0300963 struct sk_buff *skb)
Johan Hedbergb0916ea2011-01-10 13:44:55 +0200964{
965 __u8 status = *((__u8 *) skb->data);
966
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +0300967 BT_DBG("%s status 0x%2.2x", hdev->name, status);
Johan Hedbergb0916ea2011-01-10 13:44:55 +0200968
969 hci_req_complete(hdev, HCI_OP_DELETE_STORED_LINK_KEY, status);
970}
971
Johan Hedbergd5859e22011-01-25 01:19:58 +0200972static void hci_cc_set_event_mask(struct hci_dev *hdev, struct sk_buff *skb)
973{
974 __u8 status = *((__u8 *) skb->data);
975
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +0300976 BT_DBG("%s status 0x%2.2x", hdev->name, status);
Johan Hedbergd5859e22011-01-25 01:19:58 +0200977
978 hci_req_complete(hdev, HCI_OP_SET_EVENT_MASK, status);
979}
980
981static void hci_cc_write_inquiry_mode(struct hci_dev *hdev,
Gustavo Padovan807deac2012-05-17 00:36:24 -0300982 struct sk_buff *skb)
Johan Hedbergd5859e22011-01-25 01:19:58 +0200983{
984 __u8 status = *((__u8 *) skb->data);
985
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +0300986 BT_DBG("%s status 0x%2.2x", hdev->name, status);
Johan Hedbergd5859e22011-01-25 01:19:58 +0200987
988 hci_req_complete(hdev, HCI_OP_WRITE_INQUIRY_MODE, status);
989}
990
991static void hci_cc_read_inq_rsp_tx_power(struct hci_dev *hdev,
Gustavo Padovan807deac2012-05-17 00:36:24 -0300992 struct sk_buff *skb)
Johan Hedbergd5859e22011-01-25 01:19:58 +0200993{
Marcel Holtmann91c4e9b2012-03-11 19:27:21 -0700994 struct hci_rp_read_inq_rsp_tx_power *rp = (void *) skb->data;
Johan Hedbergd5859e22011-01-25 01:19:58 +0200995
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +0300996 BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
Johan Hedbergd5859e22011-01-25 01:19:58 +0200997
Marcel Holtmann91c4e9b2012-03-11 19:27:21 -0700998 if (!rp->status)
999 hdev->inq_tx_power = rp->tx_power;
1000
1001 hci_req_complete(hdev, HCI_OP_READ_INQ_RSP_TX_POWER, rp->status);
Johan Hedbergd5859e22011-01-25 01:19:58 +02001002}
1003
1004static void hci_cc_set_event_flt(struct hci_dev *hdev, struct sk_buff *skb)
1005{
1006 __u8 status = *((__u8 *) skb->data);
1007
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +03001008 BT_DBG("%s status 0x%2.2x", hdev->name, status);
Johan Hedbergd5859e22011-01-25 01:19:58 +02001009
1010 hci_req_complete(hdev, HCI_OP_SET_EVENT_FLT, status);
1011}
1012
Johan Hedberg980e1a52011-01-22 06:10:07 +02001013static void hci_cc_pin_code_reply(struct hci_dev *hdev, struct sk_buff *skb)
1014{
1015 struct hci_rp_pin_code_reply *rp = (void *) skb->data;
1016 struct hci_cp_pin_code_reply *cp;
1017 struct hci_conn *conn;
1018
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +03001019 BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
Johan Hedberg980e1a52011-01-22 06:10:07 +02001020
Johan Hedberg56e5cb82011-11-08 20:40:16 +02001021 hci_dev_lock(hdev);
1022
Johan Hedberga8b2d5c2012-01-08 23:11:15 +02001023 if (test_bit(HCI_MGMT, &hdev->dev_flags))
Johan Hedberg744cf192011-11-08 20:40:14 +02001024 mgmt_pin_code_reply_complete(hdev, &rp->bdaddr, rp->status);
Johan Hedberg980e1a52011-01-22 06:10:07 +02001025
Mikel Astizfa1bd912012-08-09 09:52:29 +02001026 if (rp->status)
Johan Hedberg56e5cb82011-11-08 20:40:16 +02001027 goto unlock;
Johan Hedberg980e1a52011-01-22 06:10:07 +02001028
1029 cp = hci_sent_cmd_data(hdev, HCI_OP_PIN_CODE_REPLY);
1030 if (!cp)
Johan Hedberg56e5cb82011-11-08 20:40:16 +02001031 goto unlock;
Johan Hedberg980e1a52011-01-22 06:10:07 +02001032
1033 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &cp->bdaddr);
1034 if (conn)
1035 conn->pin_length = cp->pin_len;
Johan Hedberg56e5cb82011-11-08 20:40:16 +02001036
1037unlock:
1038 hci_dev_unlock(hdev);
Johan Hedberg980e1a52011-01-22 06:10:07 +02001039}
1040
1041static void hci_cc_pin_code_neg_reply(struct hci_dev *hdev, struct sk_buff *skb)
1042{
1043 struct hci_rp_pin_code_neg_reply *rp = (void *) skb->data;
1044
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +03001045 BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
Johan Hedberg980e1a52011-01-22 06:10:07 +02001046
Johan Hedberg56e5cb82011-11-08 20:40:16 +02001047 hci_dev_lock(hdev);
1048
Johan Hedberga8b2d5c2012-01-08 23:11:15 +02001049 if (test_bit(HCI_MGMT, &hdev->dev_flags))
Johan Hedberg744cf192011-11-08 20:40:14 +02001050 mgmt_pin_code_neg_reply_complete(hdev, &rp->bdaddr,
Gustavo Padovan807deac2012-05-17 00:36:24 -03001051 rp->status);
Johan Hedberg56e5cb82011-11-08 20:40:16 +02001052
1053 hci_dev_unlock(hdev);
Johan Hedberg980e1a52011-01-22 06:10:07 +02001054}
Johan Hedberg56e5cb82011-11-08 20:40:16 +02001055
Ville Tervo6ed58ec2011-02-10 22:38:48 -03001056static void hci_cc_le_read_buffer_size(struct hci_dev *hdev,
1057 struct sk_buff *skb)
1058{
1059 struct hci_rp_le_read_buffer_size *rp = (void *) skb->data;
1060
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +03001061 BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
Ville Tervo6ed58ec2011-02-10 22:38:48 -03001062
1063 if (rp->status)
1064 return;
1065
1066 hdev->le_mtu = __le16_to_cpu(rp->le_mtu);
1067 hdev->le_pkts = rp->le_max_pkt;
1068
1069 hdev->le_cnt = hdev->le_pkts;
1070
1071 BT_DBG("%s le mtu %d:%d", hdev->name, hdev->le_mtu, hdev->le_pkts);
1072
1073 hci_req_complete(hdev, HCI_OP_LE_READ_BUFFER_SIZE, rp->status);
1074}
Johan Hedberg980e1a52011-01-22 06:10:07 +02001075
Johan Hedberge36b04c2012-10-19 20:57:47 +03001076static void hci_cc_le_set_event_mask(struct hci_dev *hdev, struct sk_buff *skb)
1077{
1078 __u8 status = *((__u8 *) skb->data);
1079
1080 BT_DBG("%s status 0x%2.2x", hdev->name, status);
1081
1082 hci_req_complete(hdev, HCI_OP_LE_SET_EVENT_MASK, status);
1083}
1084
Johan Hedberga5c29682011-02-19 12:05:57 -03001085static void hci_cc_user_confirm_reply(struct hci_dev *hdev, struct sk_buff *skb)
1086{
1087 struct hci_rp_user_confirm_reply *rp = (void *) skb->data;
1088
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +03001089 BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
Johan Hedberga5c29682011-02-19 12:05:57 -03001090
Johan Hedberg56e5cb82011-11-08 20:40:16 +02001091 hci_dev_lock(hdev);
1092
Johan Hedberga8b2d5c2012-01-08 23:11:15 +02001093 if (test_bit(HCI_MGMT, &hdev->dev_flags))
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001094 mgmt_user_confirm_reply_complete(hdev, &rp->bdaddr, ACL_LINK, 0,
1095 rp->status);
Johan Hedberg56e5cb82011-11-08 20:40:16 +02001096
1097 hci_dev_unlock(hdev);
Johan Hedberga5c29682011-02-19 12:05:57 -03001098}
1099
1100static void hci_cc_user_confirm_neg_reply(struct hci_dev *hdev,
Gustavo Padovan807deac2012-05-17 00:36:24 -03001101 struct sk_buff *skb)
Johan Hedberga5c29682011-02-19 12:05:57 -03001102{
1103 struct hci_rp_user_confirm_reply *rp = (void *) skb->data;
1104
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +03001105 BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
Johan Hedberga5c29682011-02-19 12:05:57 -03001106
Johan Hedberg56e5cb82011-11-08 20:40:16 +02001107 hci_dev_lock(hdev);
1108
Johan Hedberga8b2d5c2012-01-08 23:11:15 +02001109 if (test_bit(HCI_MGMT, &hdev->dev_flags))
Johan Hedberg744cf192011-11-08 20:40:14 +02001110 mgmt_user_confirm_neg_reply_complete(hdev, &rp->bdaddr,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001111 ACL_LINK, 0, rp->status);
Johan Hedberg56e5cb82011-11-08 20:40:16 +02001112
1113 hci_dev_unlock(hdev);
Johan Hedberga5c29682011-02-19 12:05:57 -03001114}
1115
Brian Gix1143d452011-11-23 08:28:34 -08001116static void hci_cc_user_passkey_reply(struct hci_dev *hdev, struct sk_buff *skb)
1117{
1118 struct hci_rp_user_confirm_reply *rp = (void *) skb->data;
1119
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +03001120 BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
Brian Gix1143d452011-11-23 08:28:34 -08001121
1122 hci_dev_lock(hdev);
1123
Johan Hedberga8b2d5c2012-01-08 23:11:15 +02001124 if (test_bit(HCI_MGMT, &hdev->dev_flags))
Johan Hedberg272d90d2012-02-09 15:26:12 +02001125 mgmt_user_passkey_reply_complete(hdev, &rp->bdaddr, ACL_LINK,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001126 0, rp->status);
Brian Gix1143d452011-11-23 08:28:34 -08001127
1128 hci_dev_unlock(hdev);
1129}
1130
1131static void hci_cc_user_passkey_neg_reply(struct hci_dev *hdev,
Gustavo Padovan807deac2012-05-17 00:36:24 -03001132 struct sk_buff *skb)
Brian Gix1143d452011-11-23 08:28:34 -08001133{
1134 struct hci_rp_user_confirm_reply *rp = (void *) skb->data;
1135
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +03001136 BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
Brian Gix1143d452011-11-23 08:28:34 -08001137
1138 hci_dev_lock(hdev);
1139
Johan Hedberga8b2d5c2012-01-08 23:11:15 +02001140 if (test_bit(HCI_MGMT, &hdev->dev_flags))
Brian Gix1143d452011-11-23 08:28:34 -08001141 mgmt_user_passkey_neg_reply_complete(hdev, &rp->bdaddr,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001142 ACL_LINK, 0, rp->status);
Brian Gix1143d452011-11-23 08:28:34 -08001143
1144 hci_dev_unlock(hdev);
1145}
1146
Szymon Jancc35938b2011-03-22 13:12:21 +01001147static void hci_cc_read_local_oob_data_reply(struct hci_dev *hdev,
Gustavo Padovan807deac2012-05-17 00:36:24 -03001148 struct sk_buff *skb)
Szymon Jancc35938b2011-03-22 13:12:21 +01001149{
1150 struct hci_rp_read_local_oob_data *rp = (void *) skb->data;
1151
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +03001152 BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
Szymon Jancc35938b2011-03-22 13:12:21 +01001153
Johan Hedberg56e5cb82011-11-08 20:40:16 +02001154 hci_dev_lock(hdev);
Johan Hedberg744cf192011-11-08 20:40:14 +02001155 mgmt_read_local_oob_data_reply_complete(hdev, rp->hash,
Szymon Jancc35938b2011-03-22 13:12:21 +01001156 rp->randomizer, rp->status);
Johan Hedberg56e5cb82011-11-08 20:40:16 +02001157 hci_dev_unlock(hdev);
Szymon Jancc35938b2011-03-22 13:12:21 +01001158}
1159
Andre Guedes07f7fa52011-12-02 21:13:31 +09001160static void hci_cc_le_set_scan_param(struct hci_dev *hdev, struct sk_buff *skb)
1161{
1162 __u8 status = *((__u8 *) skb->data);
1163
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +03001164 BT_DBG("%s status 0x%2.2x", hdev->name, status);
Andre Guedes7ba8b4b2012-02-03 17:47:59 -03001165
1166 hci_req_complete(hdev, HCI_OP_LE_SET_SCAN_PARAM, status);
Andre Guedes3fd24152012-02-03 17:48:01 -03001167
1168 if (status) {
1169 hci_dev_lock(hdev);
1170 mgmt_start_discovery_failed(hdev, status);
1171 hci_dev_unlock(hdev);
1172 return;
1173 }
Andre Guedes07f7fa52011-12-02 21:13:31 +09001174}
1175
Andre Guedeseb9d91f2011-05-26 16:23:52 -03001176static void hci_cc_le_set_scan_enable(struct hci_dev *hdev,
Gustavo Padovan807deac2012-05-17 00:36:24 -03001177 struct sk_buff *skb)
Andre Guedeseb9d91f2011-05-26 16:23:52 -03001178{
1179 struct hci_cp_le_set_scan_enable *cp;
1180 __u8 status = *((__u8 *) skb->data);
1181
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +03001182 BT_DBG("%s status 0x%2.2x", hdev->name, status);
Andre Guedeseb9d91f2011-05-26 16:23:52 -03001183
Andre Guedeseb9d91f2011-05-26 16:23:52 -03001184 cp = hci_sent_cmd_data(hdev, HCI_OP_LE_SET_SCAN_ENABLE);
1185 if (!cp)
1186 return;
1187
Andrei Emeltchenko68a8aea2011-12-19 16:14:18 +02001188 switch (cp->enable) {
1189 case LE_SCANNING_ENABLED:
Andre Guedes7ba8b4b2012-02-03 17:47:59 -03001190 hci_req_complete(hdev, HCI_OP_LE_SET_SCAN_ENABLE, status);
1191
Andre Guedes3fd24152012-02-03 17:48:01 -03001192 if (status) {
1193 hci_dev_lock(hdev);
1194 mgmt_start_discovery_failed(hdev, status);
1195 hci_dev_unlock(hdev);
Andre Guedes7ba8b4b2012-02-03 17:47:59 -03001196 return;
Andre Guedes3fd24152012-02-03 17:48:01 -03001197 }
Andre Guedes7ba8b4b2012-02-03 17:47:59 -03001198
Andre Guedesd23264a2011-11-25 20:53:38 -03001199 set_bit(HCI_LE_SCAN, &hdev->dev_flags);
1200
Andre Guedesa8f13c82011-09-09 18:56:24 -03001201 hci_dev_lock(hdev);
Andre Guedes343f9352012-02-17 20:39:37 -03001202 hci_discovery_set_state(hdev, DISCOVERY_FINDING);
Andre Guedesa8f13c82011-09-09 18:56:24 -03001203 hci_dev_unlock(hdev);
Andrei Emeltchenko68a8aea2011-12-19 16:14:18 +02001204 break;
1205
1206 case LE_SCANNING_DISABLED:
Andre Guedesc9ecc482012-03-15 16:52:08 -03001207 if (status) {
1208 hci_dev_lock(hdev);
1209 mgmt_stop_discovery_failed(hdev, status);
1210 hci_dev_unlock(hdev);
Andre Guedes7ba8b4b2012-02-03 17:47:59 -03001211 return;
Andre Guedesc9ecc482012-03-15 16:52:08 -03001212 }
Andre Guedes7ba8b4b2012-02-03 17:47:59 -03001213
Andre Guedesd23264a2011-11-25 20:53:38 -03001214 clear_bit(HCI_LE_SCAN, &hdev->dev_flags);
1215
Andre Guedesbc3dd332012-03-06 19:37:06 -03001216 if (hdev->discovery.type == DISCOV_TYPE_INTERLEAVED &&
1217 hdev->discovery.state == DISCOVERY_FINDING) {
Andre Guedes5e0452c2012-02-17 20:39:38 -03001218 mgmt_interleaved_discovery(hdev);
1219 } else {
1220 hci_dev_lock(hdev);
1221 hci_discovery_set_state(hdev, DISCOVERY_STOPPED);
1222 hci_dev_unlock(hdev);
1223 }
1224
Andrei Emeltchenko68a8aea2011-12-19 16:14:18 +02001225 break;
1226
1227 default:
1228 BT_ERR("Used reserved LE_Scan_Enable param %d", cp->enable);
1229 break;
Andre Guedes35815082011-05-26 16:23:53 -03001230 }
Andre Guedeseb9d91f2011-05-26 16:23:52 -03001231}
1232
Vinicius Costa Gomesa7a595f2011-06-09 18:50:47 -03001233static void hci_cc_le_ltk_reply(struct hci_dev *hdev, struct sk_buff *skb)
1234{
1235 struct hci_rp_le_ltk_reply *rp = (void *) skb->data;
1236
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +03001237 BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
Vinicius Costa Gomesa7a595f2011-06-09 18:50:47 -03001238
1239 if (rp->status)
1240 return;
1241
1242 hci_req_complete(hdev, HCI_OP_LE_LTK_REPLY, rp->status);
1243}
1244
1245static void hci_cc_le_ltk_neg_reply(struct hci_dev *hdev, struct sk_buff *skb)
1246{
1247 struct hci_rp_le_ltk_neg_reply *rp = (void *) skb->data;
1248
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +03001249 BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
Vinicius Costa Gomesa7a595f2011-06-09 18:50:47 -03001250
1251 if (rp->status)
1252 return;
1253
1254 hci_req_complete(hdev, HCI_OP_LE_LTK_NEG_REPLY, rp->status);
1255}
1256
Gustavo Padovan6039aa72012-05-23 04:04:18 -03001257static void hci_cc_write_le_host_supported(struct hci_dev *hdev,
1258 struct sk_buff *skb)
Andre Guedesf9b49302011-06-30 19:20:53 -03001259{
Johan Hedberg06199cf2012-02-22 16:37:11 +02001260 struct hci_cp_write_le_host_supported *sent;
Andre Guedesf9b49302011-06-30 19:20:53 -03001261 __u8 status = *((__u8 *) skb->data);
1262
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +03001263 BT_DBG("%s status 0x%2.2x", hdev->name, status);
Andre Guedesf9b49302011-06-30 19:20:53 -03001264
Johan Hedberg06199cf2012-02-22 16:37:11 +02001265 sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_LE_HOST_SUPPORTED);
Johan Hedberg8f984df2012-02-28 01:07:22 +02001266 if (!sent)
Andre Guedesf9b49302011-06-30 19:20:53 -03001267 return;
1268
Johan Hedberg8f984df2012-02-28 01:07:22 +02001269 if (!status) {
1270 if (sent->le)
1271 hdev->host_features[0] |= LMP_HOST_LE;
1272 else
1273 hdev->host_features[0] &= ~LMP_HOST_LE;
1274 }
1275
1276 if (test_bit(HCI_MGMT, &hdev->dev_flags) &&
Gustavo Padovan807deac2012-05-17 00:36:24 -03001277 !test_bit(HCI_INIT, &hdev->flags))
Johan Hedberg8f984df2012-02-28 01:07:22 +02001278 mgmt_le_enable_complete(hdev, sent->le, status);
1279
1280 hci_req_complete(hdev, HCI_OP_WRITE_LE_HOST_SUPPORTED, status);
Andre Guedesf9b49302011-06-30 19:20:53 -03001281}
1282
Andrei Emeltchenko93c284e2012-09-27 17:26:20 +03001283static void hci_cc_write_remote_amp_assoc(struct hci_dev *hdev,
1284 struct sk_buff *skb)
1285{
1286 struct hci_rp_write_remote_amp_assoc *rp = (void *) skb->data;
1287
1288 BT_DBG("%s status 0x%2.2x phy_handle 0x%2.2x",
1289 hdev->name, rp->status, rp->phy_handle);
1290
1291 if (rp->status)
1292 return;
1293
1294 amp_write_rem_assoc_continue(hdev, rp->phy_handle);
1295}
1296
Gustavo Padovan6039aa72012-05-23 04:04:18 -03001297static void hci_cs_inquiry(struct hci_dev *hdev, __u8 status)
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001298{
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +03001299 BT_DBG("%s status 0x%2.2x", hdev->name, status);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001300
1301 if (status) {
Johan Hedberg23bb5762010-12-21 23:01:27 +02001302 hci_req_complete(hdev, HCI_OP_INQUIRY, status);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001303 hci_conn_check_pending(hdev);
Johan Hedberg56e5cb82011-11-08 20:40:16 +02001304 hci_dev_lock(hdev);
Johan Hedberga8b2d5c2012-01-08 23:11:15 +02001305 if (test_bit(HCI_MGMT, &hdev->dev_flags))
Andre Guedes7a135102011-11-09 17:14:25 -03001306 mgmt_start_discovery_failed(hdev, status);
Johan Hedberg56e5cb82011-11-08 20:40:16 +02001307 hci_dev_unlock(hdev);
Johan Hedberg314b2382011-04-27 10:29:57 -04001308 return;
1309 }
1310
Andre Guedes89352e72011-11-04 14:16:53 -03001311 set_bit(HCI_INQUIRY, &hdev->flags);
1312
Johan Hedberg56e5cb82011-11-08 20:40:16 +02001313 hci_dev_lock(hdev);
Andre Guedes343f9352012-02-17 20:39:37 -03001314 hci_discovery_set_state(hdev, DISCOVERY_FINDING);
Johan Hedberg56e5cb82011-11-08 20:40:16 +02001315 hci_dev_unlock(hdev);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001316}
1317
Gustavo Padovan6039aa72012-05-23 04:04:18 -03001318static void hci_cs_create_conn(struct hci_dev *hdev, __u8 status)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001319{
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001320 struct hci_cp_create_conn *cp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001321 struct hci_conn *conn;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001322
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +03001323 BT_DBG("%s status 0x%2.2x", hdev->name, status);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001324
1325 cp = hci_sent_cmd_data(hdev, HCI_OP_CREATE_CONN);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001326 if (!cp)
1327 return;
1328
1329 hci_dev_lock(hdev);
1330
1331 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &cp->bdaddr);
1332
Andrei Emeltchenko6ed93dc2012-09-25 12:49:43 +03001333 BT_DBG("%s bdaddr %pMR hcon %p", hdev->name, &cp->bdaddr, conn);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001334
1335 if (status) {
1336 if (conn && conn->state == BT_CONNECT) {
Marcel Holtmann4c67bc72006-10-15 17:30:56 +02001337 if (status != 0x0c || conn->attempt > 2) {
1338 conn->state = BT_CLOSED;
1339 hci_proto_connect_cfm(conn, status);
1340 hci_conn_del(conn);
1341 } else
1342 conn->state = BT_CONNECT2;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001343 }
1344 } else {
1345 if (!conn) {
1346 conn = hci_conn_add(hdev, ACL_LINK, &cp->bdaddr);
1347 if (conn) {
Johan Hedberga0c808b2012-01-16 09:49:58 +02001348 conn->out = true;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001349 conn->link_mode |= HCI_LM_MASTER;
1350 } else
Gustavo F. Padovan893ef972010-07-18 15:13:37 -03001351 BT_ERR("No memory for new connection");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001352 }
1353 }
1354
1355 hci_dev_unlock(hdev);
1356}
1357
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001358static void hci_cs_add_sco(struct hci_dev *hdev, __u8 status)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001359{
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001360 struct hci_cp_add_sco *cp;
1361 struct hci_conn *acl, *sco;
1362 __u16 handle;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001363
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +03001364 BT_DBG("%s status 0x%2.2x", hdev->name, status);
Marcel Holtmannb6a0dc82007-10-20 14:55:10 +02001365
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001366 if (!status)
1367 return;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001368
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001369 cp = hci_sent_cmd_data(hdev, HCI_OP_ADD_SCO);
1370 if (!cp)
1371 return;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001372
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001373 handle = __le16_to_cpu(cp->handle);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001374
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +03001375 BT_DBG("%s handle 0x%4.4x", hdev->name, handle);
Marcel Holtmann6bd57412006-11-18 22:14:22 +01001376
1377 hci_dev_lock(hdev);
1378
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001379 acl = hci_conn_hash_lookup_handle(hdev, handle);
Andrei Emeltchenko5a08ecc2011-01-11 17:20:20 +02001380 if (acl) {
1381 sco = acl->link;
1382 if (sco) {
1383 sco->state = BT_CLOSED;
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001384
Andrei Emeltchenko5a08ecc2011-01-11 17:20:20 +02001385 hci_proto_connect_cfm(sco, status);
1386 hci_conn_del(sco);
1387 }
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001388 }
Marcel Holtmann6bd57412006-11-18 22:14:22 +01001389
1390 hci_dev_unlock(hdev);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001391}
1392
Marcel Holtmannf8558552008-07-14 20:13:49 +02001393static void hci_cs_auth_requested(struct hci_dev *hdev, __u8 status)
1394{
1395 struct hci_cp_auth_requested *cp;
1396 struct hci_conn *conn;
1397
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +03001398 BT_DBG("%s status 0x%2.2x", hdev->name, status);
Marcel Holtmannf8558552008-07-14 20:13:49 +02001399
1400 if (!status)
1401 return;
1402
1403 cp = hci_sent_cmd_data(hdev, HCI_OP_AUTH_REQUESTED);
1404 if (!cp)
1405 return;
1406
1407 hci_dev_lock(hdev);
1408
1409 conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(cp->handle));
1410 if (conn) {
1411 if (conn->state == BT_CONFIG) {
1412 hci_proto_connect_cfm(conn, status);
1413 hci_conn_put(conn);
1414 }
1415 }
1416
1417 hci_dev_unlock(hdev);
1418}
1419
1420static void hci_cs_set_conn_encrypt(struct hci_dev *hdev, __u8 status)
1421{
1422 struct hci_cp_set_conn_encrypt *cp;
1423 struct hci_conn *conn;
1424
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +03001425 BT_DBG("%s status 0x%2.2x", hdev->name, status);
Marcel Holtmannf8558552008-07-14 20:13:49 +02001426
1427 if (!status)
1428 return;
1429
1430 cp = hci_sent_cmd_data(hdev, HCI_OP_SET_CONN_ENCRYPT);
1431 if (!cp)
1432 return;
1433
1434 hci_dev_lock(hdev);
1435
1436 conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(cp->handle));
1437 if (conn) {
1438 if (conn->state == BT_CONFIG) {
1439 hci_proto_connect_cfm(conn, status);
1440 hci_conn_put(conn);
1441 }
1442 }
1443
1444 hci_dev_unlock(hdev);
1445}
1446
Johan Hedberg127178d2010-11-18 22:22:29 +02001447static int hci_outgoing_auth_needed(struct hci_dev *hdev,
Gustavo Padovan807deac2012-05-17 00:36:24 -03001448 struct hci_conn *conn)
Johan Hedberg392599b2010-11-18 22:22:28 +02001449{
Johan Hedberg392599b2010-11-18 22:22:28 +02001450 if (conn->state != BT_CONFIG || !conn->out)
1451 return 0;
1452
Johan Hedberg765c2a92011-01-19 12:06:52 +05301453 if (conn->pending_sec_level == BT_SECURITY_SDP)
Johan Hedberg392599b2010-11-18 22:22:28 +02001454 return 0;
1455
1456 /* Only request authentication for SSP connections or non-SSP
Vinicius Costa Gomese9bf2bf2011-09-02 14:51:20 -03001457 * devices with sec_level HIGH or if MITM protection is requested */
Gustavo Padovan807deac2012-05-17 00:36:24 -03001458 if (!hci_conn_ssp_enabled(conn) && !(conn->auth_type & 0x01) &&
1459 conn->pending_sec_level != BT_SECURITY_HIGH)
Johan Hedberg392599b2010-11-18 22:22:28 +02001460 return 0;
1461
Johan Hedberg392599b2010-11-18 22:22:28 +02001462 return 1;
1463}
1464
Gustavo Padovan6039aa72012-05-23 04:04:18 -03001465static int hci_resolve_name(struct hci_dev *hdev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001466 struct inquiry_entry *e)
Johan Hedberg30dc78e2012-01-04 15:44:20 +02001467{
1468 struct hci_cp_remote_name_req cp;
1469
1470 memset(&cp, 0, sizeof(cp));
1471
1472 bacpy(&cp.bdaddr, &e->data.bdaddr);
1473 cp.pscan_rep_mode = e->data.pscan_rep_mode;
1474 cp.pscan_mode = e->data.pscan_mode;
1475 cp.clock_offset = e->data.clock_offset;
1476
1477 return hci_send_cmd(hdev, HCI_OP_REMOTE_NAME_REQ, sizeof(cp), &cp);
1478}
1479
Johan Hedbergb644ba32012-01-17 21:48:47 +02001480static bool hci_resolve_next_name(struct hci_dev *hdev)
Johan Hedberg30dc78e2012-01-04 15:44:20 +02001481{
1482 struct discovery_state *discov = &hdev->discovery;
1483 struct inquiry_entry *e;
1484
Johan Hedbergb644ba32012-01-17 21:48:47 +02001485 if (list_empty(&discov->resolve))
1486 return false;
1487
1488 e = hci_inquiry_cache_lookup_resolve(hdev, BDADDR_ANY, NAME_NEEDED);
Ram Malovanyc8100892012-07-19 10:26:09 +03001489 if (!e)
1490 return false;
1491
Johan Hedbergb644ba32012-01-17 21:48:47 +02001492 if (hci_resolve_name(hdev, e) == 0) {
1493 e->name_state = NAME_PENDING;
1494 return true;
1495 }
1496
1497 return false;
1498}
1499
1500static void hci_check_pending_name(struct hci_dev *hdev, struct hci_conn *conn,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001501 bdaddr_t *bdaddr, u8 *name, u8 name_len)
Johan Hedbergb644ba32012-01-17 21:48:47 +02001502{
1503 struct discovery_state *discov = &hdev->discovery;
1504 struct inquiry_entry *e;
1505
1506 if (conn && !test_and_set_bit(HCI_CONN_MGMT_CONNECTED, &conn->flags))
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001507 mgmt_device_connected(hdev, bdaddr, ACL_LINK, 0x00, 0, name,
1508 name_len, conn->dev_class);
Johan Hedbergb644ba32012-01-17 21:48:47 +02001509
1510 if (discov->state == DISCOVERY_STOPPED)
1511 return;
1512
Johan Hedberg30dc78e2012-01-04 15:44:20 +02001513 if (discov->state == DISCOVERY_STOPPING)
1514 goto discov_complete;
1515
1516 if (discov->state != DISCOVERY_RESOLVING)
1517 return;
1518
1519 e = hci_inquiry_cache_lookup_resolve(hdev, bdaddr, NAME_PENDING);
Ram Malovany7cc83802012-07-19 10:26:10 +03001520 /* If the device was not found in a list of found devices names of which
1521 * are pending. there is no need to continue resolving a next name as it
1522 * will be done upon receiving another Remote Name Request Complete
1523 * Event */
1524 if (!e)
1525 return;
1526
1527 list_del(&e->list);
1528 if (name) {
Johan Hedberg30dc78e2012-01-04 15:44:20 +02001529 e->name_state = NAME_KNOWN;
Ram Malovany7cc83802012-07-19 10:26:10 +03001530 mgmt_remote_name(hdev, bdaddr, ACL_LINK, 0x00,
1531 e->data.rssi, name, name_len);
Ram Malovanyc3e7c0d2012-07-19 10:26:11 +03001532 } else {
1533 e->name_state = NAME_NOT_KNOWN;
Johan Hedberg30dc78e2012-01-04 15:44:20 +02001534 }
1535
Johan Hedbergb644ba32012-01-17 21:48:47 +02001536 if (hci_resolve_next_name(hdev))
Johan Hedberg30dc78e2012-01-04 15:44:20 +02001537 return;
Johan Hedberg30dc78e2012-01-04 15:44:20 +02001538
1539discov_complete:
1540 hci_discovery_set_state(hdev, DISCOVERY_STOPPED);
1541}
1542
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001543static void hci_cs_remote_name_req(struct hci_dev *hdev, __u8 status)
1544{
Johan Hedberg127178d2010-11-18 22:22:29 +02001545 struct hci_cp_remote_name_req *cp;
1546 struct hci_conn *conn;
1547
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +03001548 BT_DBG("%s status 0x%2.2x", hdev->name, status);
Johan Hedberg127178d2010-11-18 22:22:29 +02001549
1550 /* If successful wait for the name req complete event before
1551 * checking for the need to do authentication */
1552 if (!status)
1553 return;
1554
1555 cp = hci_sent_cmd_data(hdev, HCI_OP_REMOTE_NAME_REQ);
1556 if (!cp)
1557 return;
1558
1559 hci_dev_lock(hdev);
1560
1561 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &cp->bdaddr);
Johan Hedbergb644ba32012-01-17 21:48:47 +02001562
1563 if (test_bit(HCI_MGMT, &hdev->dev_flags))
1564 hci_check_pending_name(hdev, conn, &cp->bdaddr, NULL, 0);
1565
Johan Hedberg79c6c702011-04-28 11:28:55 -07001566 if (!conn)
1567 goto unlock;
1568
1569 if (!hci_outgoing_auth_needed(hdev, conn))
1570 goto unlock;
1571
Johan Hedberg51a8efd2012-01-16 06:10:31 +02001572 if (!test_and_set_bit(HCI_CONN_AUTH_PEND, &conn->flags)) {
Johan Hedberg127178d2010-11-18 22:22:29 +02001573 struct hci_cp_auth_requested cp;
1574 cp.handle = __cpu_to_le16(conn->handle);
1575 hci_send_cmd(hdev, HCI_OP_AUTH_REQUESTED, sizeof(cp), &cp);
1576 }
1577
Johan Hedberg79c6c702011-04-28 11:28:55 -07001578unlock:
Johan Hedberg127178d2010-11-18 22:22:29 +02001579 hci_dev_unlock(hdev);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001580}
1581
Marcel Holtmann769be972008-07-14 20:13:49 +02001582static void hci_cs_read_remote_features(struct hci_dev *hdev, __u8 status)
1583{
1584 struct hci_cp_read_remote_features *cp;
1585 struct hci_conn *conn;
1586
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +03001587 BT_DBG("%s status 0x%2.2x", hdev->name, status);
Marcel Holtmann769be972008-07-14 20:13:49 +02001588
1589 if (!status)
1590 return;
1591
1592 cp = hci_sent_cmd_data(hdev, HCI_OP_READ_REMOTE_FEATURES);
1593 if (!cp)
1594 return;
1595
1596 hci_dev_lock(hdev);
1597
1598 conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(cp->handle));
1599 if (conn) {
1600 if (conn->state == BT_CONFIG) {
Marcel Holtmann769be972008-07-14 20:13:49 +02001601 hci_proto_connect_cfm(conn, status);
1602 hci_conn_put(conn);
1603 }
1604 }
1605
1606 hci_dev_unlock(hdev);
1607}
1608
1609static void hci_cs_read_remote_ext_features(struct hci_dev *hdev, __u8 status)
1610{
1611 struct hci_cp_read_remote_ext_features *cp;
1612 struct hci_conn *conn;
1613
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +03001614 BT_DBG("%s status 0x%2.2x", hdev->name, status);
Marcel Holtmann769be972008-07-14 20:13:49 +02001615
1616 if (!status)
1617 return;
1618
1619 cp = hci_sent_cmd_data(hdev, HCI_OP_READ_REMOTE_EXT_FEATURES);
1620 if (!cp)
1621 return;
1622
1623 hci_dev_lock(hdev);
1624
1625 conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(cp->handle));
1626 if (conn) {
1627 if (conn->state == BT_CONFIG) {
Marcel Holtmann769be972008-07-14 20:13:49 +02001628 hci_proto_connect_cfm(conn, status);
1629 hci_conn_put(conn);
1630 }
1631 }
1632
1633 hci_dev_unlock(hdev);
1634}
1635
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001636static void hci_cs_setup_sync_conn(struct hci_dev *hdev, __u8 status)
1637{
Marcel Holtmannb6a0dc82007-10-20 14:55:10 +02001638 struct hci_cp_setup_sync_conn *cp;
1639 struct hci_conn *acl, *sco;
1640 __u16 handle;
1641
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +03001642 BT_DBG("%s status 0x%2.2x", hdev->name, status);
Marcel Holtmannb6a0dc82007-10-20 14:55:10 +02001643
1644 if (!status)
1645 return;
1646
1647 cp = hci_sent_cmd_data(hdev, HCI_OP_SETUP_SYNC_CONN);
1648 if (!cp)
1649 return;
1650
1651 handle = __le16_to_cpu(cp->handle);
1652
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +03001653 BT_DBG("%s handle 0x%4.4x", hdev->name, handle);
Marcel Holtmannb6a0dc82007-10-20 14:55:10 +02001654
1655 hci_dev_lock(hdev);
1656
1657 acl = hci_conn_hash_lookup_handle(hdev, handle);
Andrei Emeltchenko5a08ecc2011-01-11 17:20:20 +02001658 if (acl) {
1659 sco = acl->link;
1660 if (sco) {
1661 sco->state = BT_CLOSED;
Marcel Holtmannb6a0dc82007-10-20 14:55:10 +02001662
Andrei Emeltchenko5a08ecc2011-01-11 17:20:20 +02001663 hci_proto_connect_cfm(sco, status);
1664 hci_conn_del(sco);
1665 }
Marcel Holtmannb6a0dc82007-10-20 14:55:10 +02001666 }
1667
1668 hci_dev_unlock(hdev);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001669}
1670
1671static void hci_cs_sniff_mode(struct hci_dev *hdev, __u8 status)
1672{
1673 struct hci_cp_sniff_mode *cp;
1674 struct hci_conn *conn;
1675
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +03001676 BT_DBG("%s status 0x%2.2x", hdev->name, status);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001677
1678 if (!status)
1679 return;
1680
1681 cp = hci_sent_cmd_data(hdev, HCI_OP_SNIFF_MODE);
1682 if (!cp)
1683 return;
1684
1685 hci_dev_lock(hdev);
1686
1687 conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(cp->handle));
Marcel Holtmanne73439d2010-07-26 10:06:00 -04001688 if (conn) {
Johan Hedberg51a8efd2012-01-16 06:10:31 +02001689 clear_bit(HCI_CONN_MODE_CHANGE_PEND, &conn->flags);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001690
Johan Hedberg51a8efd2012-01-16 06:10:31 +02001691 if (test_and_clear_bit(HCI_CONN_SCO_SETUP_PEND, &conn->flags))
Marcel Holtmanne73439d2010-07-26 10:06:00 -04001692 hci_sco_setup(conn, status);
1693 }
1694
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001695 hci_dev_unlock(hdev);
1696}
1697
1698static void hci_cs_exit_sniff_mode(struct hci_dev *hdev, __u8 status)
1699{
1700 struct hci_cp_exit_sniff_mode *cp;
1701 struct hci_conn *conn;
1702
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +03001703 BT_DBG("%s status 0x%2.2x", hdev->name, status);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001704
1705 if (!status)
1706 return;
1707
1708 cp = hci_sent_cmd_data(hdev, HCI_OP_EXIT_SNIFF_MODE);
1709 if (!cp)
1710 return;
1711
1712 hci_dev_lock(hdev);
1713
1714 conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(cp->handle));
Marcel Holtmanne73439d2010-07-26 10:06:00 -04001715 if (conn) {
Johan Hedberg51a8efd2012-01-16 06:10:31 +02001716 clear_bit(HCI_CONN_MODE_CHANGE_PEND, &conn->flags);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001717
Johan Hedberg51a8efd2012-01-16 06:10:31 +02001718 if (test_and_clear_bit(HCI_CONN_SCO_SETUP_PEND, &conn->flags))
Marcel Holtmanne73439d2010-07-26 10:06:00 -04001719 hci_sco_setup(conn, status);
1720 }
1721
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001722 hci_dev_unlock(hdev);
1723}
1724
Johan Hedberg88c3df12012-02-09 14:27:38 +02001725static void hci_cs_disconnect(struct hci_dev *hdev, u8 status)
1726{
1727 struct hci_cp_disconnect *cp;
1728 struct hci_conn *conn;
1729
1730 if (!status)
1731 return;
1732
1733 cp = hci_sent_cmd_data(hdev, HCI_OP_DISCONNECT);
1734 if (!cp)
1735 return;
1736
1737 hci_dev_lock(hdev);
1738
1739 conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(cp->handle));
1740 if (conn)
1741 mgmt_disconnect_failed(hdev, &conn->dst, conn->type,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001742 conn->dst_type, status);
Johan Hedberg88c3df12012-02-09 14:27:38 +02001743
1744 hci_dev_unlock(hdev);
1745}
1746
Ville Tervofcd89c02011-02-10 22:38:47 -03001747static void hci_cs_le_create_conn(struct hci_dev *hdev, __u8 status)
1748{
Ville Tervofcd89c02011-02-10 22:38:47 -03001749 struct hci_conn *conn;
1750
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +03001751 BT_DBG("%s status 0x%2.2x", hdev->name, status);
Ville Tervofcd89c02011-02-10 22:38:47 -03001752
Ville Tervofcd89c02011-02-10 22:38:47 -03001753 if (status) {
Andre Guedesf00a06a2012-07-27 15:10:13 -03001754 hci_dev_lock(hdev);
Ville Tervofcd89c02011-02-10 22:38:47 -03001755
Andre Guedes0c95ab72012-07-27 15:10:14 -03001756 conn = hci_conn_hash_lookup_state(hdev, LE_LINK, BT_CONNECT);
Andre Guedesf00a06a2012-07-27 15:10:13 -03001757 if (!conn) {
1758 hci_dev_unlock(hdev);
1759 return;
1760 }
1761
Andrei Emeltchenko6ed93dc2012-09-25 12:49:43 +03001762 BT_DBG("%s bdaddr %pMR conn %p", hdev->name, &conn->dst, conn);
Andre Guedesf00a06a2012-07-27 15:10:13 -03001763
1764 conn->state = BT_CLOSED;
Andre Guedes0c95ab72012-07-27 15:10:14 -03001765 mgmt_connect_failed(hdev, &conn->dst, conn->type,
Andre Guedesf00a06a2012-07-27 15:10:13 -03001766 conn->dst_type, status);
1767 hci_proto_connect_cfm(conn, status);
1768 hci_conn_del(conn);
1769
1770 hci_dev_unlock(hdev);
1771 }
Ville Tervofcd89c02011-02-10 22:38:47 -03001772}
1773
Vinicius Costa Gomesa7a595f2011-06-09 18:50:47 -03001774static void hci_cs_le_start_enc(struct hci_dev *hdev, u8 status)
1775{
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +03001776 BT_DBG("%s status 0x%2.2x", hdev->name, status);
Vinicius Costa Gomesa7a595f2011-06-09 18:50:47 -03001777}
1778
Andrei Emeltchenkoa02226d2012-09-27 17:26:19 +03001779static void hci_cs_create_phylink(struct hci_dev *hdev, u8 status)
1780{
Andrei Emeltchenko93c284e2012-09-27 17:26:20 +03001781 struct hci_cp_create_phy_link *cp;
1782
Andrei Emeltchenkoa02226d2012-09-27 17:26:19 +03001783 BT_DBG("%s status 0x%2.2x", hdev->name, status);
Andrei Emeltchenko93c284e2012-09-27 17:26:20 +03001784
1785 if (status)
1786 return;
1787
1788 cp = hci_sent_cmd_data(hdev, HCI_OP_CREATE_PHY_LINK);
1789 if (!cp)
1790 return;
1791
1792 amp_write_remote_assoc(hdev, cp->phy_handle);
Andrei Emeltchenkoa02226d2012-09-27 17:26:19 +03001793}
1794
Andrei Emeltchenko0b26ab92012-09-27 17:26:24 +03001795static void hci_cs_accept_phylink(struct hci_dev *hdev, u8 status)
1796{
1797 struct hci_cp_accept_phy_link *cp;
1798
1799 BT_DBG("%s status 0x%2.2x", hdev->name, status);
1800
1801 if (status)
1802 return;
1803
1804 cp = hci_sent_cmd_data(hdev, HCI_OP_ACCEPT_PHY_LINK);
1805 if (!cp)
1806 return;
1807
1808 amp_write_remote_assoc(hdev, cp->phy_handle);
1809}
1810
Gustavo Padovan6039aa72012-05-23 04:04:18 -03001811static void hci_inquiry_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001812{
1813 __u8 status = *((__u8 *) skb->data);
Johan Hedberg30dc78e2012-01-04 15:44:20 +02001814 struct discovery_state *discov = &hdev->discovery;
1815 struct inquiry_entry *e;
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001816
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +03001817 BT_DBG("%s status 0x%2.2x", hdev->name, status);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001818
Johan Hedberg23bb5762010-12-21 23:01:27 +02001819 hci_req_complete(hdev, HCI_OP_INQUIRY, status);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001820
1821 hci_conn_check_pending(hdev);
Andre Guedes89352e72011-11-04 14:16:53 -03001822
1823 if (!test_and_clear_bit(HCI_INQUIRY, &hdev->flags))
1824 return;
1825
Johan Hedberga8b2d5c2012-01-08 23:11:15 +02001826 if (!test_bit(HCI_MGMT, &hdev->dev_flags))
Johan Hedberg30dc78e2012-01-04 15:44:20 +02001827 return;
1828
Johan Hedberg56e5cb82011-11-08 20:40:16 +02001829 hci_dev_lock(hdev);
Johan Hedberg30dc78e2012-01-04 15:44:20 +02001830
Andre Guedes343f9352012-02-17 20:39:37 -03001831 if (discov->state != DISCOVERY_FINDING)
Johan Hedberg30dc78e2012-01-04 15:44:20 +02001832 goto unlock;
1833
1834 if (list_empty(&discov->resolve)) {
1835 hci_discovery_set_state(hdev, DISCOVERY_STOPPED);
1836 goto unlock;
1837 }
1838
1839 e = hci_inquiry_cache_lookup_resolve(hdev, BDADDR_ANY, NAME_NEEDED);
1840 if (e && hci_resolve_name(hdev, e) == 0) {
1841 e->name_state = NAME_PENDING;
1842 hci_discovery_set_state(hdev, DISCOVERY_RESOLVING);
1843 } else {
1844 hci_discovery_set_state(hdev, DISCOVERY_STOPPED);
1845 }
1846
1847unlock:
Johan Hedberg56e5cb82011-11-08 20:40:16 +02001848 hci_dev_unlock(hdev);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001849}
1850
Gustavo Padovan6039aa72012-05-23 04:04:18 -03001851static void hci_inquiry_result_evt(struct hci_dev *hdev, struct sk_buff *skb)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001852{
Marcel Holtmann45bb4bf2005-08-09 20:27:49 -07001853 struct inquiry_data data;
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001854 struct inquiry_info *info = (void *) (skb->data + 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001855 int num_rsp = *((__u8 *) skb->data);
1856
1857 BT_DBG("%s num_rsp %d", hdev->name, num_rsp);
1858
Marcel Holtmann45bb4bf2005-08-09 20:27:49 -07001859 if (!num_rsp)
1860 return;
1861
Andre Guedes1519cc12012-03-21 00:03:38 -03001862 if (test_bit(HCI_PERIODIC_INQ, &hdev->dev_flags))
1863 return;
1864
Linus Torvalds1da177e2005-04-16 15:20:36 -07001865 hci_dev_lock(hdev);
Marcel Holtmann45bb4bf2005-08-09 20:27:49 -07001866
Johan Hedberge17acd42011-03-30 23:57:16 +03001867 for (; num_rsp; num_rsp--, info++) {
Johan Hedberg388fc8f2012-02-23 00:38:59 +02001868 bool name_known, ssp;
Johan Hedberg31754052012-01-04 13:39:52 +02001869
Linus Torvalds1da177e2005-04-16 15:20:36 -07001870 bacpy(&data.bdaddr, &info->bdaddr);
1871 data.pscan_rep_mode = info->pscan_rep_mode;
1872 data.pscan_period_mode = info->pscan_period_mode;
1873 data.pscan_mode = info->pscan_mode;
1874 memcpy(data.dev_class, info->dev_class, 3);
1875 data.clock_offset = info->clock_offset;
1876 data.rssi = 0x00;
Marcel Holtmann41a96212008-07-14 20:13:48 +02001877 data.ssp_mode = 0x00;
Johan Hedberg31754052012-01-04 13:39:52 +02001878
Johan Hedberg388fc8f2012-02-23 00:38:59 +02001879 name_known = hci_inquiry_cache_update(hdev, &data, false, &ssp);
Johan Hedberg48264f02011-11-09 13:58:58 +02001880 mgmt_device_found(hdev, &info->bdaddr, ACL_LINK, 0x00,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001881 info->dev_class, 0, !name_known, ssp, NULL,
1882 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001883 }
Marcel Holtmann45bb4bf2005-08-09 20:27:49 -07001884
Linus Torvalds1da177e2005-04-16 15:20:36 -07001885 hci_dev_unlock(hdev);
1886}
1887
Gustavo Padovan6039aa72012-05-23 04:04:18 -03001888static void hci_conn_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001889{
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001890 struct hci_ev_conn_complete *ev = (void *) skb->data;
1891 struct hci_conn *conn;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001892
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001893 BT_DBG("%s", hdev->name);
Marcel Holtmann45bb4bf2005-08-09 20:27:49 -07001894
Linus Torvalds1da177e2005-04-16 15:20:36 -07001895 hci_dev_lock(hdev);
Marcel Holtmann45bb4bf2005-08-09 20:27:49 -07001896
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001897 conn = hci_conn_hash_lookup_ba(hdev, ev->link_type, &ev->bdaddr);
Marcel Holtmann94992372009-04-19 19:30:03 +02001898 if (!conn) {
1899 if (ev->link_type != SCO_LINK)
1900 goto unlock;
1901
1902 conn = hci_conn_hash_lookup_ba(hdev, ESCO_LINK, &ev->bdaddr);
1903 if (!conn)
1904 goto unlock;
1905
1906 conn->type = SCO_LINK;
1907 }
Marcel Holtmann45bb4bf2005-08-09 20:27:49 -07001908
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001909 if (!ev->status) {
1910 conn->handle = __le16_to_cpu(ev->handle);
Marcel Holtmann769be972008-07-14 20:13:49 +02001911
1912 if (conn->type == ACL_LINK) {
1913 conn->state = BT_CONFIG;
1914 hci_conn_hold(conn);
Szymon Janca9ea3ed2012-07-19 14:46:08 +02001915
1916 if (!conn->out && !hci_conn_ssp_enabled(conn) &&
1917 !hci_find_link_key(hdev, &ev->bdaddr))
1918 conn->disc_timeout = HCI_PAIRING_TIMEOUT;
1919 else
1920 conn->disc_timeout = HCI_DISCONN_TIMEOUT;
Marcel Holtmann769be972008-07-14 20:13:49 +02001921 } else
1922 conn->state = BT_CONNECTED;
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001923
Marcel Holtmann9eba32b2009-08-22 14:19:26 -07001924 hci_conn_hold_device(conn);
Marcel Holtmann7d0db0a2008-07-14 20:13:51 +02001925 hci_conn_add_sysfs(conn);
1926
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001927 if (test_bit(HCI_AUTH, &hdev->flags))
1928 conn->link_mode |= HCI_LM_AUTH;
1929
1930 if (test_bit(HCI_ENCRYPT, &hdev->flags))
1931 conn->link_mode |= HCI_LM_ENCRYPT;
1932
1933 /* Get remote features */
1934 if (conn->type == ACL_LINK) {
1935 struct hci_cp_read_remote_features cp;
1936 cp.handle = ev->handle;
Marcel Holtmann769be972008-07-14 20:13:49 +02001937 hci_send_cmd(hdev, HCI_OP_READ_REMOTE_FEATURES,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001938 sizeof(cp), &cp);
Marcel Holtmann45bb4bf2005-08-09 20:27:49 -07001939 }
Marcel Holtmann45bb4bf2005-08-09 20:27:49 -07001940
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001941 /* Set packet type for incoming connection */
Andrei Emeltchenkod095c1e2011-12-01 14:33:27 +02001942 if (!conn->out && hdev->hci_ver < BLUETOOTH_VER_2_0) {
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001943 struct hci_cp_change_conn_ptype cp;
1944 cp.handle = ev->handle;
Marcel Holtmanna8746412008-07-14 20:13:46 +02001945 cp.pkt_type = cpu_to_le16(conn->pkt_type);
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001946 hci_send_cmd(hdev, HCI_OP_CHANGE_CONN_PTYPE, sizeof(cp),
1947 &cp);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001948 }
Johan Hedberg17d5c042011-01-22 06:09:08 +02001949 } else {
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001950 conn->state = BT_CLOSED;
Johan Hedberg17d5c042011-01-22 06:09:08 +02001951 if (conn->type == ACL_LINK)
Johan Hedberg744cf192011-11-08 20:40:14 +02001952 mgmt_connect_failed(hdev, &ev->bdaddr, conn->type,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001953 conn->dst_type, ev->status);
Johan Hedberg17d5c042011-01-22 06:09:08 +02001954 }
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001955
Marcel Holtmanne73439d2010-07-26 10:06:00 -04001956 if (conn->type == ACL_LINK)
1957 hci_sco_setup(conn, ev->status);
Marcel Holtmann45bb4bf2005-08-09 20:27:49 -07001958
Marcel Holtmann769be972008-07-14 20:13:49 +02001959 if (ev->status) {
1960 hci_proto_connect_cfm(conn, ev->status);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001961 hci_conn_del(conn);
Marcel Holtmannc89b6e62009-01-15 21:57:03 +01001962 } else if (ev->link_type != ACL_LINK)
1963 hci_proto_connect_cfm(conn, ev->status);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001964
1965unlock:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001966 hci_dev_unlock(hdev);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001967
1968 hci_conn_check_pending(hdev);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001969}
1970
Gustavo Padovan6039aa72012-05-23 04:04:18 -03001971static void hci_conn_request_evt(struct hci_dev *hdev, struct sk_buff *skb)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001972{
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001973 struct hci_ev_conn_request *ev = (void *) skb->data;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001974 int mask = hdev->link_mode;
1975
Andrei Emeltchenko6ed93dc2012-09-25 12:49:43 +03001976 BT_DBG("%s bdaddr %pMR type 0x%x", hdev->name, &ev->bdaddr,
Gustavo Padovan807deac2012-05-17 00:36:24 -03001977 ev->link_type);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001978
1979 mask |= hci_proto_connect_ind(hdev, &ev->bdaddr, ev->link_type);
1980
Szymon Janc138d22e2011-02-17 16:44:23 +01001981 if ((mask & HCI_LM_ACCEPT) &&
Gustavo Padovan807deac2012-05-17 00:36:24 -03001982 !hci_blacklist_lookup(hdev, &ev->bdaddr)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001983 /* Connection accepted */
Marcel Holtmannc7bdd502008-07-14 20:13:47 +02001984 struct inquiry_entry *ie;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001985 struct hci_conn *conn;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001986
1987 hci_dev_lock(hdev);
Marcel Holtmannb6a0dc82007-10-20 14:55:10 +02001988
Andrei Emeltchenkocc11b9c2010-11-22 13:21:37 +02001989 ie = hci_inquiry_cache_lookup(hdev, &ev->bdaddr);
1990 if (ie)
Marcel Holtmannc7bdd502008-07-14 20:13:47 +02001991 memcpy(ie->data.dev_class, ev->dev_class, 3);
1992
Gustavo Padovan8fc9ced2012-05-23 04:04:21 -03001993 conn = hci_conn_hash_lookup_ba(hdev, ev->link_type,
1994 &ev->bdaddr);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001995 if (!conn) {
Andrei Emeltchenkocc11b9c2010-11-22 13:21:37 +02001996 conn = hci_conn_add(hdev, ev->link_type, &ev->bdaddr);
1997 if (!conn) {
Gustavo F. Padovan893ef972010-07-18 15:13:37 -03001998 BT_ERR("No memory for new connection");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001999 hci_dev_unlock(hdev);
2000 return;
2001 }
2002 }
Marcel Holtmannb6a0dc82007-10-20 14:55:10 +02002003
Linus Torvalds1da177e2005-04-16 15:20:36 -07002004 memcpy(conn->dev_class, ev->dev_class, 3);
2005 conn->state = BT_CONNECT;
Marcel Holtmannb6a0dc82007-10-20 14:55:10 +02002006
Linus Torvalds1da177e2005-04-16 15:20:36 -07002007 hci_dev_unlock(hdev);
2008
Marcel Holtmannb6a0dc82007-10-20 14:55:10 +02002009 if (ev->link_type == ACL_LINK || !lmp_esco_capable(hdev)) {
2010 struct hci_cp_accept_conn_req cp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002011
Marcel Holtmannb6a0dc82007-10-20 14:55:10 +02002012 bacpy(&cp.bdaddr, &ev->bdaddr);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002013
Marcel Holtmannb6a0dc82007-10-20 14:55:10 +02002014 if (lmp_rswitch_capable(hdev) && (mask & HCI_LM_MASTER))
2015 cp.role = 0x00; /* Become master */
2016 else
2017 cp.role = 0x01; /* Remain slave */
2018
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002019 hci_send_cmd(hdev, HCI_OP_ACCEPT_CONN_REQ, sizeof(cp),
2020 &cp);
Marcel Holtmannb6a0dc82007-10-20 14:55:10 +02002021 } else {
2022 struct hci_cp_accept_sync_conn_req cp;
2023
2024 bacpy(&cp.bdaddr, &ev->bdaddr);
Marcel Holtmanna8746412008-07-14 20:13:46 +02002025 cp.pkt_type = cpu_to_le16(conn->pkt_type);
Marcel Holtmannb6a0dc82007-10-20 14:55:10 +02002026
Andrei Emeltchenko82781e62012-05-25 11:38:27 +03002027 cp.tx_bandwidth = __constant_cpu_to_le32(0x00001f40);
2028 cp.rx_bandwidth = __constant_cpu_to_le32(0x00001f40);
2029 cp.max_latency = __constant_cpu_to_le16(0xffff);
Marcel Holtmannb6a0dc82007-10-20 14:55:10 +02002030 cp.content_format = cpu_to_le16(hdev->voice_setting);
2031 cp.retrans_effort = 0xff;
2032
2033 hci_send_cmd(hdev, HCI_OP_ACCEPT_SYNC_CONN_REQ,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002034 sizeof(cp), &cp);
Marcel Holtmannb6a0dc82007-10-20 14:55:10 +02002035 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002036 } else {
2037 /* Connection rejected */
2038 struct hci_cp_reject_conn_req cp;
2039
2040 bacpy(&cp.bdaddr, &ev->bdaddr);
Andrei Emeltchenko9f5a0d72011-11-07 14:20:25 +02002041 cp.reason = HCI_ERROR_REJ_BAD_ADDR;
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002042 hci_send_cmd(hdev, HCI_OP_REJECT_CONN_REQ, sizeof(cp), &cp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002043 }
2044}
2045
Mikel Astizf0d6a0e2012-08-09 09:52:30 +02002046static u8 hci_to_mgmt_reason(u8 err)
2047{
2048 switch (err) {
2049 case HCI_ERROR_CONNECTION_TIMEOUT:
2050 return MGMT_DEV_DISCONN_TIMEOUT;
2051 case HCI_ERROR_REMOTE_USER_TERM:
2052 case HCI_ERROR_REMOTE_LOW_RESOURCES:
2053 case HCI_ERROR_REMOTE_POWER_OFF:
2054 return MGMT_DEV_DISCONN_REMOTE;
2055 case HCI_ERROR_LOCAL_HOST_TERM:
2056 return MGMT_DEV_DISCONN_LOCAL_HOST;
2057 default:
2058 return MGMT_DEV_DISCONN_UNKNOWN;
2059 }
2060}
2061
Gustavo Padovan6039aa72012-05-23 04:04:18 -03002062static void hci_disconn_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002063{
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002064 struct hci_ev_disconn_complete *ev = (void *) skb->data;
Marcel Holtmann04837f62006-07-03 10:02:33 +02002065 struct hci_conn *conn;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002066
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +03002067 BT_DBG("%s status 0x%2.2x", hdev->name, ev->status);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002068
Linus Torvalds1da177e2005-04-16 15:20:36 -07002069 hci_dev_lock(hdev);
2070
Marcel Holtmann04837f62006-07-03 10:02:33 +02002071 conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
Johan Hedbergf7520542011-01-20 12:34:39 +02002072 if (!conn)
2073 goto unlock;
Marcel Holtmann7d0db0a2008-07-14 20:13:51 +02002074
Johan Hedberg37d9ef72011-11-10 15:54:39 +02002075 if (ev->status == 0)
2076 conn->state = BT_CLOSED;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002077
Johan Hedbergb644ba32012-01-17 21:48:47 +02002078 if (test_and_clear_bit(HCI_CONN_MGMT_CONNECTED, &conn->flags) &&
Gustavo Padovan807deac2012-05-17 00:36:24 -03002079 (conn->type == ACL_LINK || conn->type == LE_LINK)) {
Mikel Astizf0d6a0e2012-08-09 09:52:30 +02002080 if (ev->status) {
Johan Hedberg88c3df12012-02-09 14:27:38 +02002081 mgmt_disconnect_failed(hdev, &conn->dst, conn->type,
Gustavo Padovan807deac2012-05-17 00:36:24 -03002082 conn->dst_type, ev->status);
Mikel Astizf0d6a0e2012-08-09 09:52:30 +02002083 } else {
2084 u8 reason = hci_to_mgmt_reason(ev->reason);
2085
Johan Hedbergafc747a2012-01-15 18:11:07 +02002086 mgmt_device_disconnected(hdev, &conn->dst, conn->type,
Mikel Astizf0d6a0e2012-08-09 09:52:30 +02002087 conn->dst_type, reason);
2088 }
Johan Hedberg37d9ef72011-11-10 15:54:39 +02002089 }
Johan Hedbergf7520542011-01-20 12:34:39 +02002090
Johan Hedberg37d9ef72011-11-10 15:54:39 +02002091 if (ev->status == 0) {
Vishal Agarwal6ec5bca2012-04-16 14:44:44 +05302092 if (conn->type == ACL_LINK && conn->flush_key)
2093 hci_remove_link_key(hdev, &conn->dst);
Johan Hedberg37d9ef72011-11-10 15:54:39 +02002094 hci_proto_disconn_cfm(conn, ev->reason);
2095 hci_conn_del(conn);
2096 }
Johan Hedbergf7520542011-01-20 12:34:39 +02002097
2098unlock:
Linus Torvalds1da177e2005-04-16 15:20:36 -07002099 hci_dev_unlock(hdev);
2100}
2101
Gustavo Padovan6039aa72012-05-23 04:04:18 -03002102static void hci_auth_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002103{
2104 struct hci_ev_auth_complete *ev = (void *) skb->data;
2105 struct hci_conn *conn;
2106
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +03002107 BT_DBG("%s status 0x%2.2x", hdev->name, ev->status);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002108
2109 hci_dev_lock(hdev);
2110
2111 conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
Waldemar Rymarkiewiczd7556e22011-05-31 15:49:26 +02002112 if (!conn)
2113 goto unlock;
2114
2115 if (!ev->status) {
Johan Hedbergaa64a8b2012-01-18 21:33:12 +02002116 if (!hci_conn_ssp_enabled(conn) &&
Gustavo Padovan807deac2012-05-17 00:36:24 -03002117 test_bit(HCI_CONN_REAUTH_PEND, &conn->flags)) {
Waldemar Rymarkiewiczd7556e22011-05-31 15:49:26 +02002118 BT_INFO("re-auth of legacy device is not possible.");
Johan Hedberg2a611692011-02-19 12:06:00 -03002119 } else {
Waldemar Rymarkiewiczd7556e22011-05-31 15:49:26 +02002120 conn->link_mode |= HCI_LM_AUTH;
2121 conn->sec_level = conn->pending_sec_level;
Johan Hedberg2a611692011-02-19 12:06:00 -03002122 }
Waldemar Rymarkiewiczd7556e22011-05-31 15:49:26 +02002123 } else {
Johan Hedbergbab73cb2012-02-09 16:07:29 +02002124 mgmt_auth_failed(hdev, &conn->dst, conn->type, conn->dst_type,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002125 ev->status);
Waldemar Rymarkiewiczd7556e22011-05-31 15:49:26 +02002126 }
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002127
Johan Hedberg51a8efd2012-01-16 06:10:31 +02002128 clear_bit(HCI_CONN_AUTH_PEND, &conn->flags);
2129 clear_bit(HCI_CONN_REAUTH_PEND, &conn->flags);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002130
Waldemar Rymarkiewiczd7556e22011-05-31 15:49:26 +02002131 if (conn->state == BT_CONFIG) {
Johan Hedbergaa64a8b2012-01-18 21:33:12 +02002132 if (!ev->status && hci_conn_ssp_enabled(conn)) {
Waldemar Rymarkiewiczd7556e22011-05-31 15:49:26 +02002133 struct hci_cp_set_conn_encrypt cp;
2134 cp.handle = ev->handle;
2135 cp.encrypt = 0x01;
2136 hci_send_cmd(hdev, HCI_OP_SET_CONN_ENCRYPT, sizeof(cp),
Gustavo Padovan807deac2012-05-17 00:36:24 -03002137 &cp);
Marcel Holtmann052b30b2009-04-26 20:01:22 +02002138 } else {
Waldemar Rymarkiewiczd7556e22011-05-31 15:49:26 +02002139 conn->state = BT_CONNECTED;
2140 hci_proto_connect_cfm(conn, ev->status);
Marcel Holtmann052b30b2009-04-26 20:01:22 +02002141 hci_conn_put(conn);
2142 }
Waldemar Rymarkiewiczd7556e22011-05-31 15:49:26 +02002143 } else {
2144 hci_auth_cfm(conn, ev->status);
Marcel Holtmann052b30b2009-04-26 20:01:22 +02002145
Waldemar Rymarkiewiczd7556e22011-05-31 15:49:26 +02002146 hci_conn_hold(conn);
2147 conn->disc_timeout = HCI_DISCONN_TIMEOUT;
2148 hci_conn_put(conn);
2149 }
2150
Johan Hedberg51a8efd2012-01-16 06:10:31 +02002151 if (test_bit(HCI_CONN_ENCRYPT_PEND, &conn->flags)) {
Waldemar Rymarkiewiczd7556e22011-05-31 15:49:26 +02002152 if (!ev->status) {
2153 struct hci_cp_set_conn_encrypt cp;
2154 cp.handle = ev->handle;
2155 cp.encrypt = 0x01;
2156 hci_send_cmd(hdev, HCI_OP_SET_CONN_ENCRYPT, sizeof(cp),
Gustavo Padovan807deac2012-05-17 00:36:24 -03002157 &cp);
Waldemar Rymarkiewiczd7556e22011-05-31 15:49:26 +02002158 } else {
Johan Hedberg51a8efd2012-01-16 06:10:31 +02002159 clear_bit(HCI_CONN_ENCRYPT_PEND, &conn->flags);
Waldemar Rymarkiewiczd7556e22011-05-31 15:49:26 +02002160 hci_encrypt_cfm(conn, ev->status, 0x00);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002161 }
2162 }
2163
Waldemar Rymarkiewiczd7556e22011-05-31 15:49:26 +02002164unlock:
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002165 hci_dev_unlock(hdev);
2166}
2167
Gustavo Padovan6039aa72012-05-23 04:04:18 -03002168static void hci_remote_name_evt(struct hci_dev *hdev, struct sk_buff *skb)
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002169{
Johan Hedberg127178d2010-11-18 22:22:29 +02002170 struct hci_ev_remote_name *ev = (void *) skb->data;
2171 struct hci_conn *conn;
2172
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002173 BT_DBG("%s", hdev->name);
2174
2175 hci_conn_check_pending(hdev);
Johan Hedberg127178d2010-11-18 22:22:29 +02002176
2177 hci_dev_lock(hdev);
2178
2179 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
Johan Hedbergb644ba32012-01-17 21:48:47 +02002180
2181 if (!test_bit(HCI_MGMT, &hdev->dev_flags))
2182 goto check_auth;
2183
2184 if (ev->status == 0)
2185 hci_check_pending_name(hdev, conn, &ev->bdaddr, ev->name,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002186 strnlen(ev->name, HCI_MAX_NAME_LENGTH));
Johan Hedbergb644ba32012-01-17 21:48:47 +02002187 else
2188 hci_check_pending_name(hdev, conn, &ev->bdaddr, NULL, 0);
2189
2190check_auth:
Johan Hedberg79c6c702011-04-28 11:28:55 -07002191 if (!conn)
2192 goto unlock;
2193
2194 if (!hci_outgoing_auth_needed(hdev, conn))
2195 goto unlock;
2196
Johan Hedberg51a8efd2012-01-16 06:10:31 +02002197 if (!test_and_set_bit(HCI_CONN_AUTH_PEND, &conn->flags)) {
Johan Hedberg127178d2010-11-18 22:22:29 +02002198 struct hci_cp_auth_requested cp;
2199 cp.handle = __cpu_to_le16(conn->handle);
2200 hci_send_cmd(hdev, HCI_OP_AUTH_REQUESTED, sizeof(cp), &cp);
2201 }
2202
Johan Hedberg79c6c702011-04-28 11:28:55 -07002203unlock:
Johan Hedberg127178d2010-11-18 22:22:29 +02002204 hci_dev_unlock(hdev);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002205}
2206
Gustavo Padovan6039aa72012-05-23 04:04:18 -03002207static void hci_encrypt_change_evt(struct hci_dev *hdev, struct sk_buff *skb)
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002208{
2209 struct hci_ev_encrypt_change *ev = (void *) skb->data;
2210 struct hci_conn *conn;
2211
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +03002212 BT_DBG("%s status 0x%2.2x", hdev->name, ev->status);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002213
2214 hci_dev_lock(hdev);
2215
2216 conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
2217 if (conn) {
2218 if (!ev->status) {
Marcel Holtmannae293192008-07-14 20:13:45 +02002219 if (ev->encrypt) {
2220 /* Encryption implies authentication */
2221 conn->link_mode |= HCI_LM_AUTH;
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002222 conn->link_mode |= HCI_LM_ENCRYPT;
Vinicius Costa Gomesda85e5e2011-06-09 18:50:53 -03002223 conn->sec_level = conn->pending_sec_level;
Marcel Holtmannae293192008-07-14 20:13:45 +02002224 } else
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002225 conn->link_mode &= ~HCI_LM_ENCRYPT;
2226 }
2227
Johan Hedberg51a8efd2012-01-16 06:10:31 +02002228 clear_bit(HCI_CONN_ENCRYPT_PEND, &conn->flags);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002229
Gustavo Padovana7d77232012-05-13 03:20:07 -03002230 if (ev->status && conn->state == BT_CONNECTED) {
Gustavo Padovand839c812012-05-16 12:17:12 -03002231 hci_acl_disconn(conn, HCI_ERROR_AUTH_FAILURE);
Gustavo Padovana7d77232012-05-13 03:20:07 -03002232 hci_conn_put(conn);
2233 goto unlock;
2234 }
2235
Marcel Holtmannf8558552008-07-14 20:13:49 +02002236 if (conn->state == BT_CONFIG) {
2237 if (!ev->status)
2238 conn->state = BT_CONNECTED;
2239
2240 hci_proto_connect_cfm(conn, ev->status);
2241 hci_conn_put(conn);
2242 } else
2243 hci_encrypt_cfm(conn, ev->status, ev->encrypt);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002244 }
2245
Gustavo Padovana7d77232012-05-13 03:20:07 -03002246unlock:
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002247 hci_dev_unlock(hdev);
2248}
2249
Gustavo Padovan6039aa72012-05-23 04:04:18 -03002250static void hci_change_link_key_complete_evt(struct hci_dev *hdev,
2251 struct sk_buff *skb)
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002252{
2253 struct hci_ev_change_link_key_complete *ev = (void *) skb->data;
2254 struct hci_conn *conn;
2255
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +03002256 BT_DBG("%s status 0x%2.2x", hdev->name, ev->status);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002257
2258 hci_dev_lock(hdev);
2259
2260 conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
2261 if (conn) {
2262 if (!ev->status)
2263 conn->link_mode |= HCI_LM_SECURE;
2264
Johan Hedberg51a8efd2012-01-16 06:10:31 +02002265 clear_bit(HCI_CONN_AUTH_PEND, &conn->flags);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002266
2267 hci_key_change_cfm(conn, ev->status);
2268 }
2269
2270 hci_dev_unlock(hdev);
2271}
2272
Gustavo Padovan6039aa72012-05-23 04:04:18 -03002273static void hci_remote_features_evt(struct hci_dev *hdev,
2274 struct sk_buff *skb)
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002275{
2276 struct hci_ev_remote_features *ev = (void *) skb->data;
2277 struct hci_conn *conn;
2278
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +03002279 BT_DBG("%s status 0x%2.2x", hdev->name, ev->status);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002280
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002281 hci_dev_lock(hdev);
2282
2283 conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
Johan Hedbergccd556f2010-11-10 17:11:51 +02002284 if (!conn)
2285 goto unlock;
Marcel Holtmann769be972008-07-14 20:13:49 +02002286
Johan Hedbergccd556f2010-11-10 17:11:51 +02002287 if (!ev->status)
2288 memcpy(conn->features, ev->features, 8);
2289
2290 if (conn->state != BT_CONFIG)
2291 goto unlock;
2292
2293 if (!ev->status && lmp_ssp_capable(hdev) && lmp_ssp_capable(conn)) {
2294 struct hci_cp_read_remote_ext_features cp;
2295 cp.handle = ev->handle;
2296 cp.page = 0x01;
2297 hci_send_cmd(hdev, HCI_OP_READ_REMOTE_EXT_FEATURES,
Gustavo Padovan807deac2012-05-17 00:36:24 -03002298 sizeof(cp), &cp);
Johan Hedberg392599b2010-11-18 22:22:28 +02002299 goto unlock;
2300 }
2301
Johan Hedberg671267b2012-05-12 16:11:50 -03002302 if (!ev->status && !test_bit(HCI_CONN_MGMT_CONNECTED, &conn->flags)) {
Johan Hedberg127178d2010-11-18 22:22:29 +02002303 struct hci_cp_remote_name_req cp;
2304 memset(&cp, 0, sizeof(cp));
2305 bacpy(&cp.bdaddr, &conn->dst);
2306 cp.pscan_rep_mode = 0x02;
2307 hci_send_cmd(hdev, HCI_OP_REMOTE_NAME_REQ, sizeof(cp), &cp);
Johan Hedbergb644ba32012-01-17 21:48:47 +02002308 } else if (!test_and_set_bit(HCI_CONN_MGMT_CONNECTED, &conn->flags))
2309 mgmt_device_connected(hdev, &conn->dst, conn->type,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002310 conn->dst_type, 0, NULL, 0,
2311 conn->dev_class);
Johan Hedberg392599b2010-11-18 22:22:28 +02002312
Johan Hedberg127178d2010-11-18 22:22:29 +02002313 if (!hci_outgoing_auth_needed(hdev, conn)) {
Johan Hedbergccd556f2010-11-10 17:11:51 +02002314 conn->state = BT_CONNECTED;
2315 hci_proto_connect_cfm(conn, ev->status);
2316 hci_conn_put(conn);
Marcel Holtmann769be972008-07-14 20:13:49 +02002317 }
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002318
Johan Hedbergccd556f2010-11-10 17:11:51 +02002319unlock:
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002320 hci_dev_unlock(hdev);
2321}
2322
Gustavo Padovan6039aa72012-05-23 04:04:18 -03002323static void hci_remote_version_evt(struct hci_dev *hdev, struct sk_buff *skb)
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002324{
2325 BT_DBG("%s", hdev->name);
2326}
2327
Gustavo Padovan6039aa72012-05-23 04:04:18 -03002328static void hci_qos_setup_complete_evt(struct hci_dev *hdev,
2329 struct sk_buff *skb)
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002330{
2331 BT_DBG("%s", hdev->name);
2332}
2333
Gustavo Padovan6039aa72012-05-23 04:04:18 -03002334static void hci_cmd_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002335{
2336 struct hci_ev_cmd_complete *ev = (void *) skb->data;
2337 __u16 opcode;
2338
2339 skb_pull(skb, sizeof(*ev));
2340
2341 opcode = __le16_to_cpu(ev->opcode);
2342
2343 switch (opcode) {
2344 case HCI_OP_INQUIRY_CANCEL:
2345 hci_cc_inquiry_cancel(hdev, skb);
2346 break;
2347
Andre Guedes4d934832012-03-21 00:03:35 -03002348 case HCI_OP_PERIODIC_INQ:
2349 hci_cc_periodic_inq(hdev, skb);
2350 break;
2351
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002352 case HCI_OP_EXIT_PERIODIC_INQ:
2353 hci_cc_exit_periodic_inq(hdev, skb);
2354 break;
2355
2356 case HCI_OP_REMOTE_NAME_REQ_CANCEL:
2357 hci_cc_remote_name_req_cancel(hdev, skb);
2358 break;
2359
2360 case HCI_OP_ROLE_DISCOVERY:
2361 hci_cc_role_discovery(hdev, skb);
2362 break;
2363
Marcel Holtmanne4e8e372008-07-14 20:13:47 +02002364 case HCI_OP_READ_LINK_POLICY:
2365 hci_cc_read_link_policy(hdev, skb);
2366 break;
2367
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002368 case HCI_OP_WRITE_LINK_POLICY:
2369 hci_cc_write_link_policy(hdev, skb);
2370 break;
2371
Marcel Holtmanne4e8e372008-07-14 20:13:47 +02002372 case HCI_OP_READ_DEF_LINK_POLICY:
2373 hci_cc_read_def_link_policy(hdev, skb);
2374 break;
2375
2376 case HCI_OP_WRITE_DEF_LINK_POLICY:
2377 hci_cc_write_def_link_policy(hdev, skb);
2378 break;
2379
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002380 case HCI_OP_RESET:
2381 hci_cc_reset(hdev, skb);
2382 break;
2383
2384 case HCI_OP_WRITE_LOCAL_NAME:
2385 hci_cc_write_local_name(hdev, skb);
2386 break;
2387
2388 case HCI_OP_READ_LOCAL_NAME:
2389 hci_cc_read_local_name(hdev, skb);
2390 break;
2391
2392 case HCI_OP_WRITE_AUTH_ENABLE:
2393 hci_cc_write_auth_enable(hdev, skb);
2394 break;
2395
2396 case HCI_OP_WRITE_ENCRYPT_MODE:
2397 hci_cc_write_encrypt_mode(hdev, skb);
2398 break;
2399
2400 case HCI_OP_WRITE_SCAN_ENABLE:
2401 hci_cc_write_scan_enable(hdev, skb);
2402 break;
2403
2404 case HCI_OP_READ_CLASS_OF_DEV:
2405 hci_cc_read_class_of_dev(hdev, skb);
2406 break;
2407
2408 case HCI_OP_WRITE_CLASS_OF_DEV:
2409 hci_cc_write_class_of_dev(hdev, skb);
2410 break;
2411
2412 case HCI_OP_READ_VOICE_SETTING:
2413 hci_cc_read_voice_setting(hdev, skb);
2414 break;
2415
2416 case HCI_OP_WRITE_VOICE_SETTING:
2417 hci_cc_write_voice_setting(hdev, skb);
2418 break;
2419
2420 case HCI_OP_HOST_BUFFER_SIZE:
2421 hci_cc_host_buffer_size(hdev, skb);
2422 break;
2423
Marcel Holtmann333140b2008-07-14 20:13:48 +02002424 case HCI_OP_WRITE_SSP_MODE:
2425 hci_cc_write_ssp_mode(hdev, skb);
2426 break;
2427
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002428 case HCI_OP_READ_LOCAL_VERSION:
2429 hci_cc_read_local_version(hdev, skb);
2430 break;
2431
2432 case HCI_OP_READ_LOCAL_COMMANDS:
2433 hci_cc_read_local_commands(hdev, skb);
2434 break;
2435
2436 case HCI_OP_READ_LOCAL_FEATURES:
2437 hci_cc_read_local_features(hdev, skb);
2438 break;
2439
Andre Guedes971e3a42011-06-30 19:20:52 -03002440 case HCI_OP_READ_LOCAL_EXT_FEATURES:
2441 hci_cc_read_local_ext_features(hdev, skb);
2442 break;
2443
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002444 case HCI_OP_READ_BUFFER_SIZE:
2445 hci_cc_read_buffer_size(hdev, skb);
2446 break;
2447
2448 case HCI_OP_READ_BD_ADDR:
2449 hci_cc_read_bd_addr(hdev, skb);
2450 break;
2451
Andrei Emeltchenko350ee4c2011-12-07 15:56:51 +02002452 case HCI_OP_READ_DATA_BLOCK_SIZE:
2453 hci_cc_read_data_block_size(hdev, skb);
2454 break;
2455
Johan Hedberg23bb5762010-12-21 23:01:27 +02002456 case HCI_OP_WRITE_CA_TIMEOUT:
2457 hci_cc_write_ca_timeout(hdev, skb);
2458 break;
2459
Andrei Emeltchenko1e89cff2011-11-24 14:52:02 +02002460 case HCI_OP_READ_FLOW_CONTROL_MODE:
2461 hci_cc_read_flow_control_mode(hdev, skb);
2462 break;
2463
Andrei Emeltchenko928abaa2011-10-12 10:53:57 +03002464 case HCI_OP_READ_LOCAL_AMP_INFO:
2465 hci_cc_read_local_amp_info(hdev, skb);
2466 break;
2467
Andrei Emeltchenko903e4542012-09-27 17:26:09 +03002468 case HCI_OP_READ_LOCAL_AMP_ASSOC:
2469 hci_cc_read_local_amp_assoc(hdev, skb);
2470 break;
2471
Johan Hedbergb0916ea2011-01-10 13:44:55 +02002472 case HCI_OP_DELETE_STORED_LINK_KEY:
2473 hci_cc_delete_stored_link_key(hdev, skb);
2474 break;
2475
Johan Hedbergd5859e22011-01-25 01:19:58 +02002476 case HCI_OP_SET_EVENT_MASK:
2477 hci_cc_set_event_mask(hdev, skb);
2478 break;
2479
2480 case HCI_OP_WRITE_INQUIRY_MODE:
2481 hci_cc_write_inquiry_mode(hdev, skb);
2482 break;
2483
2484 case HCI_OP_READ_INQ_RSP_TX_POWER:
2485 hci_cc_read_inq_rsp_tx_power(hdev, skb);
2486 break;
2487
2488 case HCI_OP_SET_EVENT_FLT:
2489 hci_cc_set_event_flt(hdev, skb);
2490 break;
2491
Johan Hedberg980e1a52011-01-22 06:10:07 +02002492 case HCI_OP_PIN_CODE_REPLY:
2493 hci_cc_pin_code_reply(hdev, skb);
2494 break;
2495
2496 case HCI_OP_PIN_CODE_NEG_REPLY:
2497 hci_cc_pin_code_neg_reply(hdev, skb);
2498 break;
2499
Szymon Jancc35938b2011-03-22 13:12:21 +01002500 case HCI_OP_READ_LOCAL_OOB_DATA:
2501 hci_cc_read_local_oob_data_reply(hdev, skb);
2502 break;
2503
Ville Tervo6ed58ec2011-02-10 22:38:48 -03002504 case HCI_OP_LE_READ_BUFFER_SIZE:
2505 hci_cc_le_read_buffer_size(hdev, skb);
2506 break;
2507
Johan Hedberge36b04c2012-10-19 20:57:47 +03002508 case HCI_OP_LE_SET_EVENT_MASK:
2509 hci_cc_le_set_event_mask(hdev, skb);
2510 break;
2511
Johan Hedberga5c29682011-02-19 12:05:57 -03002512 case HCI_OP_USER_CONFIRM_REPLY:
2513 hci_cc_user_confirm_reply(hdev, skb);
2514 break;
2515
2516 case HCI_OP_USER_CONFIRM_NEG_REPLY:
2517 hci_cc_user_confirm_neg_reply(hdev, skb);
2518 break;
2519
Brian Gix1143d452011-11-23 08:28:34 -08002520 case HCI_OP_USER_PASSKEY_REPLY:
2521 hci_cc_user_passkey_reply(hdev, skb);
2522 break;
2523
2524 case HCI_OP_USER_PASSKEY_NEG_REPLY:
2525 hci_cc_user_passkey_neg_reply(hdev, skb);
Szymon Janc16cde992012-04-13 12:32:42 +02002526 break;
Andre Guedes07f7fa52011-12-02 21:13:31 +09002527
2528 case HCI_OP_LE_SET_SCAN_PARAM:
2529 hci_cc_le_set_scan_param(hdev, skb);
Brian Gix1143d452011-11-23 08:28:34 -08002530 break;
2531
Andre Guedeseb9d91f2011-05-26 16:23:52 -03002532 case HCI_OP_LE_SET_SCAN_ENABLE:
2533 hci_cc_le_set_scan_enable(hdev, skb);
2534 break;
2535
Vinicius Costa Gomesa7a595f2011-06-09 18:50:47 -03002536 case HCI_OP_LE_LTK_REPLY:
2537 hci_cc_le_ltk_reply(hdev, skb);
2538 break;
2539
2540 case HCI_OP_LE_LTK_NEG_REPLY:
2541 hci_cc_le_ltk_neg_reply(hdev, skb);
2542 break;
2543
Andre Guedesf9b49302011-06-30 19:20:53 -03002544 case HCI_OP_WRITE_LE_HOST_SUPPORTED:
2545 hci_cc_write_le_host_supported(hdev, skb);
2546 break;
2547
Andrei Emeltchenko93c284e2012-09-27 17:26:20 +03002548 case HCI_OP_WRITE_REMOTE_AMP_ASSOC:
2549 hci_cc_write_remote_amp_assoc(hdev, skb);
2550 break;
2551
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002552 default:
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +03002553 BT_DBG("%s opcode 0x%4.4x", hdev->name, opcode);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002554 break;
2555 }
2556
Ville Tervo6bd32322011-02-16 16:32:41 +02002557 if (ev->opcode != HCI_OP_NOP)
2558 del_timer(&hdev->cmd_timer);
2559
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002560 if (ev->ncmd) {
2561 atomic_set(&hdev->cmd_cnt, 1);
2562 if (!skb_queue_empty(&hdev->cmd_q))
Gustavo F. Padovanc347b762011-12-14 23:53:47 -02002563 queue_work(hdev->workqueue, &hdev->cmd_work);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002564 }
2565}
2566
Gustavo Padovan6039aa72012-05-23 04:04:18 -03002567static void hci_cmd_status_evt(struct hci_dev *hdev, struct sk_buff *skb)
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002568{
2569 struct hci_ev_cmd_status *ev = (void *) skb->data;
2570 __u16 opcode;
2571
2572 skb_pull(skb, sizeof(*ev));
2573
2574 opcode = __le16_to_cpu(ev->opcode);
2575
2576 switch (opcode) {
2577 case HCI_OP_INQUIRY:
2578 hci_cs_inquiry(hdev, ev->status);
2579 break;
2580
2581 case HCI_OP_CREATE_CONN:
2582 hci_cs_create_conn(hdev, ev->status);
2583 break;
2584
2585 case HCI_OP_ADD_SCO:
2586 hci_cs_add_sco(hdev, ev->status);
2587 break;
2588
Marcel Holtmannf8558552008-07-14 20:13:49 +02002589 case HCI_OP_AUTH_REQUESTED:
2590 hci_cs_auth_requested(hdev, ev->status);
2591 break;
2592
2593 case HCI_OP_SET_CONN_ENCRYPT:
2594 hci_cs_set_conn_encrypt(hdev, ev->status);
2595 break;
2596
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002597 case HCI_OP_REMOTE_NAME_REQ:
2598 hci_cs_remote_name_req(hdev, ev->status);
2599 break;
2600
Marcel Holtmann769be972008-07-14 20:13:49 +02002601 case HCI_OP_READ_REMOTE_FEATURES:
2602 hci_cs_read_remote_features(hdev, ev->status);
2603 break;
2604
2605 case HCI_OP_READ_REMOTE_EXT_FEATURES:
2606 hci_cs_read_remote_ext_features(hdev, ev->status);
2607 break;
2608
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002609 case HCI_OP_SETUP_SYNC_CONN:
2610 hci_cs_setup_sync_conn(hdev, ev->status);
2611 break;
2612
2613 case HCI_OP_SNIFF_MODE:
2614 hci_cs_sniff_mode(hdev, ev->status);
2615 break;
2616
2617 case HCI_OP_EXIT_SNIFF_MODE:
2618 hci_cs_exit_sniff_mode(hdev, ev->status);
2619 break;
2620
Johan Hedberg8962ee72011-01-20 12:40:27 +02002621 case HCI_OP_DISCONNECT:
Johan Hedberg88c3df12012-02-09 14:27:38 +02002622 hci_cs_disconnect(hdev, ev->status);
Johan Hedberg8962ee72011-01-20 12:40:27 +02002623 break;
2624
Ville Tervofcd89c02011-02-10 22:38:47 -03002625 case HCI_OP_LE_CREATE_CONN:
2626 hci_cs_le_create_conn(hdev, ev->status);
2627 break;
2628
Vinicius Costa Gomesa7a595f2011-06-09 18:50:47 -03002629 case HCI_OP_LE_START_ENC:
2630 hci_cs_le_start_enc(hdev, ev->status);
2631 break;
2632
Andrei Emeltchenkoa02226d2012-09-27 17:26:19 +03002633 case HCI_OP_CREATE_PHY_LINK:
2634 hci_cs_create_phylink(hdev, ev->status);
2635 break;
2636
Andrei Emeltchenko0b26ab92012-09-27 17:26:24 +03002637 case HCI_OP_ACCEPT_PHY_LINK:
2638 hci_cs_accept_phylink(hdev, ev->status);
2639 break;
2640
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002641 default:
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +03002642 BT_DBG("%s opcode 0x%4.4x", hdev->name, opcode);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002643 break;
2644 }
2645
Ville Tervo6bd32322011-02-16 16:32:41 +02002646 if (ev->opcode != HCI_OP_NOP)
2647 del_timer(&hdev->cmd_timer);
2648
Gustavo F. Padovan10572132011-03-16 15:36:29 -03002649 if (ev->ncmd && !test_bit(HCI_RESET, &hdev->flags)) {
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002650 atomic_set(&hdev->cmd_cnt, 1);
2651 if (!skb_queue_empty(&hdev->cmd_q))
Gustavo F. Padovanc347b762011-12-14 23:53:47 -02002652 queue_work(hdev->workqueue, &hdev->cmd_work);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002653 }
2654}
2655
Gustavo Padovan6039aa72012-05-23 04:04:18 -03002656static void hci_role_change_evt(struct hci_dev *hdev, struct sk_buff *skb)
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002657{
2658 struct hci_ev_role_change *ev = (void *) skb->data;
2659 struct hci_conn *conn;
2660
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +03002661 BT_DBG("%s status 0x%2.2x", hdev->name, ev->status);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002662
2663 hci_dev_lock(hdev);
2664
2665 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
2666 if (conn) {
2667 if (!ev->status) {
2668 if (ev->role)
2669 conn->link_mode &= ~HCI_LM_MASTER;
2670 else
2671 conn->link_mode |= HCI_LM_MASTER;
2672 }
2673
Johan Hedberg51a8efd2012-01-16 06:10:31 +02002674 clear_bit(HCI_CONN_RSWITCH_PEND, &conn->flags);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002675
2676 hci_role_switch_cfm(conn, ev->status, ev->role);
2677 }
2678
2679 hci_dev_unlock(hdev);
2680}
2681
Gustavo Padovan6039aa72012-05-23 04:04:18 -03002682static void hci_num_comp_pkts_evt(struct hci_dev *hdev, struct sk_buff *skb)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002683{
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002684 struct hci_ev_num_comp_pkts *ev = (void *) skb->data;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002685 int i;
2686
Andrei Emeltchenko32ac5b92011-12-19 16:31:29 +02002687 if (hdev->flow_ctl_mode != HCI_FLOW_CTL_MODE_PACKET_BASED) {
2688 BT_ERR("Wrong event for mode %d", hdev->flow_ctl_mode);
2689 return;
2690 }
2691
Andrei Emeltchenkoc5993de2011-12-30 12:07:47 +02002692 if (skb->len < sizeof(*ev) || skb->len < sizeof(*ev) +
Gustavo Padovan807deac2012-05-17 00:36:24 -03002693 ev->num_hndl * sizeof(struct hci_comp_pkts_info)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002694 BT_DBG("%s bad parameters", hdev->name);
2695 return;
2696 }
2697
Andrei Emeltchenkoc5993de2011-12-30 12:07:47 +02002698 BT_DBG("%s num_hndl %d", hdev->name, ev->num_hndl);
2699
Andrei Emeltchenko613a1c02011-12-19 16:31:30 +02002700 for (i = 0; i < ev->num_hndl; i++) {
2701 struct hci_comp_pkts_info *info = &ev->handles[i];
Linus Torvalds1da177e2005-04-16 15:20:36 -07002702 struct hci_conn *conn;
2703 __u16 handle, count;
2704
Andrei Emeltchenko613a1c02011-12-19 16:31:30 +02002705 handle = __le16_to_cpu(info->handle);
2706 count = __le16_to_cpu(info->count);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002707
2708 conn = hci_conn_hash_lookup_handle(hdev, handle);
Andrei Emeltchenkof4280912011-12-07 15:56:52 +02002709 if (!conn)
2710 continue;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002711
Andrei Emeltchenkof4280912011-12-07 15:56:52 +02002712 conn->sent -= count;
2713
2714 switch (conn->type) {
2715 case ACL_LINK:
2716 hdev->acl_cnt += count;
2717 if (hdev->acl_cnt > hdev->acl_pkts)
2718 hdev->acl_cnt = hdev->acl_pkts;
2719 break;
2720
2721 case LE_LINK:
2722 if (hdev->le_pkts) {
2723 hdev->le_cnt += count;
2724 if (hdev->le_cnt > hdev->le_pkts)
2725 hdev->le_cnt = hdev->le_pkts;
2726 } else {
Andrei Emeltchenko70f230202010-12-01 16:58:25 +02002727 hdev->acl_cnt += count;
2728 if (hdev->acl_cnt > hdev->acl_pkts)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002729 hdev->acl_cnt = hdev->acl_pkts;
2730 }
Andrei Emeltchenkof4280912011-12-07 15:56:52 +02002731 break;
2732
2733 case SCO_LINK:
2734 hdev->sco_cnt += count;
2735 if (hdev->sco_cnt > hdev->sco_pkts)
2736 hdev->sco_cnt = hdev->sco_pkts;
2737 break;
2738
2739 default:
2740 BT_ERR("Unknown type %d conn %p", conn->type, conn);
2741 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002742 }
2743 }
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002744
Gustavo F. Padovan3eff45e2011-12-15 00:50:02 -02002745 queue_work(hdev->workqueue, &hdev->tx_work);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002746}
2747
Andrei Emeltchenko76ef7cf2012-10-10 17:38:29 +03002748static struct hci_conn *__hci_conn_lookup_handle(struct hci_dev *hdev,
2749 __u16 handle)
2750{
2751 struct hci_chan *chan;
2752
2753 switch (hdev->dev_type) {
2754 case HCI_BREDR:
2755 return hci_conn_hash_lookup_handle(hdev, handle);
2756 case HCI_AMP:
2757 chan = hci_chan_lookup_handle(hdev, handle);
2758 if (chan)
2759 return chan->conn;
2760 break;
2761 default:
2762 BT_ERR("%s unknown dev_type %d", hdev->name, hdev->dev_type);
2763 break;
2764 }
2765
2766 return NULL;
2767}
2768
Gustavo Padovan6039aa72012-05-23 04:04:18 -03002769static void hci_num_comp_blocks_evt(struct hci_dev *hdev, struct sk_buff *skb)
Andrei Emeltchenko25e89e92012-01-04 12:41:58 +02002770{
2771 struct hci_ev_num_comp_blocks *ev = (void *) skb->data;
2772 int i;
2773
2774 if (hdev->flow_ctl_mode != HCI_FLOW_CTL_MODE_BLOCK_BASED) {
2775 BT_ERR("Wrong event for mode %d", hdev->flow_ctl_mode);
2776 return;
2777 }
2778
2779 if (skb->len < sizeof(*ev) || skb->len < sizeof(*ev) +
Gustavo Padovan807deac2012-05-17 00:36:24 -03002780 ev->num_hndl * sizeof(struct hci_comp_blocks_info)) {
Andrei Emeltchenko25e89e92012-01-04 12:41:58 +02002781 BT_DBG("%s bad parameters", hdev->name);
2782 return;
2783 }
2784
2785 BT_DBG("%s num_blocks %d num_hndl %d", hdev->name, ev->num_blocks,
Gustavo Padovan807deac2012-05-17 00:36:24 -03002786 ev->num_hndl);
Andrei Emeltchenko25e89e92012-01-04 12:41:58 +02002787
2788 for (i = 0; i < ev->num_hndl; i++) {
2789 struct hci_comp_blocks_info *info = &ev->handles[i];
Andrei Emeltchenko76ef7cf2012-10-10 17:38:29 +03002790 struct hci_conn *conn = NULL;
Andrei Emeltchenko25e89e92012-01-04 12:41:58 +02002791 __u16 handle, block_count;
2792
2793 handle = __le16_to_cpu(info->handle);
2794 block_count = __le16_to_cpu(info->blocks);
2795
Andrei Emeltchenko76ef7cf2012-10-10 17:38:29 +03002796 conn = __hci_conn_lookup_handle(hdev, handle);
Andrei Emeltchenko25e89e92012-01-04 12:41:58 +02002797 if (!conn)
2798 continue;
2799
2800 conn->sent -= block_count;
2801
2802 switch (conn->type) {
2803 case ACL_LINK:
Andrei Emeltchenkobd1eb662012-10-10 17:38:30 +03002804 case AMP_LINK:
Andrei Emeltchenko25e89e92012-01-04 12:41:58 +02002805 hdev->block_cnt += block_count;
2806 if (hdev->block_cnt > hdev->num_blocks)
2807 hdev->block_cnt = hdev->num_blocks;
2808 break;
2809
2810 default:
2811 BT_ERR("Unknown type %d conn %p", conn->type, conn);
2812 break;
2813 }
2814 }
2815
2816 queue_work(hdev->workqueue, &hdev->tx_work);
2817}
2818
Gustavo Padovan6039aa72012-05-23 04:04:18 -03002819static void hci_mode_change_evt(struct hci_dev *hdev, struct sk_buff *skb)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002820{
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002821 struct hci_ev_mode_change *ev = (void *) skb->data;
Marcel Holtmann04837f62006-07-03 10:02:33 +02002822 struct hci_conn *conn;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002823
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +03002824 BT_DBG("%s status 0x%2.2x", hdev->name, ev->status);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002825
2826 hci_dev_lock(hdev);
2827
Marcel Holtmann04837f62006-07-03 10:02:33 +02002828 conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
2829 if (conn) {
2830 conn->mode = ev->mode;
2831 conn->interval = __le16_to_cpu(ev->interval);
2832
Gustavo Padovan8fc9ced2012-05-23 04:04:21 -03002833 if (!test_and_clear_bit(HCI_CONN_MODE_CHANGE_PEND,
2834 &conn->flags)) {
Marcel Holtmann04837f62006-07-03 10:02:33 +02002835 if (conn->mode == HCI_CM_ACTIVE)
Johan Hedberg58a681e2012-01-16 06:47:28 +02002836 set_bit(HCI_CONN_POWER_SAVE, &conn->flags);
Marcel Holtmann04837f62006-07-03 10:02:33 +02002837 else
Johan Hedberg58a681e2012-01-16 06:47:28 +02002838 clear_bit(HCI_CONN_POWER_SAVE, &conn->flags);
Marcel Holtmann04837f62006-07-03 10:02:33 +02002839 }
Marcel Holtmanne73439d2010-07-26 10:06:00 -04002840
Johan Hedberg51a8efd2012-01-16 06:10:31 +02002841 if (test_and_clear_bit(HCI_CONN_SCO_SETUP_PEND, &conn->flags))
Marcel Holtmanne73439d2010-07-26 10:06:00 -04002842 hci_sco_setup(conn, ev->status);
Marcel Holtmann04837f62006-07-03 10:02:33 +02002843 }
2844
2845 hci_dev_unlock(hdev);
2846}
2847
Gustavo Padovan6039aa72012-05-23 04:04:18 -03002848static void hci_pin_code_request_evt(struct hci_dev *hdev, struct sk_buff *skb)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002849{
Marcel Holtmann052b30b2009-04-26 20:01:22 +02002850 struct hci_ev_pin_code_req *ev = (void *) skb->data;
2851 struct hci_conn *conn;
2852
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002853 BT_DBG("%s", hdev->name);
Marcel Holtmann052b30b2009-04-26 20:01:22 +02002854
2855 hci_dev_lock(hdev);
2856
2857 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
Waldemar Rymarkiewiczb6f98042011-09-23 10:01:30 +02002858 if (!conn)
2859 goto unlock;
2860
2861 if (conn->state == BT_CONNECTED) {
Marcel Holtmann052b30b2009-04-26 20:01:22 +02002862 hci_conn_hold(conn);
2863 conn->disc_timeout = HCI_PAIRING_TIMEOUT;
2864 hci_conn_put(conn);
2865 }
2866
Johan Hedberga8b2d5c2012-01-08 23:11:15 +02002867 if (!test_bit(HCI_PAIRABLE, &hdev->dev_flags))
Johan Hedberg03b555e2011-01-04 15:40:05 +02002868 hci_send_cmd(hdev, HCI_OP_PIN_CODE_NEG_REPLY,
Gustavo Padovan807deac2012-05-17 00:36:24 -03002869 sizeof(ev->bdaddr), &ev->bdaddr);
Johan Hedberga8b2d5c2012-01-08 23:11:15 +02002870 else if (test_bit(HCI_MGMT, &hdev->dev_flags)) {
Waldemar Rymarkiewicza770bb52011-04-28 12:07:59 +02002871 u8 secure;
2872
2873 if (conn->pending_sec_level == BT_SECURITY_HIGH)
2874 secure = 1;
2875 else
2876 secure = 0;
2877
Johan Hedberg744cf192011-11-08 20:40:14 +02002878 mgmt_pin_code_request(hdev, &ev->bdaddr, secure);
Waldemar Rymarkiewicza770bb52011-04-28 12:07:59 +02002879 }
Johan Hedberg980e1a52011-01-22 06:10:07 +02002880
Waldemar Rymarkiewiczb6f98042011-09-23 10:01:30 +02002881unlock:
Marcel Holtmann052b30b2009-04-26 20:01:22 +02002882 hci_dev_unlock(hdev);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002883}
2884
Gustavo Padovan6039aa72012-05-23 04:04:18 -03002885static void hci_link_key_request_evt(struct hci_dev *hdev, struct sk_buff *skb)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002886{
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002887 struct hci_ev_link_key_req *ev = (void *) skb->data;
2888 struct hci_cp_link_key_reply cp;
2889 struct hci_conn *conn;
2890 struct link_key *key;
2891
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002892 BT_DBG("%s", hdev->name);
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002893
Johan Hedberga8b2d5c2012-01-08 23:11:15 +02002894 if (!test_bit(HCI_LINK_KEYS, &hdev->dev_flags))
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002895 return;
2896
2897 hci_dev_lock(hdev);
2898
2899 key = hci_find_link_key(hdev, &ev->bdaddr);
2900 if (!key) {
Andrei Emeltchenko6ed93dc2012-09-25 12:49:43 +03002901 BT_DBG("%s link key not found for %pMR", hdev->name,
2902 &ev->bdaddr);
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002903 goto not_found;
2904 }
2905
Andrei Emeltchenko6ed93dc2012-09-25 12:49:43 +03002906 BT_DBG("%s found key type %u for %pMR", hdev->name, key->type,
2907 &ev->bdaddr);
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002908
Johan Hedberga8b2d5c2012-01-08 23:11:15 +02002909 if (!test_bit(HCI_DEBUG_KEYS, &hdev->dev_flags) &&
Gustavo Padovan807deac2012-05-17 00:36:24 -03002910 key->type == HCI_LK_DEBUG_COMBINATION) {
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002911 BT_DBG("%s ignoring debug key", hdev->name);
2912 goto not_found;
2913 }
2914
2915 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
Waldemar Rymarkiewicz60b83f52011-04-28 12:07:56 +02002916 if (conn) {
2917 if (key->type == HCI_LK_UNAUTH_COMBINATION &&
Gustavo Padovan807deac2012-05-17 00:36:24 -03002918 conn->auth_type != 0xff && (conn->auth_type & 0x01)) {
Waldemar Rymarkiewicz60b83f52011-04-28 12:07:56 +02002919 BT_DBG("%s ignoring unauthenticated key", hdev->name);
2920 goto not_found;
2921 }
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002922
Waldemar Rymarkiewicz60b83f52011-04-28 12:07:56 +02002923 if (key->type == HCI_LK_COMBINATION && key->pin_len < 16 &&
Gustavo Padovan807deac2012-05-17 00:36:24 -03002924 conn->pending_sec_level == BT_SECURITY_HIGH) {
Gustavo Padovan8fc9ced2012-05-23 04:04:21 -03002925 BT_DBG("%s ignoring key unauthenticated for high security",
2926 hdev->name);
Waldemar Rymarkiewicz60b83f52011-04-28 12:07:56 +02002927 goto not_found;
2928 }
2929
2930 conn->key_type = key->type;
2931 conn->pin_length = key->pin_len;
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002932 }
2933
2934 bacpy(&cp.bdaddr, &ev->bdaddr);
Andrei Emeltchenko9b3b4462012-05-23 11:31:20 +03002935 memcpy(cp.link_key, key->val, HCI_LINK_KEY_SIZE);
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002936
2937 hci_send_cmd(hdev, HCI_OP_LINK_KEY_REPLY, sizeof(cp), &cp);
2938
2939 hci_dev_unlock(hdev);
2940
2941 return;
2942
2943not_found:
2944 hci_send_cmd(hdev, HCI_OP_LINK_KEY_NEG_REPLY, 6, &ev->bdaddr);
2945 hci_dev_unlock(hdev);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002946}
2947
Gustavo Padovan6039aa72012-05-23 04:04:18 -03002948static void hci_link_key_notify_evt(struct hci_dev *hdev, struct sk_buff *skb)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002949{
Marcel Holtmann052b30b2009-04-26 20:01:22 +02002950 struct hci_ev_link_key_notify *ev = (void *) skb->data;
2951 struct hci_conn *conn;
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002952 u8 pin_len = 0;
Marcel Holtmann052b30b2009-04-26 20:01:22 +02002953
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002954 BT_DBG("%s", hdev->name);
Marcel Holtmann052b30b2009-04-26 20:01:22 +02002955
2956 hci_dev_lock(hdev);
2957
2958 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
2959 if (conn) {
2960 hci_conn_hold(conn);
2961 conn->disc_timeout = HCI_DISCONN_TIMEOUT;
Johan Hedberg980e1a52011-01-22 06:10:07 +02002962 pin_len = conn->pin_length;
Waldemar Rymarkiewicz13d39312011-04-28 12:07:55 +02002963
2964 if (ev->key_type != HCI_LK_CHANGED_COMBINATION)
2965 conn->key_type = ev->key_type;
2966
Marcel Holtmann052b30b2009-04-26 20:01:22 +02002967 hci_conn_put(conn);
2968 }
2969
Johan Hedberga8b2d5c2012-01-08 23:11:15 +02002970 if (test_bit(HCI_LINK_KEYS, &hdev->dev_flags))
Johan Hedbergd25e28a2011-04-28 11:28:59 -07002971 hci_add_link_key(hdev, conn, 1, &ev->bdaddr, ev->link_key,
Gustavo Padovan807deac2012-05-17 00:36:24 -03002972 ev->key_type, pin_len);
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002973
Marcel Holtmann052b30b2009-04-26 20:01:22 +02002974 hci_dev_unlock(hdev);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002975}
2976
Gustavo Padovan6039aa72012-05-23 04:04:18 -03002977static void hci_clock_offset_evt(struct hci_dev *hdev, struct sk_buff *skb)
Marcel Holtmann04837f62006-07-03 10:02:33 +02002978{
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002979 struct hci_ev_clock_offset *ev = (void *) skb->data;
Marcel Holtmann04837f62006-07-03 10:02:33 +02002980 struct hci_conn *conn;
2981
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +03002982 BT_DBG("%s status 0x%2.2x", hdev->name, ev->status);
Marcel Holtmann04837f62006-07-03 10:02:33 +02002983
2984 hci_dev_lock(hdev);
2985
2986 conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
Linus Torvalds1da177e2005-04-16 15:20:36 -07002987 if (conn && !ev->status) {
2988 struct inquiry_entry *ie;
2989
Andrei Emeltchenkocc11b9c2010-11-22 13:21:37 +02002990 ie = hci_inquiry_cache_lookup(hdev, &conn->dst);
2991 if (ie) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002992 ie->data.clock_offset = ev->clock_offset;
2993 ie->timestamp = jiffies;
2994 }
2995 }
2996
2997 hci_dev_unlock(hdev);
2998}
2999
Gustavo Padovan6039aa72012-05-23 04:04:18 -03003000static void hci_pkt_type_change_evt(struct hci_dev *hdev, struct sk_buff *skb)
Marcel Holtmanna8746412008-07-14 20:13:46 +02003001{
3002 struct hci_ev_pkt_type_change *ev = (void *) skb->data;
3003 struct hci_conn *conn;
3004
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +03003005 BT_DBG("%s status 0x%2.2x", hdev->name, ev->status);
Marcel Holtmanna8746412008-07-14 20:13:46 +02003006
3007 hci_dev_lock(hdev);
3008
3009 conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
3010 if (conn && !ev->status)
3011 conn->pkt_type = __le16_to_cpu(ev->pkt_type);
3012
3013 hci_dev_unlock(hdev);
3014}
3015
Gustavo Padovan6039aa72012-05-23 04:04:18 -03003016static void hci_pscan_rep_mode_evt(struct hci_dev *hdev, struct sk_buff *skb)
Marcel Holtmann85a1e932005-08-09 20:28:02 -07003017{
Marcel Holtmanna9de9242007-10-20 13:33:56 +02003018 struct hci_ev_pscan_rep_mode *ev = (void *) skb->data;
Marcel Holtmann85a1e932005-08-09 20:28:02 -07003019 struct inquiry_entry *ie;
3020
3021 BT_DBG("%s", hdev->name);
3022
3023 hci_dev_lock(hdev);
3024
Andrei Emeltchenkocc11b9c2010-11-22 13:21:37 +02003025 ie = hci_inquiry_cache_lookup(hdev, &ev->bdaddr);
3026 if (ie) {
Marcel Holtmann85a1e932005-08-09 20:28:02 -07003027 ie->data.pscan_rep_mode = ev->pscan_rep_mode;
3028 ie->timestamp = jiffies;
3029 }
3030
3031 hci_dev_unlock(hdev);
3032}
3033
Gustavo Padovan6039aa72012-05-23 04:04:18 -03003034static void hci_inquiry_result_with_rssi_evt(struct hci_dev *hdev,
3035 struct sk_buff *skb)
Marcel Holtmanna9de9242007-10-20 13:33:56 +02003036{
3037 struct inquiry_data data;
3038 int num_rsp = *((__u8 *) skb->data);
Johan Hedberg388fc8f2012-02-23 00:38:59 +02003039 bool name_known, ssp;
Marcel Holtmanna9de9242007-10-20 13:33:56 +02003040
3041 BT_DBG("%s num_rsp %d", hdev->name, num_rsp);
3042
3043 if (!num_rsp)
3044 return;
3045
Andre Guedes1519cc12012-03-21 00:03:38 -03003046 if (test_bit(HCI_PERIODIC_INQ, &hdev->dev_flags))
3047 return;
3048
Marcel Holtmanna9de9242007-10-20 13:33:56 +02003049 hci_dev_lock(hdev);
3050
3051 if ((skb->len - 1) / num_rsp != sizeof(struct inquiry_info_with_rssi)) {
Szymon Janc138d22e2011-02-17 16:44:23 +01003052 struct inquiry_info_with_rssi_and_pscan_mode *info;
3053 info = (void *) (skb->data + 1);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02003054
Johan Hedberge17acd42011-03-30 23:57:16 +03003055 for (; num_rsp; num_rsp--, info++) {
Marcel Holtmanna9de9242007-10-20 13:33:56 +02003056 bacpy(&data.bdaddr, &info->bdaddr);
3057 data.pscan_rep_mode = info->pscan_rep_mode;
3058 data.pscan_period_mode = info->pscan_period_mode;
3059 data.pscan_mode = info->pscan_mode;
3060 memcpy(data.dev_class, info->dev_class, 3);
3061 data.clock_offset = info->clock_offset;
3062 data.rssi = info->rssi;
Marcel Holtmann41a96212008-07-14 20:13:48 +02003063 data.ssp_mode = 0x00;
Johan Hedberg31754052012-01-04 13:39:52 +02003064
3065 name_known = hci_inquiry_cache_update(hdev, &data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003066 false, &ssp);
Johan Hedberg48264f02011-11-09 13:58:58 +02003067 mgmt_device_found(hdev, &info->bdaddr, ACL_LINK, 0x00,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003068 info->dev_class, info->rssi,
3069 !name_known, ssp, NULL, 0);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02003070 }
3071 } else {
3072 struct inquiry_info_with_rssi *info = (void *) (skb->data + 1);
3073
Johan Hedberge17acd42011-03-30 23:57:16 +03003074 for (; num_rsp; num_rsp--, info++) {
Marcel Holtmanna9de9242007-10-20 13:33:56 +02003075 bacpy(&data.bdaddr, &info->bdaddr);
3076 data.pscan_rep_mode = info->pscan_rep_mode;
3077 data.pscan_period_mode = info->pscan_period_mode;
3078 data.pscan_mode = 0x00;
3079 memcpy(data.dev_class, info->dev_class, 3);
3080 data.clock_offset = info->clock_offset;
3081 data.rssi = info->rssi;
Marcel Holtmann41a96212008-07-14 20:13:48 +02003082 data.ssp_mode = 0x00;
Johan Hedberg31754052012-01-04 13:39:52 +02003083 name_known = hci_inquiry_cache_update(hdev, &data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003084 false, &ssp);
Johan Hedberg48264f02011-11-09 13:58:58 +02003085 mgmt_device_found(hdev, &info->bdaddr, ACL_LINK, 0x00,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003086 info->dev_class, info->rssi,
3087 !name_known, ssp, NULL, 0);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02003088 }
3089 }
3090
3091 hci_dev_unlock(hdev);
3092}
3093
Gustavo Padovan6039aa72012-05-23 04:04:18 -03003094static void hci_remote_ext_features_evt(struct hci_dev *hdev,
3095 struct sk_buff *skb)
Marcel Holtmanna9de9242007-10-20 13:33:56 +02003096{
Marcel Holtmann41a96212008-07-14 20:13:48 +02003097 struct hci_ev_remote_ext_features *ev = (void *) skb->data;
3098 struct hci_conn *conn;
3099
Marcel Holtmanna9de9242007-10-20 13:33:56 +02003100 BT_DBG("%s", hdev->name);
Marcel Holtmann41a96212008-07-14 20:13:48 +02003101
Marcel Holtmann41a96212008-07-14 20:13:48 +02003102 hci_dev_lock(hdev);
3103
3104 conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
Johan Hedbergccd556f2010-11-10 17:11:51 +02003105 if (!conn)
3106 goto unlock;
Marcel Holtmann41a96212008-07-14 20:13:48 +02003107
Johan Hedbergccd556f2010-11-10 17:11:51 +02003108 if (!ev->status && ev->page == 0x01) {
3109 struct inquiry_entry *ie;
Marcel Holtmann41a96212008-07-14 20:13:48 +02003110
Andrei Emeltchenkocc11b9c2010-11-22 13:21:37 +02003111 ie = hci_inquiry_cache_lookup(hdev, &conn->dst);
3112 if (ie)
Johan Hedberg02b7cc62012-02-28 02:28:43 +02003113 ie->data.ssp_mode = (ev->features[0] & LMP_HOST_SSP);
Marcel Holtmann769be972008-07-14 20:13:49 +02003114
Johan Hedberg02b7cc62012-02-28 02:28:43 +02003115 if (ev->features[0] & LMP_HOST_SSP)
Johan Hedberg58a681e2012-01-16 06:47:28 +02003116 set_bit(HCI_CONN_SSP_ENABLED, &conn->flags);
Marcel Holtmann41a96212008-07-14 20:13:48 +02003117 }
3118
Johan Hedbergccd556f2010-11-10 17:11:51 +02003119 if (conn->state != BT_CONFIG)
3120 goto unlock;
3121
Johan Hedberg671267b2012-05-12 16:11:50 -03003122 if (!ev->status && !test_bit(HCI_CONN_MGMT_CONNECTED, &conn->flags)) {
Johan Hedberg127178d2010-11-18 22:22:29 +02003123 struct hci_cp_remote_name_req cp;
3124 memset(&cp, 0, sizeof(cp));
3125 bacpy(&cp.bdaddr, &conn->dst);
3126 cp.pscan_rep_mode = 0x02;
3127 hci_send_cmd(hdev, HCI_OP_REMOTE_NAME_REQ, sizeof(cp), &cp);
Johan Hedbergb644ba32012-01-17 21:48:47 +02003128 } else if (!test_and_set_bit(HCI_CONN_MGMT_CONNECTED, &conn->flags))
3129 mgmt_device_connected(hdev, &conn->dst, conn->type,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003130 conn->dst_type, 0, NULL, 0,
3131 conn->dev_class);
Johan Hedberg392599b2010-11-18 22:22:28 +02003132
Johan Hedberg127178d2010-11-18 22:22:29 +02003133 if (!hci_outgoing_auth_needed(hdev, conn)) {
Johan Hedbergccd556f2010-11-10 17:11:51 +02003134 conn->state = BT_CONNECTED;
3135 hci_proto_connect_cfm(conn, ev->status);
3136 hci_conn_put(conn);
3137 }
3138
3139unlock:
Marcel Holtmann41a96212008-07-14 20:13:48 +02003140 hci_dev_unlock(hdev);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02003141}
3142
Gustavo Padovan6039aa72012-05-23 04:04:18 -03003143static void hci_sync_conn_complete_evt(struct hci_dev *hdev,
3144 struct sk_buff *skb)
Marcel Holtmanna9de9242007-10-20 13:33:56 +02003145{
Marcel Holtmannb6a0dc82007-10-20 14:55:10 +02003146 struct hci_ev_sync_conn_complete *ev = (void *) skb->data;
3147 struct hci_conn *conn;
3148
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +03003149 BT_DBG("%s status 0x%2.2x", hdev->name, ev->status);
Marcel Holtmannb6a0dc82007-10-20 14:55:10 +02003150
3151 hci_dev_lock(hdev);
3152
3153 conn = hci_conn_hash_lookup_ba(hdev, ev->link_type, &ev->bdaddr);
Marcel Holtmann9dc0a3a2008-07-14 20:13:46 +02003154 if (!conn) {
3155 if (ev->link_type == ESCO_LINK)
3156 goto unlock;
3157
3158 conn = hci_conn_hash_lookup_ba(hdev, ESCO_LINK, &ev->bdaddr);
3159 if (!conn)
3160 goto unlock;
3161
3162 conn->type = SCO_LINK;
3163 }
Marcel Holtmannb6a0dc82007-10-20 14:55:10 +02003164
Marcel Holtmann732547f2009-04-19 19:14:14 +02003165 switch (ev->status) {
3166 case 0x00:
Marcel Holtmannb6a0dc82007-10-20 14:55:10 +02003167 conn->handle = __le16_to_cpu(ev->handle);
3168 conn->state = BT_CONNECTED;
Marcel Holtmann7d0db0a2008-07-14 20:13:51 +02003169
Marcel Holtmann9eba32b2009-08-22 14:19:26 -07003170 hci_conn_hold_device(conn);
Marcel Holtmann7d0db0a2008-07-14 20:13:51 +02003171 hci_conn_add_sysfs(conn);
Marcel Holtmann732547f2009-04-19 19:14:14 +02003172 break;
3173
Stephen Coe705e5712010-02-16 11:29:44 -05003174 case 0x11: /* Unsupported Feature or Parameter Value */
Marcel Holtmann732547f2009-04-19 19:14:14 +02003175 case 0x1c: /* SCO interval rejected */
Nick Pelly1038a002010-02-03 11:42:26 -08003176 case 0x1a: /* Unsupported Remote Feature */
Marcel Holtmann732547f2009-04-19 19:14:14 +02003177 case 0x1f: /* Unspecified error */
3178 if (conn->out && conn->attempt < 2) {
3179 conn->pkt_type = (hdev->esco_type & SCO_ESCO_MASK) |
3180 (hdev->esco_type & EDR_ESCO_MASK);
3181 hci_setup_sync(conn, conn->link->handle);
3182 goto unlock;
3183 }
3184 /* fall through */
3185
3186 default:
Marcel Holtmannb6a0dc82007-10-20 14:55:10 +02003187 conn->state = BT_CLOSED;
Marcel Holtmann732547f2009-04-19 19:14:14 +02003188 break;
3189 }
Marcel Holtmannb6a0dc82007-10-20 14:55:10 +02003190
3191 hci_proto_connect_cfm(conn, ev->status);
3192 if (ev->status)
3193 hci_conn_del(conn);
3194
3195unlock:
3196 hci_dev_unlock(hdev);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02003197}
3198
Gustavo Padovan6039aa72012-05-23 04:04:18 -03003199static void hci_sync_conn_changed_evt(struct hci_dev *hdev, struct sk_buff *skb)
Marcel Holtmanna9de9242007-10-20 13:33:56 +02003200{
3201 BT_DBG("%s", hdev->name);
3202}
3203
Gustavo Padovan6039aa72012-05-23 04:04:18 -03003204static void hci_sniff_subrate_evt(struct hci_dev *hdev, struct sk_buff *skb)
Marcel Holtmann04837f62006-07-03 10:02:33 +02003205{
Marcel Holtmanna9de9242007-10-20 13:33:56 +02003206 struct hci_ev_sniff_subrate *ev = (void *) skb->data;
Marcel Holtmann04837f62006-07-03 10:02:33 +02003207
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +03003208 BT_DBG("%s status 0x%2.2x", hdev->name, ev->status);
Marcel Holtmann04837f62006-07-03 10:02:33 +02003209}
3210
Gustavo Padovan6039aa72012-05-23 04:04:18 -03003211static void hci_extended_inquiry_result_evt(struct hci_dev *hdev,
3212 struct sk_buff *skb)
Marcel Holtmanna9de9242007-10-20 13:33:56 +02003213{
3214 struct inquiry_data data;
3215 struct extended_inquiry_info *info = (void *) (skb->data + 1);
3216 int num_rsp = *((__u8 *) skb->data);
Vishal Agarwal9d939d92012-04-26 19:19:56 +05303217 size_t eir_len;
Marcel Holtmanna9de9242007-10-20 13:33:56 +02003218
3219 BT_DBG("%s num_rsp %d", hdev->name, num_rsp);
3220
3221 if (!num_rsp)
3222 return;
3223
Andre Guedes1519cc12012-03-21 00:03:38 -03003224 if (test_bit(HCI_PERIODIC_INQ, &hdev->dev_flags))
3225 return;
3226
Marcel Holtmanna9de9242007-10-20 13:33:56 +02003227 hci_dev_lock(hdev);
3228
Johan Hedberge17acd42011-03-30 23:57:16 +03003229 for (; num_rsp; num_rsp--, info++) {
Johan Hedberg388fc8f2012-02-23 00:38:59 +02003230 bool name_known, ssp;
Johan Hedberg561aafb2012-01-04 13:31:59 +02003231
Marcel Holtmanna9de9242007-10-20 13:33:56 +02003232 bacpy(&data.bdaddr, &info->bdaddr);
Szymon Janc138d22e2011-02-17 16:44:23 +01003233 data.pscan_rep_mode = info->pscan_rep_mode;
3234 data.pscan_period_mode = info->pscan_period_mode;
3235 data.pscan_mode = 0x00;
Marcel Holtmanna9de9242007-10-20 13:33:56 +02003236 memcpy(data.dev_class, info->dev_class, 3);
Szymon Janc138d22e2011-02-17 16:44:23 +01003237 data.clock_offset = info->clock_offset;
3238 data.rssi = info->rssi;
Marcel Holtmann41a96212008-07-14 20:13:48 +02003239 data.ssp_mode = 0x01;
Johan Hedberg561aafb2012-01-04 13:31:59 +02003240
Johan Hedberga8b2d5c2012-01-08 23:11:15 +02003241 if (test_bit(HCI_MGMT, &hdev->dev_flags))
Johan Hedberg4ddb1932012-01-15 20:04:43 +02003242 name_known = eir_has_data_type(info->data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003243 sizeof(info->data),
3244 EIR_NAME_COMPLETE);
Johan Hedberg561aafb2012-01-04 13:31:59 +02003245 else
3246 name_known = true;
3247
Johan Hedberg388fc8f2012-02-23 00:38:59 +02003248 name_known = hci_inquiry_cache_update(hdev, &data, name_known,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003249 &ssp);
Vishal Agarwal9d939d92012-04-26 19:19:56 +05303250 eir_len = eir_get_length(info->data, sizeof(info->data));
Johan Hedberg48264f02011-11-09 13:58:58 +02003251 mgmt_device_found(hdev, &info->bdaddr, ACL_LINK, 0x00,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003252 info->dev_class, info->rssi, !name_known,
Vishal Agarwal9d939d92012-04-26 19:19:56 +05303253 ssp, info->data, eir_len);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02003254 }
3255
3256 hci_dev_unlock(hdev);
3257}
3258
Johan Hedberg1c2e0042012-06-08 23:31:13 +08003259static void hci_key_refresh_complete_evt(struct hci_dev *hdev,
3260 struct sk_buff *skb)
3261{
3262 struct hci_ev_key_refresh_complete *ev = (void *) skb->data;
3263 struct hci_conn *conn;
3264
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +03003265 BT_DBG("%s status 0x%2.2x handle 0x%4.4x", hdev->name, ev->status,
Johan Hedberg1c2e0042012-06-08 23:31:13 +08003266 __le16_to_cpu(ev->handle));
3267
3268 hci_dev_lock(hdev);
3269
3270 conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
3271 if (!conn)
3272 goto unlock;
3273
3274 if (!ev->status)
3275 conn->sec_level = conn->pending_sec_level;
3276
3277 clear_bit(HCI_CONN_ENCRYPT_PEND, &conn->flags);
3278
3279 if (ev->status && conn->state == BT_CONNECTED) {
3280 hci_acl_disconn(conn, HCI_ERROR_AUTH_FAILURE);
3281 hci_conn_put(conn);
3282 goto unlock;
3283 }
3284
3285 if (conn->state == BT_CONFIG) {
3286 if (!ev->status)
3287 conn->state = BT_CONNECTED;
3288
3289 hci_proto_connect_cfm(conn, ev->status);
3290 hci_conn_put(conn);
3291 } else {
3292 hci_auth_cfm(conn, ev->status);
3293
3294 hci_conn_hold(conn);
3295 conn->disc_timeout = HCI_DISCONN_TIMEOUT;
3296 hci_conn_put(conn);
3297 }
3298
3299unlock:
3300 hci_dev_unlock(hdev);
3301}
3302
Gustavo Padovan6039aa72012-05-23 04:04:18 -03003303static u8 hci_get_auth_req(struct hci_conn *conn)
Johan Hedberg17fa4b92011-01-25 13:28:33 +02003304{
3305 /* If remote requests dedicated bonding follow that lead */
3306 if (conn->remote_auth == 0x02 || conn->remote_auth == 0x03) {
3307 /* If both remote and local IO capabilities allow MITM
3308 * protection then require it, otherwise don't */
3309 if (conn->remote_cap == 0x03 || conn->io_capability == 0x03)
3310 return 0x02;
3311 else
3312 return 0x03;
3313 }
3314
3315 /* If remote requests no-bonding follow that lead */
3316 if (conn->remote_auth == 0x00 || conn->remote_auth == 0x01)
Waldemar Rymarkiewicz58797bf2011-04-28 12:07:58 +02003317 return conn->remote_auth | (conn->auth_type & 0x01);
Johan Hedberg17fa4b92011-01-25 13:28:33 +02003318
3319 return conn->auth_type;
3320}
3321
Gustavo Padovan6039aa72012-05-23 04:04:18 -03003322static void hci_io_capa_request_evt(struct hci_dev *hdev, struct sk_buff *skb)
Marcel Holtmann04936842008-07-14 20:13:48 +02003323{
3324 struct hci_ev_io_capa_request *ev = (void *) skb->data;
3325 struct hci_conn *conn;
3326
3327 BT_DBG("%s", hdev->name);
3328
3329 hci_dev_lock(hdev);
3330
3331 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
Johan Hedberg03b555e2011-01-04 15:40:05 +02003332 if (!conn)
3333 goto unlock;
Marcel Holtmann04936842008-07-14 20:13:48 +02003334
Johan Hedberg03b555e2011-01-04 15:40:05 +02003335 hci_conn_hold(conn);
3336
Johan Hedberga8b2d5c2012-01-08 23:11:15 +02003337 if (!test_bit(HCI_MGMT, &hdev->dev_flags))
Johan Hedberg03b555e2011-01-04 15:40:05 +02003338 goto unlock;
3339
Johan Hedberga8b2d5c2012-01-08 23:11:15 +02003340 if (test_bit(HCI_PAIRABLE, &hdev->dev_flags) ||
Gustavo Padovan807deac2012-05-17 00:36:24 -03003341 (conn->remote_auth & ~0x01) == HCI_AT_NO_BONDING) {
Johan Hedberg17fa4b92011-01-25 13:28:33 +02003342 struct hci_cp_io_capability_reply cp;
3343
3344 bacpy(&cp.bdaddr, &ev->bdaddr);
Hemant Gupta7a7f1e72012-01-16 13:34:29 +05303345 /* Change the IO capability from KeyboardDisplay
3346 * to DisplayYesNo as it is not supported by BT spec. */
3347 cp.capability = (conn->io_capability == 0x04) ?
3348 0x01 : conn->io_capability;
Johan Hedberg7cbc9bd2011-04-28 11:29:04 -07003349 conn->auth_type = hci_get_auth_req(conn);
3350 cp.authentication = conn->auth_type;
Johan Hedberg17fa4b92011-01-25 13:28:33 +02003351
Gustavo Padovan8fc9ced2012-05-23 04:04:21 -03003352 if (hci_find_remote_oob_data(hdev, &conn->dst) &&
3353 (conn->out || test_bit(HCI_CONN_REMOTE_OOB, &conn->flags)))
Szymon Jancce85ee12011-03-22 13:12:23 +01003354 cp.oob_data = 0x01;
3355 else
3356 cp.oob_data = 0x00;
3357
Johan Hedberg17fa4b92011-01-25 13:28:33 +02003358 hci_send_cmd(hdev, HCI_OP_IO_CAPABILITY_REPLY,
Gustavo Padovan807deac2012-05-17 00:36:24 -03003359 sizeof(cp), &cp);
Johan Hedberg03b555e2011-01-04 15:40:05 +02003360 } else {
3361 struct hci_cp_io_capability_neg_reply cp;
3362
3363 bacpy(&cp.bdaddr, &ev->bdaddr);
Andrei Emeltchenko9f5a0d72011-11-07 14:20:25 +02003364 cp.reason = HCI_ERROR_PAIRING_NOT_ALLOWED;
Johan Hedberg03b555e2011-01-04 15:40:05 +02003365
3366 hci_send_cmd(hdev, HCI_OP_IO_CAPABILITY_NEG_REPLY,
Gustavo Padovan807deac2012-05-17 00:36:24 -03003367 sizeof(cp), &cp);
Johan Hedberg03b555e2011-01-04 15:40:05 +02003368 }
3369
3370unlock:
3371 hci_dev_unlock(hdev);
3372}
3373
Gustavo Padovan6039aa72012-05-23 04:04:18 -03003374static void hci_io_capa_reply_evt(struct hci_dev *hdev, struct sk_buff *skb)
Johan Hedberg03b555e2011-01-04 15:40:05 +02003375{
3376 struct hci_ev_io_capa_reply *ev = (void *) skb->data;
3377 struct hci_conn *conn;
3378
3379 BT_DBG("%s", hdev->name);
3380
3381 hci_dev_lock(hdev);
3382
3383 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
3384 if (!conn)
3385 goto unlock;
3386
Johan Hedberg03b555e2011-01-04 15:40:05 +02003387 conn->remote_cap = ev->capability;
Johan Hedberg03b555e2011-01-04 15:40:05 +02003388 conn->remote_auth = ev->authentication;
Johan Hedberg58a681e2012-01-16 06:47:28 +02003389 if (ev->oob_data)
3390 set_bit(HCI_CONN_REMOTE_OOB, &conn->flags);
Johan Hedberg03b555e2011-01-04 15:40:05 +02003391
3392unlock:
Marcel Holtmann04936842008-07-14 20:13:48 +02003393 hci_dev_unlock(hdev);
3394}
3395
Gustavo Padovan6039aa72012-05-23 04:04:18 -03003396static void hci_user_confirm_request_evt(struct hci_dev *hdev,
3397 struct sk_buff *skb)
Johan Hedberga5c29682011-02-19 12:05:57 -03003398{
3399 struct hci_ev_user_confirm_req *ev = (void *) skb->data;
Johan Hedberg55bc1a32011-04-28 11:28:56 -07003400 int loc_mitm, rem_mitm, confirm_hint = 0;
Johan Hedberg7a828902011-04-28 11:28:53 -07003401 struct hci_conn *conn;
Johan Hedberga5c29682011-02-19 12:05:57 -03003402
3403 BT_DBG("%s", hdev->name);
3404
3405 hci_dev_lock(hdev);
3406
Johan Hedberga8b2d5c2012-01-08 23:11:15 +02003407 if (!test_bit(HCI_MGMT, &hdev->dev_flags))
Johan Hedberg7a828902011-04-28 11:28:53 -07003408 goto unlock;
Johan Hedberga5c29682011-02-19 12:05:57 -03003409
Johan Hedberg7a828902011-04-28 11:28:53 -07003410 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
3411 if (!conn)
3412 goto unlock;
3413
3414 loc_mitm = (conn->auth_type & 0x01);
3415 rem_mitm = (conn->remote_auth & 0x01);
3416
3417 /* If we require MITM but the remote device can't provide that
3418 * (it has NoInputNoOutput) then reject the confirmation
3419 * request. The only exception is when we're dedicated bonding
3420 * initiators (connect_cfm_cb set) since then we always have the MITM
3421 * bit set. */
3422 if (!conn->connect_cfm_cb && loc_mitm && conn->remote_cap == 0x03) {
3423 BT_DBG("Rejecting request: remote device can't provide MITM");
3424 hci_send_cmd(hdev, HCI_OP_USER_CONFIRM_NEG_REPLY,
Gustavo Padovan807deac2012-05-17 00:36:24 -03003425 sizeof(ev->bdaddr), &ev->bdaddr);
Johan Hedberg7a828902011-04-28 11:28:53 -07003426 goto unlock;
3427 }
3428
3429 /* If no side requires MITM protection; auto-accept */
3430 if ((!loc_mitm || conn->remote_cap == 0x03) &&
Gustavo Padovan807deac2012-05-17 00:36:24 -03003431 (!rem_mitm || conn->io_capability == 0x03)) {
Johan Hedberg55bc1a32011-04-28 11:28:56 -07003432
3433 /* If we're not the initiators request authorization to
3434 * proceed from user space (mgmt_user_confirm with
3435 * confirm_hint set to 1). */
Johan Hedberg51a8efd2012-01-16 06:10:31 +02003436 if (!test_bit(HCI_CONN_AUTH_PEND, &conn->flags)) {
Johan Hedberg55bc1a32011-04-28 11:28:56 -07003437 BT_DBG("Confirming auto-accept as acceptor");
3438 confirm_hint = 1;
3439 goto confirm;
3440 }
3441
Johan Hedberg9f616562011-04-28 11:28:54 -07003442 BT_DBG("Auto-accept of user confirmation with %ums delay",
Gustavo Padovan807deac2012-05-17 00:36:24 -03003443 hdev->auto_accept_delay);
Johan Hedberg9f616562011-04-28 11:28:54 -07003444
3445 if (hdev->auto_accept_delay > 0) {
3446 int delay = msecs_to_jiffies(hdev->auto_accept_delay);
3447 mod_timer(&conn->auto_accept_timer, jiffies + delay);
3448 goto unlock;
3449 }
3450
Johan Hedberg7a828902011-04-28 11:28:53 -07003451 hci_send_cmd(hdev, HCI_OP_USER_CONFIRM_REPLY,
Gustavo Padovan807deac2012-05-17 00:36:24 -03003452 sizeof(ev->bdaddr), &ev->bdaddr);
Johan Hedberg7a828902011-04-28 11:28:53 -07003453 goto unlock;
3454 }
3455
Johan Hedberg55bc1a32011-04-28 11:28:56 -07003456confirm:
Johan Hedberg272d90d2012-02-09 15:26:12 +02003457 mgmt_user_confirm_request(hdev, &ev->bdaddr, ACL_LINK, 0, ev->passkey,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003458 confirm_hint);
Johan Hedberg7a828902011-04-28 11:28:53 -07003459
3460unlock:
Johan Hedberga5c29682011-02-19 12:05:57 -03003461 hci_dev_unlock(hdev);
3462}
3463
Gustavo Padovan6039aa72012-05-23 04:04:18 -03003464static void hci_user_passkey_request_evt(struct hci_dev *hdev,
3465 struct sk_buff *skb)
Brian Gix1143d452011-11-23 08:28:34 -08003466{
3467 struct hci_ev_user_passkey_req *ev = (void *) skb->data;
3468
3469 BT_DBG("%s", hdev->name);
3470
Johan Hedberga8b2d5c2012-01-08 23:11:15 +02003471 if (test_bit(HCI_MGMT, &hdev->dev_flags))
Johan Hedberg272d90d2012-02-09 15:26:12 +02003472 mgmt_user_passkey_request(hdev, &ev->bdaddr, ACL_LINK, 0);
Brian Gix1143d452011-11-23 08:28:34 -08003473}
3474
Johan Hedberg92a25252012-09-06 18:39:26 +03003475static void hci_user_passkey_notify_evt(struct hci_dev *hdev,
3476 struct sk_buff *skb)
3477{
3478 struct hci_ev_user_passkey_notify *ev = (void *) skb->data;
3479 struct hci_conn *conn;
3480
3481 BT_DBG("%s", hdev->name);
3482
3483 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
3484 if (!conn)
3485 return;
3486
3487 conn->passkey_notify = __le32_to_cpu(ev->passkey);
3488 conn->passkey_entered = 0;
3489
3490 if (test_bit(HCI_MGMT, &hdev->dev_flags))
3491 mgmt_user_passkey_notify(hdev, &conn->dst, conn->type,
3492 conn->dst_type, conn->passkey_notify,
3493 conn->passkey_entered);
3494}
3495
3496static void hci_keypress_notify_evt(struct hci_dev *hdev, struct sk_buff *skb)
3497{
3498 struct hci_ev_keypress_notify *ev = (void *) skb->data;
3499 struct hci_conn *conn;
3500
3501 BT_DBG("%s", hdev->name);
3502
3503 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
3504 if (!conn)
3505 return;
3506
3507 switch (ev->type) {
3508 case HCI_KEYPRESS_STARTED:
3509 conn->passkey_entered = 0;
3510 return;
3511
3512 case HCI_KEYPRESS_ENTERED:
3513 conn->passkey_entered++;
3514 break;
3515
3516 case HCI_KEYPRESS_ERASED:
3517 conn->passkey_entered--;
3518 break;
3519
3520 case HCI_KEYPRESS_CLEARED:
3521 conn->passkey_entered = 0;
3522 break;
3523
3524 case HCI_KEYPRESS_COMPLETED:
3525 return;
3526 }
3527
3528 if (test_bit(HCI_MGMT, &hdev->dev_flags))
3529 mgmt_user_passkey_notify(hdev, &conn->dst, conn->type,
3530 conn->dst_type, conn->passkey_notify,
3531 conn->passkey_entered);
3532}
3533
Gustavo Padovan6039aa72012-05-23 04:04:18 -03003534static void hci_simple_pair_complete_evt(struct hci_dev *hdev,
3535 struct sk_buff *skb)
Marcel Holtmann04936842008-07-14 20:13:48 +02003536{
3537 struct hci_ev_simple_pair_complete *ev = (void *) skb->data;
3538 struct hci_conn *conn;
3539
3540 BT_DBG("%s", hdev->name);
3541
3542 hci_dev_lock(hdev);
3543
3544 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
Johan Hedberg2a611692011-02-19 12:06:00 -03003545 if (!conn)
3546 goto unlock;
Marcel Holtmann04936842008-07-14 20:13:48 +02003547
Johan Hedberg2a611692011-02-19 12:06:00 -03003548 /* To avoid duplicate auth_failed events to user space we check
3549 * the HCI_CONN_AUTH_PEND flag which will be set if we
3550 * initiated the authentication. A traditional auth_complete
3551 * event gets always produced as initiator and is also mapped to
3552 * the mgmt_auth_failed event */
Mikel Astizfa1bd912012-08-09 09:52:29 +02003553 if (!test_bit(HCI_CONN_AUTH_PEND, &conn->flags) && ev->status)
Johan Hedbergbab73cb2012-02-09 16:07:29 +02003554 mgmt_auth_failed(hdev, &conn->dst, conn->type, conn->dst_type,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003555 ev->status);
Johan Hedberg2a611692011-02-19 12:06:00 -03003556
3557 hci_conn_put(conn);
3558
3559unlock:
Marcel Holtmann04936842008-07-14 20:13:48 +02003560 hci_dev_unlock(hdev);
3561}
3562
Gustavo Padovan6039aa72012-05-23 04:04:18 -03003563static void hci_remote_host_features_evt(struct hci_dev *hdev,
3564 struct sk_buff *skb)
Marcel Holtmann41a96212008-07-14 20:13:48 +02003565{
3566 struct hci_ev_remote_host_features *ev = (void *) skb->data;
3567 struct inquiry_entry *ie;
3568
3569 BT_DBG("%s", hdev->name);
3570
3571 hci_dev_lock(hdev);
3572
Andrei Emeltchenkocc11b9c2010-11-22 13:21:37 +02003573 ie = hci_inquiry_cache_lookup(hdev, &ev->bdaddr);
3574 if (ie)
Johan Hedberg02b7cc62012-02-28 02:28:43 +02003575 ie->data.ssp_mode = (ev->features[0] & LMP_HOST_SSP);
Marcel Holtmann41a96212008-07-14 20:13:48 +02003576
3577 hci_dev_unlock(hdev);
3578}
3579
Gustavo Padovan6039aa72012-05-23 04:04:18 -03003580static void hci_remote_oob_data_request_evt(struct hci_dev *hdev,
3581 struct sk_buff *skb)
Szymon Janc2763eda2011-03-22 13:12:22 +01003582{
3583 struct hci_ev_remote_oob_data_request *ev = (void *) skb->data;
3584 struct oob_data *data;
3585
3586 BT_DBG("%s", hdev->name);
3587
3588 hci_dev_lock(hdev);
3589
Johan Hedberga8b2d5c2012-01-08 23:11:15 +02003590 if (!test_bit(HCI_MGMT, &hdev->dev_flags))
Szymon Jance1ba1f12011-04-06 13:01:59 +02003591 goto unlock;
3592
Szymon Janc2763eda2011-03-22 13:12:22 +01003593 data = hci_find_remote_oob_data(hdev, &ev->bdaddr);
3594 if (data) {
3595 struct hci_cp_remote_oob_data_reply cp;
3596
3597 bacpy(&cp.bdaddr, &ev->bdaddr);
3598 memcpy(cp.hash, data->hash, sizeof(cp.hash));
3599 memcpy(cp.randomizer, data->randomizer, sizeof(cp.randomizer));
3600
3601 hci_send_cmd(hdev, HCI_OP_REMOTE_OOB_DATA_REPLY, sizeof(cp),
Gustavo Padovan807deac2012-05-17 00:36:24 -03003602 &cp);
Szymon Janc2763eda2011-03-22 13:12:22 +01003603 } else {
3604 struct hci_cp_remote_oob_data_neg_reply cp;
3605
3606 bacpy(&cp.bdaddr, &ev->bdaddr);
3607 hci_send_cmd(hdev, HCI_OP_REMOTE_OOB_DATA_NEG_REPLY, sizeof(cp),
Gustavo Padovan807deac2012-05-17 00:36:24 -03003608 &cp);
Szymon Janc2763eda2011-03-22 13:12:22 +01003609 }
3610
Szymon Jance1ba1f12011-04-06 13:01:59 +02003611unlock:
Szymon Janc2763eda2011-03-22 13:12:22 +01003612 hci_dev_unlock(hdev);
3613}
3614
Gustavo Padovan6039aa72012-05-23 04:04:18 -03003615static void hci_le_conn_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
Ville Tervofcd89c02011-02-10 22:38:47 -03003616{
3617 struct hci_ev_le_conn_complete *ev = (void *) skb->data;
3618 struct hci_conn *conn;
3619
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +03003620 BT_DBG("%s status 0x%2.2x", hdev->name, ev->status);
Ville Tervofcd89c02011-02-10 22:38:47 -03003621
3622 hci_dev_lock(hdev);
3623
Andre Guedesb47a09b2012-07-27 15:10:15 -03003624 conn = hci_conn_hash_lookup_state(hdev, LE_LINK, BT_CONNECT);
Ville Tervob62f3282011-02-10 22:38:50 -03003625 if (!conn) {
3626 conn = hci_conn_add(hdev, LE_LINK, &ev->bdaddr);
3627 if (!conn) {
3628 BT_ERR("No memory for new connection");
Andre Guedes230fd162012-07-27 15:10:10 -03003629 goto unlock;
Ville Tervob62f3282011-02-10 22:38:50 -03003630 }
Andre Guedes29b79882011-05-31 14:20:54 -03003631
3632 conn->dst_type = ev->bdaddr_type;
Andre Guedesb9b343d2012-07-27 15:10:11 -03003633
3634 if (ev->role == LE_CONN_ROLE_MASTER) {
3635 conn->out = true;
3636 conn->link_mode |= HCI_LM_MASTER;
3637 }
Ville Tervob62f3282011-02-10 22:38:50 -03003638 }
Ville Tervofcd89c02011-02-10 22:38:47 -03003639
Andre Guedescd17dec2012-07-27 15:10:16 -03003640 if (ev->status) {
3641 mgmt_connect_failed(hdev, &conn->dst, conn->type,
3642 conn->dst_type, ev->status);
3643 hci_proto_connect_cfm(conn, ev->status);
3644 conn->state = BT_CLOSED;
3645 hci_conn_del(conn);
3646 goto unlock;
3647 }
3648
Johan Hedbergb644ba32012-01-17 21:48:47 +02003649 if (!test_and_set_bit(HCI_CONN_MGMT_CONNECTED, &conn->flags))
3650 mgmt_device_connected(hdev, &ev->bdaddr, conn->type,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003651 conn->dst_type, 0, NULL, 0, NULL);
Vinicius Costa Gomes83bc71b2011-05-06 18:41:43 -03003652
Vinicius Costa Gomes7b5c0d52011-06-09 18:50:50 -03003653 conn->sec_level = BT_SECURITY_LOW;
Ville Tervofcd89c02011-02-10 22:38:47 -03003654 conn->handle = __le16_to_cpu(ev->handle);
3655 conn->state = BT_CONNECTED;
3656
3657 hci_conn_hold_device(conn);
3658 hci_conn_add_sysfs(conn);
3659
3660 hci_proto_connect_cfm(conn, ev->status);
3661
3662unlock:
3663 hci_dev_unlock(hdev);
3664}
3665
Gustavo Padovan6039aa72012-05-23 04:04:18 -03003666static void hci_le_adv_report_evt(struct hci_dev *hdev, struct sk_buff *skb)
Andre Guedes9aa04c92011-05-26 16:23:51 -03003667{
Andre Guedese95beb42011-09-26 20:48:35 -03003668 u8 num_reports = skb->data[0];
3669 void *ptr = &skb->data[1];
Andre Guedes3c9e9192012-01-10 18:20:50 -03003670 s8 rssi;
Andre Guedes9aa04c92011-05-26 16:23:51 -03003671
3672 hci_dev_lock(hdev);
3673
Andre Guedese95beb42011-09-26 20:48:35 -03003674 while (num_reports--) {
3675 struct hci_ev_le_advertising_info *ev = ptr;
Andre Guedes9aa04c92011-05-26 16:23:51 -03003676
Andre Guedes3c9e9192012-01-10 18:20:50 -03003677 rssi = ev->data[ev->length];
3678 mgmt_device_found(hdev, &ev->bdaddr, LE_LINK, ev->bdaddr_type,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003679 NULL, rssi, 0, 1, ev->data, ev->length);
Andre Guedes3c9e9192012-01-10 18:20:50 -03003680
Andre Guedese95beb42011-09-26 20:48:35 -03003681 ptr += sizeof(*ev) + ev->length + 1;
Andre Guedes9aa04c92011-05-26 16:23:51 -03003682 }
3683
3684 hci_dev_unlock(hdev);
3685}
3686
Gustavo Padovan6039aa72012-05-23 04:04:18 -03003687static void hci_le_ltk_request_evt(struct hci_dev *hdev, struct sk_buff *skb)
Vinicius Costa Gomesa7a595f2011-06-09 18:50:47 -03003688{
3689 struct hci_ev_le_ltk_req *ev = (void *) skb->data;
3690 struct hci_cp_le_ltk_reply cp;
Vinicius Costa Gomesbea710f2011-07-07 18:59:37 -03003691 struct hci_cp_le_ltk_neg_reply neg;
Vinicius Costa Gomesa7a595f2011-06-09 18:50:47 -03003692 struct hci_conn *conn;
Vinicius Costa Gomesc9839a12012-02-02 21:08:01 -03003693 struct smp_ltk *ltk;
Vinicius Costa Gomesa7a595f2011-06-09 18:50:47 -03003694
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +03003695 BT_DBG("%s handle 0x%4.4x", hdev->name, __le16_to_cpu(ev->handle));
Vinicius Costa Gomesa7a595f2011-06-09 18:50:47 -03003696
3697 hci_dev_lock(hdev);
3698
3699 conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
Vinicius Costa Gomesbea710f2011-07-07 18:59:37 -03003700 if (conn == NULL)
3701 goto not_found;
Vinicius Costa Gomesa7a595f2011-06-09 18:50:47 -03003702
Vinicius Costa Gomesbea710f2011-07-07 18:59:37 -03003703 ltk = hci_find_ltk(hdev, ev->ediv, ev->random);
3704 if (ltk == NULL)
3705 goto not_found;
3706
3707 memcpy(cp.ltk, ltk->val, sizeof(ltk->val));
Vinicius Costa Gomesa7a595f2011-06-09 18:50:47 -03003708 cp.handle = cpu_to_le16(conn->handle);
Vinicius Costa Gomesc9839a12012-02-02 21:08:01 -03003709
3710 if (ltk->authenticated)
3711 conn->sec_level = BT_SECURITY_HIGH;
Vinicius Costa Gomesa7a595f2011-06-09 18:50:47 -03003712
3713 hci_send_cmd(hdev, HCI_OP_LE_LTK_REPLY, sizeof(cp), &cp);
3714
Vinicius Costa Gomesc9839a12012-02-02 21:08:01 -03003715 if (ltk->type & HCI_SMP_STK) {
3716 list_del(&ltk->list);
3717 kfree(ltk);
3718 }
3719
Vinicius Costa Gomesa7a595f2011-06-09 18:50:47 -03003720 hci_dev_unlock(hdev);
Vinicius Costa Gomesbea710f2011-07-07 18:59:37 -03003721
3722 return;
3723
3724not_found:
3725 neg.handle = ev->handle;
3726 hci_send_cmd(hdev, HCI_OP_LE_LTK_NEG_REPLY, sizeof(neg), &neg);
3727 hci_dev_unlock(hdev);
Vinicius Costa Gomesa7a595f2011-06-09 18:50:47 -03003728}
3729
Gustavo Padovan6039aa72012-05-23 04:04:18 -03003730static void hci_le_meta_evt(struct hci_dev *hdev, struct sk_buff *skb)
Ville Tervofcd89c02011-02-10 22:38:47 -03003731{
3732 struct hci_ev_le_meta *le_ev = (void *) skb->data;
3733
3734 skb_pull(skb, sizeof(*le_ev));
3735
3736 switch (le_ev->subevent) {
3737 case HCI_EV_LE_CONN_COMPLETE:
3738 hci_le_conn_complete_evt(hdev, skb);
3739 break;
3740
Andre Guedes9aa04c92011-05-26 16:23:51 -03003741 case HCI_EV_LE_ADVERTISING_REPORT:
3742 hci_le_adv_report_evt(hdev, skb);
3743 break;
3744
Vinicius Costa Gomesa7a595f2011-06-09 18:50:47 -03003745 case HCI_EV_LE_LTK_REQ:
3746 hci_le_ltk_request_evt(hdev, skb);
3747 break;
3748
Ville Tervofcd89c02011-02-10 22:38:47 -03003749 default:
3750 break;
3751 }
3752}
3753
Andrei Emeltchenko9495b2e2012-09-27 17:26:22 +03003754static void hci_chan_selected_evt(struct hci_dev *hdev, struct sk_buff *skb)
3755{
3756 struct hci_ev_channel_selected *ev = (void *) skb->data;
3757 struct hci_conn *hcon;
3758
3759 BT_DBG("%s handle 0x%2.2x", hdev->name, ev->phy_handle);
3760
3761 skb_pull(skb, sizeof(*ev));
3762
3763 hcon = hci_conn_hash_lookup_handle(hdev, ev->phy_handle);
3764 if (!hcon)
3765 return;
3766
3767 amp_read_loc_assoc_final_data(hdev, hcon);
3768}
3769
Linus Torvalds1da177e2005-04-16 15:20:36 -07003770void hci_event_packet(struct hci_dev *hdev, struct sk_buff *skb)
3771{
Marcel Holtmanna9de9242007-10-20 13:33:56 +02003772 struct hci_event_hdr *hdr = (void *) skb->data;
3773 __u8 event = hdr->evt;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003774
3775 skb_pull(skb, HCI_EVENT_HDR_SIZE);
3776
Marcel Holtmanna9de9242007-10-20 13:33:56 +02003777 switch (event) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003778 case HCI_EV_INQUIRY_COMPLETE:
3779 hci_inquiry_complete_evt(hdev, skb);
3780 break;
3781
3782 case HCI_EV_INQUIRY_RESULT:
3783 hci_inquiry_result_evt(hdev, skb);
3784 break;
3785
Marcel Holtmanna9de9242007-10-20 13:33:56 +02003786 case HCI_EV_CONN_COMPLETE:
3787 hci_conn_complete_evt(hdev, skb);
Marcel Holtmann21d9e302005-09-13 01:32:25 +02003788 break;
3789
Linus Torvalds1da177e2005-04-16 15:20:36 -07003790 case HCI_EV_CONN_REQUEST:
3791 hci_conn_request_evt(hdev, skb);
3792 break;
3793
Linus Torvalds1da177e2005-04-16 15:20:36 -07003794 case HCI_EV_DISCONN_COMPLETE:
3795 hci_disconn_complete_evt(hdev, skb);
3796 break;
3797
Linus Torvalds1da177e2005-04-16 15:20:36 -07003798 case HCI_EV_AUTH_COMPLETE:
3799 hci_auth_complete_evt(hdev, skb);
3800 break;
3801
Marcel Holtmanna9de9242007-10-20 13:33:56 +02003802 case HCI_EV_REMOTE_NAME:
3803 hci_remote_name_evt(hdev, skb);
3804 break;
3805
Linus Torvalds1da177e2005-04-16 15:20:36 -07003806 case HCI_EV_ENCRYPT_CHANGE:
3807 hci_encrypt_change_evt(hdev, skb);
3808 break;
3809
Marcel Holtmanna9de9242007-10-20 13:33:56 +02003810 case HCI_EV_CHANGE_LINK_KEY_COMPLETE:
3811 hci_change_link_key_complete_evt(hdev, skb);
3812 break;
3813
3814 case HCI_EV_REMOTE_FEATURES:
3815 hci_remote_features_evt(hdev, skb);
3816 break;
3817
3818 case HCI_EV_REMOTE_VERSION:
3819 hci_remote_version_evt(hdev, skb);
3820 break;
3821
3822 case HCI_EV_QOS_SETUP_COMPLETE:
3823 hci_qos_setup_complete_evt(hdev, skb);
3824 break;
3825
3826 case HCI_EV_CMD_COMPLETE:
3827 hci_cmd_complete_evt(hdev, skb);
3828 break;
3829
3830 case HCI_EV_CMD_STATUS:
3831 hci_cmd_status_evt(hdev, skb);
3832 break;
3833
3834 case HCI_EV_ROLE_CHANGE:
3835 hci_role_change_evt(hdev, skb);
3836 break;
3837
3838 case HCI_EV_NUM_COMP_PKTS:
3839 hci_num_comp_pkts_evt(hdev, skb);
3840 break;
3841
3842 case HCI_EV_MODE_CHANGE:
3843 hci_mode_change_evt(hdev, skb);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003844 break;
3845
3846 case HCI_EV_PIN_CODE_REQ:
3847 hci_pin_code_request_evt(hdev, skb);
3848 break;
3849
3850 case HCI_EV_LINK_KEY_REQ:
3851 hci_link_key_request_evt(hdev, skb);
3852 break;
3853
3854 case HCI_EV_LINK_KEY_NOTIFY:
3855 hci_link_key_notify_evt(hdev, skb);
3856 break;
3857
3858 case HCI_EV_CLOCK_OFFSET:
3859 hci_clock_offset_evt(hdev, skb);
3860 break;
3861
Marcel Holtmanna8746412008-07-14 20:13:46 +02003862 case HCI_EV_PKT_TYPE_CHANGE:
3863 hci_pkt_type_change_evt(hdev, skb);
3864 break;
3865
Marcel Holtmann85a1e932005-08-09 20:28:02 -07003866 case HCI_EV_PSCAN_REP_MODE:
3867 hci_pscan_rep_mode_evt(hdev, skb);
3868 break;
3869
Marcel Holtmanna9de9242007-10-20 13:33:56 +02003870 case HCI_EV_INQUIRY_RESULT_WITH_RSSI:
3871 hci_inquiry_result_with_rssi_evt(hdev, skb);
3872 break;
3873
3874 case HCI_EV_REMOTE_EXT_FEATURES:
3875 hci_remote_ext_features_evt(hdev, skb);
3876 break;
3877
3878 case HCI_EV_SYNC_CONN_COMPLETE:
3879 hci_sync_conn_complete_evt(hdev, skb);
3880 break;
3881
3882 case HCI_EV_SYNC_CONN_CHANGED:
3883 hci_sync_conn_changed_evt(hdev, skb);
3884 break;
3885
Marcel Holtmann04837f62006-07-03 10:02:33 +02003886 case HCI_EV_SNIFF_SUBRATE:
3887 hci_sniff_subrate_evt(hdev, skb);
3888 break;
3889
Marcel Holtmanna9de9242007-10-20 13:33:56 +02003890 case HCI_EV_EXTENDED_INQUIRY_RESULT:
3891 hci_extended_inquiry_result_evt(hdev, skb);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003892 break;
3893
Johan Hedberg1c2e0042012-06-08 23:31:13 +08003894 case HCI_EV_KEY_REFRESH_COMPLETE:
3895 hci_key_refresh_complete_evt(hdev, skb);
3896 break;
3897
Marcel Holtmann04936842008-07-14 20:13:48 +02003898 case HCI_EV_IO_CAPA_REQUEST:
3899 hci_io_capa_request_evt(hdev, skb);
3900 break;
3901
Johan Hedberg03b555e2011-01-04 15:40:05 +02003902 case HCI_EV_IO_CAPA_REPLY:
3903 hci_io_capa_reply_evt(hdev, skb);
3904 break;
3905
Johan Hedberga5c29682011-02-19 12:05:57 -03003906 case HCI_EV_USER_CONFIRM_REQUEST:
3907 hci_user_confirm_request_evt(hdev, skb);
3908 break;
3909
Brian Gix1143d452011-11-23 08:28:34 -08003910 case HCI_EV_USER_PASSKEY_REQUEST:
3911 hci_user_passkey_request_evt(hdev, skb);
3912 break;
3913
Johan Hedberg92a25252012-09-06 18:39:26 +03003914 case HCI_EV_USER_PASSKEY_NOTIFY:
3915 hci_user_passkey_notify_evt(hdev, skb);
3916 break;
3917
3918 case HCI_EV_KEYPRESS_NOTIFY:
3919 hci_keypress_notify_evt(hdev, skb);
3920 break;
3921
Marcel Holtmann04936842008-07-14 20:13:48 +02003922 case HCI_EV_SIMPLE_PAIR_COMPLETE:
3923 hci_simple_pair_complete_evt(hdev, skb);
3924 break;
3925
Marcel Holtmann41a96212008-07-14 20:13:48 +02003926 case HCI_EV_REMOTE_HOST_FEATURES:
3927 hci_remote_host_features_evt(hdev, skb);
3928 break;
3929
Ville Tervofcd89c02011-02-10 22:38:47 -03003930 case HCI_EV_LE_META:
3931 hci_le_meta_evt(hdev, skb);
3932 break;
3933
Andrei Emeltchenko9495b2e2012-09-27 17:26:22 +03003934 case HCI_EV_CHANNEL_SELECTED:
3935 hci_chan_selected_evt(hdev, skb);
3936 break;
3937
Szymon Janc2763eda2011-03-22 13:12:22 +01003938 case HCI_EV_REMOTE_OOB_DATA_REQUEST:
3939 hci_remote_oob_data_request_evt(hdev, skb);
3940 break;
3941
Andrei Emeltchenko25e89e92012-01-04 12:41:58 +02003942 case HCI_EV_NUM_COMP_BLOCKS:
3943 hci_num_comp_blocks_evt(hdev, skb);
3944 break;
3945
Marcel Holtmanna9de9242007-10-20 13:33:56 +02003946 default:
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +03003947 BT_DBG("%s event 0x%2.2x", hdev->name, event);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003948 break;
3949 }
3950
3951 kfree_skb(skb);
3952 hdev->stat.evt_rx++;
3953}