blob: 4165895049b31e07efb3e3eac94653b29ca8fd74 [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>
42#include <asm/uaccess.h>
43#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
Marcel Holtmanna9de9242007-10-20 13:33:56 +020061 hci_req_complete(hdev, 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
177 hci_req_complete(hdev, status);
178}
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
186 hci_req_complete(hdev, status);
187}
188
189static void hci_cc_write_local_name(struct hci_dev *hdev, struct sk_buff *skb)
190{
191 __u8 status = *((__u8 *) skb->data);
192 void *sent;
193
194 BT_DBG("%s status 0x%x", hdev->name, status);
195
Marcel Holtmannf383f272008-07-14 20:13:47 +0200196 if (status)
197 return;
198
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200199 sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_LOCAL_NAME);
200 if (!sent)
201 return;
202
Marcel Holtmannf383f272008-07-14 20:13:47 +0200203 memcpy(hdev->dev_name, sent, 248);
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200204}
205
206static void hci_cc_read_local_name(struct hci_dev *hdev, struct sk_buff *skb)
207{
208 struct hci_rp_read_local_name *rp = (void *) skb->data;
209
210 BT_DBG("%s status 0x%x", hdev->name, rp->status);
211
212 if (rp->status)
213 return;
214
215 memcpy(hdev->dev_name, rp->name, 248);
216}
217
218static void hci_cc_write_auth_enable(struct hci_dev *hdev, struct sk_buff *skb)
219{
220 __u8 status = *((__u8 *) skb->data);
221 void *sent;
222
223 BT_DBG("%s status 0x%x", hdev->name, status);
224
225 sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_AUTH_ENABLE);
226 if (!sent)
227 return;
228
229 if (!status) {
230 __u8 param = *((__u8 *) sent);
231
232 if (param == AUTH_ENABLED)
233 set_bit(HCI_AUTH, &hdev->flags);
234 else
235 clear_bit(HCI_AUTH, &hdev->flags);
236 }
237
238 hci_req_complete(hdev, status);
239}
240
241static void hci_cc_write_encrypt_mode(struct hci_dev *hdev, struct sk_buff *skb)
242{
243 __u8 status = *((__u8 *) skb->data);
244 void *sent;
245
246 BT_DBG("%s status 0x%x", hdev->name, status);
247
248 sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_ENCRYPT_MODE);
249 if (!sent)
250 return;
251
252 if (!status) {
253 __u8 param = *((__u8 *) sent);
254
255 if (param)
256 set_bit(HCI_ENCRYPT, &hdev->flags);
257 else
258 clear_bit(HCI_ENCRYPT, &hdev->flags);
259 }
260
261 hci_req_complete(hdev, status);
262}
263
264static void hci_cc_write_scan_enable(struct hci_dev *hdev, struct sk_buff *skb)
265{
266 __u8 status = *((__u8 *) skb->data);
267 void *sent;
268
269 BT_DBG("%s status 0x%x", hdev->name, status);
270
271 sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_SCAN_ENABLE);
272 if (!sent)
273 return;
274
275 if (!status) {
276 __u8 param = *((__u8 *) sent);
277
278 clear_bit(HCI_PSCAN, &hdev->flags);
279 clear_bit(HCI_ISCAN, &hdev->flags);
280
281 if (param & SCAN_INQUIRY)
282 set_bit(HCI_ISCAN, &hdev->flags);
283
284 if (param & SCAN_PAGE)
285 set_bit(HCI_PSCAN, &hdev->flags);
286 }
287
288 hci_req_complete(hdev, status);
289}
290
291static void hci_cc_read_class_of_dev(struct hci_dev *hdev, struct sk_buff *skb)
292{
293 struct hci_rp_read_class_of_dev *rp = (void *) skb->data;
294
295 BT_DBG("%s status 0x%x", hdev->name, rp->status);
296
297 if (rp->status)
298 return;
299
300 memcpy(hdev->dev_class, rp->dev_class, 3);
301
302 BT_DBG("%s class 0x%.2x%.2x%.2x", hdev->name,
303 hdev->dev_class[2], hdev->dev_class[1], hdev->dev_class[0]);
304}
305
306static void hci_cc_write_class_of_dev(struct hci_dev *hdev, struct sk_buff *skb)
307{
308 __u8 status = *((__u8 *) skb->data);
309 void *sent;
310
311 BT_DBG("%s status 0x%x", hdev->name, status);
312
Marcel Holtmannf383f272008-07-14 20:13:47 +0200313 if (status)
314 return;
315
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200316 sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_CLASS_OF_DEV);
317 if (!sent)
318 return;
319
Marcel Holtmannf383f272008-07-14 20:13:47 +0200320 memcpy(hdev->dev_class, sent, 3);
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200321}
322
323static void hci_cc_read_voice_setting(struct hci_dev *hdev, struct sk_buff *skb)
324{
325 struct hci_rp_read_voice_setting *rp = (void *) skb->data;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700326 __u16 setting;
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200327
328 BT_DBG("%s status 0x%x", hdev->name, rp->status);
329
330 if (rp->status)
331 return;
332
333 setting = __le16_to_cpu(rp->voice_setting);
334
Marcel Holtmannf383f272008-07-14 20:13:47 +0200335 if (hdev->voice_setting == setting)
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200336 return;
337
338 hdev->voice_setting = setting;
339
340 BT_DBG("%s voice setting 0x%04x", hdev->name, setting);
341
342 if (hdev->notify) {
343 tasklet_disable(&hdev->tx_task);
344 hdev->notify(hdev, HCI_NOTIFY_VOICE_SETTING);
345 tasklet_enable(&hdev->tx_task);
346 }
347}
348
349static void hci_cc_write_voice_setting(struct hci_dev *hdev, struct sk_buff *skb)
350{
351 __u8 status = *((__u8 *) skb->data);
Marcel Holtmannf383f272008-07-14 20:13:47 +0200352 __u16 setting;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700353 void *sent;
354
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200355 BT_DBG("%s status 0x%x", hdev->name, status);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700356
Marcel Holtmannf383f272008-07-14 20:13:47 +0200357 if (status)
358 return;
359
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200360 sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_VOICE_SETTING);
361 if (!sent)
362 return;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700363
Marcel Holtmannf383f272008-07-14 20:13:47 +0200364 setting = get_unaligned_le16(sent);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700365
Marcel Holtmannf383f272008-07-14 20:13:47 +0200366 if (hdev->voice_setting == setting)
367 return;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700368
Marcel Holtmannf383f272008-07-14 20:13:47 +0200369 hdev->voice_setting = setting;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700370
Marcel Holtmannf383f272008-07-14 20:13:47 +0200371 BT_DBG("%s voice setting 0x%04x", hdev->name, setting);
372
373 if (hdev->notify) {
374 tasklet_disable(&hdev->tx_task);
375 hdev->notify(hdev, HCI_NOTIFY_VOICE_SETTING);
376 tasklet_enable(&hdev->tx_task);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700377 }
378}
379
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200380static void hci_cc_host_buffer_size(struct hci_dev *hdev, struct sk_buff *skb)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700381{
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200382 __u8 status = *((__u8 *) skb->data);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700383
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200384 BT_DBG("%s status 0x%x", hdev->name, status);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700385
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200386 hci_req_complete(hdev, status);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700387}
388
Marcel Holtmann333140b2008-07-14 20:13:48 +0200389static void hci_cc_read_ssp_mode(struct hci_dev *hdev, struct sk_buff *skb)
390{
391 struct hci_rp_read_ssp_mode *rp = (void *) skb->data;
392
393 BT_DBG("%s status 0x%x", hdev->name, rp->status);
394
395 if (rp->status)
396 return;
397
398 hdev->ssp_mode = rp->mode;
399}
400
401static void hci_cc_write_ssp_mode(struct hci_dev *hdev, struct sk_buff *skb)
402{
403 __u8 status = *((__u8 *) skb->data);
404 void *sent;
405
406 BT_DBG("%s status 0x%x", hdev->name, status);
407
408 if (status)
409 return;
410
411 sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_SSP_MODE);
412 if (!sent)
413 return;
414
415 hdev->ssp_mode = *((__u8 *) sent);
416}
417
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200418static void hci_cc_read_local_version(struct hci_dev *hdev, struct sk_buff *skb)
419{
420 struct hci_rp_read_local_version *rp = (void *) skb->data;
421
422 BT_DBG("%s status 0x%x", hdev->name, rp->status);
423
424 if (rp->status)
425 return;
426
427 hdev->hci_ver = rp->hci_ver;
Marcel Holtmanne4e8e372008-07-14 20:13:47 +0200428 hdev->hci_rev = __le16_to_cpu(rp->hci_rev);
429 hdev->manufacturer = __le16_to_cpu(rp->manufacturer);
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200430
431 BT_DBG("%s manufacturer %d hci ver %d:%d", hdev->name,
432 hdev->manufacturer,
433 hdev->hci_ver, hdev->hci_rev);
434}
435
436static void hci_cc_read_local_commands(struct hci_dev *hdev, struct sk_buff *skb)
437{
438 struct hci_rp_read_local_commands *rp = (void *) skb->data;
439
440 BT_DBG("%s status 0x%x", hdev->name, rp->status);
441
442 if (rp->status)
443 return;
444
445 memcpy(hdev->commands, rp->commands, sizeof(hdev->commands));
446}
447
448static void hci_cc_read_local_features(struct hci_dev *hdev, struct sk_buff *skb)
449{
450 struct hci_rp_read_local_features *rp = (void *) skb->data;
451
452 BT_DBG("%s status 0x%x", hdev->name, rp->status);
453
454 if (rp->status)
455 return;
456
457 memcpy(hdev->features, rp->features, 8);
458
459 /* Adjust default settings according to features
460 * supported by device. */
461
462 if (hdev->features[0] & LMP_3SLOT)
463 hdev->pkt_type |= (HCI_DM3 | HCI_DH3);
464
465 if (hdev->features[0] & LMP_5SLOT)
466 hdev->pkt_type |= (HCI_DM5 | HCI_DH5);
467
468 if (hdev->features[1] & LMP_HV2) {
469 hdev->pkt_type |= (HCI_HV2);
470 hdev->esco_type |= (ESCO_HV2);
471 }
472
473 if (hdev->features[1] & LMP_HV3) {
474 hdev->pkt_type |= (HCI_HV3);
475 hdev->esco_type |= (ESCO_HV3);
476 }
477
478 if (hdev->features[3] & LMP_ESCO)
479 hdev->esco_type |= (ESCO_EV3);
480
481 if (hdev->features[4] & LMP_EV4)
482 hdev->esco_type |= (ESCO_EV4);
483
484 if (hdev->features[4] & LMP_EV5)
485 hdev->esco_type |= (ESCO_EV5);
486
Marcel Holtmannefc76882009-02-06 09:13:37 +0100487 if (hdev->features[5] & LMP_EDR_ESCO_2M)
488 hdev->esco_type |= (ESCO_2EV3);
489
490 if (hdev->features[5] & LMP_EDR_ESCO_3M)
491 hdev->esco_type |= (ESCO_3EV3);
492
493 if (hdev->features[5] & LMP_EDR_3S_ESCO)
494 hdev->esco_type |= (ESCO_2EV5 | ESCO_3EV5);
495
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200496 BT_DBG("%s features 0x%.2x%.2x%.2x%.2x%.2x%.2x%.2x%.2x", hdev->name,
497 hdev->features[0], hdev->features[1],
498 hdev->features[2], hdev->features[3],
499 hdev->features[4], hdev->features[5],
500 hdev->features[6], hdev->features[7]);
501}
502
503static void hci_cc_read_buffer_size(struct hci_dev *hdev, struct sk_buff *skb)
504{
505 struct hci_rp_read_buffer_size *rp = (void *) skb->data;
506
507 BT_DBG("%s status 0x%x", hdev->name, rp->status);
508
509 if (rp->status)
510 return;
511
512 hdev->acl_mtu = __le16_to_cpu(rp->acl_mtu);
513 hdev->sco_mtu = rp->sco_mtu;
514 hdev->acl_pkts = __le16_to_cpu(rp->acl_max_pkt);
515 hdev->sco_pkts = __le16_to_cpu(rp->sco_max_pkt);
516
517 if (test_bit(HCI_QUIRK_FIXUP_BUFFER_SIZE, &hdev->quirks)) {
518 hdev->sco_mtu = 64;
519 hdev->sco_pkts = 8;
520 }
521
522 hdev->acl_cnt = hdev->acl_pkts;
523 hdev->sco_cnt = hdev->sco_pkts;
524
525 BT_DBG("%s acl mtu %d:%d sco mtu %d:%d", hdev->name,
526 hdev->acl_mtu, hdev->acl_pkts,
527 hdev->sco_mtu, hdev->sco_pkts);
528}
529
530static void hci_cc_read_bd_addr(struct hci_dev *hdev, struct sk_buff *skb)
531{
532 struct hci_rp_read_bd_addr *rp = (void *) skb->data;
533
534 BT_DBG("%s status 0x%x", hdev->name, rp->status);
535
536 if (!rp->status)
537 bacpy(&hdev->bdaddr, &rp->bdaddr);
538
539 hci_req_complete(hdev, rp->status);
540}
541
542static inline void hci_cs_inquiry(struct hci_dev *hdev, __u8 status)
543{
544 BT_DBG("%s status 0x%x", hdev->name, status);
545
546 if (status) {
547 hci_req_complete(hdev, status);
548
549 hci_conn_check_pending(hdev);
550 } else
551 set_bit(HCI_INQUIRY, &hdev->flags);
552}
553
Linus Torvalds1da177e2005-04-16 15:20:36 -0700554static inline void hci_cs_create_conn(struct hci_dev *hdev, __u8 status)
555{
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200556 struct hci_cp_create_conn *cp;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700557 struct hci_conn *conn;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700558
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200559 BT_DBG("%s status 0x%x", hdev->name, status);
560
561 cp = hci_sent_cmd_data(hdev, HCI_OP_CREATE_CONN);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700562 if (!cp)
563 return;
564
565 hci_dev_lock(hdev);
566
567 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &cp->bdaddr);
568
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200569 BT_DBG("%s bdaddr %s conn %p", hdev->name, batostr(&cp->bdaddr), conn);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700570
571 if (status) {
572 if (conn && conn->state == BT_CONNECT) {
Marcel Holtmann4c67bc72006-10-15 17:30:56 +0200573 if (status != 0x0c || conn->attempt > 2) {
574 conn->state = BT_CLOSED;
575 hci_proto_connect_cfm(conn, status);
576 hci_conn_del(conn);
577 } else
578 conn->state = BT_CONNECT2;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700579 }
580 } else {
581 if (!conn) {
582 conn = hci_conn_add(hdev, ACL_LINK, &cp->bdaddr);
583 if (conn) {
584 conn->out = 1;
585 conn->link_mode |= HCI_LM_MASTER;
586 } else
Gustavo F. Padovan893ef972010-07-18 15:13:37 -0300587 BT_ERR("No memory for new connection");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700588 }
589 }
590
591 hci_dev_unlock(hdev);
592}
593
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200594static void hci_cs_add_sco(struct hci_dev *hdev, __u8 status)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700595{
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200596 struct hci_cp_add_sco *cp;
597 struct hci_conn *acl, *sco;
598 __u16 handle;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700599
Marcel Holtmannb6a0dc82007-10-20 14:55:10 +0200600 BT_DBG("%s status 0x%x", hdev->name, status);
601
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200602 if (!status)
603 return;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700604
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200605 cp = hci_sent_cmd_data(hdev, HCI_OP_ADD_SCO);
606 if (!cp)
607 return;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700608
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200609 handle = __le16_to_cpu(cp->handle);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700610
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200611 BT_DBG("%s handle %d", hdev->name, handle);
Marcel Holtmann6bd57412006-11-18 22:14:22 +0100612
613 hci_dev_lock(hdev);
614
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200615 acl = hci_conn_hash_lookup_handle(hdev, handle);
616 if (acl && (sco = acl->link)) {
617 sco->state = BT_CLOSED;
618
619 hci_proto_connect_cfm(sco, status);
620 hci_conn_del(sco);
621 }
Marcel Holtmann6bd57412006-11-18 22:14:22 +0100622
623 hci_dev_unlock(hdev);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700624}
625
Marcel Holtmannf8558552008-07-14 20:13:49 +0200626static void hci_cs_auth_requested(struct hci_dev *hdev, __u8 status)
627{
628 struct hci_cp_auth_requested *cp;
629 struct hci_conn *conn;
630
631 BT_DBG("%s status 0x%x", hdev->name, status);
632
633 if (!status)
634 return;
635
636 cp = hci_sent_cmd_data(hdev, HCI_OP_AUTH_REQUESTED);
637 if (!cp)
638 return;
639
640 hci_dev_lock(hdev);
641
642 conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(cp->handle));
643 if (conn) {
644 if (conn->state == BT_CONFIG) {
645 hci_proto_connect_cfm(conn, status);
646 hci_conn_put(conn);
647 }
648 }
649
650 hci_dev_unlock(hdev);
651}
652
653static void hci_cs_set_conn_encrypt(struct hci_dev *hdev, __u8 status)
654{
655 struct hci_cp_set_conn_encrypt *cp;
656 struct hci_conn *conn;
657
658 BT_DBG("%s status 0x%x", hdev->name, status);
659
660 if (!status)
661 return;
662
663 cp = hci_sent_cmd_data(hdev, HCI_OP_SET_CONN_ENCRYPT);
664 if (!cp)
665 return;
666
667 hci_dev_lock(hdev);
668
669 conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(cp->handle));
670 if (conn) {
671 if (conn->state == BT_CONFIG) {
672 hci_proto_connect_cfm(conn, status);
673 hci_conn_put(conn);
674 }
675 }
676
677 hci_dev_unlock(hdev);
678}
679
Johan Hedberg127178d2010-11-18 22:22:29 +0200680static int hci_outgoing_auth_needed(struct hci_dev *hdev,
Johan Hedberg392599b2010-11-18 22:22:28 +0200681 struct hci_conn *conn)
682{
Johan Hedberg392599b2010-11-18 22:22:28 +0200683 if (conn->state != BT_CONFIG || !conn->out)
684 return 0;
685
686 if (conn->sec_level == BT_SECURITY_SDP)
687 return 0;
688
689 /* Only request authentication for SSP connections or non-SSP
690 * devices with sec_level HIGH */
691 if (!(hdev->ssp_mode > 0 && conn->ssp_mode > 0) &&
692 conn->sec_level != BT_SECURITY_HIGH)
693 return 0;
694
Johan Hedberg392599b2010-11-18 22:22:28 +0200695 return 1;
696}
697
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200698static void hci_cs_remote_name_req(struct hci_dev *hdev, __u8 status)
699{
Johan Hedberg127178d2010-11-18 22:22:29 +0200700 struct hci_cp_remote_name_req *cp;
701 struct hci_conn *conn;
702
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200703 BT_DBG("%s status 0x%x", hdev->name, status);
Johan Hedberg127178d2010-11-18 22:22:29 +0200704
705 /* If successful wait for the name req complete event before
706 * checking for the need to do authentication */
707 if (!status)
708 return;
709
710 cp = hci_sent_cmd_data(hdev, HCI_OP_REMOTE_NAME_REQ);
711 if (!cp)
712 return;
713
714 hci_dev_lock(hdev);
715
716 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &cp->bdaddr);
717 if (conn && hci_outgoing_auth_needed(hdev, conn)) {
718 struct hci_cp_auth_requested cp;
719 cp.handle = __cpu_to_le16(conn->handle);
720 hci_send_cmd(hdev, HCI_OP_AUTH_REQUESTED, sizeof(cp), &cp);
721 }
722
723 hci_dev_unlock(hdev);
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200724}
725
Marcel Holtmann769be972008-07-14 20:13:49 +0200726static void hci_cs_read_remote_features(struct hci_dev *hdev, __u8 status)
727{
728 struct hci_cp_read_remote_features *cp;
729 struct hci_conn *conn;
730
731 BT_DBG("%s status 0x%x", hdev->name, status);
732
733 if (!status)
734 return;
735
736 cp = hci_sent_cmd_data(hdev, HCI_OP_READ_REMOTE_FEATURES);
737 if (!cp)
738 return;
739
740 hci_dev_lock(hdev);
741
742 conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(cp->handle));
743 if (conn) {
744 if (conn->state == BT_CONFIG) {
Marcel Holtmann769be972008-07-14 20:13:49 +0200745 hci_proto_connect_cfm(conn, status);
746 hci_conn_put(conn);
747 }
748 }
749
750 hci_dev_unlock(hdev);
751}
752
753static void hci_cs_read_remote_ext_features(struct hci_dev *hdev, __u8 status)
754{
755 struct hci_cp_read_remote_ext_features *cp;
756 struct hci_conn *conn;
757
758 BT_DBG("%s status 0x%x", hdev->name, status);
759
760 if (!status)
761 return;
762
763 cp = hci_sent_cmd_data(hdev, HCI_OP_READ_REMOTE_EXT_FEATURES);
764 if (!cp)
765 return;
766
767 hci_dev_lock(hdev);
768
769 conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(cp->handle));
770 if (conn) {
771 if (conn->state == BT_CONFIG) {
Marcel Holtmann769be972008-07-14 20:13:49 +0200772 hci_proto_connect_cfm(conn, status);
773 hci_conn_put(conn);
774 }
775 }
776
777 hci_dev_unlock(hdev);
778}
779
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200780static void hci_cs_setup_sync_conn(struct hci_dev *hdev, __u8 status)
781{
Marcel Holtmannb6a0dc82007-10-20 14:55:10 +0200782 struct hci_cp_setup_sync_conn *cp;
783 struct hci_conn *acl, *sco;
784 __u16 handle;
785
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200786 BT_DBG("%s status 0x%x", hdev->name, status);
Marcel Holtmannb6a0dc82007-10-20 14:55:10 +0200787
788 if (!status)
789 return;
790
791 cp = hci_sent_cmd_data(hdev, HCI_OP_SETUP_SYNC_CONN);
792 if (!cp)
793 return;
794
795 handle = __le16_to_cpu(cp->handle);
796
797 BT_DBG("%s handle %d", hdev->name, handle);
798
799 hci_dev_lock(hdev);
800
801 acl = hci_conn_hash_lookup_handle(hdev, handle);
802 if (acl && (sco = acl->link)) {
803 sco->state = BT_CLOSED;
804
805 hci_proto_connect_cfm(sco, status);
806 hci_conn_del(sco);
807 }
808
809 hci_dev_unlock(hdev);
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200810}
811
812static void hci_cs_sniff_mode(struct hci_dev *hdev, __u8 status)
813{
814 struct hci_cp_sniff_mode *cp;
815 struct hci_conn *conn;
816
817 BT_DBG("%s status 0x%x", hdev->name, status);
818
819 if (!status)
820 return;
821
822 cp = hci_sent_cmd_data(hdev, HCI_OP_SNIFF_MODE);
823 if (!cp)
824 return;
825
826 hci_dev_lock(hdev);
827
828 conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(cp->handle));
Marcel Holtmanne73439d2010-07-26 10:06:00 -0400829 if (conn) {
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200830 clear_bit(HCI_CONN_MODE_CHANGE_PEND, &conn->pend);
831
Marcel Holtmanne73439d2010-07-26 10:06:00 -0400832 if (test_and_clear_bit(HCI_CONN_SCO_SETUP_PEND, &conn->pend))
833 hci_sco_setup(conn, status);
834 }
835
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200836 hci_dev_unlock(hdev);
837}
838
839static void hci_cs_exit_sniff_mode(struct hci_dev *hdev, __u8 status)
840{
841 struct hci_cp_exit_sniff_mode *cp;
842 struct hci_conn *conn;
843
844 BT_DBG("%s status 0x%x", hdev->name, status);
845
846 if (!status)
847 return;
848
849 cp = hci_sent_cmd_data(hdev, HCI_OP_EXIT_SNIFF_MODE);
850 if (!cp)
851 return;
852
853 hci_dev_lock(hdev);
854
855 conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(cp->handle));
Marcel Holtmanne73439d2010-07-26 10:06:00 -0400856 if (conn) {
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200857 clear_bit(HCI_CONN_MODE_CHANGE_PEND, &conn->pend);
858
Marcel Holtmanne73439d2010-07-26 10:06:00 -0400859 if (test_and_clear_bit(HCI_CONN_SCO_SETUP_PEND, &conn->pend))
860 hci_sco_setup(conn, status);
861 }
862
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200863 hci_dev_unlock(hdev);
864}
865
866static inline void hci_inquiry_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
867{
868 __u8 status = *((__u8 *) skb->data);
869
870 BT_DBG("%s status %d", hdev->name, status);
871
872 clear_bit(HCI_INQUIRY, &hdev->flags);
873
874 hci_req_complete(hdev, status);
875
876 hci_conn_check_pending(hdev);
877}
878
Linus Torvalds1da177e2005-04-16 15:20:36 -0700879static inline void hci_inquiry_result_evt(struct hci_dev *hdev, struct sk_buff *skb)
880{
Marcel Holtmann45bb4bf2005-08-09 20:27:49 -0700881 struct inquiry_data data;
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200882 struct inquiry_info *info = (void *) (skb->data + 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700883 int num_rsp = *((__u8 *) skb->data);
884
885 BT_DBG("%s num_rsp %d", hdev->name, num_rsp);
886
Marcel Holtmann45bb4bf2005-08-09 20:27:49 -0700887 if (!num_rsp)
888 return;
889
Linus Torvalds1da177e2005-04-16 15:20:36 -0700890 hci_dev_lock(hdev);
Marcel Holtmann45bb4bf2005-08-09 20:27:49 -0700891
Linus Torvalds1da177e2005-04-16 15:20:36 -0700892 for (; num_rsp; num_rsp--) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700893 bacpy(&data.bdaddr, &info->bdaddr);
894 data.pscan_rep_mode = info->pscan_rep_mode;
895 data.pscan_period_mode = info->pscan_period_mode;
896 data.pscan_mode = info->pscan_mode;
897 memcpy(data.dev_class, info->dev_class, 3);
898 data.clock_offset = info->clock_offset;
899 data.rssi = 0x00;
Marcel Holtmann41a96212008-07-14 20:13:48 +0200900 data.ssp_mode = 0x00;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700901 info++;
902 hci_inquiry_cache_update(hdev, &data);
903 }
Marcel Holtmann45bb4bf2005-08-09 20:27:49 -0700904
Linus Torvalds1da177e2005-04-16 15:20:36 -0700905 hci_dev_unlock(hdev);
906}
907
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200908static inline void hci_conn_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700909{
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200910 struct hci_ev_conn_complete *ev = (void *) skb->data;
911 struct hci_conn *conn;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700912
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200913 BT_DBG("%s", hdev->name);
Marcel Holtmann45bb4bf2005-08-09 20:27:49 -0700914
Linus Torvalds1da177e2005-04-16 15:20:36 -0700915 hci_dev_lock(hdev);
Marcel Holtmann45bb4bf2005-08-09 20:27:49 -0700916
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200917 conn = hci_conn_hash_lookup_ba(hdev, ev->link_type, &ev->bdaddr);
Marcel Holtmann94992372009-04-19 19:30:03 +0200918 if (!conn) {
919 if (ev->link_type != SCO_LINK)
920 goto unlock;
921
922 conn = hci_conn_hash_lookup_ba(hdev, ESCO_LINK, &ev->bdaddr);
923 if (!conn)
924 goto unlock;
925
926 conn->type = SCO_LINK;
927 }
Marcel Holtmann45bb4bf2005-08-09 20:27:49 -0700928
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200929 if (!ev->status) {
930 conn->handle = __le16_to_cpu(ev->handle);
Marcel Holtmann769be972008-07-14 20:13:49 +0200931
932 if (conn->type == ACL_LINK) {
933 conn->state = BT_CONFIG;
934 hci_conn_hold(conn);
Marcel Holtmann052b30b2009-04-26 20:01:22 +0200935 conn->disc_timeout = HCI_DISCONN_TIMEOUT;
Marcel Holtmann769be972008-07-14 20:13:49 +0200936 } else
937 conn->state = BT_CONNECTED;
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200938
Marcel Holtmann9eba32b2009-08-22 14:19:26 -0700939 hci_conn_hold_device(conn);
Marcel Holtmann7d0db0a2008-07-14 20:13:51 +0200940 hci_conn_add_sysfs(conn);
941
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200942 if (test_bit(HCI_AUTH, &hdev->flags))
943 conn->link_mode |= HCI_LM_AUTH;
944
945 if (test_bit(HCI_ENCRYPT, &hdev->flags))
946 conn->link_mode |= HCI_LM_ENCRYPT;
947
948 /* Get remote features */
949 if (conn->type == ACL_LINK) {
950 struct hci_cp_read_remote_features cp;
951 cp.handle = ev->handle;
Marcel Holtmann769be972008-07-14 20:13:49 +0200952 hci_send_cmd(hdev, HCI_OP_READ_REMOTE_FEATURES,
953 sizeof(cp), &cp);
Marcel Holtmann45bb4bf2005-08-09 20:27:49 -0700954 }
Marcel Holtmann45bb4bf2005-08-09 20:27:49 -0700955
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200956 /* Set packet type for incoming connection */
Marcel Holtmanna8746412008-07-14 20:13:46 +0200957 if (!conn->out && hdev->hci_ver < 3) {
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200958 struct hci_cp_change_conn_ptype cp;
959 cp.handle = ev->handle;
Marcel Holtmanna8746412008-07-14 20:13:46 +0200960 cp.pkt_type = cpu_to_le16(conn->pkt_type);
961 hci_send_cmd(hdev, HCI_OP_CHANGE_CONN_PTYPE,
962 sizeof(cp), &cp);
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200963 }
964 } else
965 conn->state = BT_CLOSED;
966
Marcel Holtmanne73439d2010-07-26 10:06:00 -0400967 if (conn->type == ACL_LINK)
968 hci_sco_setup(conn, ev->status);
Marcel Holtmann45bb4bf2005-08-09 20:27:49 -0700969
Marcel Holtmann769be972008-07-14 20:13:49 +0200970 if (ev->status) {
971 hci_proto_connect_cfm(conn, ev->status);
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200972 hci_conn_del(conn);
Marcel Holtmannc89b6e62009-01-15 21:57:03 +0100973 } else if (ev->link_type != ACL_LINK)
974 hci_proto_connect_cfm(conn, ev->status);
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200975
976unlock:
Linus Torvalds1da177e2005-04-16 15:20:36 -0700977 hci_dev_unlock(hdev);
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200978
979 hci_conn_check_pending(hdev);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700980}
981
Linus Torvalds1da177e2005-04-16 15:20:36 -0700982static inline void hci_conn_request_evt(struct hci_dev *hdev, struct sk_buff *skb)
983{
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200984 struct hci_ev_conn_request *ev = (void *) skb->data;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700985 int mask = hdev->link_mode;
986
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200987 BT_DBG("%s bdaddr %s type 0x%x", hdev->name,
988 batostr(&ev->bdaddr), ev->link_type);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700989
990 mask |= hci_proto_connect_ind(hdev, &ev->bdaddr, ev->link_type);
991
Johan Hedbergf0358562010-05-18 13:20:32 +0200992 if ((mask & HCI_LM_ACCEPT) && !hci_blacklist_lookup(hdev, &ev->bdaddr)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700993 /* Connection accepted */
Marcel Holtmannc7bdd502008-07-14 20:13:47 +0200994 struct inquiry_entry *ie;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700995 struct hci_conn *conn;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700996
997 hci_dev_lock(hdev);
Marcel Holtmannb6a0dc82007-10-20 14:55:10 +0200998
Marcel Holtmannc7bdd502008-07-14 20:13:47 +0200999 if ((ie = hci_inquiry_cache_lookup(hdev, &ev->bdaddr)))
1000 memcpy(ie->data.dev_class, ev->dev_class, 3);
1001
Linus Torvalds1da177e2005-04-16 15:20:36 -07001002 conn = hci_conn_hash_lookup_ba(hdev, ev->link_type, &ev->bdaddr);
1003 if (!conn) {
1004 if (!(conn = hci_conn_add(hdev, ev->link_type, &ev->bdaddr))) {
Gustavo F. Padovan893ef972010-07-18 15:13:37 -03001005 BT_ERR("No memory for new connection");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001006 hci_dev_unlock(hdev);
1007 return;
1008 }
1009 }
Marcel Holtmannb6a0dc82007-10-20 14:55:10 +02001010
Linus Torvalds1da177e2005-04-16 15:20:36 -07001011 memcpy(conn->dev_class, ev->dev_class, 3);
1012 conn->state = BT_CONNECT;
Marcel Holtmannb6a0dc82007-10-20 14:55:10 +02001013
Linus Torvalds1da177e2005-04-16 15:20:36 -07001014 hci_dev_unlock(hdev);
1015
Marcel Holtmannb6a0dc82007-10-20 14:55:10 +02001016 if (ev->link_type == ACL_LINK || !lmp_esco_capable(hdev)) {
1017 struct hci_cp_accept_conn_req cp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001018
Marcel Holtmannb6a0dc82007-10-20 14:55:10 +02001019 bacpy(&cp.bdaddr, &ev->bdaddr);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001020
Marcel Holtmannb6a0dc82007-10-20 14:55:10 +02001021 if (lmp_rswitch_capable(hdev) && (mask & HCI_LM_MASTER))
1022 cp.role = 0x00; /* Become master */
1023 else
1024 cp.role = 0x01; /* Remain slave */
1025
1026 hci_send_cmd(hdev, HCI_OP_ACCEPT_CONN_REQ,
1027 sizeof(cp), &cp);
1028 } else {
1029 struct hci_cp_accept_sync_conn_req cp;
1030
1031 bacpy(&cp.bdaddr, &ev->bdaddr);
Marcel Holtmanna8746412008-07-14 20:13:46 +02001032 cp.pkt_type = cpu_to_le16(conn->pkt_type);
Marcel Holtmannb6a0dc82007-10-20 14:55:10 +02001033
1034 cp.tx_bandwidth = cpu_to_le32(0x00001f40);
1035 cp.rx_bandwidth = cpu_to_le32(0x00001f40);
1036 cp.max_latency = cpu_to_le16(0xffff);
1037 cp.content_format = cpu_to_le16(hdev->voice_setting);
1038 cp.retrans_effort = 0xff;
1039
1040 hci_send_cmd(hdev, HCI_OP_ACCEPT_SYNC_CONN_REQ,
1041 sizeof(cp), &cp);
1042 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001043 } else {
1044 /* Connection rejected */
1045 struct hci_cp_reject_conn_req cp;
1046
1047 bacpy(&cp.bdaddr, &ev->bdaddr);
1048 cp.reason = 0x0f;
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001049 hci_send_cmd(hdev, HCI_OP_REJECT_CONN_REQ, sizeof(cp), &cp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001050 }
1051}
1052
Linus Torvalds1da177e2005-04-16 15:20:36 -07001053static inline void hci_disconn_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
1054{
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001055 struct hci_ev_disconn_complete *ev = (void *) skb->data;
Marcel Holtmann04837f62006-07-03 10:02:33 +02001056 struct hci_conn *conn;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001057
1058 BT_DBG("%s status %d", hdev->name, ev->status);
1059
1060 if (ev->status)
1061 return;
1062
1063 hci_dev_lock(hdev);
1064
Marcel Holtmann04837f62006-07-03 10:02:33 +02001065 conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
Linus Torvalds1da177e2005-04-16 15:20:36 -07001066 if (conn) {
1067 conn->state = BT_CLOSED;
Marcel Holtmann7d0db0a2008-07-14 20:13:51 +02001068
Marcel Holtmann2950f212009-02-12 14:02:50 +01001069 hci_proto_disconn_cfm(conn, ev->reason);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001070 hci_conn_del(conn);
1071 }
1072
1073 hci_dev_unlock(hdev);
1074}
1075
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001076static inline void hci_auth_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
1077{
1078 struct hci_ev_auth_complete *ev = (void *) skb->data;
1079 struct hci_conn *conn;
1080
1081 BT_DBG("%s status %d", hdev->name, ev->status);
1082
1083 hci_dev_lock(hdev);
1084
1085 conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
1086 if (conn) {
1087 if (!ev->status)
1088 conn->link_mode |= HCI_LM_AUTH;
Johan Hedbergda213f42010-06-18 11:08:56 +03001089 else
1090 conn->sec_level = BT_SECURITY_LOW;
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001091
1092 clear_bit(HCI_CONN_AUTH_PEND, &conn->pend);
1093
Marcel Holtmannf8558552008-07-14 20:13:49 +02001094 if (conn->state == BT_CONFIG) {
1095 if (!ev->status && hdev->ssp_mode > 0 &&
1096 conn->ssp_mode > 0) {
1097 struct hci_cp_set_conn_encrypt cp;
1098 cp.handle = ev->handle;
1099 cp.encrypt = 0x01;
1100 hci_send_cmd(hdev, HCI_OP_SET_CONN_ENCRYPT,
1101 sizeof(cp), &cp);
1102 } else {
1103 conn->state = BT_CONNECTED;
1104 hci_proto_connect_cfm(conn, ev->status);
1105 hci_conn_put(conn);
1106 }
Marcel Holtmann052b30b2009-04-26 20:01:22 +02001107 } else {
Marcel Holtmannf8558552008-07-14 20:13:49 +02001108 hci_auth_cfm(conn, ev->status);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001109
Marcel Holtmann052b30b2009-04-26 20:01:22 +02001110 hci_conn_hold(conn);
1111 conn->disc_timeout = HCI_DISCONN_TIMEOUT;
1112 hci_conn_put(conn);
1113 }
1114
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001115 if (test_bit(HCI_CONN_ENCRYPT_PEND, &conn->pend)) {
1116 if (!ev->status) {
1117 struct hci_cp_set_conn_encrypt cp;
Marcel Holtmannf8558552008-07-14 20:13:49 +02001118 cp.handle = ev->handle;
1119 cp.encrypt = 0x01;
1120 hci_send_cmd(hdev, HCI_OP_SET_CONN_ENCRYPT,
1121 sizeof(cp), &cp);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001122 } else {
1123 clear_bit(HCI_CONN_ENCRYPT_PEND, &conn->pend);
1124 hci_encrypt_cfm(conn, ev->status, 0x00);
1125 }
1126 }
1127 }
1128
1129 hci_dev_unlock(hdev);
1130}
1131
1132static inline void hci_remote_name_evt(struct hci_dev *hdev, struct sk_buff *skb)
1133{
Johan Hedberg127178d2010-11-18 22:22:29 +02001134 struct hci_ev_remote_name *ev = (void *) skb->data;
1135 struct hci_conn *conn;
1136
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001137 BT_DBG("%s", hdev->name);
1138
1139 hci_conn_check_pending(hdev);
Johan Hedberg127178d2010-11-18 22:22:29 +02001140
1141 hci_dev_lock(hdev);
1142
1143 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
1144 if (conn && hci_outgoing_auth_needed(hdev, conn)) {
1145 struct hci_cp_auth_requested cp;
1146 cp.handle = __cpu_to_le16(conn->handle);
1147 hci_send_cmd(hdev, HCI_OP_AUTH_REQUESTED, sizeof(cp), &cp);
1148 }
1149
1150 hci_dev_unlock(hdev);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001151}
1152
1153static inline void hci_encrypt_change_evt(struct hci_dev *hdev, struct sk_buff *skb)
1154{
1155 struct hci_ev_encrypt_change *ev = (void *) skb->data;
1156 struct hci_conn *conn;
1157
1158 BT_DBG("%s status %d", hdev->name, ev->status);
1159
1160 hci_dev_lock(hdev);
1161
1162 conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
1163 if (conn) {
1164 if (!ev->status) {
Marcel Holtmannae293192008-07-14 20:13:45 +02001165 if (ev->encrypt) {
1166 /* Encryption implies authentication */
1167 conn->link_mode |= HCI_LM_AUTH;
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001168 conn->link_mode |= HCI_LM_ENCRYPT;
Marcel Holtmannae293192008-07-14 20:13:45 +02001169 } else
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001170 conn->link_mode &= ~HCI_LM_ENCRYPT;
1171 }
1172
1173 clear_bit(HCI_CONN_ENCRYPT_PEND, &conn->pend);
1174
Marcel Holtmannf8558552008-07-14 20:13:49 +02001175 if (conn->state == BT_CONFIG) {
1176 if (!ev->status)
1177 conn->state = BT_CONNECTED;
1178
1179 hci_proto_connect_cfm(conn, ev->status);
1180 hci_conn_put(conn);
1181 } else
1182 hci_encrypt_cfm(conn, ev->status, ev->encrypt);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001183 }
1184
1185 hci_dev_unlock(hdev);
1186}
1187
1188static inline void hci_change_link_key_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
1189{
1190 struct hci_ev_change_link_key_complete *ev = (void *) skb->data;
1191 struct hci_conn *conn;
1192
1193 BT_DBG("%s status %d", hdev->name, ev->status);
1194
1195 hci_dev_lock(hdev);
1196
1197 conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
1198 if (conn) {
1199 if (!ev->status)
1200 conn->link_mode |= HCI_LM_SECURE;
1201
1202 clear_bit(HCI_CONN_AUTH_PEND, &conn->pend);
1203
1204 hci_key_change_cfm(conn, ev->status);
1205 }
1206
1207 hci_dev_unlock(hdev);
1208}
1209
1210static inline void hci_remote_features_evt(struct hci_dev *hdev, struct sk_buff *skb)
1211{
1212 struct hci_ev_remote_features *ev = (void *) skb->data;
1213 struct hci_conn *conn;
1214
1215 BT_DBG("%s status %d", hdev->name, ev->status);
1216
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001217 hci_dev_lock(hdev);
1218
1219 conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
Johan Hedbergccd556f2010-11-10 17:11:51 +02001220 if (!conn)
1221 goto unlock;
Marcel Holtmann769be972008-07-14 20:13:49 +02001222
Johan Hedbergccd556f2010-11-10 17:11:51 +02001223 if (!ev->status)
1224 memcpy(conn->features, ev->features, 8);
1225
1226 if (conn->state != BT_CONFIG)
1227 goto unlock;
1228
1229 if (!ev->status && lmp_ssp_capable(hdev) && lmp_ssp_capable(conn)) {
1230 struct hci_cp_read_remote_ext_features cp;
1231 cp.handle = ev->handle;
1232 cp.page = 0x01;
1233 hci_send_cmd(hdev, HCI_OP_READ_REMOTE_EXT_FEATURES,
Marcel Holtmann769be972008-07-14 20:13:49 +02001234 sizeof(cp), &cp);
Johan Hedberg392599b2010-11-18 22:22:28 +02001235 goto unlock;
1236 }
1237
Johan Hedberg127178d2010-11-18 22:22:29 +02001238 if (!ev->status) {
1239 struct hci_cp_remote_name_req cp;
1240 memset(&cp, 0, sizeof(cp));
1241 bacpy(&cp.bdaddr, &conn->dst);
1242 cp.pscan_rep_mode = 0x02;
1243 hci_send_cmd(hdev, HCI_OP_REMOTE_NAME_REQ, sizeof(cp), &cp);
1244 }
Johan Hedberg392599b2010-11-18 22:22:28 +02001245
Johan Hedberg127178d2010-11-18 22:22:29 +02001246 if (!hci_outgoing_auth_needed(hdev, conn)) {
Johan Hedbergccd556f2010-11-10 17:11:51 +02001247 conn->state = BT_CONNECTED;
1248 hci_proto_connect_cfm(conn, ev->status);
1249 hci_conn_put(conn);
Marcel Holtmann769be972008-07-14 20:13:49 +02001250 }
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001251
Johan Hedbergccd556f2010-11-10 17:11:51 +02001252unlock:
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001253 hci_dev_unlock(hdev);
1254}
1255
1256static inline void hci_remote_version_evt(struct hci_dev *hdev, struct sk_buff *skb)
1257{
1258 BT_DBG("%s", hdev->name);
1259}
1260
1261static inline void hci_qos_setup_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
1262{
1263 BT_DBG("%s", hdev->name);
1264}
1265
1266static inline void hci_cmd_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
1267{
1268 struct hci_ev_cmd_complete *ev = (void *) skb->data;
1269 __u16 opcode;
1270
1271 skb_pull(skb, sizeof(*ev));
1272
1273 opcode = __le16_to_cpu(ev->opcode);
1274
1275 switch (opcode) {
1276 case HCI_OP_INQUIRY_CANCEL:
1277 hci_cc_inquiry_cancel(hdev, skb);
1278 break;
1279
1280 case HCI_OP_EXIT_PERIODIC_INQ:
1281 hci_cc_exit_periodic_inq(hdev, skb);
1282 break;
1283
1284 case HCI_OP_REMOTE_NAME_REQ_CANCEL:
1285 hci_cc_remote_name_req_cancel(hdev, skb);
1286 break;
1287
1288 case HCI_OP_ROLE_DISCOVERY:
1289 hci_cc_role_discovery(hdev, skb);
1290 break;
1291
Marcel Holtmanne4e8e372008-07-14 20:13:47 +02001292 case HCI_OP_READ_LINK_POLICY:
1293 hci_cc_read_link_policy(hdev, skb);
1294 break;
1295
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001296 case HCI_OP_WRITE_LINK_POLICY:
1297 hci_cc_write_link_policy(hdev, skb);
1298 break;
1299
Marcel Holtmanne4e8e372008-07-14 20:13:47 +02001300 case HCI_OP_READ_DEF_LINK_POLICY:
1301 hci_cc_read_def_link_policy(hdev, skb);
1302 break;
1303
1304 case HCI_OP_WRITE_DEF_LINK_POLICY:
1305 hci_cc_write_def_link_policy(hdev, skb);
1306 break;
1307
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001308 case HCI_OP_RESET:
1309 hci_cc_reset(hdev, skb);
1310 break;
1311
1312 case HCI_OP_WRITE_LOCAL_NAME:
1313 hci_cc_write_local_name(hdev, skb);
1314 break;
1315
1316 case HCI_OP_READ_LOCAL_NAME:
1317 hci_cc_read_local_name(hdev, skb);
1318 break;
1319
1320 case HCI_OP_WRITE_AUTH_ENABLE:
1321 hci_cc_write_auth_enable(hdev, skb);
1322 break;
1323
1324 case HCI_OP_WRITE_ENCRYPT_MODE:
1325 hci_cc_write_encrypt_mode(hdev, skb);
1326 break;
1327
1328 case HCI_OP_WRITE_SCAN_ENABLE:
1329 hci_cc_write_scan_enable(hdev, skb);
1330 break;
1331
1332 case HCI_OP_READ_CLASS_OF_DEV:
1333 hci_cc_read_class_of_dev(hdev, skb);
1334 break;
1335
1336 case HCI_OP_WRITE_CLASS_OF_DEV:
1337 hci_cc_write_class_of_dev(hdev, skb);
1338 break;
1339
1340 case HCI_OP_READ_VOICE_SETTING:
1341 hci_cc_read_voice_setting(hdev, skb);
1342 break;
1343
1344 case HCI_OP_WRITE_VOICE_SETTING:
1345 hci_cc_write_voice_setting(hdev, skb);
1346 break;
1347
1348 case HCI_OP_HOST_BUFFER_SIZE:
1349 hci_cc_host_buffer_size(hdev, skb);
1350 break;
1351
Marcel Holtmann333140b2008-07-14 20:13:48 +02001352 case HCI_OP_READ_SSP_MODE:
1353 hci_cc_read_ssp_mode(hdev, skb);
1354 break;
1355
1356 case HCI_OP_WRITE_SSP_MODE:
1357 hci_cc_write_ssp_mode(hdev, skb);
1358 break;
1359
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001360 case HCI_OP_READ_LOCAL_VERSION:
1361 hci_cc_read_local_version(hdev, skb);
1362 break;
1363
1364 case HCI_OP_READ_LOCAL_COMMANDS:
1365 hci_cc_read_local_commands(hdev, skb);
1366 break;
1367
1368 case HCI_OP_READ_LOCAL_FEATURES:
1369 hci_cc_read_local_features(hdev, skb);
1370 break;
1371
1372 case HCI_OP_READ_BUFFER_SIZE:
1373 hci_cc_read_buffer_size(hdev, skb);
1374 break;
1375
1376 case HCI_OP_READ_BD_ADDR:
1377 hci_cc_read_bd_addr(hdev, skb);
1378 break;
1379
1380 default:
1381 BT_DBG("%s opcode 0x%x", hdev->name, opcode);
1382 break;
1383 }
1384
1385 if (ev->ncmd) {
1386 atomic_set(&hdev->cmd_cnt, 1);
1387 if (!skb_queue_empty(&hdev->cmd_q))
Marcel Holtmannc78ae282009-11-18 01:02:54 +01001388 tasklet_schedule(&hdev->cmd_task);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001389 }
1390}
1391
1392static inline void hci_cmd_status_evt(struct hci_dev *hdev, struct sk_buff *skb)
1393{
1394 struct hci_ev_cmd_status *ev = (void *) skb->data;
1395 __u16 opcode;
1396
1397 skb_pull(skb, sizeof(*ev));
1398
1399 opcode = __le16_to_cpu(ev->opcode);
1400
1401 switch (opcode) {
1402 case HCI_OP_INQUIRY:
1403 hci_cs_inquiry(hdev, ev->status);
1404 break;
1405
1406 case HCI_OP_CREATE_CONN:
1407 hci_cs_create_conn(hdev, ev->status);
1408 break;
1409
1410 case HCI_OP_ADD_SCO:
1411 hci_cs_add_sco(hdev, ev->status);
1412 break;
1413
Marcel Holtmannf8558552008-07-14 20:13:49 +02001414 case HCI_OP_AUTH_REQUESTED:
1415 hci_cs_auth_requested(hdev, ev->status);
1416 break;
1417
1418 case HCI_OP_SET_CONN_ENCRYPT:
1419 hci_cs_set_conn_encrypt(hdev, ev->status);
1420 break;
1421
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001422 case HCI_OP_REMOTE_NAME_REQ:
1423 hci_cs_remote_name_req(hdev, ev->status);
1424 break;
1425
Marcel Holtmann769be972008-07-14 20:13:49 +02001426 case HCI_OP_READ_REMOTE_FEATURES:
1427 hci_cs_read_remote_features(hdev, ev->status);
1428 break;
1429
1430 case HCI_OP_READ_REMOTE_EXT_FEATURES:
1431 hci_cs_read_remote_ext_features(hdev, ev->status);
1432 break;
1433
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001434 case HCI_OP_SETUP_SYNC_CONN:
1435 hci_cs_setup_sync_conn(hdev, ev->status);
1436 break;
1437
1438 case HCI_OP_SNIFF_MODE:
1439 hci_cs_sniff_mode(hdev, ev->status);
1440 break;
1441
1442 case HCI_OP_EXIT_SNIFF_MODE:
1443 hci_cs_exit_sniff_mode(hdev, ev->status);
1444 break;
1445
1446 default:
1447 BT_DBG("%s opcode 0x%x", hdev->name, opcode);
1448 break;
1449 }
1450
1451 if (ev->ncmd) {
1452 atomic_set(&hdev->cmd_cnt, 1);
1453 if (!skb_queue_empty(&hdev->cmd_q))
Marcel Holtmannc78ae282009-11-18 01:02:54 +01001454 tasklet_schedule(&hdev->cmd_task);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001455 }
1456}
1457
1458static inline void hci_role_change_evt(struct hci_dev *hdev, struct sk_buff *skb)
1459{
1460 struct hci_ev_role_change *ev = (void *) skb->data;
1461 struct hci_conn *conn;
1462
1463 BT_DBG("%s status %d", hdev->name, ev->status);
1464
1465 hci_dev_lock(hdev);
1466
1467 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
1468 if (conn) {
1469 if (!ev->status) {
1470 if (ev->role)
1471 conn->link_mode &= ~HCI_LM_MASTER;
1472 else
1473 conn->link_mode |= HCI_LM_MASTER;
1474 }
1475
1476 clear_bit(HCI_CONN_RSWITCH_PEND, &conn->pend);
1477
1478 hci_role_switch_cfm(conn, ev->status, ev->role);
1479 }
1480
1481 hci_dev_unlock(hdev);
1482}
1483
Linus Torvalds1da177e2005-04-16 15:20:36 -07001484static inline void hci_num_comp_pkts_evt(struct hci_dev *hdev, struct sk_buff *skb)
1485{
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001486 struct hci_ev_num_comp_pkts *ev = (void *) skb->data;
Marcel Holtmann1ebb9252005-11-08 09:57:21 -08001487 __le16 *ptr;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001488 int i;
1489
1490 skb_pull(skb, sizeof(*ev));
1491
1492 BT_DBG("%s num_hndl %d", hdev->name, ev->num_hndl);
1493
1494 if (skb->len < ev->num_hndl * 4) {
1495 BT_DBG("%s bad parameters", hdev->name);
1496 return;
1497 }
1498
1499 tasklet_disable(&hdev->tx_task);
1500
Marcel Holtmann1ebb9252005-11-08 09:57:21 -08001501 for (i = 0, ptr = (__le16 *) skb->data; i < ev->num_hndl; i++) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001502 struct hci_conn *conn;
1503 __u16 handle, count;
1504
Harvey Harrison83985312008-05-02 16:25:46 -07001505 handle = get_unaligned_le16(ptr++);
1506 count = get_unaligned_le16(ptr++);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001507
1508 conn = hci_conn_hash_lookup_handle(hdev, handle);
1509 if (conn) {
1510 conn->sent -= count;
1511
Marcel Holtmann5b7f9902007-07-11 09:51:55 +02001512 if (conn->type == ACL_LINK) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001513 if ((hdev->acl_cnt += count) > hdev->acl_pkts)
1514 hdev->acl_cnt = hdev->acl_pkts;
Marcel Holtmann5b7f9902007-07-11 09:51:55 +02001515 } else {
1516 if ((hdev->sco_cnt += count) > hdev->sco_pkts)
1517 hdev->sco_cnt = hdev->sco_pkts;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001518 }
1519 }
1520 }
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001521
Marcel Holtmannc78ae282009-11-18 01:02:54 +01001522 tasklet_schedule(&hdev->tx_task);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001523
1524 tasklet_enable(&hdev->tx_task);
1525}
1526
Marcel Holtmann04837f62006-07-03 10:02:33 +02001527static inline void hci_mode_change_evt(struct hci_dev *hdev, struct sk_buff *skb)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001528{
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001529 struct hci_ev_mode_change *ev = (void *) skb->data;
Marcel Holtmann04837f62006-07-03 10:02:33 +02001530 struct hci_conn *conn;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001531
1532 BT_DBG("%s status %d", hdev->name, ev->status);
1533
1534 hci_dev_lock(hdev);
1535
Marcel Holtmann04837f62006-07-03 10:02:33 +02001536 conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
1537 if (conn) {
1538 conn->mode = ev->mode;
1539 conn->interval = __le16_to_cpu(ev->interval);
1540
1541 if (!test_and_clear_bit(HCI_CONN_MODE_CHANGE_PEND, &conn->pend)) {
1542 if (conn->mode == HCI_CM_ACTIVE)
1543 conn->power_save = 1;
1544 else
1545 conn->power_save = 0;
1546 }
Marcel Holtmanne73439d2010-07-26 10:06:00 -04001547
1548 if (test_and_clear_bit(HCI_CONN_SCO_SETUP_PEND, &conn->pend))
1549 hci_sco_setup(conn, ev->status);
Marcel Holtmann04837f62006-07-03 10:02:33 +02001550 }
1551
1552 hci_dev_unlock(hdev);
1553}
1554
Linus Torvalds1da177e2005-04-16 15:20:36 -07001555static inline void hci_pin_code_request_evt(struct hci_dev *hdev, struct sk_buff *skb)
1556{
Marcel Holtmann052b30b2009-04-26 20:01:22 +02001557 struct hci_ev_pin_code_req *ev = (void *) skb->data;
1558 struct hci_conn *conn;
1559
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001560 BT_DBG("%s", hdev->name);
Marcel Holtmann052b30b2009-04-26 20:01:22 +02001561
1562 hci_dev_lock(hdev);
1563
1564 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
Marcel Holtmann3d7a9d12009-05-09 12:09:21 -07001565 if (conn && conn->state == BT_CONNECTED) {
Marcel Holtmann052b30b2009-04-26 20:01:22 +02001566 hci_conn_hold(conn);
1567 conn->disc_timeout = HCI_PAIRING_TIMEOUT;
1568 hci_conn_put(conn);
1569 }
1570
1571 hci_dev_unlock(hdev);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001572}
1573
Linus Torvalds1da177e2005-04-16 15:20:36 -07001574static inline void hci_link_key_request_evt(struct hci_dev *hdev, struct sk_buff *skb)
1575{
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001576 BT_DBG("%s", hdev->name);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001577}
1578
Linus Torvalds1da177e2005-04-16 15:20:36 -07001579static inline void hci_link_key_notify_evt(struct hci_dev *hdev, struct sk_buff *skb)
1580{
Marcel Holtmann052b30b2009-04-26 20:01:22 +02001581 struct hci_ev_link_key_notify *ev = (void *) skb->data;
1582 struct hci_conn *conn;
1583
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001584 BT_DBG("%s", hdev->name);
Marcel Holtmann052b30b2009-04-26 20:01:22 +02001585
1586 hci_dev_lock(hdev);
1587
1588 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
1589 if (conn) {
1590 hci_conn_hold(conn);
1591 conn->disc_timeout = HCI_DISCONN_TIMEOUT;
1592 hci_conn_put(conn);
1593 }
1594
1595 hci_dev_unlock(hdev);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001596}
1597
Marcel Holtmann04837f62006-07-03 10:02:33 +02001598static inline void hci_clock_offset_evt(struct hci_dev *hdev, struct sk_buff *skb)
1599{
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001600 struct hci_ev_clock_offset *ev = (void *) skb->data;
Marcel Holtmann04837f62006-07-03 10:02:33 +02001601 struct hci_conn *conn;
1602
1603 BT_DBG("%s status %d", hdev->name, ev->status);
1604
1605 hci_dev_lock(hdev);
1606
1607 conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
Linus Torvalds1da177e2005-04-16 15:20:36 -07001608 if (conn && !ev->status) {
1609 struct inquiry_entry *ie;
1610
1611 if ((ie = hci_inquiry_cache_lookup(hdev, &conn->dst))) {
1612 ie->data.clock_offset = ev->clock_offset;
1613 ie->timestamp = jiffies;
1614 }
1615 }
1616
1617 hci_dev_unlock(hdev);
1618}
1619
Marcel Holtmanna8746412008-07-14 20:13:46 +02001620static inline void hci_pkt_type_change_evt(struct hci_dev *hdev, struct sk_buff *skb)
1621{
1622 struct hci_ev_pkt_type_change *ev = (void *) skb->data;
1623 struct hci_conn *conn;
1624
1625 BT_DBG("%s status %d", hdev->name, ev->status);
1626
1627 hci_dev_lock(hdev);
1628
1629 conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
1630 if (conn && !ev->status)
1631 conn->pkt_type = __le16_to_cpu(ev->pkt_type);
1632
1633 hci_dev_unlock(hdev);
1634}
1635
Marcel Holtmann85a1e932005-08-09 20:28:02 -07001636static inline void hci_pscan_rep_mode_evt(struct hci_dev *hdev, struct sk_buff *skb)
1637{
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001638 struct hci_ev_pscan_rep_mode *ev = (void *) skb->data;
Marcel Holtmann85a1e932005-08-09 20:28:02 -07001639 struct inquiry_entry *ie;
1640
1641 BT_DBG("%s", hdev->name);
1642
1643 hci_dev_lock(hdev);
1644
1645 if ((ie = hci_inquiry_cache_lookup(hdev, &ev->bdaddr))) {
1646 ie->data.pscan_rep_mode = ev->pscan_rep_mode;
1647 ie->timestamp = jiffies;
1648 }
1649
1650 hci_dev_unlock(hdev);
1651}
1652
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001653static inline void hci_inquiry_result_with_rssi_evt(struct hci_dev *hdev, struct sk_buff *skb)
1654{
1655 struct inquiry_data data;
1656 int num_rsp = *((__u8 *) skb->data);
1657
1658 BT_DBG("%s num_rsp %d", hdev->name, num_rsp);
1659
1660 if (!num_rsp)
1661 return;
1662
1663 hci_dev_lock(hdev);
1664
1665 if ((skb->len - 1) / num_rsp != sizeof(struct inquiry_info_with_rssi)) {
1666 struct inquiry_info_with_rssi_and_pscan_mode *info = (void *) (skb->data + 1);
1667
1668 for (; num_rsp; num_rsp--) {
1669 bacpy(&data.bdaddr, &info->bdaddr);
1670 data.pscan_rep_mode = info->pscan_rep_mode;
1671 data.pscan_period_mode = info->pscan_period_mode;
1672 data.pscan_mode = info->pscan_mode;
1673 memcpy(data.dev_class, info->dev_class, 3);
1674 data.clock_offset = info->clock_offset;
1675 data.rssi = info->rssi;
Marcel Holtmann41a96212008-07-14 20:13:48 +02001676 data.ssp_mode = 0x00;
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001677 info++;
1678 hci_inquiry_cache_update(hdev, &data);
1679 }
1680 } else {
1681 struct inquiry_info_with_rssi *info = (void *) (skb->data + 1);
1682
1683 for (; num_rsp; num_rsp--) {
1684 bacpy(&data.bdaddr, &info->bdaddr);
1685 data.pscan_rep_mode = info->pscan_rep_mode;
1686 data.pscan_period_mode = info->pscan_period_mode;
1687 data.pscan_mode = 0x00;
1688 memcpy(data.dev_class, info->dev_class, 3);
1689 data.clock_offset = info->clock_offset;
1690 data.rssi = info->rssi;
Marcel Holtmann41a96212008-07-14 20:13:48 +02001691 data.ssp_mode = 0x00;
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001692 info++;
1693 hci_inquiry_cache_update(hdev, &data);
1694 }
1695 }
1696
1697 hci_dev_unlock(hdev);
1698}
1699
1700static inline void hci_remote_ext_features_evt(struct hci_dev *hdev, struct sk_buff *skb)
1701{
Marcel Holtmann41a96212008-07-14 20:13:48 +02001702 struct hci_ev_remote_ext_features *ev = (void *) skb->data;
1703 struct hci_conn *conn;
1704
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001705 BT_DBG("%s", hdev->name);
Marcel Holtmann41a96212008-07-14 20:13:48 +02001706
Marcel Holtmann41a96212008-07-14 20:13:48 +02001707 hci_dev_lock(hdev);
1708
1709 conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
Johan Hedbergccd556f2010-11-10 17:11:51 +02001710 if (!conn)
1711 goto unlock;
Marcel Holtmann41a96212008-07-14 20:13:48 +02001712
Johan Hedbergccd556f2010-11-10 17:11:51 +02001713 if (!ev->status && ev->page == 0x01) {
1714 struct inquiry_entry *ie;
Marcel Holtmann41a96212008-07-14 20:13:48 +02001715
Johan Hedbergccd556f2010-11-10 17:11:51 +02001716 if ((ie = hci_inquiry_cache_lookup(hdev, &conn->dst)))
1717 ie->data.ssp_mode = (ev->features[0] & 0x01);
Marcel Holtmann769be972008-07-14 20:13:49 +02001718
Johan Hedbergccd556f2010-11-10 17:11:51 +02001719 conn->ssp_mode = (ev->features[0] & 0x01);
Marcel Holtmann41a96212008-07-14 20:13:48 +02001720 }
1721
Johan Hedbergccd556f2010-11-10 17:11:51 +02001722 if (conn->state != BT_CONFIG)
1723 goto unlock;
1724
Johan Hedberg127178d2010-11-18 22:22:29 +02001725 if (!ev->status) {
1726 struct hci_cp_remote_name_req cp;
1727 memset(&cp, 0, sizeof(cp));
1728 bacpy(&cp.bdaddr, &conn->dst);
1729 cp.pscan_rep_mode = 0x02;
1730 hci_send_cmd(hdev, HCI_OP_REMOTE_NAME_REQ, sizeof(cp), &cp);
1731 }
Johan Hedberg392599b2010-11-18 22:22:28 +02001732
Johan Hedberg127178d2010-11-18 22:22:29 +02001733 if (!hci_outgoing_auth_needed(hdev, conn)) {
Johan Hedbergccd556f2010-11-10 17:11:51 +02001734 conn->state = BT_CONNECTED;
1735 hci_proto_connect_cfm(conn, ev->status);
1736 hci_conn_put(conn);
1737 }
1738
1739unlock:
Marcel Holtmann41a96212008-07-14 20:13:48 +02001740 hci_dev_unlock(hdev);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001741}
1742
1743static inline void hci_sync_conn_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
1744{
Marcel Holtmannb6a0dc82007-10-20 14:55:10 +02001745 struct hci_ev_sync_conn_complete *ev = (void *) skb->data;
1746 struct hci_conn *conn;
1747
1748 BT_DBG("%s status %d", hdev->name, ev->status);
1749
1750 hci_dev_lock(hdev);
1751
1752 conn = hci_conn_hash_lookup_ba(hdev, ev->link_type, &ev->bdaddr);
Marcel Holtmann9dc0a3a2008-07-14 20:13:46 +02001753 if (!conn) {
1754 if (ev->link_type == ESCO_LINK)
1755 goto unlock;
1756
1757 conn = hci_conn_hash_lookup_ba(hdev, ESCO_LINK, &ev->bdaddr);
1758 if (!conn)
1759 goto unlock;
1760
1761 conn->type = SCO_LINK;
1762 }
Marcel Holtmannb6a0dc82007-10-20 14:55:10 +02001763
Marcel Holtmann732547f2009-04-19 19:14:14 +02001764 switch (ev->status) {
1765 case 0x00:
Marcel Holtmannb6a0dc82007-10-20 14:55:10 +02001766 conn->handle = __le16_to_cpu(ev->handle);
1767 conn->state = BT_CONNECTED;
Marcel Holtmann7d0db0a2008-07-14 20:13:51 +02001768
Marcel Holtmann9eba32b2009-08-22 14:19:26 -07001769 hci_conn_hold_device(conn);
Marcel Holtmann7d0db0a2008-07-14 20:13:51 +02001770 hci_conn_add_sysfs(conn);
Marcel Holtmann732547f2009-04-19 19:14:14 +02001771 break;
1772
Stephen Coe705e5712010-02-16 11:29:44 -05001773 case 0x11: /* Unsupported Feature or Parameter Value */
Marcel Holtmann732547f2009-04-19 19:14:14 +02001774 case 0x1c: /* SCO interval rejected */
Nick Pelly1038a002010-02-03 11:42:26 -08001775 case 0x1a: /* Unsupported Remote Feature */
Marcel Holtmann732547f2009-04-19 19:14:14 +02001776 case 0x1f: /* Unspecified error */
1777 if (conn->out && conn->attempt < 2) {
1778 conn->pkt_type = (hdev->esco_type & SCO_ESCO_MASK) |
1779 (hdev->esco_type & EDR_ESCO_MASK);
1780 hci_setup_sync(conn, conn->link->handle);
1781 goto unlock;
1782 }
1783 /* fall through */
1784
1785 default:
Marcel Holtmannb6a0dc82007-10-20 14:55:10 +02001786 conn->state = BT_CLOSED;
Marcel Holtmann732547f2009-04-19 19:14:14 +02001787 break;
1788 }
Marcel Holtmannb6a0dc82007-10-20 14:55:10 +02001789
1790 hci_proto_connect_cfm(conn, ev->status);
1791 if (ev->status)
1792 hci_conn_del(conn);
1793
1794unlock:
1795 hci_dev_unlock(hdev);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001796}
1797
1798static inline void hci_sync_conn_changed_evt(struct hci_dev *hdev, struct sk_buff *skb)
1799{
1800 BT_DBG("%s", hdev->name);
1801}
1802
Marcel Holtmann04837f62006-07-03 10:02:33 +02001803static inline void hci_sniff_subrate_evt(struct hci_dev *hdev, struct sk_buff *skb)
1804{
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001805 struct hci_ev_sniff_subrate *ev = (void *) skb->data;
Marcel Holtmann04837f62006-07-03 10:02:33 +02001806 struct hci_conn *conn;
1807
1808 BT_DBG("%s status %d", hdev->name, ev->status);
1809
1810 hci_dev_lock(hdev);
1811
1812 conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
1813 if (conn) {
1814 }
1815
1816 hci_dev_unlock(hdev);
1817}
1818
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001819static inline void hci_extended_inquiry_result_evt(struct hci_dev *hdev, struct sk_buff *skb)
1820{
1821 struct inquiry_data data;
1822 struct extended_inquiry_info *info = (void *) (skb->data + 1);
1823 int num_rsp = *((__u8 *) skb->data);
1824
1825 BT_DBG("%s num_rsp %d", hdev->name, num_rsp);
1826
1827 if (!num_rsp)
1828 return;
1829
1830 hci_dev_lock(hdev);
1831
1832 for (; num_rsp; num_rsp--) {
1833 bacpy(&data.bdaddr, &info->bdaddr);
1834 data.pscan_rep_mode = info->pscan_rep_mode;
1835 data.pscan_period_mode = info->pscan_period_mode;
1836 data.pscan_mode = 0x00;
1837 memcpy(data.dev_class, info->dev_class, 3);
1838 data.clock_offset = info->clock_offset;
1839 data.rssi = info->rssi;
Marcel Holtmann41a96212008-07-14 20:13:48 +02001840 data.ssp_mode = 0x01;
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001841 info++;
1842 hci_inquiry_cache_update(hdev, &data);
1843 }
1844
1845 hci_dev_unlock(hdev);
1846}
1847
Marcel Holtmann04936842008-07-14 20:13:48 +02001848static inline void hci_io_capa_request_evt(struct hci_dev *hdev, struct sk_buff *skb)
1849{
1850 struct hci_ev_io_capa_request *ev = (void *) skb->data;
1851 struct hci_conn *conn;
1852
1853 BT_DBG("%s", hdev->name);
1854
1855 hci_dev_lock(hdev);
1856
1857 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
1858 if (conn)
1859 hci_conn_hold(conn);
1860
1861 hci_dev_unlock(hdev);
1862}
1863
1864static inline void hci_simple_pair_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
1865{
1866 struct hci_ev_simple_pair_complete *ev = (void *) skb->data;
1867 struct hci_conn *conn;
1868
1869 BT_DBG("%s", hdev->name);
1870
1871 hci_dev_lock(hdev);
1872
1873 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
1874 if (conn)
1875 hci_conn_put(conn);
1876
1877 hci_dev_unlock(hdev);
1878}
1879
Marcel Holtmann41a96212008-07-14 20:13:48 +02001880static inline void hci_remote_host_features_evt(struct hci_dev *hdev, struct sk_buff *skb)
1881{
1882 struct hci_ev_remote_host_features *ev = (void *) skb->data;
1883 struct inquiry_entry *ie;
1884
1885 BT_DBG("%s", hdev->name);
1886
1887 hci_dev_lock(hdev);
1888
1889 if ((ie = hci_inquiry_cache_lookup(hdev, &ev->bdaddr)))
1890 ie->data.ssp_mode = (ev->features[0] & 0x01);
1891
1892 hci_dev_unlock(hdev);
1893}
1894
Linus Torvalds1da177e2005-04-16 15:20:36 -07001895void hci_event_packet(struct hci_dev *hdev, struct sk_buff *skb)
1896{
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001897 struct hci_event_hdr *hdr = (void *) skb->data;
1898 __u8 event = hdr->evt;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001899
1900 skb_pull(skb, HCI_EVENT_HDR_SIZE);
1901
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001902 switch (event) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001903 case HCI_EV_INQUIRY_COMPLETE:
1904 hci_inquiry_complete_evt(hdev, skb);
1905 break;
1906
1907 case HCI_EV_INQUIRY_RESULT:
1908 hci_inquiry_result_evt(hdev, skb);
1909 break;
1910
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001911 case HCI_EV_CONN_COMPLETE:
1912 hci_conn_complete_evt(hdev, skb);
Marcel Holtmann21d9e302005-09-13 01:32:25 +02001913 break;
1914
Linus Torvalds1da177e2005-04-16 15:20:36 -07001915 case HCI_EV_CONN_REQUEST:
1916 hci_conn_request_evt(hdev, skb);
1917 break;
1918
Linus Torvalds1da177e2005-04-16 15:20:36 -07001919 case HCI_EV_DISCONN_COMPLETE:
1920 hci_disconn_complete_evt(hdev, skb);
1921 break;
1922
Linus Torvalds1da177e2005-04-16 15:20:36 -07001923 case HCI_EV_AUTH_COMPLETE:
1924 hci_auth_complete_evt(hdev, skb);
1925 break;
1926
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001927 case HCI_EV_REMOTE_NAME:
1928 hci_remote_name_evt(hdev, skb);
1929 break;
1930
Linus Torvalds1da177e2005-04-16 15:20:36 -07001931 case HCI_EV_ENCRYPT_CHANGE:
1932 hci_encrypt_change_evt(hdev, skb);
1933 break;
1934
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001935 case HCI_EV_CHANGE_LINK_KEY_COMPLETE:
1936 hci_change_link_key_complete_evt(hdev, skb);
1937 break;
1938
1939 case HCI_EV_REMOTE_FEATURES:
1940 hci_remote_features_evt(hdev, skb);
1941 break;
1942
1943 case HCI_EV_REMOTE_VERSION:
1944 hci_remote_version_evt(hdev, skb);
1945 break;
1946
1947 case HCI_EV_QOS_SETUP_COMPLETE:
1948 hci_qos_setup_complete_evt(hdev, skb);
1949 break;
1950
1951 case HCI_EV_CMD_COMPLETE:
1952 hci_cmd_complete_evt(hdev, skb);
1953 break;
1954
1955 case HCI_EV_CMD_STATUS:
1956 hci_cmd_status_evt(hdev, skb);
1957 break;
1958
1959 case HCI_EV_ROLE_CHANGE:
1960 hci_role_change_evt(hdev, skb);
1961 break;
1962
1963 case HCI_EV_NUM_COMP_PKTS:
1964 hci_num_comp_pkts_evt(hdev, skb);
1965 break;
1966
1967 case HCI_EV_MODE_CHANGE:
1968 hci_mode_change_evt(hdev, skb);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001969 break;
1970
1971 case HCI_EV_PIN_CODE_REQ:
1972 hci_pin_code_request_evt(hdev, skb);
1973 break;
1974
1975 case HCI_EV_LINK_KEY_REQ:
1976 hci_link_key_request_evt(hdev, skb);
1977 break;
1978
1979 case HCI_EV_LINK_KEY_NOTIFY:
1980 hci_link_key_notify_evt(hdev, skb);
1981 break;
1982
1983 case HCI_EV_CLOCK_OFFSET:
1984 hci_clock_offset_evt(hdev, skb);
1985 break;
1986
Marcel Holtmanna8746412008-07-14 20:13:46 +02001987 case HCI_EV_PKT_TYPE_CHANGE:
1988 hci_pkt_type_change_evt(hdev, skb);
1989 break;
1990
Marcel Holtmann85a1e932005-08-09 20:28:02 -07001991 case HCI_EV_PSCAN_REP_MODE:
1992 hci_pscan_rep_mode_evt(hdev, skb);
1993 break;
1994
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001995 case HCI_EV_INQUIRY_RESULT_WITH_RSSI:
1996 hci_inquiry_result_with_rssi_evt(hdev, skb);
1997 break;
1998
1999 case HCI_EV_REMOTE_EXT_FEATURES:
2000 hci_remote_ext_features_evt(hdev, skb);
2001 break;
2002
2003 case HCI_EV_SYNC_CONN_COMPLETE:
2004 hci_sync_conn_complete_evt(hdev, skb);
2005 break;
2006
2007 case HCI_EV_SYNC_CONN_CHANGED:
2008 hci_sync_conn_changed_evt(hdev, skb);
2009 break;
2010
Marcel Holtmann04837f62006-07-03 10:02:33 +02002011 case HCI_EV_SNIFF_SUBRATE:
2012 hci_sniff_subrate_evt(hdev, skb);
2013 break;
2014
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002015 case HCI_EV_EXTENDED_INQUIRY_RESULT:
2016 hci_extended_inquiry_result_evt(hdev, skb);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002017 break;
2018
Marcel Holtmann04936842008-07-14 20:13:48 +02002019 case HCI_EV_IO_CAPA_REQUEST:
2020 hci_io_capa_request_evt(hdev, skb);
2021 break;
2022
2023 case HCI_EV_SIMPLE_PAIR_COMPLETE:
2024 hci_simple_pair_complete_evt(hdev, skb);
2025 break;
2026
Marcel Holtmann41a96212008-07-14 20:13:48 +02002027 case HCI_EV_REMOTE_HOST_FEATURES:
2028 hci_remote_host_features_evt(hdev, skb);
2029 break;
2030
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002031 default:
2032 BT_DBG("%s event 0x%x", hdev->name, event);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002033 break;
2034 }
2035
2036 kfree_skb(skb);
2037 hdev->stat.evt_rx++;
2038}
2039
2040/* Generate internal stack event */
2041void hci_si_event(struct hci_dev *hdev, int type, int dlen, void *data)
2042{
2043 struct hci_event_hdr *hdr;
2044 struct hci_ev_stack_internal *ev;
2045 struct sk_buff *skb;
2046
2047 skb = bt_skb_alloc(HCI_EVENT_HDR_SIZE + sizeof(*ev) + dlen, GFP_ATOMIC);
2048 if (!skb)
2049 return;
2050
2051 hdr = (void *) skb_put(skb, HCI_EVENT_HDR_SIZE);
2052 hdr->evt = HCI_EV_STACK_INTERNAL;
2053 hdr->plen = sizeof(*ev) + dlen;
2054
2055 ev = (void *) skb_put(skb, sizeof(*ev) + dlen);
2056 ev->type = type;
2057 memcpy(ev->data, data, dlen);
2058
Marcel Holtmann576c7d82005-08-06 12:36:54 +02002059 bt_cb(skb)->incoming = 1;
Patrick McHardya61bbcf2005-08-14 17:24:31 -07002060 __net_timestamp(skb);
Marcel Holtmann576c7d82005-08-06 12:36:54 +02002061
Marcel Holtmann0d48d932005-08-09 20:30:28 -07002062 bt_cb(skb)->pkt_type = HCI_EVENT_PKT;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002063 skb->dev = (void *) hdev;
2064 hci_send_to_sock(hdev, skb);
2065 kfree_skb(skb);
2066}