blob: b2570159a04418bf213a512f6f1e1589faf7ff8a [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
Linus Torvalds1da177e2005-04-16 15:20:36 -070027#include <linux/module.h>
28
29#include <linux/types.h>
30#include <linux/errno.h>
31#include <linux/kernel.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070032#include <linux/slab.h>
33#include <linux/poll.h>
34#include <linux/fcntl.h>
35#include <linux/init.h>
36#include <linux/skbuff.h>
37#include <linux/interrupt.h>
38#include <linux/notifier.h>
39#include <net/sock.h>
40
41#include <asm/system.h>
Andrei Emeltchenko70f230202010-12-01 16:58:25 +020042#include <linux/uaccess.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070043#include <asm/unaligned.h>
44
45#include <net/bluetooth/bluetooth.h>
46#include <net/bluetooth/hci_core.h>
47
Linus Torvalds1da177e2005-04-16 15:20:36 -070048/* Handle HCI Event packets */
49
Marcel Holtmanna9de9242007-10-20 13:33:56 +020050static void hci_cc_inquiry_cancel(struct hci_dev *hdev, struct sk_buff *skb)
Linus Torvalds1da177e2005-04-16 15:20:36 -070051{
Marcel Holtmanna9de9242007-10-20 13:33:56 +020052 __u8 status = *((__u8 *) skb->data);
Linus Torvalds1da177e2005-04-16 15:20:36 -070053
Marcel Holtmanna9de9242007-10-20 13:33:56 +020054 BT_DBG("%s status 0x%x", hdev->name, status);
Linus Torvalds1da177e2005-04-16 15:20:36 -070055
Marcel Holtmanna9de9242007-10-20 13:33:56 +020056 if (status)
57 return;
Linus Torvalds1da177e2005-04-16 15:20:36 -070058
Marcel Holtmanna9de9242007-10-20 13:33:56 +020059 clear_bit(HCI_INQUIRY, &hdev->flags);
Marcel Holtmann6bd57412006-11-18 22:14:22 +010060
Johan Hedberg23bb5762010-12-21 23:01:27 +020061 hci_req_complete(hdev, HCI_OP_INQUIRY_CANCEL, status);
Marcel Holtmann6bd57412006-11-18 22:14:22 +010062
Marcel Holtmanna9de9242007-10-20 13:33:56 +020063 hci_conn_check_pending(hdev);
Linus Torvalds1da177e2005-04-16 15:20:36 -070064}
65
Marcel Holtmanna9de9242007-10-20 13:33:56 +020066static void hci_cc_exit_periodic_inq(struct hci_dev *hdev, struct sk_buff *skb)
Linus Torvalds1da177e2005-04-16 15:20:36 -070067{
Marcel Holtmanna9de9242007-10-20 13:33:56 +020068 __u8 status = *((__u8 *) skb->data);
69
70 BT_DBG("%s status 0x%x", hdev->name, status);
71
72 if (status)
73 return;
74
75 clear_bit(HCI_INQUIRY, &hdev->flags);
76
77 hci_conn_check_pending(hdev);
78}
79
80static void hci_cc_remote_name_req_cancel(struct hci_dev *hdev, struct sk_buff *skb)
81{
82 BT_DBG("%s", hdev->name);
83}
84
85static void hci_cc_role_discovery(struct hci_dev *hdev, struct sk_buff *skb)
86{
87 struct hci_rp_role_discovery *rp = (void *) skb->data;
Linus Torvalds1da177e2005-04-16 15:20:36 -070088 struct hci_conn *conn;
Linus Torvalds1da177e2005-04-16 15:20:36 -070089
Marcel Holtmanna9de9242007-10-20 13:33:56 +020090 BT_DBG("%s status 0x%x", hdev->name, rp->status);
Linus Torvalds1da177e2005-04-16 15:20:36 -070091
Marcel Holtmanna9de9242007-10-20 13:33:56 +020092 if (rp->status)
93 return;
Linus Torvalds1da177e2005-04-16 15:20:36 -070094
Marcel Holtmanna9de9242007-10-20 13:33:56 +020095 hci_dev_lock(hdev);
Linus Torvalds1da177e2005-04-16 15:20:36 -070096
Marcel Holtmanna9de9242007-10-20 13:33:56 +020097 conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(rp->handle));
98 if (conn) {
99 if (rp->role)
100 conn->link_mode &= ~HCI_LM_MASTER;
101 else
102 conn->link_mode |= HCI_LM_MASTER;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700103 }
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200104
105 hci_dev_unlock(hdev);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700106}
107
Marcel Holtmanne4e8e372008-07-14 20:13:47 +0200108static void hci_cc_read_link_policy(struct hci_dev *hdev, struct sk_buff *skb)
109{
110 struct hci_rp_read_link_policy *rp = (void *) skb->data;
111 struct hci_conn *conn;
112
113 BT_DBG("%s status 0x%x", hdev->name, rp->status);
114
115 if (rp->status)
116 return;
117
118 hci_dev_lock(hdev);
119
120 conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(rp->handle));
121 if (conn)
122 conn->link_policy = __le16_to_cpu(rp->policy);
123
124 hci_dev_unlock(hdev);
125}
126
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200127static void hci_cc_write_link_policy(struct hci_dev *hdev, struct sk_buff *skb)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700128{
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200129 struct hci_rp_write_link_policy *rp = (void *) skb->data;
130 struct hci_conn *conn;
131 void *sent;
132
133 BT_DBG("%s status 0x%x", hdev->name, rp->status);
134
135 if (rp->status)
136 return;
137
138 sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_LINK_POLICY);
139 if (!sent)
140 return;
141
142 hci_dev_lock(hdev);
143
144 conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(rp->handle));
Marcel Holtmanne4e8e372008-07-14 20:13:47 +0200145 if (conn)
Harvey Harrison83985312008-05-02 16:25:46 -0700146 conn->link_policy = get_unaligned_le16(sent + 2);
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200147
148 hci_dev_unlock(hdev);
149}
150
Marcel Holtmanne4e8e372008-07-14 20:13:47 +0200151static void hci_cc_read_def_link_policy(struct hci_dev *hdev, struct sk_buff *skb)
152{
153 struct hci_rp_read_def_link_policy *rp = (void *) skb->data;
154
155 BT_DBG("%s status 0x%x", hdev->name, rp->status);
156
157 if (rp->status)
158 return;
159
160 hdev->link_policy = __le16_to_cpu(rp->policy);
161}
162
163static void hci_cc_write_def_link_policy(struct hci_dev *hdev, struct sk_buff *skb)
164{
165 __u8 status = *((__u8 *) skb->data);
166 void *sent;
167
168 BT_DBG("%s status 0x%x", hdev->name, status);
169
170 sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_DEF_LINK_POLICY);
171 if (!sent)
172 return;
173
174 if (!status)
175 hdev->link_policy = get_unaligned_le16(sent);
176
Johan Hedberg23bb5762010-12-21 23:01:27 +0200177 hci_req_complete(hdev, HCI_OP_WRITE_DEF_LINK_POLICY, status);
Marcel Holtmanne4e8e372008-07-14 20:13:47 +0200178}
179
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200180static void hci_cc_reset(struct hci_dev *hdev, struct sk_buff *skb)
181{
182 __u8 status = *((__u8 *) skb->data);
183
184 BT_DBG("%s status 0x%x", hdev->name, status);
185
Gustavo F. Padovanf630cf02011-03-16 15:36:29 -0300186 clear_bit(HCI_RESET, &hdev->flags);
187
Johan Hedberg23bb5762010-12-21 23:01:27 +0200188 hci_req_complete(hdev, HCI_OP_RESET, status);
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200189}
190
191static void hci_cc_write_local_name(struct hci_dev *hdev, struct sk_buff *skb)
192{
193 __u8 status = *((__u8 *) skb->data);
194 void *sent;
195
196 BT_DBG("%s status 0x%x", hdev->name, status);
197
Marcel Holtmannf383f272008-07-14 20:13:47 +0200198 if (status)
199 return;
200
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200201 sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_LOCAL_NAME);
202 if (!sent)
203 return;
204
Marcel Holtmannf383f272008-07-14 20:13:47 +0200205 memcpy(hdev->dev_name, sent, 248);
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200206}
207
208static void hci_cc_read_local_name(struct hci_dev *hdev, struct sk_buff *skb)
209{
210 struct hci_rp_read_local_name *rp = (void *) skb->data;
211
212 BT_DBG("%s status 0x%x", hdev->name, rp->status);
213
214 if (rp->status)
215 return;
216
217 memcpy(hdev->dev_name, rp->name, 248);
218}
219
220static void hci_cc_write_auth_enable(struct hci_dev *hdev, struct sk_buff *skb)
221{
222 __u8 status = *((__u8 *) skb->data);
223 void *sent;
224
225 BT_DBG("%s status 0x%x", hdev->name, status);
226
227 sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_AUTH_ENABLE);
228 if (!sent)
229 return;
230
231 if (!status) {
232 __u8 param = *((__u8 *) sent);
233
234 if (param == AUTH_ENABLED)
235 set_bit(HCI_AUTH, &hdev->flags);
236 else
237 clear_bit(HCI_AUTH, &hdev->flags);
238 }
239
Johan Hedberg23bb5762010-12-21 23:01:27 +0200240 hci_req_complete(hdev, HCI_OP_WRITE_AUTH_ENABLE, status);
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200241}
242
243static void hci_cc_write_encrypt_mode(struct hci_dev *hdev, struct sk_buff *skb)
244{
245 __u8 status = *((__u8 *) skb->data);
246 void *sent;
247
248 BT_DBG("%s status 0x%x", hdev->name, status);
249
250 sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_ENCRYPT_MODE);
251 if (!sent)
252 return;
253
254 if (!status) {
255 __u8 param = *((__u8 *) sent);
256
257 if (param)
258 set_bit(HCI_ENCRYPT, &hdev->flags);
259 else
260 clear_bit(HCI_ENCRYPT, &hdev->flags);
261 }
262
Johan Hedberg23bb5762010-12-21 23:01:27 +0200263 hci_req_complete(hdev, HCI_OP_WRITE_ENCRYPT_MODE, status);
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200264}
265
266static void hci_cc_write_scan_enable(struct hci_dev *hdev, struct sk_buff *skb)
267{
268 __u8 status = *((__u8 *) skb->data);
269 void *sent;
270
271 BT_DBG("%s status 0x%x", hdev->name, status);
272
273 sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_SCAN_ENABLE);
274 if (!sent)
275 return;
276
277 if (!status) {
278 __u8 param = *((__u8 *) sent);
Johan Hedberg9fbcbb42010-12-30 00:18:33 +0200279 int old_pscan, old_iscan;
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200280
Johan Hedberg9fbcbb42010-12-30 00:18:33 +0200281 old_pscan = test_and_clear_bit(HCI_PSCAN, &hdev->flags);
282 old_iscan = test_and_clear_bit(HCI_ISCAN, &hdev->flags);
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200283
Johan Hedberg73f22f62010-12-29 16:00:25 +0200284 if (param & SCAN_INQUIRY) {
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200285 set_bit(HCI_ISCAN, &hdev->flags);
Johan Hedberg9fbcbb42010-12-30 00:18:33 +0200286 if (!old_iscan)
287 mgmt_discoverable(hdev->id, 1);
288 } else if (old_iscan)
Johan Hedberg73f22f62010-12-29 16:00:25 +0200289 mgmt_discoverable(hdev->id, 0);
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200290
Johan Hedberg9fbcbb42010-12-30 00:18:33 +0200291 if (param & SCAN_PAGE) {
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200292 set_bit(HCI_PSCAN, &hdev->flags);
Johan Hedberg9fbcbb42010-12-30 00:18:33 +0200293 if (!old_pscan)
294 mgmt_connectable(hdev->id, 1);
295 } else if (old_pscan)
296 mgmt_connectable(hdev->id, 0);
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200297 }
298
Johan Hedberg23bb5762010-12-21 23:01:27 +0200299 hci_req_complete(hdev, HCI_OP_WRITE_SCAN_ENABLE, status);
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200300}
301
302static void hci_cc_read_class_of_dev(struct hci_dev *hdev, struct sk_buff *skb)
303{
304 struct hci_rp_read_class_of_dev *rp = (void *) skb->data;
305
306 BT_DBG("%s status 0x%x", hdev->name, rp->status);
307
308 if (rp->status)
309 return;
310
311 memcpy(hdev->dev_class, rp->dev_class, 3);
312
313 BT_DBG("%s class 0x%.2x%.2x%.2x", hdev->name,
314 hdev->dev_class[2], hdev->dev_class[1], hdev->dev_class[0]);
315}
316
317static void hci_cc_write_class_of_dev(struct hci_dev *hdev, struct sk_buff *skb)
318{
319 __u8 status = *((__u8 *) skb->data);
320 void *sent;
321
322 BT_DBG("%s status 0x%x", hdev->name, status);
323
Marcel Holtmannf383f272008-07-14 20:13:47 +0200324 if (status)
325 return;
326
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200327 sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_CLASS_OF_DEV);
328 if (!sent)
329 return;
330
Marcel Holtmannf383f272008-07-14 20:13:47 +0200331 memcpy(hdev->dev_class, sent, 3);
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200332}
333
334static void hci_cc_read_voice_setting(struct hci_dev *hdev, struct sk_buff *skb)
335{
336 struct hci_rp_read_voice_setting *rp = (void *) skb->data;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700337 __u16 setting;
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200338
339 BT_DBG("%s status 0x%x", hdev->name, rp->status);
340
341 if (rp->status)
342 return;
343
344 setting = __le16_to_cpu(rp->voice_setting);
345
Marcel Holtmannf383f272008-07-14 20:13:47 +0200346 if (hdev->voice_setting == setting)
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200347 return;
348
349 hdev->voice_setting = setting;
350
351 BT_DBG("%s voice setting 0x%04x", hdev->name, setting);
352
353 if (hdev->notify) {
354 tasklet_disable(&hdev->tx_task);
355 hdev->notify(hdev, HCI_NOTIFY_VOICE_SETTING);
356 tasklet_enable(&hdev->tx_task);
357 }
358}
359
360static void hci_cc_write_voice_setting(struct hci_dev *hdev, struct sk_buff *skb)
361{
362 __u8 status = *((__u8 *) skb->data);
Marcel Holtmannf383f272008-07-14 20:13:47 +0200363 __u16 setting;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700364 void *sent;
365
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200366 BT_DBG("%s status 0x%x", hdev->name, status);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700367
Marcel Holtmannf383f272008-07-14 20:13:47 +0200368 if (status)
369 return;
370
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200371 sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_VOICE_SETTING);
372 if (!sent)
373 return;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700374
Marcel Holtmannf383f272008-07-14 20:13:47 +0200375 setting = get_unaligned_le16(sent);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700376
Marcel Holtmannf383f272008-07-14 20:13:47 +0200377 if (hdev->voice_setting == setting)
378 return;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700379
Marcel Holtmannf383f272008-07-14 20:13:47 +0200380 hdev->voice_setting = setting;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700381
Marcel Holtmannf383f272008-07-14 20:13:47 +0200382 BT_DBG("%s voice setting 0x%04x", hdev->name, setting);
383
384 if (hdev->notify) {
385 tasklet_disable(&hdev->tx_task);
386 hdev->notify(hdev, HCI_NOTIFY_VOICE_SETTING);
387 tasklet_enable(&hdev->tx_task);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700388 }
389}
390
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200391static void hci_cc_host_buffer_size(struct hci_dev *hdev, struct sk_buff *skb)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700392{
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200393 __u8 status = *((__u8 *) skb->data);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700394
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200395 BT_DBG("%s status 0x%x", hdev->name, status);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700396
Johan Hedberg23bb5762010-12-21 23:01:27 +0200397 hci_req_complete(hdev, HCI_OP_HOST_BUFFER_SIZE, status);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700398}
399
Marcel Holtmann333140b2008-07-14 20:13:48 +0200400static void hci_cc_read_ssp_mode(struct hci_dev *hdev, struct sk_buff *skb)
401{
402 struct hci_rp_read_ssp_mode *rp = (void *) skb->data;
403
404 BT_DBG("%s status 0x%x", hdev->name, rp->status);
405
406 if (rp->status)
407 return;
408
409 hdev->ssp_mode = rp->mode;
410}
411
412static void hci_cc_write_ssp_mode(struct hci_dev *hdev, struct sk_buff *skb)
413{
414 __u8 status = *((__u8 *) skb->data);
415 void *sent;
416
417 BT_DBG("%s status 0x%x", hdev->name, status);
418
419 if (status)
420 return;
421
422 sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_SSP_MODE);
423 if (!sent)
424 return;
425
426 hdev->ssp_mode = *((__u8 *) sent);
427}
428
Johan Hedbergd5859e22011-01-25 01:19:58 +0200429static u8 hci_get_inquiry_mode(struct hci_dev *hdev)
430{
431 if (hdev->features[6] & LMP_EXT_INQ)
432 return 2;
433
434 if (hdev->features[3] & LMP_RSSI_INQ)
435 return 1;
436
437 if (hdev->manufacturer == 11 && hdev->hci_rev == 0x00 &&
438 hdev->lmp_subver == 0x0757)
439 return 1;
440
441 if (hdev->manufacturer == 15) {
442 if (hdev->hci_rev == 0x03 && hdev->lmp_subver == 0x6963)
443 return 1;
444 if (hdev->hci_rev == 0x09 && hdev->lmp_subver == 0x6963)
445 return 1;
446 if (hdev->hci_rev == 0x00 && hdev->lmp_subver == 0x6965)
447 return 1;
448 }
449
450 if (hdev->manufacturer == 31 && hdev->hci_rev == 0x2005 &&
451 hdev->lmp_subver == 0x1805)
452 return 1;
453
454 return 0;
455}
456
457static void hci_setup_inquiry_mode(struct hci_dev *hdev)
458{
459 u8 mode;
460
461 mode = hci_get_inquiry_mode(hdev);
462
463 hci_send_cmd(hdev, HCI_OP_WRITE_INQUIRY_MODE, 1, &mode);
464}
465
466static void hci_setup_event_mask(struct hci_dev *hdev)
467{
468 /* The second byte is 0xff instead of 0x9f (two reserved bits
469 * disabled) since a Broadcom 1.2 dongle doesn't respond to the
470 * command otherwise */
471 u8 events[8] = { 0xff, 0xff, 0xfb, 0xff, 0x00, 0x00, 0x00, 0x00 };
472
473 /* Events for 1.2 and newer controllers */
474 if (hdev->lmp_ver > 1) {
475 events[4] |= 0x01; /* Flow Specification Complete */
476 events[4] |= 0x02; /* Inquiry Result with RSSI */
477 events[4] |= 0x04; /* Read Remote Extended Features Complete */
478 events[5] |= 0x08; /* Synchronous Connection Complete */
479 events[5] |= 0x10; /* Synchronous Connection Changed */
480 }
481
482 if (hdev->features[3] & LMP_RSSI_INQ)
483 events[4] |= 0x04; /* Inquiry Result with RSSI */
484
485 if (hdev->features[5] & LMP_SNIFF_SUBR)
486 events[5] |= 0x20; /* Sniff Subrating */
487
488 if (hdev->features[5] & LMP_PAUSE_ENC)
489 events[5] |= 0x80; /* Encryption Key Refresh Complete */
490
491 if (hdev->features[6] & LMP_EXT_INQ)
492 events[5] |= 0x40; /* Extended Inquiry Result */
493
494 if (hdev->features[6] & LMP_NO_FLUSH)
495 events[7] |= 0x01; /* Enhanced Flush Complete */
496
497 if (hdev->features[7] & LMP_LSTO)
498 events[6] |= 0x80; /* Link Supervision Timeout Changed */
499
500 if (hdev->features[6] & LMP_SIMPLE_PAIR) {
501 events[6] |= 0x01; /* IO Capability Request */
502 events[6] |= 0x02; /* IO Capability Response */
503 events[6] |= 0x04; /* User Confirmation Request */
504 events[6] |= 0x08; /* User Passkey Request */
505 events[6] |= 0x10; /* Remote OOB Data Request */
506 events[6] |= 0x20; /* Simple Pairing Complete */
507 events[7] |= 0x04; /* User Passkey Notification */
508 events[7] |= 0x08; /* Keypress Notification */
509 events[7] |= 0x10; /* Remote Host Supported
510 * Features Notification */
511 }
512
513 if (hdev->features[4] & LMP_LE)
514 events[7] |= 0x20; /* LE Meta-Event */
515
516 hci_send_cmd(hdev, HCI_OP_SET_EVENT_MASK, sizeof(events), events);
517}
518
519static void hci_setup(struct hci_dev *hdev)
520{
521 hci_setup_event_mask(hdev);
522
523 if (hdev->lmp_ver > 1)
524 hci_send_cmd(hdev, HCI_OP_READ_LOCAL_COMMANDS, 0, NULL);
525
526 if (hdev->features[6] & LMP_SIMPLE_PAIR) {
527 u8 mode = 0x01;
528 hci_send_cmd(hdev, HCI_OP_WRITE_SSP_MODE, sizeof(mode), &mode);
529 }
530
531 if (hdev->features[3] & LMP_RSSI_INQ)
532 hci_setup_inquiry_mode(hdev);
533
534 if (hdev->features[7] & LMP_INQ_TX_PWR)
535 hci_send_cmd(hdev, HCI_OP_READ_INQ_RSP_TX_POWER, 0, NULL);
536}
537
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200538static void hci_cc_read_local_version(struct hci_dev *hdev, struct sk_buff *skb)
539{
540 struct hci_rp_read_local_version *rp = (void *) skb->data;
541
542 BT_DBG("%s status 0x%x", hdev->name, rp->status);
543
544 if (rp->status)
545 return;
546
547 hdev->hci_ver = rp->hci_ver;
Marcel Holtmanne4e8e372008-07-14 20:13:47 +0200548 hdev->hci_rev = __le16_to_cpu(rp->hci_rev);
Johan Hedbergd5859e22011-01-25 01:19:58 +0200549 hdev->lmp_ver = rp->lmp_ver;
Marcel Holtmanne4e8e372008-07-14 20:13:47 +0200550 hdev->manufacturer = __le16_to_cpu(rp->manufacturer);
Johan Hedbergd5859e22011-01-25 01:19:58 +0200551 hdev->lmp_subver = __le16_to_cpu(rp->lmp_subver);
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200552
553 BT_DBG("%s manufacturer %d hci ver %d:%d", hdev->name,
554 hdev->manufacturer,
555 hdev->hci_ver, hdev->hci_rev);
Johan Hedbergd5859e22011-01-25 01:19:58 +0200556
557 if (test_bit(HCI_INIT, &hdev->flags))
558 hci_setup(hdev);
559}
560
561static void hci_setup_link_policy(struct hci_dev *hdev)
562{
563 u16 link_policy = 0;
564
565 if (hdev->features[0] & LMP_RSWITCH)
566 link_policy |= HCI_LP_RSWITCH;
567 if (hdev->features[0] & LMP_HOLD)
568 link_policy |= HCI_LP_HOLD;
569 if (hdev->features[0] & LMP_SNIFF)
570 link_policy |= HCI_LP_SNIFF;
571 if (hdev->features[1] & LMP_PARK)
572 link_policy |= HCI_LP_PARK;
573
574 link_policy = cpu_to_le16(link_policy);
575 hci_send_cmd(hdev, HCI_OP_WRITE_DEF_LINK_POLICY,
576 sizeof(link_policy), &link_policy);
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200577}
578
579static void hci_cc_read_local_commands(struct hci_dev *hdev, struct sk_buff *skb)
580{
581 struct hci_rp_read_local_commands *rp = (void *) skb->data;
582
583 BT_DBG("%s status 0x%x", hdev->name, rp->status);
584
585 if (rp->status)
Johan Hedbergd5859e22011-01-25 01:19:58 +0200586 goto done;
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200587
588 memcpy(hdev->commands, rp->commands, sizeof(hdev->commands));
Johan Hedbergd5859e22011-01-25 01:19:58 +0200589
590 if (test_bit(HCI_INIT, &hdev->flags) && (hdev->commands[5] & 0x10))
591 hci_setup_link_policy(hdev);
592
593done:
594 hci_req_complete(hdev, HCI_OP_READ_LOCAL_COMMANDS, rp->status);
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200595}
596
597static void hci_cc_read_local_features(struct hci_dev *hdev, struct sk_buff *skb)
598{
599 struct hci_rp_read_local_features *rp = (void *) skb->data;
600
601 BT_DBG("%s status 0x%x", hdev->name, rp->status);
602
603 if (rp->status)
604 return;
605
606 memcpy(hdev->features, rp->features, 8);
607
608 /* Adjust default settings according to features
609 * supported by device. */
610
611 if (hdev->features[0] & LMP_3SLOT)
612 hdev->pkt_type |= (HCI_DM3 | HCI_DH3);
613
614 if (hdev->features[0] & LMP_5SLOT)
615 hdev->pkt_type |= (HCI_DM5 | HCI_DH5);
616
617 if (hdev->features[1] & LMP_HV2) {
618 hdev->pkt_type |= (HCI_HV2);
619 hdev->esco_type |= (ESCO_HV2);
620 }
621
622 if (hdev->features[1] & LMP_HV3) {
623 hdev->pkt_type |= (HCI_HV3);
624 hdev->esco_type |= (ESCO_HV3);
625 }
626
627 if (hdev->features[3] & LMP_ESCO)
628 hdev->esco_type |= (ESCO_EV3);
629
630 if (hdev->features[4] & LMP_EV4)
631 hdev->esco_type |= (ESCO_EV4);
632
633 if (hdev->features[4] & LMP_EV5)
634 hdev->esco_type |= (ESCO_EV5);
635
Marcel Holtmannefc76882009-02-06 09:13:37 +0100636 if (hdev->features[5] & LMP_EDR_ESCO_2M)
637 hdev->esco_type |= (ESCO_2EV3);
638
639 if (hdev->features[5] & LMP_EDR_ESCO_3M)
640 hdev->esco_type |= (ESCO_3EV3);
641
642 if (hdev->features[5] & LMP_EDR_3S_ESCO)
643 hdev->esco_type |= (ESCO_2EV5 | ESCO_3EV5);
644
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200645 BT_DBG("%s features 0x%.2x%.2x%.2x%.2x%.2x%.2x%.2x%.2x", hdev->name,
646 hdev->features[0], hdev->features[1],
647 hdev->features[2], hdev->features[3],
648 hdev->features[4], hdev->features[5],
649 hdev->features[6], hdev->features[7]);
650}
651
652static void hci_cc_read_buffer_size(struct hci_dev *hdev, struct sk_buff *skb)
653{
654 struct hci_rp_read_buffer_size *rp = (void *) skb->data;
655
656 BT_DBG("%s status 0x%x", hdev->name, rp->status);
657
658 if (rp->status)
659 return;
660
661 hdev->acl_mtu = __le16_to_cpu(rp->acl_mtu);
662 hdev->sco_mtu = rp->sco_mtu;
663 hdev->acl_pkts = __le16_to_cpu(rp->acl_max_pkt);
664 hdev->sco_pkts = __le16_to_cpu(rp->sco_max_pkt);
665
666 if (test_bit(HCI_QUIRK_FIXUP_BUFFER_SIZE, &hdev->quirks)) {
667 hdev->sco_mtu = 64;
668 hdev->sco_pkts = 8;
669 }
670
671 hdev->acl_cnt = hdev->acl_pkts;
672 hdev->sco_cnt = hdev->sco_pkts;
673
674 BT_DBG("%s acl mtu %d:%d sco mtu %d:%d", hdev->name,
675 hdev->acl_mtu, hdev->acl_pkts,
676 hdev->sco_mtu, hdev->sco_pkts);
677}
678
679static void hci_cc_read_bd_addr(struct hci_dev *hdev, struct sk_buff *skb)
680{
681 struct hci_rp_read_bd_addr *rp = (void *) skb->data;
682
683 BT_DBG("%s status 0x%x", hdev->name, rp->status);
684
685 if (!rp->status)
686 bacpy(&hdev->bdaddr, &rp->bdaddr);
687
Johan Hedberg23bb5762010-12-21 23:01:27 +0200688 hci_req_complete(hdev, HCI_OP_READ_BD_ADDR, rp->status);
689}
690
691static void hci_cc_write_ca_timeout(struct hci_dev *hdev, struct sk_buff *skb)
692{
693 __u8 status = *((__u8 *) skb->data);
694
695 BT_DBG("%s status 0x%x", hdev->name, status);
696
697 hci_req_complete(hdev, HCI_OP_WRITE_CA_TIMEOUT, status);
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200698}
699
Johan Hedbergb0916ea2011-01-10 13:44:55 +0200700static void hci_cc_delete_stored_link_key(struct hci_dev *hdev,
701 struct sk_buff *skb)
702{
703 __u8 status = *((__u8 *) skb->data);
704
705 BT_DBG("%s status 0x%x", hdev->name, status);
706
707 hci_req_complete(hdev, HCI_OP_DELETE_STORED_LINK_KEY, status);
708}
709
Johan Hedbergd5859e22011-01-25 01:19:58 +0200710static void hci_cc_set_event_mask(struct hci_dev *hdev, struct sk_buff *skb)
711{
712 __u8 status = *((__u8 *) skb->data);
713
714 BT_DBG("%s status 0x%x", hdev->name, status);
715
716 hci_req_complete(hdev, HCI_OP_SET_EVENT_MASK, status);
717}
718
719static void hci_cc_write_inquiry_mode(struct hci_dev *hdev,
720 struct sk_buff *skb)
721{
722 __u8 status = *((__u8 *) skb->data);
723
724 BT_DBG("%s status 0x%x", hdev->name, status);
725
726 hci_req_complete(hdev, HCI_OP_WRITE_INQUIRY_MODE, status);
727}
728
729static void hci_cc_read_inq_rsp_tx_power(struct hci_dev *hdev,
730 struct sk_buff *skb)
731{
732 __u8 status = *((__u8 *) skb->data);
733
734 BT_DBG("%s status 0x%x", hdev->name, status);
735
736 hci_req_complete(hdev, HCI_OP_READ_INQ_RSP_TX_POWER, status);
737}
738
739static void hci_cc_set_event_flt(struct hci_dev *hdev, struct sk_buff *skb)
740{
741 __u8 status = *((__u8 *) skb->data);
742
743 BT_DBG("%s status 0x%x", hdev->name, status);
744
745 hci_req_complete(hdev, HCI_OP_SET_EVENT_FLT, status);
746}
747
Johan Hedberg980e1a52011-01-22 06:10:07 +0200748static void hci_cc_pin_code_reply(struct hci_dev *hdev, struct sk_buff *skb)
749{
750 struct hci_rp_pin_code_reply *rp = (void *) skb->data;
751 struct hci_cp_pin_code_reply *cp;
752 struct hci_conn *conn;
753
754 BT_DBG("%s status 0x%x", hdev->name, rp->status);
755
756 if (test_bit(HCI_MGMT, &hdev->flags))
757 mgmt_pin_code_reply_complete(hdev->id, &rp->bdaddr, rp->status);
758
759 if (rp->status != 0)
760 return;
761
762 cp = hci_sent_cmd_data(hdev, HCI_OP_PIN_CODE_REPLY);
763 if (!cp)
764 return;
765
766 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &cp->bdaddr);
767 if (conn)
768 conn->pin_length = cp->pin_len;
769}
770
771static void hci_cc_pin_code_neg_reply(struct hci_dev *hdev, struct sk_buff *skb)
772{
773 struct hci_rp_pin_code_neg_reply *rp = (void *) skb->data;
774
775 BT_DBG("%s status 0x%x", hdev->name, rp->status);
776
777 if (test_bit(HCI_MGMT, &hdev->flags))
778 mgmt_pin_code_neg_reply_complete(hdev->id, &rp->bdaddr,
779 rp->status);
780}
Ville Tervo6ed58ec2011-02-10 22:38:48 -0300781static void hci_cc_le_read_buffer_size(struct hci_dev *hdev,
782 struct sk_buff *skb)
783{
784 struct hci_rp_le_read_buffer_size *rp = (void *) skb->data;
785
786 BT_DBG("%s status 0x%x", hdev->name, rp->status);
787
788 if (rp->status)
789 return;
790
791 hdev->le_mtu = __le16_to_cpu(rp->le_mtu);
792 hdev->le_pkts = rp->le_max_pkt;
793
794 hdev->le_cnt = hdev->le_pkts;
795
796 BT_DBG("%s le mtu %d:%d", hdev->name, hdev->le_mtu, hdev->le_pkts);
797
798 hci_req_complete(hdev, HCI_OP_LE_READ_BUFFER_SIZE, rp->status);
799}
Johan Hedberg980e1a52011-01-22 06:10:07 +0200800
Johan Hedberga5c29682011-02-19 12:05:57 -0300801static void hci_cc_user_confirm_reply(struct hci_dev *hdev, struct sk_buff *skb)
802{
803 struct hci_rp_user_confirm_reply *rp = (void *) skb->data;
804
805 BT_DBG("%s status 0x%x", hdev->name, rp->status);
806
807 if (test_bit(HCI_MGMT, &hdev->flags))
808 mgmt_user_confirm_reply_complete(hdev->id, &rp->bdaddr,
809 rp->status);
810}
811
812static void hci_cc_user_confirm_neg_reply(struct hci_dev *hdev,
813 struct sk_buff *skb)
814{
815 struct hci_rp_user_confirm_reply *rp = (void *) skb->data;
816
817 BT_DBG("%s status 0x%x", hdev->name, rp->status);
818
819 if (test_bit(HCI_MGMT, &hdev->flags))
820 mgmt_user_confirm_neg_reply_complete(hdev->id, &rp->bdaddr,
821 rp->status);
822}
823
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200824static inline void hci_cs_inquiry(struct hci_dev *hdev, __u8 status)
825{
826 BT_DBG("%s status 0x%x", hdev->name, status);
827
828 if (status) {
Johan Hedberg23bb5762010-12-21 23:01:27 +0200829 hci_req_complete(hdev, HCI_OP_INQUIRY, status);
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200830
831 hci_conn_check_pending(hdev);
832 } else
833 set_bit(HCI_INQUIRY, &hdev->flags);
834}
835
Linus Torvalds1da177e2005-04-16 15:20:36 -0700836static inline void hci_cs_create_conn(struct hci_dev *hdev, __u8 status)
837{
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200838 struct hci_cp_create_conn *cp;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700839 struct hci_conn *conn;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700840
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200841 BT_DBG("%s status 0x%x", hdev->name, status);
842
843 cp = hci_sent_cmd_data(hdev, HCI_OP_CREATE_CONN);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700844 if (!cp)
845 return;
846
847 hci_dev_lock(hdev);
848
849 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &cp->bdaddr);
850
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200851 BT_DBG("%s bdaddr %s conn %p", hdev->name, batostr(&cp->bdaddr), conn);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700852
853 if (status) {
854 if (conn && conn->state == BT_CONNECT) {
Marcel Holtmann4c67bc72006-10-15 17:30:56 +0200855 if (status != 0x0c || conn->attempt > 2) {
856 conn->state = BT_CLOSED;
857 hci_proto_connect_cfm(conn, status);
858 hci_conn_del(conn);
859 } else
860 conn->state = BT_CONNECT2;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700861 }
862 } else {
863 if (!conn) {
864 conn = hci_conn_add(hdev, ACL_LINK, &cp->bdaddr);
865 if (conn) {
866 conn->out = 1;
867 conn->link_mode |= HCI_LM_MASTER;
868 } else
Gustavo F. Padovan893ef972010-07-18 15:13:37 -0300869 BT_ERR("No memory for new connection");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700870 }
871 }
872
873 hci_dev_unlock(hdev);
874}
875
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200876static void hci_cs_add_sco(struct hci_dev *hdev, __u8 status)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700877{
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200878 struct hci_cp_add_sco *cp;
879 struct hci_conn *acl, *sco;
880 __u16 handle;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700881
Marcel Holtmannb6a0dc82007-10-20 14:55:10 +0200882 BT_DBG("%s status 0x%x", hdev->name, status);
883
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200884 if (!status)
885 return;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700886
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200887 cp = hci_sent_cmd_data(hdev, HCI_OP_ADD_SCO);
888 if (!cp)
889 return;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700890
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200891 handle = __le16_to_cpu(cp->handle);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700892
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200893 BT_DBG("%s handle %d", hdev->name, handle);
Marcel Holtmann6bd57412006-11-18 22:14:22 +0100894
895 hci_dev_lock(hdev);
896
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200897 acl = hci_conn_hash_lookup_handle(hdev, handle);
Andrei Emeltchenko5a08ecc2011-01-11 17:20:20 +0200898 if (acl) {
899 sco = acl->link;
900 if (sco) {
901 sco->state = BT_CLOSED;
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200902
Andrei Emeltchenko5a08ecc2011-01-11 17:20:20 +0200903 hci_proto_connect_cfm(sco, status);
904 hci_conn_del(sco);
905 }
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200906 }
Marcel Holtmann6bd57412006-11-18 22:14:22 +0100907
908 hci_dev_unlock(hdev);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700909}
910
Marcel Holtmannf8558552008-07-14 20:13:49 +0200911static void hci_cs_auth_requested(struct hci_dev *hdev, __u8 status)
912{
913 struct hci_cp_auth_requested *cp;
914 struct hci_conn *conn;
915
916 BT_DBG("%s status 0x%x", hdev->name, status);
917
918 if (!status)
919 return;
920
921 cp = hci_sent_cmd_data(hdev, HCI_OP_AUTH_REQUESTED);
922 if (!cp)
923 return;
924
925 hci_dev_lock(hdev);
926
927 conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(cp->handle));
928 if (conn) {
929 if (conn->state == BT_CONFIG) {
930 hci_proto_connect_cfm(conn, status);
931 hci_conn_put(conn);
932 }
933 }
934
935 hci_dev_unlock(hdev);
936}
937
938static void hci_cs_set_conn_encrypt(struct hci_dev *hdev, __u8 status)
939{
940 struct hci_cp_set_conn_encrypt *cp;
941 struct hci_conn *conn;
942
943 BT_DBG("%s status 0x%x", hdev->name, status);
944
945 if (!status)
946 return;
947
948 cp = hci_sent_cmd_data(hdev, HCI_OP_SET_CONN_ENCRYPT);
949 if (!cp)
950 return;
951
952 hci_dev_lock(hdev);
953
954 conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(cp->handle));
955 if (conn) {
956 if (conn->state == BT_CONFIG) {
957 hci_proto_connect_cfm(conn, status);
958 hci_conn_put(conn);
959 }
960 }
961
962 hci_dev_unlock(hdev);
963}
964
Johan Hedberg127178d2010-11-18 22:22:29 +0200965static int hci_outgoing_auth_needed(struct hci_dev *hdev,
Szymon Janc138d22e2011-02-17 16:44:23 +0100966 struct hci_conn *conn)
Johan Hedberg392599b2010-11-18 22:22:28 +0200967{
Johan Hedberg392599b2010-11-18 22:22:28 +0200968 if (conn->state != BT_CONFIG || !conn->out)
969 return 0;
970
Johan Hedberg765c2a92011-01-19 12:06:52 +0530971 if (conn->pending_sec_level == BT_SECURITY_SDP)
Johan Hedberg392599b2010-11-18 22:22:28 +0200972 return 0;
973
974 /* Only request authentication for SSP connections or non-SSP
975 * devices with sec_level HIGH */
976 if (!(hdev->ssp_mode > 0 && conn->ssp_mode > 0) &&
Johan Hedberg765c2a92011-01-19 12:06:52 +0530977 conn->pending_sec_level != BT_SECURITY_HIGH)
Johan Hedberg392599b2010-11-18 22:22:28 +0200978 return 0;
979
Johan Hedberg392599b2010-11-18 22:22:28 +0200980 return 1;
981}
982
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200983static void hci_cs_remote_name_req(struct hci_dev *hdev, __u8 status)
984{
Johan Hedberg127178d2010-11-18 22:22:29 +0200985 struct hci_cp_remote_name_req *cp;
986 struct hci_conn *conn;
987
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200988 BT_DBG("%s status 0x%x", hdev->name, status);
Johan Hedberg127178d2010-11-18 22:22:29 +0200989
990 /* If successful wait for the name req complete event before
991 * checking for the need to do authentication */
992 if (!status)
993 return;
994
995 cp = hci_sent_cmd_data(hdev, HCI_OP_REMOTE_NAME_REQ);
996 if (!cp)
997 return;
998
999 hci_dev_lock(hdev);
1000
1001 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &cp->bdaddr);
1002 if (conn && hci_outgoing_auth_needed(hdev, conn)) {
1003 struct hci_cp_auth_requested cp;
1004 cp.handle = __cpu_to_le16(conn->handle);
1005 hci_send_cmd(hdev, HCI_OP_AUTH_REQUESTED, sizeof(cp), &cp);
1006 }
1007
1008 hci_dev_unlock(hdev);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001009}
1010
Marcel Holtmann769be972008-07-14 20:13:49 +02001011static void hci_cs_read_remote_features(struct hci_dev *hdev, __u8 status)
1012{
1013 struct hci_cp_read_remote_features *cp;
1014 struct hci_conn *conn;
1015
1016 BT_DBG("%s status 0x%x", hdev->name, status);
1017
1018 if (!status)
1019 return;
1020
1021 cp = hci_sent_cmd_data(hdev, HCI_OP_READ_REMOTE_FEATURES);
1022 if (!cp)
1023 return;
1024
1025 hci_dev_lock(hdev);
1026
1027 conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(cp->handle));
1028 if (conn) {
1029 if (conn->state == BT_CONFIG) {
Marcel Holtmann769be972008-07-14 20:13:49 +02001030 hci_proto_connect_cfm(conn, status);
1031 hci_conn_put(conn);
1032 }
1033 }
1034
1035 hci_dev_unlock(hdev);
1036}
1037
1038static void hci_cs_read_remote_ext_features(struct hci_dev *hdev, __u8 status)
1039{
1040 struct hci_cp_read_remote_ext_features *cp;
1041 struct hci_conn *conn;
1042
1043 BT_DBG("%s status 0x%x", hdev->name, status);
1044
1045 if (!status)
1046 return;
1047
1048 cp = hci_sent_cmd_data(hdev, HCI_OP_READ_REMOTE_EXT_FEATURES);
1049 if (!cp)
1050 return;
1051
1052 hci_dev_lock(hdev);
1053
1054 conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(cp->handle));
1055 if (conn) {
1056 if (conn->state == BT_CONFIG) {
Marcel Holtmann769be972008-07-14 20:13:49 +02001057 hci_proto_connect_cfm(conn, status);
1058 hci_conn_put(conn);
1059 }
1060 }
1061
1062 hci_dev_unlock(hdev);
1063}
1064
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001065static void hci_cs_setup_sync_conn(struct hci_dev *hdev, __u8 status)
1066{
Marcel Holtmannb6a0dc82007-10-20 14:55:10 +02001067 struct hci_cp_setup_sync_conn *cp;
1068 struct hci_conn *acl, *sco;
1069 __u16 handle;
1070
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001071 BT_DBG("%s status 0x%x", hdev->name, status);
Marcel Holtmannb6a0dc82007-10-20 14:55:10 +02001072
1073 if (!status)
1074 return;
1075
1076 cp = hci_sent_cmd_data(hdev, HCI_OP_SETUP_SYNC_CONN);
1077 if (!cp)
1078 return;
1079
1080 handle = __le16_to_cpu(cp->handle);
1081
1082 BT_DBG("%s handle %d", hdev->name, handle);
1083
1084 hci_dev_lock(hdev);
1085
1086 acl = hci_conn_hash_lookup_handle(hdev, handle);
Andrei Emeltchenko5a08ecc2011-01-11 17:20:20 +02001087 if (acl) {
1088 sco = acl->link;
1089 if (sco) {
1090 sco->state = BT_CLOSED;
Marcel Holtmannb6a0dc82007-10-20 14:55:10 +02001091
Andrei Emeltchenko5a08ecc2011-01-11 17:20:20 +02001092 hci_proto_connect_cfm(sco, status);
1093 hci_conn_del(sco);
1094 }
Marcel Holtmannb6a0dc82007-10-20 14:55:10 +02001095 }
1096
1097 hci_dev_unlock(hdev);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001098}
1099
1100static void hci_cs_sniff_mode(struct hci_dev *hdev, __u8 status)
1101{
1102 struct hci_cp_sniff_mode *cp;
1103 struct hci_conn *conn;
1104
1105 BT_DBG("%s status 0x%x", hdev->name, status);
1106
1107 if (!status)
1108 return;
1109
1110 cp = hci_sent_cmd_data(hdev, HCI_OP_SNIFF_MODE);
1111 if (!cp)
1112 return;
1113
1114 hci_dev_lock(hdev);
1115
1116 conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(cp->handle));
Marcel Holtmanne73439d2010-07-26 10:06:00 -04001117 if (conn) {
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001118 clear_bit(HCI_CONN_MODE_CHANGE_PEND, &conn->pend);
1119
Marcel Holtmanne73439d2010-07-26 10:06:00 -04001120 if (test_and_clear_bit(HCI_CONN_SCO_SETUP_PEND, &conn->pend))
1121 hci_sco_setup(conn, status);
1122 }
1123
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001124 hci_dev_unlock(hdev);
1125}
1126
1127static void hci_cs_exit_sniff_mode(struct hci_dev *hdev, __u8 status)
1128{
1129 struct hci_cp_exit_sniff_mode *cp;
1130 struct hci_conn *conn;
1131
1132 BT_DBG("%s status 0x%x", hdev->name, status);
1133
1134 if (!status)
1135 return;
1136
1137 cp = hci_sent_cmd_data(hdev, HCI_OP_EXIT_SNIFF_MODE);
1138 if (!cp)
1139 return;
1140
1141 hci_dev_lock(hdev);
1142
1143 conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(cp->handle));
Marcel Holtmanne73439d2010-07-26 10:06:00 -04001144 if (conn) {
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001145 clear_bit(HCI_CONN_MODE_CHANGE_PEND, &conn->pend);
1146
Marcel Holtmanne73439d2010-07-26 10:06:00 -04001147 if (test_and_clear_bit(HCI_CONN_SCO_SETUP_PEND, &conn->pend))
1148 hci_sco_setup(conn, status);
1149 }
1150
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001151 hci_dev_unlock(hdev);
1152}
1153
Ville Tervofcd89c02011-02-10 22:38:47 -03001154static void hci_cs_le_create_conn(struct hci_dev *hdev, __u8 status)
1155{
1156 struct hci_cp_le_create_conn *cp;
1157 struct hci_conn *conn;
1158
1159 BT_DBG("%s status 0x%x", hdev->name, status);
1160
1161 cp = hci_sent_cmd_data(hdev, HCI_OP_LE_CREATE_CONN);
1162 if (!cp)
1163 return;
1164
1165 hci_dev_lock(hdev);
1166
1167 conn = hci_conn_hash_lookup_ba(hdev, LE_LINK, &cp->peer_addr);
1168
1169 BT_DBG("%s bdaddr %s conn %p", hdev->name, batostr(&cp->peer_addr),
1170 conn);
1171
1172 if (status) {
1173 if (conn && conn->state == BT_CONNECT) {
1174 conn->state = BT_CLOSED;
1175 hci_proto_connect_cfm(conn, status);
1176 hci_conn_del(conn);
1177 }
1178 } else {
1179 if (!conn) {
1180 conn = hci_conn_add(hdev, LE_LINK, &cp->peer_addr);
1181 if (conn)
1182 conn->out = 1;
1183 else
1184 BT_ERR("No memory for new connection");
1185 }
1186 }
1187
1188 hci_dev_unlock(hdev);
1189}
1190
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001191static inline void hci_inquiry_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
1192{
1193 __u8 status = *((__u8 *) skb->data);
1194
1195 BT_DBG("%s status %d", hdev->name, status);
1196
1197 clear_bit(HCI_INQUIRY, &hdev->flags);
1198
Johan Hedberg23bb5762010-12-21 23:01:27 +02001199 hci_req_complete(hdev, HCI_OP_INQUIRY, status);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001200
1201 hci_conn_check_pending(hdev);
1202}
1203
Linus Torvalds1da177e2005-04-16 15:20:36 -07001204static inline void hci_inquiry_result_evt(struct hci_dev *hdev, struct sk_buff *skb)
1205{
Marcel Holtmann45bb4bf2005-08-09 20:27:49 -07001206 struct inquiry_data data;
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001207 struct inquiry_info *info = (void *) (skb->data + 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001208 int num_rsp = *((__u8 *) skb->data);
1209
1210 BT_DBG("%s num_rsp %d", hdev->name, num_rsp);
1211
Marcel Holtmann45bb4bf2005-08-09 20:27:49 -07001212 if (!num_rsp)
1213 return;
1214
Linus Torvalds1da177e2005-04-16 15:20:36 -07001215 hci_dev_lock(hdev);
Marcel Holtmann45bb4bf2005-08-09 20:27:49 -07001216
Linus Torvalds1da177e2005-04-16 15:20:36 -07001217 for (; num_rsp; num_rsp--) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001218 bacpy(&data.bdaddr, &info->bdaddr);
1219 data.pscan_rep_mode = info->pscan_rep_mode;
1220 data.pscan_period_mode = info->pscan_period_mode;
1221 data.pscan_mode = info->pscan_mode;
1222 memcpy(data.dev_class, info->dev_class, 3);
1223 data.clock_offset = info->clock_offset;
1224 data.rssi = 0x00;
Marcel Holtmann41a96212008-07-14 20:13:48 +02001225 data.ssp_mode = 0x00;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001226 info++;
1227 hci_inquiry_cache_update(hdev, &data);
1228 }
Marcel Holtmann45bb4bf2005-08-09 20:27:49 -07001229
Linus Torvalds1da177e2005-04-16 15:20:36 -07001230 hci_dev_unlock(hdev);
1231}
1232
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001233static inline void hci_conn_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001234{
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001235 struct hci_ev_conn_complete *ev = (void *) skb->data;
1236 struct hci_conn *conn;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001237
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001238 BT_DBG("%s", hdev->name);
Marcel Holtmann45bb4bf2005-08-09 20:27:49 -07001239
Linus Torvalds1da177e2005-04-16 15:20:36 -07001240 hci_dev_lock(hdev);
Marcel Holtmann45bb4bf2005-08-09 20:27:49 -07001241
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001242 conn = hci_conn_hash_lookup_ba(hdev, ev->link_type, &ev->bdaddr);
Marcel Holtmann94992372009-04-19 19:30:03 +02001243 if (!conn) {
1244 if (ev->link_type != SCO_LINK)
1245 goto unlock;
1246
1247 conn = hci_conn_hash_lookup_ba(hdev, ESCO_LINK, &ev->bdaddr);
1248 if (!conn)
1249 goto unlock;
1250
1251 conn->type = SCO_LINK;
1252 }
Marcel Holtmann45bb4bf2005-08-09 20:27:49 -07001253
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001254 if (!ev->status) {
1255 conn->handle = __le16_to_cpu(ev->handle);
Marcel Holtmann769be972008-07-14 20:13:49 +02001256
1257 if (conn->type == ACL_LINK) {
1258 conn->state = BT_CONFIG;
1259 hci_conn_hold(conn);
Marcel Holtmann052b30b2009-04-26 20:01:22 +02001260 conn->disc_timeout = HCI_DISCONN_TIMEOUT;
Johan Hedbergf7520542011-01-20 12:34:39 +02001261 mgmt_connected(hdev->id, &ev->bdaddr);
Marcel Holtmann769be972008-07-14 20:13:49 +02001262 } else
1263 conn->state = BT_CONNECTED;
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001264
Marcel Holtmann9eba32b2009-08-22 14:19:26 -07001265 hci_conn_hold_device(conn);
Marcel Holtmann7d0db0a2008-07-14 20:13:51 +02001266 hci_conn_add_sysfs(conn);
1267
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001268 if (test_bit(HCI_AUTH, &hdev->flags))
1269 conn->link_mode |= HCI_LM_AUTH;
1270
1271 if (test_bit(HCI_ENCRYPT, &hdev->flags))
1272 conn->link_mode |= HCI_LM_ENCRYPT;
1273
1274 /* Get remote features */
1275 if (conn->type == ACL_LINK) {
1276 struct hci_cp_read_remote_features cp;
1277 cp.handle = ev->handle;
Marcel Holtmann769be972008-07-14 20:13:49 +02001278 hci_send_cmd(hdev, HCI_OP_READ_REMOTE_FEATURES,
1279 sizeof(cp), &cp);
Marcel Holtmann45bb4bf2005-08-09 20:27:49 -07001280 }
Marcel Holtmann45bb4bf2005-08-09 20:27:49 -07001281
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001282 /* Set packet type for incoming connection */
Marcel Holtmanna8746412008-07-14 20:13:46 +02001283 if (!conn->out && hdev->hci_ver < 3) {
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001284 struct hci_cp_change_conn_ptype cp;
1285 cp.handle = ev->handle;
Marcel Holtmanna8746412008-07-14 20:13:46 +02001286 cp.pkt_type = cpu_to_le16(conn->pkt_type);
1287 hci_send_cmd(hdev, HCI_OP_CHANGE_CONN_PTYPE,
1288 sizeof(cp), &cp);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001289 }
Johan Hedberg17d5c042011-01-22 06:09:08 +02001290 } else {
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001291 conn->state = BT_CLOSED;
Johan Hedberg17d5c042011-01-22 06:09:08 +02001292 if (conn->type == ACL_LINK)
1293 mgmt_connect_failed(hdev->id, &ev->bdaddr, ev->status);
1294 }
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001295
Marcel Holtmanne73439d2010-07-26 10:06:00 -04001296 if (conn->type == ACL_LINK)
1297 hci_sco_setup(conn, ev->status);
Marcel Holtmann45bb4bf2005-08-09 20:27:49 -07001298
Marcel Holtmann769be972008-07-14 20:13:49 +02001299 if (ev->status) {
1300 hci_proto_connect_cfm(conn, ev->status);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001301 hci_conn_del(conn);
Marcel Holtmannc89b6e62009-01-15 21:57:03 +01001302 } else if (ev->link_type != ACL_LINK)
1303 hci_proto_connect_cfm(conn, ev->status);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001304
1305unlock:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001306 hci_dev_unlock(hdev);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001307
1308 hci_conn_check_pending(hdev);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001309}
1310
Linus Torvalds1da177e2005-04-16 15:20:36 -07001311static inline void hci_conn_request_evt(struct hci_dev *hdev, struct sk_buff *skb)
1312{
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001313 struct hci_ev_conn_request *ev = (void *) skb->data;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001314 int mask = hdev->link_mode;
1315
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001316 BT_DBG("%s bdaddr %s type 0x%x", hdev->name,
1317 batostr(&ev->bdaddr), ev->link_type);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001318
1319 mask |= hci_proto_connect_ind(hdev, &ev->bdaddr, ev->link_type);
1320
Szymon Janc138d22e2011-02-17 16:44:23 +01001321 if ((mask & HCI_LM_ACCEPT) &&
1322 !hci_blacklist_lookup(hdev, &ev->bdaddr)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001323 /* Connection accepted */
Marcel Holtmannc7bdd502008-07-14 20:13:47 +02001324 struct inquiry_entry *ie;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001325 struct hci_conn *conn;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001326
1327 hci_dev_lock(hdev);
Marcel Holtmannb6a0dc82007-10-20 14:55:10 +02001328
Andrei Emeltchenkocc11b9c2010-11-22 13:21:37 +02001329 ie = hci_inquiry_cache_lookup(hdev, &ev->bdaddr);
1330 if (ie)
Marcel Holtmannc7bdd502008-07-14 20:13:47 +02001331 memcpy(ie->data.dev_class, ev->dev_class, 3);
1332
Linus Torvalds1da177e2005-04-16 15:20:36 -07001333 conn = hci_conn_hash_lookup_ba(hdev, ev->link_type, &ev->bdaddr);
1334 if (!conn) {
Andrei Emeltchenkocc11b9c2010-11-22 13:21:37 +02001335 conn = hci_conn_add(hdev, ev->link_type, &ev->bdaddr);
1336 if (!conn) {
Gustavo F. Padovan893ef972010-07-18 15:13:37 -03001337 BT_ERR("No memory for new connection");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001338 hci_dev_unlock(hdev);
1339 return;
1340 }
1341 }
Marcel Holtmannb6a0dc82007-10-20 14:55:10 +02001342
Linus Torvalds1da177e2005-04-16 15:20:36 -07001343 memcpy(conn->dev_class, ev->dev_class, 3);
1344 conn->state = BT_CONNECT;
Marcel Holtmannb6a0dc82007-10-20 14:55:10 +02001345
Linus Torvalds1da177e2005-04-16 15:20:36 -07001346 hci_dev_unlock(hdev);
1347
Marcel Holtmannb6a0dc82007-10-20 14:55:10 +02001348 if (ev->link_type == ACL_LINK || !lmp_esco_capable(hdev)) {
1349 struct hci_cp_accept_conn_req cp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001350
Marcel Holtmannb6a0dc82007-10-20 14:55:10 +02001351 bacpy(&cp.bdaddr, &ev->bdaddr);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001352
Marcel Holtmannb6a0dc82007-10-20 14:55:10 +02001353 if (lmp_rswitch_capable(hdev) && (mask & HCI_LM_MASTER))
1354 cp.role = 0x00; /* Become master */
1355 else
1356 cp.role = 0x01; /* Remain slave */
1357
1358 hci_send_cmd(hdev, HCI_OP_ACCEPT_CONN_REQ,
1359 sizeof(cp), &cp);
1360 } else {
1361 struct hci_cp_accept_sync_conn_req cp;
1362
1363 bacpy(&cp.bdaddr, &ev->bdaddr);
Marcel Holtmanna8746412008-07-14 20:13:46 +02001364 cp.pkt_type = cpu_to_le16(conn->pkt_type);
Marcel Holtmannb6a0dc82007-10-20 14:55:10 +02001365
1366 cp.tx_bandwidth = cpu_to_le32(0x00001f40);
1367 cp.rx_bandwidth = cpu_to_le32(0x00001f40);
1368 cp.max_latency = cpu_to_le16(0xffff);
1369 cp.content_format = cpu_to_le16(hdev->voice_setting);
1370 cp.retrans_effort = 0xff;
1371
1372 hci_send_cmd(hdev, HCI_OP_ACCEPT_SYNC_CONN_REQ,
1373 sizeof(cp), &cp);
1374 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001375 } else {
1376 /* Connection rejected */
1377 struct hci_cp_reject_conn_req cp;
1378
1379 bacpy(&cp.bdaddr, &ev->bdaddr);
1380 cp.reason = 0x0f;
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001381 hci_send_cmd(hdev, HCI_OP_REJECT_CONN_REQ, sizeof(cp), &cp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001382 }
1383}
1384
Linus Torvalds1da177e2005-04-16 15:20:36 -07001385static inline void hci_disconn_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
1386{
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001387 struct hci_ev_disconn_complete *ev = (void *) skb->data;
Marcel Holtmann04837f62006-07-03 10:02:33 +02001388 struct hci_conn *conn;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001389
1390 BT_DBG("%s status %d", hdev->name, ev->status);
1391
Johan Hedberg8962ee72011-01-20 12:40:27 +02001392 if (ev->status) {
1393 mgmt_disconnect_failed(hdev->id);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001394 return;
Johan Hedberg8962ee72011-01-20 12:40:27 +02001395 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001396
1397 hci_dev_lock(hdev);
1398
Marcel Holtmann04837f62006-07-03 10:02:33 +02001399 conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
Johan Hedbergf7520542011-01-20 12:34:39 +02001400 if (!conn)
1401 goto unlock;
Marcel Holtmann7d0db0a2008-07-14 20:13:51 +02001402
Johan Hedbergf7520542011-01-20 12:34:39 +02001403 conn->state = BT_CLOSED;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001404
Johan Hedbergf7520542011-01-20 12:34:39 +02001405 if (conn->type == ACL_LINK)
1406 mgmt_disconnected(hdev->id, &conn->dst);
1407
1408 hci_proto_disconn_cfm(conn, ev->reason);
1409 hci_conn_del(conn);
1410
1411unlock:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001412 hci_dev_unlock(hdev);
1413}
1414
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001415static inline void hci_auth_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
1416{
1417 struct hci_ev_auth_complete *ev = (void *) skb->data;
1418 struct hci_conn *conn;
1419
1420 BT_DBG("%s status %d", hdev->name, ev->status);
1421
1422 hci_dev_lock(hdev);
1423
1424 conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
1425 if (conn) {
Johan Hedberg765c2a92011-01-19 12:06:52 +05301426 if (!ev->status) {
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001427 conn->link_mode |= HCI_LM_AUTH;
Johan Hedberg765c2a92011-01-19 12:06:52 +05301428 conn->sec_level = conn->pending_sec_level;
Johan Hedberg2a611692011-02-19 12:06:00 -03001429 } else {
1430 mgmt_auth_failed(hdev->id, &conn->dst, ev->status);
Johan Hedbergda213f42010-06-18 11:08:56 +03001431 conn->sec_level = BT_SECURITY_LOW;
Johan Hedberg2a611692011-02-19 12:06:00 -03001432 }
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001433
1434 clear_bit(HCI_CONN_AUTH_PEND, &conn->pend);
1435
Marcel Holtmannf8558552008-07-14 20:13:49 +02001436 if (conn->state == BT_CONFIG) {
1437 if (!ev->status && hdev->ssp_mode > 0 &&
1438 conn->ssp_mode > 0) {
1439 struct hci_cp_set_conn_encrypt cp;
1440 cp.handle = ev->handle;
1441 cp.encrypt = 0x01;
1442 hci_send_cmd(hdev, HCI_OP_SET_CONN_ENCRYPT,
1443 sizeof(cp), &cp);
1444 } else {
1445 conn->state = BT_CONNECTED;
1446 hci_proto_connect_cfm(conn, ev->status);
1447 hci_conn_put(conn);
1448 }
Marcel Holtmann052b30b2009-04-26 20:01:22 +02001449 } else {
Marcel Holtmannf8558552008-07-14 20:13:49 +02001450 hci_auth_cfm(conn, ev->status);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001451
Marcel Holtmann052b30b2009-04-26 20:01:22 +02001452 hci_conn_hold(conn);
1453 conn->disc_timeout = HCI_DISCONN_TIMEOUT;
1454 hci_conn_put(conn);
1455 }
1456
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001457 if (test_bit(HCI_CONN_ENCRYPT_PEND, &conn->pend)) {
1458 if (!ev->status) {
1459 struct hci_cp_set_conn_encrypt cp;
Marcel Holtmannf8558552008-07-14 20:13:49 +02001460 cp.handle = ev->handle;
1461 cp.encrypt = 0x01;
1462 hci_send_cmd(hdev, HCI_OP_SET_CONN_ENCRYPT,
1463 sizeof(cp), &cp);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001464 } else {
1465 clear_bit(HCI_CONN_ENCRYPT_PEND, &conn->pend);
1466 hci_encrypt_cfm(conn, ev->status, 0x00);
1467 }
1468 }
1469 }
1470
1471 hci_dev_unlock(hdev);
1472}
1473
1474static inline void hci_remote_name_evt(struct hci_dev *hdev, struct sk_buff *skb)
1475{
Johan Hedberg127178d2010-11-18 22:22:29 +02001476 struct hci_ev_remote_name *ev = (void *) skb->data;
1477 struct hci_conn *conn;
1478
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001479 BT_DBG("%s", hdev->name);
1480
1481 hci_conn_check_pending(hdev);
Johan Hedberg127178d2010-11-18 22:22:29 +02001482
1483 hci_dev_lock(hdev);
1484
1485 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
1486 if (conn && hci_outgoing_auth_needed(hdev, conn)) {
1487 struct hci_cp_auth_requested cp;
1488 cp.handle = __cpu_to_le16(conn->handle);
1489 hci_send_cmd(hdev, HCI_OP_AUTH_REQUESTED, sizeof(cp), &cp);
1490 }
1491
1492 hci_dev_unlock(hdev);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001493}
1494
1495static inline void hci_encrypt_change_evt(struct hci_dev *hdev, struct sk_buff *skb)
1496{
1497 struct hci_ev_encrypt_change *ev = (void *) skb->data;
1498 struct hci_conn *conn;
1499
1500 BT_DBG("%s status %d", hdev->name, ev->status);
1501
1502 hci_dev_lock(hdev);
1503
1504 conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
1505 if (conn) {
1506 if (!ev->status) {
Marcel Holtmannae293192008-07-14 20:13:45 +02001507 if (ev->encrypt) {
1508 /* Encryption implies authentication */
1509 conn->link_mode |= HCI_LM_AUTH;
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001510 conn->link_mode |= HCI_LM_ENCRYPT;
Marcel Holtmannae293192008-07-14 20:13:45 +02001511 } else
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001512 conn->link_mode &= ~HCI_LM_ENCRYPT;
1513 }
1514
1515 clear_bit(HCI_CONN_ENCRYPT_PEND, &conn->pend);
1516
Marcel Holtmannf8558552008-07-14 20:13:49 +02001517 if (conn->state == BT_CONFIG) {
1518 if (!ev->status)
1519 conn->state = BT_CONNECTED;
1520
1521 hci_proto_connect_cfm(conn, ev->status);
1522 hci_conn_put(conn);
1523 } else
1524 hci_encrypt_cfm(conn, ev->status, ev->encrypt);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001525 }
1526
1527 hci_dev_unlock(hdev);
1528}
1529
1530static inline void hci_change_link_key_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
1531{
1532 struct hci_ev_change_link_key_complete *ev = (void *) skb->data;
1533 struct hci_conn *conn;
1534
1535 BT_DBG("%s status %d", hdev->name, ev->status);
1536
1537 hci_dev_lock(hdev);
1538
1539 conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
1540 if (conn) {
1541 if (!ev->status)
1542 conn->link_mode |= HCI_LM_SECURE;
1543
1544 clear_bit(HCI_CONN_AUTH_PEND, &conn->pend);
1545
1546 hci_key_change_cfm(conn, ev->status);
1547 }
1548
1549 hci_dev_unlock(hdev);
1550}
1551
1552static inline void hci_remote_features_evt(struct hci_dev *hdev, struct sk_buff *skb)
1553{
1554 struct hci_ev_remote_features *ev = (void *) skb->data;
1555 struct hci_conn *conn;
1556
1557 BT_DBG("%s status %d", hdev->name, ev->status);
1558
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001559 hci_dev_lock(hdev);
1560
1561 conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
Johan Hedbergccd556f2010-11-10 17:11:51 +02001562 if (!conn)
1563 goto unlock;
Marcel Holtmann769be972008-07-14 20:13:49 +02001564
Johan Hedbergccd556f2010-11-10 17:11:51 +02001565 if (!ev->status)
1566 memcpy(conn->features, ev->features, 8);
1567
1568 if (conn->state != BT_CONFIG)
1569 goto unlock;
1570
1571 if (!ev->status && lmp_ssp_capable(hdev) && lmp_ssp_capable(conn)) {
1572 struct hci_cp_read_remote_ext_features cp;
1573 cp.handle = ev->handle;
1574 cp.page = 0x01;
1575 hci_send_cmd(hdev, HCI_OP_READ_REMOTE_EXT_FEATURES,
Marcel Holtmann769be972008-07-14 20:13:49 +02001576 sizeof(cp), &cp);
Johan Hedberg392599b2010-11-18 22:22:28 +02001577 goto unlock;
1578 }
1579
Johan Hedberg127178d2010-11-18 22:22:29 +02001580 if (!ev->status) {
1581 struct hci_cp_remote_name_req cp;
1582 memset(&cp, 0, sizeof(cp));
1583 bacpy(&cp.bdaddr, &conn->dst);
1584 cp.pscan_rep_mode = 0x02;
1585 hci_send_cmd(hdev, HCI_OP_REMOTE_NAME_REQ, sizeof(cp), &cp);
1586 }
Johan Hedberg392599b2010-11-18 22:22:28 +02001587
Johan Hedberg127178d2010-11-18 22:22:29 +02001588 if (!hci_outgoing_auth_needed(hdev, conn)) {
Johan Hedbergccd556f2010-11-10 17:11:51 +02001589 conn->state = BT_CONNECTED;
1590 hci_proto_connect_cfm(conn, ev->status);
1591 hci_conn_put(conn);
Marcel Holtmann769be972008-07-14 20:13:49 +02001592 }
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001593
Johan Hedbergccd556f2010-11-10 17:11:51 +02001594unlock:
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001595 hci_dev_unlock(hdev);
1596}
1597
1598static inline void hci_remote_version_evt(struct hci_dev *hdev, struct sk_buff *skb)
1599{
1600 BT_DBG("%s", hdev->name);
1601}
1602
1603static inline void hci_qos_setup_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
1604{
1605 BT_DBG("%s", hdev->name);
1606}
1607
1608static inline void hci_cmd_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
1609{
1610 struct hci_ev_cmd_complete *ev = (void *) skb->data;
1611 __u16 opcode;
1612
1613 skb_pull(skb, sizeof(*ev));
1614
1615 opcode = __le16_to_cpu(ev->opcode);
1616
1617 switch (opcode) {
1618 case HCI_OP_INQUIRY_CANCEL:
1619 hci_cc_inquiry_cancel(hdev, skb);
1620 break;
1621
1622 case HCI_OP_EXIT_PERIODIC_INQ:
1623 hci_cc_exit_periodic_inq(hdev, skb);
1624 break;
1625
1626 case HCI_OP_REMOTE_NAME_REQ_CANCEL:
1627 hci_cc_remote_name_req_cancel(hdev, skb);
1628 break;
1629
1630 case HCI_OP_ROLE_DISCOVERY:
1631 hci_cc_role_discovery(hdev, skb);
1632 break;
1633
Marcel Holtmanne4e8e372008-07-14 20:13:47 +02001634 case HCI_OP_READ_LINK_POLICY:
1635 hci_cc_read_link_policy(hdev, skb);
1636 break;
1637
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001638 case HCI_OP_WRITE_LINK_POLICY:
1639 hci_cc_write_link_policy(hdev, skb);
1640 break;
1641
Marcel Holtmanne4e8e372008-07-14 20:13:47 +02001642 case HCI_OP_READ_DEF_LINK_POLICY:
1643 hci_cc_read_def_link_policy(hdev, skb);
1644 break;
1645
1646 case HCI_OP_WRITE_DEF_LINK_POLICY:
1647 hci_cc_write_def_link_policy(hdev, skb);
1648 break;
1649
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001650 case HCI_OP_RESET:
1651 hci_cc_reset(hdev, skb);
1652 break;
1653
1654 case HCI_OP_WRITE_LOCAL_NAME:
1655 hci_cc_write_local_name(hdev, skb);
1656 break;
1657
1658 case HCI_OP_READ_LOCAL_NAME:
1659 hci_cc_read_local_name(hdev, skb);
1660 break;
1661
1662 case HCI_OP_WRITE_AUTH_ENABLE:
1663 hci_cc_write_auth_enable(hdev, skb);
1664 break;
1665
1666 case HCI_OP_WRITE_ENCRYPT_MODE:
1667 hci_cc_write_encrypt_mode(hdev, skb);
1668 break;
1669
1670 case HCI_OP_WRITE_SCAN_ENABLE:
1671 hci_cc_write_scan_enable(hdev, skb);
1672 break;
1673
1674 case HCI_OP_READ_CLASS_OF_DEV:
1675 hci_cc_read_class_of_dev(hdev, skb);
1676 break;
1677
1678 case HCI_OP_WRITE_CLASS_OF_DEV:
1679 hci_cc_write_class_of_dev(hdev, skb);
1680 break;
1681
1682 case HCI_OP_READ_VOICE_SETTING:
1683 hci_cc_read_voice_setting(hdev, skb);
1684 break;
1685
1686 case HCI_OP_WRITE_VOICE_SETTING:
1687 hci_cc_write_voice_setting(hdev, skb);
1688 break;
1689
1690 case HCI_OP_HOST_BUFFER_SIZE:
1691 hci_cc_host_buffer_size(hdev, skb);
1692 break;
1693
Marcel Holtmann333140b2008-07-14 20:13:48 +02001694 case HCI_OP_READ_SSP_MODE:
1695 hci_cc_read_ssp_mode(hdev, skb);
1696 break;
1697
1698 case HCI_OP_WRITE_SSP_MODE:
1699 hci_cc_write_ssp_mode(hdev, skb);
1700 break;
1701
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001702 case HCI_OP_READ_LOCAL_VERSION:
1703 hci_cc_read_local_version(hdev, skb);
1704 break;
1705
1706 case HCI_OP_READ_LOCAL_COMMANDS:
1707 hci_cc_read_local_commands(hdev, skb);
1708 break;
1709
1710 case HCI_OP_READ_LOCAL_FEATURES:
1711 hci_cc_read_local_features(hdev, skb);
1712 break;
1713
1714 case HCI_OP_READ_BUFFER_SIZE:
1715 hci_cc_read_buffer_size(hdev, skb);
1716 break;
1717
1718 case HCI_OP_READ_BD_ADDR:
1719 hci_cc_read_bd_addr(hdev, skb);
1720 break;
1721
Johan Hedberg23bb5762010-12-21 23:01:27 +02001722 case HCI_OP_WRITE_CA_TIMEOUT:
1723 hci_cc_write_ca_timeout(hdev, skb);
1724 break;
1725
Johan Hedbergb0916ea2011-01-10 13:44:55 +02001726 case HCI_OP_DELETE_STORED_LINK_KEY:
1727 hci_cc_delete_stored_link_key(hdev, skb);
1728 break;
1729
Johan Hedbergd5859e22011-01-25 01:19:58 +02001730 case HCI_OP_SET_EVENT_MASK:
1731 hci_cc_set_event_mask(hdev, skb);
1732 break;
1733
1734 case HCI_OP_WRITE_INQUIRY_MODE:
1735 hci_cc_write_inquiry_mode(hdev, skb);
1736 break;
1737
1738 case HCI_OP_READ_INQ_RSP_TX_POWER:
1739 hci_cc_read_inq_rsp_tx_power(hdev, skb);
1740 break;
1741
1742 case HCI_OP_SET_EVENT_FLT:
1743 hci_cc_set_event_flt(hdev, skb);
1744 break;
1745
Johan Hedberg980e1a52011-01-22 06:10:07 +02001746 case HCI_OP_PIN_CODE_REPLY:
1747 hci_cc_pin_code_reply(hdev, skb);
1748 break;
1749
1750 case HCI_OP_PIN_CODE_NEG_REPLY:
1751 hci_cc_pin_code_neg_reply(hdev, skb);
1752 break;
1753
Ville Tervo6ed58ec2011-02-10 22:38:48 -03001754 case HCI_OP_LE_READ_BUFFER_SIZE:
1755 hci_cc_le_read_buffer_size(hdev, skb);
1756 break;
1757
Johan Hedberga5c29682011-02-19 12:05:57 -03001758 case HCI_OP_USER_CONFIRM_REPLY:
1759 hci_cc_user_confirm_reply(hdev, skb);
1760 break;
1761
1762 case HCI_OP_USER_CONFIRM_NEG_REPLY:
1763 hci_cc_user_confirm_neg_reply(hdev, skb);
1764 break;
1765
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001766 default:
1767 BT_DBG("%s opcode 0x%x", hdev->name, opcode);
1768 break;
1769 }
1770
Ville Tervo6bd32322011-02-16 16:32:41 +02001771 if (ev->opcode != HCI_OP_NOP)
1772 del_timer(&hdev->cmd_timer);
1773
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001774 if (ev->ncmd) {
1775 atomic_set(&hdev->cmd_cnt, 1);
1776 if (!skb_queue_empty(&hdev->cmd_q))
Marcel Holtmannc78ae282009-11-18 01:02:54 +01001777 tasklet_schedule(&hdev->cmd_task);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001778 }
1779}
1780
1781static inline void hci_cmd_status_evt(struct hci_dev *hdev, struct sk_buff *skb)
1782{
1783 struct hci_ev_cmd_status *ev = (void *) skb->data;
1784 __u16 opcode;
1785
1786 skb_pull(skb, sizeof(*ev));
1787
1788 opcode = __le16_to_cpu(ev->opcode);
1789
1790 switch (opcode) {
1791 case HCI_OP_INQUIRY:
1792 hci_cs_inquiry(hdev, ev->status);
1793 break;
1794
1795 case HCI_OP_CREATE_CONN:
1796 hci_cs_create_conn(hdev, ev->status);
1797 break;
1798
1799 case HCI_OP_ADD_SCO:
1800 hci_cs_add_sco(hdev, ev->status);
1801 break;
1802
Marcel Holtmannf8558552008-07-14 20:13:49 +02001803 case HCI_OP_AUTH_REQUESTED:
1804 hci_cs_auth_requested(hdev, ev->status);
1805 break;
1806
1807 case HCI_OP_SET_CONN_ENCRYPT:
1808 hci_cs_set_conn_encrypt(hdev, ev->status);
1809 break;
1810
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001811 case HCI_OP_REMOTE_NAME_REQ:
1812 hci_cs_remote_name_req(hdev, ev->status);
1813 break;
1814
Marcel Holtmann769be972008-07-14 20:13:49 +02001815 case HCI_OP_READ_REMOTE_FEATURES:
1816 hci_cs_read_remote_features(hdev, ev->status);
1817 break;
1818
1819 case HCI_OP_READ_REMOTE_EXT_FEATURES:
1820 hci_cs_read_remote_ext_features(hdev, ev->status);
1821 break;
1822
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001823 case HCI_OP_SETUP_SYNC_CONN:
1824 hci_cs_setup_sync_conn(hdev, ev->status);
1825 break;
1826
1827 case HCI_OP_SNIFF_MODE:
1828 hci_cs_sniff_mode(hdev, ev->status);
1829 break;
1830
1831 case HCI_OP_EXIT_SNIFF_MODE:
1832 hci_cs_exit_sniff_mode(hdev, ev->status);
1833 break;
1834
Johan Hedberg8962ee72011-01-20 12:40:27 +02001835 case HCI_OP_DISCONNECT:
1836 if (ev->status != 0)
1837 mgmt_disconnect_failed(hdev->id);
1838 break;
1839
Ville Tervofcd89c02011-02-10 22:38:47 -03001840 case HCI_OP_LE_CREATE_CONN:
1841 hci_cs_le_create_conn(hdev, ev->status);
1842 break;
1843
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001844 default:
1845 BT_DBG("%s opcode 0x%x", hdev->name, opcode);
1846 break;
1847 }
1848
Ville Tervo6bd32322011-02-16 16:32:41 +02001849 if (ev->opcode != HCI_OP_NOP)
1850 del_timer(&hdev->cmd_timer);
1851
Gustavo F. Padovanf630cf02011-03-16 15:36:29 -03001852 if (ev->ncmd && !test_bit(HCI_RESET, &hdev->flags)) {
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001853 atomic_set(&hdev->cmd_cnt, 1);
1854 if (!skb_queue_empty(&hdev->cmd_q))
Marcel Holtmannc78ae282009-11-18 01:02:54 +01001855 tasklet_schedule(&hdev->cmd_task);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001856 }
1857}
1858
1859static inline void hci_role_change_evt(struct hci_dev *hdev, struct sk_buff *skb)
1860{
1861 struct hci_ev_role_change *ev = (void *) skb->data;
1862 struct hci_conn *conn;
1863
1864 BT_DBG("%s status %d", hdev->name, ev->status);
1865
1866 hci_dev_lock(hdev);
1867
1868 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
1869 if (conn) {
1870 if (!ev->status) {
1871 if (ev->role)
1872 conn->link_mode &= ~HCI_LM_MASTER;
1873 else
1874 conn->link_mode |= HCI_LM_MASTER;
1875 }
1876
1877 clear_bit(HCI_CONN_RSWITCH_PEND, &conn->pend);
1878
1879 hci_role_switch_cfm(conn, ev->status, ev->role);
1880 }
1881
1882 hci_dev_unlock(hdev);
1883}
1884
Linus Torvalds1da177e2005-04-16 15:20:36 -07001885static inline void hci_num_comp_pkts_evt(struct hci_dev *hdev, struct sk_buff *skb)
1886{
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001887 struct hci_ev_num_comp_pkts *ev = (void *) skb->data;
Marcel Holtmann1ebb9252005-11-08 09:57:21 -08001888 __le16 *ptr;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001889 int i;
1890
1891 skb_pull(skb, sizeof(*ev));
1892
1893 BT_DBG("%s num_hndl %d", hdev->name, ev->num_hndl);
1894
1895 if (skb->len < ev->num_hndl * 4) {
1896 BT_DBG("%s bad parameters", hdev->name);
1897 return;
1898 }
1899
1900 tasklet_disable(&hdev->tx_task);
1901
Marcel Holtmann1ebb9252005-11-08 09:57:21 -08001902 for (i = 0, ptr = (__le16 *) skb->data; i < ev->num_hndl; i++) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001903 struct hci_conn *conn;
1904 __u16 handle, count;
1905
Harvey Harrison83985312008-05-02 16:25:46 -07001906 handle = get_unaligned_le16(ptr++);
1907 count = get_unaligned_le16(ptr++);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001908
1909 conn = hci_conn_hash_lookup_handle(hdev, handle);
1910 if (conn) {
1911 conn->sent -= count;
1912
Marcel Holtmann5b7f9902007-07-11 09:51:55 +02001913 if (conn->type == ACL_LINK) {
Andrei Emeltchenko70f230202010-12-01 16:58:25 +02001914 hdev->acl_cnt += count;
1915 if (hdev->acl_cnt > hdev->acl_pkts)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001916 hdev->acl_cnt = hdev->acl_pkts;
Ville Tervo6ed58ec2011-02-10 22:38:48 -03001917 } else if (conn->type == LE_LINK) {
1918 if (hdev->le_pkts) {
1919 hdev->le_cnt += count;
1920 if (hdev->le_cnt > hdev->le_pkts)
1921 hdev->le_cnt = hdev->le_pkts;
1922 } else {
1923 hdev->acl_cnt += count;
1924 if (hdev->acl_cnt > hdev->acl_pkts)
1925 hdev->acl_cnt = hdev->acl_pkts;
1926 }
Marcel Holtmann5b7f9902007-07-11 09:51:55 +02001927 } else {
Andrei Emeltchenko70f230202010-12-01 16:58:25 +02001928 hdev->sco_cnt += count;
1929 if (hdev->sco_cnt > hdev->sco_pkts)
Marcel Holtmann5b7f9902007-07-11 09:51:55 +02001930 hdev->sco_cnt = hdev->sco_pkts;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001931 }
1932 }
1933 }
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001934
Marcel Holtmannc78ae282009-11-18 01:02:54 +01001935 tasklet_schedule(&hdev->tx_task);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001936
1937 tasklet_enable(&hdev->tx_task);
1938}
1939
Marcel Holtmann04837f62006-07-03 10:02:33 +02001940static inline void hci_mode_change_evt(struct hci_dev *hdev, struct sk_buff *skb)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001941{
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001942 struct hci_ev_mode_change *ev = (void *) skb->data;
Marcel Holtmann04837f62006-07-03 10:02:33 +02001943 struct hci_conn *conn;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001944
1945 BT_DBG("%s status %d", hdev->name, ev->status);
1946
1947 hci_dev_lock(hdev);
1948
Marcel Holtmann04837f62006-07-03 10:02:33 +02001949 conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
1950 if (conn) {
1951 conn->mode = ev->mode;
1952 conn->interval = __le16_to_cpu(ev->interval);
1953
1954 if (!test_and_clear_bit(HCI_CONN_MODE_CHANGE_PEND, &conn->pend)) {
1955 if (conn->mode == HCI_CM_ACTIVE)
1956 conn->power_save = 1;
1957 else
1958 conn->power_save = 0;
1959 }
Marcel Holtmanne73439d2010-07-26 10:06:00 -04001960
1961 if (test_and_clear_bit(HCI_CONN_SCO_SETUP_PEND, &conn->pend))
1962 hci_sco_setup(conn, ev->status);
Marcel Holtmann04837f62006-07-03 10:02:33 +02001963 }
1964
1965 hci_dev_unlock(hdev);
1966}
1967
Linus Torvalds1da177e2005-04-16 15:20:36 -07001968static inline void hci_pin_code_request_evt(struct hci_dev *hdev, struct sk_buff *skb)
1969{
Marcel Holtmann052b30b2009-04-26 20:01:22 +02001970 struct hci_ev_pin_code_req *ev = (void *) skb->data;
1971 struct hci_conn *conn;
1972
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001973 BT_DBG("%s", hdev->name);
Marcel Holtmann052b30b2009-04-26 20:01:22 +02001974
1975 hci_dev_lock(hdev);
1976
1977 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
Marcel Holtmann3d7a9d12009-05-09 12:09:21 -07001978 if (conn && conn->state == BT_CONNECTED) {
Marcel Holtmann052b30b2009-04-26 20:01:22 +02001979 hci_conn_hold(conn);
1980 conn->disc_timeout = HCI_PAIRING_TIMEOUT;
1981 hci_conn_put(conn);
1982 }
1983
Johan Hedberg03b555e2011-01-04 15:40:05 +02001984 if (!test_bit(HCI_PAIRABLE, &hdev->flags))
1985 hci_send_cmd(hdev, HCI_OP_PIN_CODE_NEG_REPLY,
1986 sizeof(ev->bdaddr), &ev->bdaddr);
1987
Johan Hedberg980e1a52011-01-22 06:10:07 +02001988 if (test_bit(HCI_MGMT, &hdev->flags))
1989 mgmt_pin_code_request(hdev->id, &ev->bdaddr);
1990
Marcel Holtmann052b30b2009-04-26 20:01:22 +02001991 hci_dev_unlock(hdev);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001992}
1993
Linus Torvalds1da177e2005-04-16 15:20:36 -07001994static inline void hci_link_key_request_evt(struct hci_dev *hdev, struct sk_buff *skb)
1995{
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02001996 struct hci_ev_link_key_req *ev = (void *) skb->data;
1997 struct hci_cp_link_key_reply cp;
1998 struct hci_conn *conn;
1999 struct link_key *key;
2000
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002001 BT_DBG("%s", hdev->name);
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002002
2003 if (!test_bit(HCI_LINK_KEYS, &hdev->flags))
2004 return;
2005
2006 hci_dev_lock(hdev);
2007
2008 key = hci_find_link_key(hdev, &ev->bdaddr);
2009 if (!key) {
2010 BT_DBG("%s link key not found for %s", hdev->name,
2011 batostr(&ev->bdaddr));
2012 goto not_found;
2013 }
2014
2015 BT_DBG("%s found key type %u for %s", hdev->name, key->type,
2016 batostr(&ev->bdaddr));
2017
2018 if (!test_bit(HCI_DEBUG_KEYS, &hdev->flags) && key->type == 0x03) {
2019 BT_DBG("%s ignoring debug key", hdev->name);
2020 goto not_found;
2021 }
2022
2023 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
2024
2025 if (key->type == 0x04 && conn && conn->auth_type != 0xff &&
2026 (conn->auth_type & 0x01)) {
2027 BT_DBG("%s ignoring unauthenticated key", hdev->name);
2028 goto not_found;
2029 }
2030
2031 bacpy(&cp.bdaddr, &ev->bdaddr);
2032 memcpy(cp.link_key, key->val, 16);
2033
2034 hci_send_cmd(hdev, HCI_OP_LINK_KEY_REPLY, sizeof(cp), &cp);
2035
2036 hci_dev_unlock(hdev);
2037
2038 return;
2039
2040not_found:
2041 hci_send_cmd(hdev, HCI_OP_LINK_KEY_NEG_REPLY, 6, &ev->bdaddr);
2042 hci_dev_unlock(hdev);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002043}
2044
Linus Torvalds1da177e2005-04-16 15:20:36 -07002045static inline void hci_link_key_notify_evt(struct hci_dev *hdev, struct sk_buff *skb)
2046{
Marcel Holtmann052b30b2009-04-26 20:01:22 +02002047 struct hci_ev_link_key_notify *ev = (void *) skb->data;
2048 struct hci_conn *conn;
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002049 u8 pin_len = 0;
Marcel Holtmann052b30b2009-04-26 20:01:22 +02002050
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002051 BT_DBG("%s", hdev->name);
Marcel Holtmann052b30b2009-04-26 20:01:22 +02002052
2053 hci_dev_lock(hdev);
2054
2055 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
2056 if (conn) {
2057 hci_conn_hold(conn);
2058 conn->disc_timeout = HCI_DISCONN_TIMEOUT;
Johan Hedberg980e1a52011-01-22 06:10:07 +02002059 pin_len = conn->pin_length;
Marcel Holtmann052b30b2009-04-26 20:01:22 +02002060 hci_conn_put(conn);
2061 }
2062
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002063 if (test_bit(HCI_LINK_KEYS, &hdev->flags))
2064 hci_add_link_key(hdev, 1, &ev->bdaddr, ev->link_key,
2065 ev->key_type, pin_len);
2066
Marcel Holtmann052b30b2009-04-26 20:01:22 +02002067 hci_dev_unlock(hdev);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002068}
2069
Marcel Holtmann04837f62006-07-03 10:02:33 +02002070static inline void hci_clock_offset_evt(struct hci_dev *hdev, struct sk_buff *skb)
2071{
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002072 struct hci_ev_clock_offset *ev = (void *) skb->data;
Marcel Holtmann04837f62006-07-03 10:02:33 +02002073 struct hci_conn *conn;
2074
2075 BT_DBG("%s status %d", hdev->name, ev->status);
2076
2077 hci_dev_lock(hdev);
2078
2079 conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
Linus Torvalds1da177e2005-04-16 15:20:36 -07002080 if (conn && !ev->status) {
2081 struct inquiry_entry *ie;
2082
Andrei Emeltchenkocc11b9c2010-11-22 13:21:37 +02002083 ie = hci_inquiry_cache_lookup(hdev, &conn->dst);
2084 if (ie) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002085 ie->data.clock_offset = ev->clock_offset;
2086 ie->timestamp = jiffies;
2087 }
2088 }
2089
2090 hci_dev_unlock(hdev);
2091}
2092
Marcel Holtmanna8746412008-07-14 20:13:46 +02002093static inline void hci_pkt_type_change_evt(struct hci_dev *hdev, struct sk_buff *skb)
2094{
2095 struct hci_ev_pkt_type_change *ev = (void *) skb->data;
2096 struct hci_conn *conn;
2097
2098 BT_DBG("%s status %d", hdev->name, ev->status);
2099
2100 hci_dev_lock(hdev);
2101
2102 conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
2103 if (conn && !ev->status)
2104 conn->pkt_type = __le16_to_cpu(ev->pkt_type);
2105
2106 hci_dev_unlock(hdev);
2107}
2108
Marcel Holtmann85a1e932005-08-09 20:28:02 -07002109static inline void hci_pscan_rep_mode_evt(struct hci_dev *hdev, struct sk_buff *skb)
2110{
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002111 struct hci_ev_pscan_rep_mode *ev = (void *) skb->data;
Marcel Holtmann85a1e932005-08-09 20:28:02 -07002112 struct inquiry_entry *ie;
2113
2114 BT_DBG("%s", hdev->name);
2115
2116 hci_dev_lock(hdev);
2117
Andrei Emeltchenkocc11b9c2010-11-22 13:21:37 +02002118 ie = hci_inquiry_cache_lookup(hdev, &ev->bdaddr);
2119 if (ie) {
Marcel Holtmann85a1e932005-08-09 20:28:02 -07002120 ie->data.pscan_rep_mode = ev->pscan_rep_mode;
2121 ie->timestamp = jiffies;
2122 }
2123
2124 hci_dev_unlock(hdev);
2125}
2126
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002127static inline void hci_inquiry_result_with_rssi_evt(struct hci_dev *hdev, struct sk_buff *skb)
2128{
2129 struct inquiry_data data;
2130 int num_rsp = *((__u8 *) skb->data);
2131
2132 BT_DBG("%s num_rsp %d", hdev->name, num_rsp);
2133
2134 if (!num_rsp)
2135 return;
2136
2137 hci_dev_lock(hdev);
2138
2139 if ((skb->len - 1) / num_rsp != sizeof(struct inquiry_info_with_rssi)) {
Szymon Janc138d22e2011-02-17 16:44:23 +01002140 struct inquiry_info_with_rssi_and_pscan_mode *info;
2141 info = (void *) (skb->data + 1);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002142
2143 for (; num_rsp; num_rsp--) {
2144 bacpy(&data.bdaddr, &info->bdaddr);
2145 data.pscan_rep_mode = info->pscan_rep_mode;
2146 data.pscan_period_mode = info->pscan_period_mode;
2147 data.pscan_mode = info->pscan_mode;
2148 memcpy(data.dev_class, info->dev_class, 3);
2149 data.clock_offset = info->clock_offset;
2150 data.rssi = info->rssi;
Marcel Holtmann41a96212008-07-14 20:13:48 +02002151 data.ssp_mode = 0x00;
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002152 info++;
2153 hci_inquiry_cache_update(hdev, &data);
2154 }
2155 } else {
2156 struct inquiry_info_with_rssi *info = (void *) (skb->data + 1);
2157
2158 for (; num_rsp; num_rsp--) {
2159 bacpy(&data.bdaddr, &info->bdaddr);
2160 data.pscan_rep_mode = info->pscan_rep_mode;
2161 data.pscan_period_mode = info->pscan_period_mode;
2162 data.pscan_mode = 0x00;
2163 memcpy(data.dev_class, info->dev_class, 3);
2164 data.clock_offset = info->clock_offset;
2165 data.rssi = info->rssi;
Marcel Holtmann41a96212008-07-14 20:13:48 +02002166 data.ssp_mode = 0x00;
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002167 info++;
2168 hci_inquiry_cache_update(hdev, &data);
2169 }
2170 }
2171
2172 hci_dev_unlock(hdev);
2173}
2174
2175static inline void hci_remote_ext_features_evt(struct hci_dev *hdev, struct sk_buff *skb)
2176{
Marcel Holtmann41a96212008-07-14 20:13:48 +02002177 struct hci_ev_remote_ext_features *ev = (void *) skb->data;
2178 struct hci_conn *conn;
2179
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002180 BT_DBG("%s", hdev->name);
Marcel Holtmann41a96212008-07-14 20:13:48 +02002181
Marcel Holtmann41a96212008-07-14 20:13:48 +02002182 hci_dev_lock(hdev);
2183
2184 conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
Johan Hedbergccd556f2010-11-10 17:11:51 +02002185 if (!conn)
2186 goto unlock;
Marcel Holtmann41a96212008-07-14 20:13:48 +02002187
Johan Hedbergccd556f2010-11-10 17:11:51 +02002188 if (!ev->status && ev->page == 0x01) {
2189 struct inquiry_entry *ie;
Marcel Holtmann41a96212008-07-14 20:13:48 +02002190
Andrei Emeltchenkocc11b9c2010-11-22 13:21:37 +02002191 ie = hci_inquiry_cache_lookup(hdev, &conn->dst);
2192 if (ie)
Johan Hedbergccd556f2010-11-10 17:11:51 +02002193 ie->data.ssp_mode = (ev->features[0] & 0x01);
Marcel Holtmann769be972008-07-14 20:13:49 +02002194
Johan Hedbergccd556f2010-11-10 17:11:51 +02002195 conn->ssp_mode = (ev->features[0] & 0x01);
Marcel Holtmann41a96212008-07-14 20:13:48 +02002196 }
2197
Johan Hedbergccd556f2010-11-10 17:11:51 +02002198 if (conn->state != BT_CONFIG)
2199 goto unlock;
2200
Johan Hedberg127178d2010-11-18 22:22:29 +02002201 if (!ev->status) {
2202 struct hci_cp_remote_name_req cp;
2203 memset(&cp, 0, sizeof(cp));
2204 bacpy(&cp.bdaddr, &conn->dst);
2205 cp.pscan_rep_mode = 0x02;
2206 hci_send_cmd(hdev, HCI_OP_REMOTE_NAME_REQ, sizeof(cp), &cp);
2207 }
Johan Hedberg392599b2010-11-18 22:22:28 +02002208
Johan Hedberg127178d2010-11-18 22:22:29 +02002209 if (!hci_outgoing_auth_needed(hdev, conn)) {
Johan Hedbergccd556f2010-11-10 17:11:51 +02002210 conn->state = BT_CONNECTED;
2211 hci_proto_connect_cfm(conn, ev->status);
2212 hci_conn_put(conn);
2213 }
2214
2215unlock:
Marcel Holtmann41a96212008-07-14 20:13:48 +02002216 hci_dev_unlock(hdev);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002217}
2218
2219static inline void hci_sync_conn_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
2220{
Marcel Holtmannb6a0dc82007-10-20 14:55:10 +02002221 struct hci_ev_sync_conn_complete *ev = (void *) skb->data;
2222 struct hci_conn *conn;
2223
2224 BT_DBG("%s status %d", hdev->name, ev->status);
2225
2226 hci_dev_lock(hdev);
2227
2228 conn = hci_conn_hash_lookup_ba(hdev, ev->link_type, &ev->bdaddr);
Marcel Holtmann9dc0a3a2008-07-14 20:13:46 +02002229 if (!conn) {
2230 if (ev->link_type == ESCO_LINK)
2231 goto unlock;
2232
2233 conn = hci_conn_hash_lookup_ba(hdev, ESCO_LINK, &ev->bdaddr);
2234 if (!conn)
2235 goto unlock;
2236
2237 conn->type = SCO_LINK;
2238 }
Marcel Holtmannb6a0dc82007-10-20 14:55:10 +02002239
Marcel Holtmann732547f2009-04-19 19:14:14 +02002240 switch (ev->status) {
2241 case 0x00:
Marcel Holtmannb6a0dc82007-10-20 14:55:10 +02002242 conn->handle = __le16_to_cpu(ev->handle);
2243 conn->state = BT_CONNECTED;
Marcel Holtmann7d0db0a2008-07-14 20:13:51 +02002244
Marcel Holtmann9eba32b2009-08-22 14:19:26 -07002245 hci_conn_hold_device(conn);
Marcel Holtmann7d0db0a2008-07-14 20:13:51 +02002246 hci_conn_add_sysfs(conn);
Marcel Holtmann732547f2009-04-19 19:14:14 +02002247 break;
2248
Stephen Coe705e5712010-02-16 11:29:44 -05002249 case 0x11: /* Unsupported Feature or Parameter Value */
Marcel Holtmann732547f2009-04-19 19:14:14 +02002250 case 0x1c: /* SCO interval rejected */
Nick Pelly1038a002010-02-03 11:42:26 -08002251 case 0x1a: /* Unsupported Remote Feature */
Marcel Holtmann732547f2009-04-19 19:14:14 +02002252 case 0x1f: /* Unspecified error */
2253 if (conn->out && conn->attempt < 2) {
2254 conn->pkt_type = (hdev->esco_type & SCO_ESCO_MASK) |
2255 (hdev->esco_type & EDR_ESCO_MASK);
2256 hci_setup_sync(conn, conn->link->handle);
2257 goto unlock;
2258 }
2259 /* fall through */
2260
2261 default:
Marcel Holtmannb6a0dc82007-10-20 14:55:10 +02002262 conn->state = BT_CLOSED;
Marcel Holtmann732547f2009-04-19 19:14:14 +02002263 break;
2264 }
Marcel Holtmannb6a0dc82007-10-20 14:55:10 +02002265
2266 hci_proto_connect_cfm(conn, ev->status);
2267 if (ev->status)
2268 hci_conn_del(conn);
2269
2270unlock:
2271 hci_dev_unlock(hdev);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002272}
2273
2274static inline void hci_sync_conn_changed_evt(struct hci_dev *hdev, struct sk_buff *skb)
2275{
2276 BT_DBG("%s", hdev->name);
2277}
2278
Marcel Holtmann04837f62006-07-03 10:02:33 +02002279static inline void hci_sniff_subrate_evt(struct hci_dev *hdev, struct sk_buff *skb)
2280{
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002281 struct hci_ev_sniff_subrate *ev = (void *) skb->data;
Marcel Holtmann04837f62006-07-03 10:02:33 +02002282
2283 BT_DBG("%s status %d", hdev->name, ev->status);
Marcel Holtmann04837f62006-07-03 10:02:33 +02002284}
2285
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002286static inline void hci_extended_inquiry_result_evt(struct hci_dev *hdev, struct sk_buff *skb)
2287{
2288 struct inquiry_data data;
2289 struct extended_inquiry_info *info = (void *) (skb->data + 1);
2290 int num_rsp = *((__u8 *) skb->data);
2291
2292 BT_DBG("%s num_rsp %d", hdev->name, num_rsp);
2293
2294 if (!num_rsp)
2295 return;
2296
2297 hci_dev_lock(hdev);
2298
2299 for (; num_rsp; num_rsp--) {
2300 bacpy(&data.bdaddr, &info->bdaddr);
Szymon Janc138d22e2011-02-17 16:44:23 +01002301 data.pscan_rep_mode = info->pscan_rep_mode;
2302 data.pscan_period_mode = info->pscan_period_mode;
2303 data.pscan_mode = 0x00;
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002304 memcpy(data.dev_class, info->dev_class, 3);
Szymon Janc138d22e2011-02-17 16:44:23 +01002305 data.clock_offset = info->clock_offset;
2306 data.rssi = info->rssi;
Marcel Holtmann41a96212008-07-14 20:13:48 +02002307 data.ssp_mode = 0x01;
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002308 info++;
2309 hci_inquiry_cache_update(hdev, &data);
2310 }
2311
2312 hci_dev_unlock(hdev);
2313}
2314
Johan Hedberg17fa4b92011-01-25 13:28:33 +02002315static inline u8 hci_get_auth_req(struct hci_conn *conn)
2316{
2317 /* If remote requests dedicated bonding follow that lead */
2318 if (conn->remote_auth == 0x02 || conn->remote_auth == 0x03) {
2319 /* If both remote and local IO capabilities allow MITM
2320 * protection then require it, otherwise don't */
2321 if (conn->remote_cap == 0x03 || conn->io_capability == 0x03)
2322 return 0x02;
2323 else
2324 return 0x03;
2325 }
2326
2327 /* If remote requests no-bonding follow that lead */
2328 if (conn->remote_auth == 0x00 || conn->remote_auth == 0x01)
2329 return 0x00;
2330
2331 return conn->auth_type;
2332}
2333
Marcel Holtmann04936842008-07-14 20:13:48 +02002334static inline void hci_io_capa_request_evt(struct hci_dev *hdev, struct sk_buff *skb)
2335{
2336 struct hci_ev_io_capa_request *ev = (void *) skb->data;
2337 struct hci_conn *conn;
2338
2339 BT_DBG("%s", hdev->name);
2340
2341 hci_dev_lock(hdev);
2342
2343 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
Johan Hedberg03b555e2011-01-04 15:40:05 +02002344 if (!conn)
2345 goto unlock;
Marcel Holtmann04936842008-07-14 20:13:48 +02002346
Johan Hedberg03b555e2011-01-04 15:40:05 +02002347 hci_conn_hold(conn);
2348
2349 if (!test_bit(HCI_MGMT, &hdev->flags))
2350 goto unlock;
2351
2352 if (test_bit(HCI_PAIRABLE, &hdev->flags) ||
2353 (conn->remote_auth & ~0x01) == HCI_AT_NO_BONDING) {
Johan Hedberg17fa4b92011-01-25 13:28:33 +02002354 struct hci_cp_io_capability_reply cp;
2355
2356 bacpy(&cp.bdaddr, &ev->bdaddr);
2357 cp.capability = conn->io_capability;
2358 cp.oob_data = 0;
2359 cp.authentication = hci_get_auth_req(conn);
2360
2361 hci_send_cmd(hdev, HCI_OP_IO_CAPABILITY_REPLY,
2362 sizeof(cp), &cp);
Johan Hedberg03b555e2011-01-04 15:40:05 +02002363 } else {
2364 struct hci_cp_io_capability_neg_reply cp;
2365
2366 bacpy(&cp.bdaddr, &ev->bdaddr);
2367 cp.reason = 0x16; /* Pairing not allowed */
2368
2369 hci_send_cmd(hdev, HCI_OP_IO_CAPABILITY_NEG_REPLY,
2370 sizeof(cp), &cp);
2371 }
2372
2373unlock:
2374 hci_dev_unlock(hdev);
2375}
2376
2377static inline void hci_io_capa_reply_evt(struct hci_dev *hdev, struct sk_buff *skb)
2378{
2379 struct hci_ev_io_capa_reply *ev = (void *) skb->data;
2380 struct hci_conn *conn;
2381
2382 BT_DBG("%s", hdev->name);
2383
2384 hci_dev_lock(hdev);
2385
2386 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
2387 if (!conn)
2388 goto unlock;
2389
Johan Hedberg03b555e2011-01-04 15:40:05 +02002390 conn->remote_cap = ev->capability;
2391 conn->remote_oob = ev->oob_data;
2392 conn->remote_auth = ev->authentication;
2393
2394unlock:
Marcel Holtmann04936842008-07-14 20:13:48 +02002395 hci_dev_unlock(hdev);
2396}
2397
Johan Hedberga5c29682011-02-19 12:05:57 -03002398static inline void hci_user_confirm_request_evt(struct hci_dev *hdev,
2399 struct sk_buff *skb)
2400{
2401 struct hci_ev_user_confirm_req *ev = (void *) skb->data;
2402
2403 BT_DBG("%s", hdev->name);
2404
2405 hci_dev_lock(hdev);
2406
2407 if (test_bit(HCI_MGMT, &hdev->flags))
2408 mgmt_user_confirm_request(hdev->id, &ev->bdaddr, ev->passkey);
2409
2410 hci_dev_unlock(hdev);
2411}
2412
Marcel Holtmann04936842008-07-14 20:13:48 +02002413static inline void hci_simple_pair_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
2414{
2415 struct hci_ev_simple_pair_complete *ev = (void *) skb->data;
2416 struct hci_conn *conn;
2417
2418 BT_DBG("%s", hdev->name);
2419
2420 hci_dev_lock(hdev);
2421
2422 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
Johan Hedberg2a611692011-02-19 12:06:00 -03002423 if (!conn)
2424 goto unlock;
Marcel Holtmann04936842008-07-14 20:13:48 +02002425
Johan Hedberg2a611692011-02-19 12:06:00 -03002426 /* To avoid duplicate auth_failed events to user space we check
2427 * the HCI_CONN_AUTH_PEND flag which will be set if we
2428 * initiated the authentication. A traditional auth_complete
2429 * event gets always produced as initiator and is also mapped to
2430 * the mgmt_auth_failed event */
2431 if (!test_bit(HCI_CONN_AUTH_PEND, &conn->pend) && ev->status != 0)
2432 mgmt_auth_failed(hdev->id, &conn->dst, ev->status);
2433
2434 hci_conn_put(conn);
2435
2436unlock:
Marcel Holtmann04936842008-07-14 20:13:48 +02002437 hci_dev_unlock(hdev);
2438}
2439
Marcel Holtmann41a96212008-07-14 20:13:48 +02002440static inline void hci_remote_host_features_evt(struct hci_dev *hdev, struct sk_buff *skb)
2441{
2442 struct hci_ev_remote_host_features *ev = (void *) skb->data;
2443 struct inquiry_entry *ie;
2444
2445 BT_DBG("%s", hdev->name);
2446
2447 hci_dev_lock(hdev);
2448
Andrei Emeltchenkocc11b9c2010-11-22 13:21:37 +02002449 ie = hci_inquiry_cache_lookup(hdev, &ev->bdaddr);
2450 if (ie)
Marcel Holtmann41a96212008-07-14 20:13:48 +02002451 ie->data.ssp_mode = (ev->features[0] & 0x01);
2452
2453 hci_dev_unlock(hdev);
2454}
2455
Ville Tervofcd89c02011-02-10 22:38:47 -03002456static inline void hci_le_conn_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
2457{
2458 struct hci_ev_le_conn_complete *ev = (void *) skb->data;
2459 struct hci_conn *conn;
2460
2461 BT_DBG("%s status %d", hdev->name, ev->status);
2462
2463 hci_dev_lock(hdev);
2464
2465 conn = hci_conn_hash_lookup_ba(hdev, LE_LINK, &ev->bdaddr);
Ville Tervob62f3282011-02-10 22:38:50 -03002466 if (!conn) {
2467 conn = hci_conn_add(hdev, LE_LINK, &ev->bdaddr);
2468 if (!conn) {
2469 BT_ERR("No memory for new connection");
2470 hci_dev_unlock(hdev);
2471 return;
2472 }
2473 }
Ville Tervofcd89c02011-02-10 22:38:47 -03002474
2475 if (ev->status) {
2476 hci_proto_connect_cfm(conn, ev->status);
2477 conn->state = BT_CLOSED;
2478 hci_conn_del(conn);
2479 goto unlock;
2480 }
2481
2482 conn->handle = __le16_to_cpu(ev->handle);
2483 conn->state = BT_CONNECTED;
2484
2485 hci_conn_hold_device(conn);
2486 hci_conn_add_sysfs(conn);
2487
2488 hci_proto_connect_cfm(conn, ev->status);
2489
2490unlock:
2491 hci_dev_unlock(hdev);
2492}
2493
2494static inline void hci_le_meta_evt(struct hci_dev *hdev, struct sk_buff *skb)
2495{
2496 struct hci_ev_le_meta *le_ev = (void *) skb->data;
2497
2498 skb_pull(skb, sizeof(*le_ev));
2499
2500 switch (le_ev->subevent) {
2501 case HCI_EV_LE_CONN_COMPLETE:
2502 hci_le_conn_complete_evt(hdev, skb);
2503 break;
2504
2505 default:
2506 break;
2507 }
2508}
2509
Linus Torvalds1da177e2005-04-16 15:20:36 -07002510void hci_event_packet(struct hci_dev *hdev, struct sk_buff *skb)
2511{
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002512 struct hci_event_hdr *hdr = (void *) skb->data;
2513 __u8 event = hdr->evt;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002514
2515 skb_pull(skb, HCI_EVENT_HDR_SIZE);
2516
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002517 switch (event) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002518 case HCI_EV_INQUIRY_COMPLETE:
2519 hci_inquiry_complete_evt(hdev, skb);
2520 break;
2521
2522 case HCI_EV_INQUIRY_RESULT:
2523 hci_inquiry_result_evt(hdev, skb);
2524 break;
2525
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002526 case HCI_EV_CONN_COMPLETE:
2527 hci_conn_complete_evt(hdev, skb);
Marcel Holtmann21d9e302005-09-13 01:32:25 +02002528 break;
2529
Linus Torvalds1da177e2005-04-16 15:20:36 -07002530 case HCI_EV_CONN_REQUEST:
2531 hci_conn_request_evt(hdev, skb);
2532 break;
2533
Linus Torvalds1da177e2005-04-16 15:20:36 -07002534 case HCI_EV_DISCONN_COMPLETE:
2535 hci_disconn_complete_evt(hdev, skb);
2536 break;
2537
Linus Torvalds1da177e2005-04-16 15:20:36 -07002538 case HCI_EV_AUTH_COMPLETE:
2539 hci_auth_complete_evt(hdev, skb);
2540 break;
2541
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002542 case HCI_EV_REMOTE_NAME:
2543 hci_remote_name_evt(hdev, skb);
2544 break;
2545
Linus Torvalds1da177e2005-04-16 15:20:36 -07002546 case HCI_EV_ENCRYPT_CHANGE:
2547 hci_encrypt_change_evt(hdev, skb);
2548 break;
2549
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002550 case HCI_EV_CHANGE_LINK_KEY_COMPLETE:
2551 hci_change_link_key_complete_evt(hdev, skb);
2552 break;
2553
2554 case HCI_EV_REMOTE_FEATURES:
2555 hci_remote_features_evt(hdev, skb);
2556 break;
2557
2558 case HCI_EV_REMOTE_VERSION:
2559 hci_remote_version_evt(hdev, skb);
2560 break;
2561
2562 case HCI_EV_QOS_SETUP_COMPLETE:
2563 hci_qos_setup_complete_evt(hdev, skb);
2564 break;
2565
2566 case HCI_EV_CMD_COMPLETE:
2567 hci_cmd_complete_evt(hdev, skb);
2568 break;
2569
2570 case HCI_EV_CMD_STATUS:
2571 hci_cmd_status_evt(hdev, skb);
2572 break;
2573
2574 case HCI_EV_ROLE_CHANGE:
2575 hci_role_change_evt(hdev, skb);
2576 break;
2577
2578 case HCI_EV_NUM_COMP_PKTS:
2579 hci_num_comp_pkts_evt(hdev, skb);
2580 break;
2581
2582 case HCI_EV_MODE_CHANGE:
2583 hci_mode_change_evt(hdev, skb);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002584 break;
2585
2586 case HCI_EV_PIN_CODE_REQ:
2587 hci_pin_code_request_evt(hdev, skb);
2588 break;
2589
2590 case HCI_EV_LINK_KEY_REQ:
2591 hci_link_key_request_evt(hdev, skb);
2592 break;
2593
2594 case HCI_EV_LINK_KEY_NOTIFY:
2595 hci_link_key_notify_evt(hdev, skb);
2596 break;
2597
2598 case HCI_EV_CLOCK_OFFSET:
2599 hci_clock_offset_evt(hdev, skb);
2600 break;
2601
Marcel Holtmanna8746412008-07-14 20:13:46 +02002602 case HCI_EV_PKT_TYPE_CHANGE:
2603 hci_pkt_type_change_evt(hdev, skb);
2604 break;
2605
Marcel Holtmann85a1e932005-08-09 20:28:02 -07002606 case HCI_EV_PSCAN_REP_MODE:
2607 hci_pscan_rep_mode_evt(hdev, skb);
2608 break;
2609
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002610 case HCI_EV_INQUIRY_RESULT_WITH_RSSI:
2611 hci_inquiry_result_with_rssi_evt(hdev, skb);
2612 break;
2613
2614 case HCI_EV_REMOTE_EXT_FEATURES:
2615 hci_remote_ext_features_evt(hdev, skb);
2616 break;
2617
2618 case HCI_EV_SYNC_CONN_COMPLETE:
2619 hci_sync_conn_complete_evt(hdev, skb);
2620 break;
2621
2622 case HCI_EV_SYNC_CONN_CHANGED:
2623 hci_sync_conn_changed_evt(hdev, skb);
2624 break;
2625
Marcel Holtmann04837f62006-07-03 10:02:33 +02002626 case HCI_EV_SNIFF_SUBRATE:
2627 hci_sniff_subrate_evt(hdev, skb);
2628 break;
2629
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002630 case HCI_EV_EXTENDED_INQUIRY_RESULT:
2631 hci_extended_inquiry_result_evt(hdev, skb);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002632 break;
2633
Marcel Holtmann04936842008-07-14 20:13:48 +02002634 case HCI_EV_IO_CAPA_REQUEST:
2635 hci_io_capa_request_evt(hdev, skb);
2636 break;
2637
Johan Hedberg03b555e2011-01-04 15:40:05 +02002638 case HCI_EV_IO_CAPA_REPLY:
2639 hci_io_capa_reply_evt(hdev, skb);
2640 break;
2641
Johan Hedberga5c29682011-02-19 12:05:57 -03002642 case HCI_EV_USER_CONFIRM_REQUEST:
2643 hci_user_confirm_request_evt(hdev, skb);
2644 break;
2645
Marcel Holtmann04936842008-07-14 20:13:48 +02002646 case HCI_EV_SIMPLE_PAIR_COMPLETE:
2647 hci_simple_pair_complete_evt(hdev, skb);
2648 break;
2649
Marcel Holtmann41a96212008-07-14 20:13:48 +02002650 case HCI_EV_REMOTE_HOST_FEATURES:
2651 hci_remote_host_features_evt(hdev, skb);
2652 break;
2653
Ville Tervofcd89c02011-02-10 22:38:47 -03002654 case HCI_EV_LE_META:
2655 hci_le_meta_evt(hdev, skb);
2656 break;
2657
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002658 default:
2659 BT_DBG("%s event 0x%x", hdev->name, event);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002660 break;
2661 }
2662
2663 kfree_skb(skb);
2664 hdev->stat.evt_rx++;
2665}
2666
2667/* Generate internal stack event */
2668void hci_si_event(struct hci_dev *hdev, int type, int dlen, void *data)
2669{
2670 struct hci_event_hdr *hdr;
2671 struct hci_ev_stack_internal *ev;
2672 struct sk_buff *skb;
2673
2674 skb = bt_skb_alloc(HCI_EVENT_HDR_SIZE + sizeof(*ev) + dlen, GFP_ATOMIC);
2675 if (!skb)
2676 return;
2677
2678 hdr = (void *) skb_put(skb, HCI_EVENT_HDR_SIZE);
2679 hdr->evt = HCI_EV_STACK_INTERNAL;
2680 hdr->plen = sizeof(*ev) + dlen;
2681
2682 ev = (void *) skb_put(skb, sizeof(*ev) + dlen);
2683 ev->type = type;
2684 memcpy(ev->data, data, dlen);
2685
Marcel Holtmann576c7d82005-08-06 12:36:54 +02002686 bt_cb(skb)->incoming = 1;
Patrick McHardya61bbcf2005-08-14 17:24:31 -07002687 __net_timestamp(skb);
Marcel Holtmann576c7d82005-08-06 12:36:54 +02002688
Marcel Holtmann0d48d932005-08-09 20:30:28 -07002689 bt_cb(skb)->pkt_type = HCI_EVENT_PKT;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002690 skb->dev = (void *) hdev;
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02002691 hci_send_to_sock(hdev, skb, NULL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002692 kfree_skb(skb);
2693}