blob: cee46cbe7aebbd21591b7846213e8dc7b58d5541 [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
Johan Hedberg23bb5762010-12-21 23:01:27 +0200186 hci_req_complete(hdev, HCI_OP_RESET, status);
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200187}
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
Johan Hedberg23bb5762010-12-21 23:01:27 +0200238 hci_req_complete(hdev, HCI_OP_WRITE_AUTH_ENABLE, status);
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200239}
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
Johan Hedberg23bb5762010-12-21 23:01:27 +0200261 hci_req_complete(hdev, HCI_OP_WRITE_ENCRYPT_MODE, status);
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200262}
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);
Johan Hedberg9fbcbb42010-12-30 00:18:33 +0200277 int old_pscan, old_iscan;
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200278
Johan Hedberg9fbcbb42010-12-30 00:18:33 +0200279 old_pscan = test_and_clear_bit(HCI_PSCAN, &hdev->flags);
280 old_iscan = test_and_clear_bit(HCI_ISCAN, &hdev->flags);
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200281
Johan Hedberg73f22f62010-12-29 16:00:25 +0200282 if (param & SCAN_INQUIRY) {
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200283 set_bit(HCI_ISCAN, &hdev->flags);
Johan Hedberg9fbcbb42010-12-30 00:18:33 +0200284 if (!old_iscan)
285 mgmt_discoverable(hdev->id, 1);
286 } else if (old_iscan)
Johan Hedberg73f22f62010-12-29 16:00:25 +0200287 mgmt_discoverable(hdev->id, 0);
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200288
Johan Hedberg9fbcbb42010-12-30 00:18:33 +0200289 if (param & SCAN_PAGE) {
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200290 set_bit(HCI_PSCAN, &hdev->flags);
Johan Hedberg9fbcbb42010-12-30 00:18:33 +0200291 if (!old_pscan)
292 mgmt_connectable(hdev->id, 1);
293 } else if (old_pscan)
294 mgmt_connectable(hdev->id, 0);
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200295 }
296
Johan Hedberg23bb5762010-12-21 23:01:27 +0200297 hci_req_complete(hdev, HCI_OP_WRITE_SCAN_ENABLE, status);
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200298}
299
300static void hci_cc_read_class_of_dev(struct hci_dev *hdev, struct sk_buff *skb)
301{
302 struct hci_rp_read_class_of_dev *rp = (void *) skb->data;
303
304 BT_DBG("%s status 0x%x", hdev->name, rp->status);
305
306 if (rp->status)
307 return;
308
309 memcpy(hdev->dev_class, rp->dev_class, 3);
310
311 BT_DBG("%s class 0x%.2x%.2x%.2x", hdev->name,
312 hdev->dev_class[2], hdev->dev_class[1], hdev->dev_class[0]);
313}
314
315static void hci_cc_write_class_of_dev(struct hci_dev *hdev, struct sk_buff *skb)
316{
317 __u8 status = *((__u8 *) skb->data);
318 void *sent;
319
320 BT_DBG("%s status 0x%x", hdev->name, status);
321
Marcel Holtmannf383f272008-07-14 20:13:47 +0200322 if (status)
323 return;
324
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200325 sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_CLASS_OF_DEV);
326 if (!sent)
327 return;
328
Marcel Holtmannf383f272008-07-14 20:13:47 +0200329 memcpy(hdev->dev_class, sent, 3);
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200330}
331
332static void hci_cc_read_voice_setting(struct hci_dev *hdev, struct sk_buff *skb)
333{
334 struct hci_rp_read_voice_setting *rp = (void *) skb->data;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700335 __u16 setting;
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200336
337 BT_DBG("%s status 0x%x", hdev->name, rp->status);
338
339 if (rp->status)
340 return;
341
342 setting = __le16_to_cpu(rp->voice_setting);
343
Marcel Holtmannf383f272008-07-14 20:13:47 +0200344 if (hdev->voice_setting == setting)
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200345 return;
346
347 hdev->voice_setting = setting;
348
349 BT_DBG("%s voice setting 0x%04x", hdev->name, setting);
350
351 if (hdev->notify) {
352 tasklet_disable(&hdev->tx_task);
353 hdev->notify(hdev, HCI_NOTIFY_VOICE_SETTING);
354 tasklet_enable(&hdev->tx_task);
355 }
356}
357
358static void hci_cc_write_voice_setting(struct hci_dev *hdev, struct sk_buff *skb)
359{
360 __u8 status = *((__u8 *) skb->data);
Marcel Holtmannf383f272008-07-14 20:13:47 +0200361 __u16 setting;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700362 void *sent;
363
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200364 BT_DBG("%s status 0x%x", hdev->name, status);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700365
Marcel Holtmannf383f272008-07-14 20:13:47 +0200366 if (status)
367 return;
368
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200369 sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_VOICE_SETTING);
370 if (!sent)
371 return;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700372
Marcel Holtmannf383f272008-07-14 20:13:47 +0200373 setting = get_unaligned_le16(sent);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700374
Marcel Holtmannf383f272008-07-14 20:13:47 +0200375 if (hdev->voice_setting == setting)
376 return;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700377
Marcel Holtmannf383f272008-07-14 20:13:47 +0200378 hdev->voice_setting = setting;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700379
Marcel Holtmannf383f272008-07-14 20:13:47 +0200380 BT_DBG("%s voice setting 0x%04x", hdev->name, setting);
381
382 if (hdev->notify) {
383 tasklet_disable(&hdev->tx_task);
384 hdev->notify(hdev, HCI_NOTIFY_VOICE_SETTING);
385 tasklet_enable(&hdev->tx_task);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700386 }
387}
388
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200389static void hci_cc_host_buffer_size(struct hci_dev *hdev, struct sk_buff *skb)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700390{
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200391 __u8 status = *((__u8 *) skb->data);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700392
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200393 BT_DBG("%s status 0x%x", hdev->name, status);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700394
Johan Hedberg23bb5762010-12-21 23:01:27 +0200395 hci_req_complete(hdev, HCI_OP_HOST_BUFFER_SIZE, status);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700396}
397
Marcel Holtmann333140b2008-07-14 20:13:48 +0200398static void hci_cc_read_ssp_mode(struct hci_dev *hdev, struct sk_buff *skb)
399{
400 struct hci_rp_read_ssp_mode *rp = (void *) skb->data;
401
402 BT_DBG("%s status 0x%x", hdev->name, rp->status);
403
404 if (rp->status)
405 return;
406
407 hdev->ssp_mode = rp->mode;
408}
409
410static void hci_cc_write_ssp_mode(struct hci_dev *hdev, struct sk_buff *skb)
411{
412 __u8 status = *((__u8 *) skb->data);
413 void *sent;
414
415 BT_DBG("%s status 0x%x", hdev->name, status);
416
417 if (status)
418 return;
419
420 sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_SSP_MODE);
421 if (!sent)
422 return;
423
424 hdev->ssp_mode = *((__u8 *) sent);
425}
426
Johan Hedbergd5859e22011-01-25 01:19:58 +0200427static u8 hci_get_inquiry_mode(struct hci_dev *hdev)
428{
429 if (hdev->features[6] & LMP_EXT_INQ)
430 return 2;
431
432 if (hdev->features[3] & LMP_RSSI_INQ)
433 return 1;
434
435 if (hdev->manufacturer == 11 && hdev->hci_rev == 0x00 &&
436 hdev->lmp_subver == 0x0757)
437 return 1;
438
439 if (hdev->manufacturer == 15) {
440 if (hdev->hci_rev == 0x03 && hdev->lmp_subver == 0x6963)
441 return 1;
442 if (hdev->hci_rev == 0x09 && hdev->lmp_subver == 0x6963)
443 return 1;
444 if (hdev->hci_rev == 0x00 && hdev->lmp_subver == 0x6965)
445 return 1;
446 }
447
448 if (hdev->manufacturer == 31 && hdev->hci_rev == 0x2005 &&
449 hdev->lmp_subver == 0x1805)
450 return 1;
451
452 return 0;
453}
454
455static void hci_setup_inquiry_mode(struct hci_dev *hdev)
456{
457 u8 mode;
458
459 mode = hci_get_inquiry_mode(hdev);
460
461 hci_send_cmd(hdev, HCI_OP_WRITE_INQUIRY_MODE, 1, &mode);
462}
463
464static void hci_setup_event_mask(struct hci_dev *hdev)
465{
466 /* The second byte is 0xff instead of 0x9f (two reserved bits
467 * disabled) since a Broadcom 1.2 dongle doesn't respond to the
468 * command otherwise */
469 u8 events[8] = { 0xff, 0xff, 0xfb, 0xff, 0x00, 0x00, 0x00, 0x00 };
470
471 /* Events for 1.2 and newer controllers */
472 if (hdev->lmp_ver > 1) {
473 events[4] |= 0x01; /* Flow Specification Complete */
474 events[4] |= 0x02; /* Inquiry Result with RSSI */
475 events[4] |= 0x04; /* Read Remote Extended Features Complete */
476 events[5] |= 0x08; /* Synchronous Connection Complete */
477 events[5] |= 0x10; /* Synchronous Connection Changed */
478 }
479
480 if (hdev->features[3] & LMP_RSSI_INQ)
481 events[4] |= 0x04; /* Inquiry Result with RSSI */
482
483 if (hdev->features[5] & LMP_SNIFF_SUBR)
484 events[5] |= 0x20; /* Sniff Subrating */
485
486 if (hdev->features[5] & LMP_PAUSE_ENC)
487 events[5] |= 0x80; /* Encryption Key Refresh Complete */
488
489 if (hdev->features[6] & LMP_EXT_INQ)
490 events[5] |= 0x40; /* Extended Inquiry Result */
491
492 if (hdev->features[6] & LMP_NO_FLUSH)
493 events[7] |= 0x01; /* Enhanced Flush Complete */
494
495 if (hdev->features[7] & LMP_LSTO)
496 events[6] |= 0x80; /* Link Supervision Timeout Changed */
497
498 if (hdev->features[6] & LMP_SIMPLE_PAIR) {
499 events[6] |= 0x01; /* IO Capability Request */
500 events[6] |= 0x02; /* IO Capability Response */
501 events[6] |= 0x04; /* User Confirmation Request */
502 events[6] |= 0x08; /* User Passkey Request */
503 events[6] |= 0x10; /* Remote OOB Data Request */
504 events[6] |= 0x20; /* Simple Pairing Complete */
505 events[7] |= 0x04; /* User Passkey Notification */
506 events[7] |= 0x08; /* Keypress Notification */
507 events[7] |= 0x10; /* Remote Host Supported
508 * Features Notification */
509 }
510
511 if (hdev->features[4] & LMP_LE)
512 events[7] |= 0x20; /* LE Meta-Event */
513
514 hci_send_cmd(hdev, HCI_OP_SET_EVENT_MASK, sizeof(events), events);
515}
516
517static void hci_setup(struct hci_dev *hdev)
518{
519 hci_setup_event_mask(hdev);
520
521 if (hdev->lmp_ver > 1)
522 hci_send_cmd(hdev, HCI_OP_READ_LOCAL_COMMANDS, 0, NULL);
523
524 if (hdev->features[6] & LMP_SIMPLE_PAIR) {
525 u8 mode = 0x01;
526 hci_send_cmd(hdev, HCI_OP_WRITE_SSP_MODE, sizeof(mode), &mode);
527 }
528
529 if (hdev->features[3] & LMP_RSSI_INQ)
530 hci_setup_inquiry_mode(hdev);
531
532 if (hdev->features[7] & LMP_INQ_TX_PWR)
533 hci_send_cmd(hdev, HCI_OP_READ_INQ_RSP_TX_POWER, 0, NULL);
534}
535
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200536static void hci_cc_read_local_version(struct hci_dev *hdev, struct sk_buff *skb)
537{
538 struct hci_rp_read_local_version *rp = (void *) skb->data;
539
540 BT_DBG("%s status 0x%x", hdev->name, rp->status);
541
542 if (rp->status)
543 return;
544
545 hdev->hci_ver = rp->hci_ver;
Marcel Holtmanne4e8e372008-07-14 20:13:47 +0200546 hdev->hci_rev = __le16_to_cpu(rp->hci_rev);
Johan Hedbergd5859e22011-01-25 01:19:58 +0200547 hdev->lmp_ver = rp->lmp_ver;
Marcel Holtmanne4e8e372008-07-14 20:13:47 +0200548 hdev->manufacturer = __le16_to_cpu(rp->manufacturer);
Johan Hedbergd5859e22011-01-25 01:19:58 +0200549 hdev->lmp_subver = __le16_to_cpu(rp->lmp_subver);
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200550
551 BT_DBG("%s manufacturer %d hci ver %d:%d", hdev->name,
552 hdev->manufacturer,
553 hdev->hci_ver, hdev->hci_rev);
Johan Hedbergd5859e22011-01-25 01:19:58 +0200554
555 if (test_bit(HCI_INIT, &hdev->flags))
556 hci_setup(hdev);
557}
558
559static void hci_setup_link_policy(struct hci_dev *hdev)
560{
561 u16 link_policy = 0;
562
563 if (hdev->features[0] & LMP_RSWITCH)
564 link_policy |= HCI_LP_RSWITCH;
565 if (hdev->features[0] & LMP_HOLD)
566 link_policy |= HCI_LP_HOLD;
567 if (hdev->features[0] & LMP_SNIFF)
568 link_policy |= HCI_LP_SNIFF;
569 if (hdev->features[1] & LMP_PARK)
570 link_policy |= HCI_LP_PARK;
571
572 link_policy = cpu_to_le16(link_policy);
573 hci_send_cmd(hdev, HCI_OP_WRITE_DEF_LINK_POLICY,
574 sizeof(link_policy), &link_policy);
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200575}
576
577static void hci_cc_read_local_commands(struct hci_dev *hdev, struct sk_buff *skb)
578{
579 struct hci_rp_read_local_commands *rp = (void *) skb->data;
580
581 BT_DBG("%s status 0x%x", hdev->name, rp->status);
582
583 if (rp->status)
Johan Hedbergd5859e22011-01-25 01:19:58 +0200584 goto done;
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200585
586 memcpy(hdev->commands, rp->commands, sizeof(hdev->commands));
Johan Hedbergd5859e22011-01-25 01:19:58 +0200587
588 if (test_bit(HCI_INIT, &hdev->flags) && (hdev->commands[5] & 0x10))
589 hci_setup_link_policy(hdev);
590
591done:
592 hci_req_complete(hdev, HCI_OP_READ_LOCAL_COMMANDS, rp->status);
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200593}
594
595static void hci_cc_read_local_features(struct hci_dev *hdev, struct sk_buff *skb)
596{
597 struct hci_rp_read_local_features *rp = (void *) skb->data;
598
599 BT_DBG("%s status 0x%x", hdev->name, rp->status);
600
601 if (rp->status)
602 return;
603
604 memcpy(hdev->features, rp->features, 8);
605
606 /* Adjust default settings according to features
607 * supported by device. */
608
609 if (hdev->features[0] & LMP_3SLOT)
610 hdev->pkt_type |= (HCI_DM3 | HCI_DH3);
611
612 if (hdev->features[0] & LMP_5SLOT)
613 hdev->pkt_type |= (HCI_DM5 | HCI_DH5);
614
615 if (hdev->features[1] & LMP_HV2) {
616 hdev->pkt_type |= (HCI_HV2);
617 hdev->esco_type |= (ESCO_HV2);
618 }
619
620 if (hdev->features[1] & LMP_HV3) {
621 hdev->pkt_type |= (HCI_HV3);
622 hdev->esco_type |= (ESCO_HV3);
623 }
624
625 if (hdev->features[3] & LMP_ESCO)
626 hdev->esco_type |= (ESCO_EV3);
627
628 if (hdev->features[4] & LMP_EV4)
629 hdev->esco_type |= (ESCO_EV4);
630
631 if (hdev->features[4] & LMP_EV5)
632 hdev->esco_type |= (ESCO_EV5);
633
Marcel Holtmannefc76882009-02-06 09:13:37 +0100634 if (hdev->features[5] & LMP_EDR_ESCO_2M)
635 hdev->esco_type |= (ESCO_2EV3);
636
637 if (hdev->features[5] & LMP_EDR_ESCO_3M)
638 hdev->esco_type |= (ESCO_3EV3);
639
640 if (hdev->features[5] & LMP_EDR_3S_ESCO)
641 hdev->esco_type |= (ESCO_2EV5 | ESCO_3EV5);
642
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200643 BT_DBG("%s features 0x%.2x%.2x%.2x%.2x%.2x%.2x%.2x%.2x", hdev->name,
644 hdev->features[0], hdev->features[1],
645 hdev->features[2], hdev->features[3],
646 hdev->features[4], hdev->features[5],
647 hdev->features[6], hdev->features[7]);
648}
649
650static void hci_cc_read_buffer_size(struct hci_dev *hdev, struct sk_buff *skb)
651{
652 struct hci_rp_read_buffer_size *rp = (void *) skb->data;
653
654 BT_DBG("%s status 0x%x", hdev->name, rp->status);
655
656 if (rp->status)
657 return;
658
659 hdev->acl_mtu = __le16_to_cpu(rp->acl_mtu);
660 hdev->sco_mtu = rp->sco_mtu;
661 hdev->acl_pkts = __le16_to_cpu(rp->acl_max_pkt);
662 hdev->sco_pkts = __le16_to_cpu(rp->sco_max_pkt);
663
664 if (test_bit(HCI_QUIRK_FIXUP_BUFFER_SIZE, &hdev->quirks)) {
665 hdev->sco_mtu = 64;
666 hdev->sco_pkts = 8;
667 }
668
669 hdev->acl_cnt = hdev->acl_pkts;
670 hdev->sco_cnt = hdev->sco_pkts;
671
672 BT_DBG("%s acl mtu %d:%d sco mtu %d:%d", hdev->name,
673 hdev->acl_mtu, hdev->acl_pkts,
674 hdev->sco_mtu, hdev->sco_pkts);
675}
676
677static void hci_cc_read_bd_addr(struct hci_dev *hdev, struct sk_buff *skb)
678{
679 struct hci_rp_read_bd_addr *rp = (void *) skb->data;
680
681 BT_DBG("%s status 0x%x", hdev->name, rp->status);
682
683 if (!rp->status)
684 bacpy(&hdev->bdaddr, &rp->bdaddr);
685
Johan Hedberg23bb5762010-12-21 23:01:27 +0200686 hci_req_complete(hdev, HCI_OP_READ_BD_ADDR, rp->status);
687}
688
689static void hci_cc_write_ca_timeout(struct hci_dev *hdev, struct sk_buff *skb)
690{
691 __u8 status = *((__u8 *) skb->data);
692
693 BT_DBG("%s status 0x%x", hdev->name, status);
694
695 hci_req_complete(hdev, HCI_OP_WRITE_CA_TIMEOUT, status);
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200696}
697
Johan Hedbergb0916ea2011-01-10 13:44:55 +0200698static void hci_cc_delete_stored_link_key(struct hci_dev *hdev,
699 struct sk_buff *skb)
700{
701 __u8 status = *((__u8 *) skb->data);
702
703 BT_DBG("%s status 0x%x", hdev->name, status);
704
705 hci_req_complete(hdev, HCI_OP_DELETE_STORED_LINK_KEY, status);
706}
707
Johan Hedbergd5859e22011-01-25 01:19:58 +0200708static void hci_cc_set_event_mask(struct hci_dev *hdev, struct sk_buff *skb)
709{
710 __u8 status = *((__u8 *) skb->data);
711
712 BT_DBG("%s status 0x%x", hdev->name, status);
713
714 hci_req_complete(hdev, HCI_OP_SET_EVENT_MASK, status);
715}
716
717static void hci_cc_write_inquiry_mode(struct hci_dev *hdev,
718 struct sk_buff *skb)
719{
720 __u8 status = *((__u8 *) skb->data);
721
722 BT_DBG("%s status 0x%x", hdev->name, status);
723
724 hci_req_complete(hdev, HCI_OP_WRITE_INQUIRY_MODE, status);
725}
726
727static void hci_cc_read_inq_rsp_tx_power(struct hci_dev *hdev,
728 struct sk_buff *skb)
729{
730 __u8 status = *((__u8 *) skb->data);
731
732 BT_DBG("%s status 0x%x", hdev->name, status);
733
734 hci_req_complete(hdev, HCI_OP_READ_INQ_RSP_TX_POWER, status);
735}
736
737static void hci_cc_set_event_flt(struct hci_dev *hdev, struct sk_buff *skb)
738{
739 __u8 status = *((__u8 *) skb->data);
740
741 BT_DBG("%s status 0x%x", hdev->name, status);
742
743 hci_req_complete(hdev, HCI_OP_SET_EVENT_FLT, status);
744}
745
Johan Hedberg980e1a52011-01-22 06:10:07 +0200746static void hci_cc_pin_code_reply(struct hci_dev *hdev, struct sk_buff *skb)
747{
748 struct hci_rp_pin_code_reply *rp = (void *) skb->data;
749 struct hci_cp_pin_code_reply *cp;
750 struct hci_conn *conn;
751
752 BT_DBG("%s status 0x%x", hdev->name, rp->status);
753
754 if (test_bit(HCI_MGMT, &hdev->flags))
755 mgmt_pin_code_reply_complete(hdev->id, &rp->bdaddr, rp->status);
756
757 if (rp->status != 0)
758 return;
759
760 cp = hci_sent_cmd_data(hdev, HCI_OP_PIN_CODE_REPLY);
761 if (!cp)
762 return;
763
764 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &cp->bdaddr);
765 if (conn)
766 conn->pin_length = cp->pin_len;
767}
768
769static void hci_cc_pin_code_neg_reply(struct hci_dev *hdev, struct sk_buff *skb)
770{
771 struct hci_rp_pin_code_neg_reply *rp = (void *) skb->data;
772
773 BT_DBG("%s status 0x%x", hdev->name, rp->status);
774
775 if (test_bit(HCI_MGMT, &hdev->flags))
776 mgmt_pin_code_neg_reply_complete(hdev->id, &rp->bdaddr,
777 rp->status);
778}
779
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200780static inline void hci_cs_inquiry(struct hci_dev *hdev, __u8 status)
781{
782 BT_DBG("%s status 0x%x", hdev->name, status);
783
784 if (status) {
Johan Hedberg23bb5762010-12-21 23:01:27 +0200785 hci_req_complete(hdev, HCI_OP_INQUIRY, status);
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200786
787 hci_conn_check_pending(hdev);
788 } else
789 set_bit(HCI_INQUIRY, &hdev->flags);
790}
791
Linus Torvalds1da177e2005-04-16 15:20:36 -0700792static inline void hci_cs_create_conn(struct hci_dev *hdev, __u8 status)
793{
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200794 struct hci_cp_create_conn *cp;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700795 struct hci_conn *conn;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700796
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200797 BT_DBG("%s status 0x%x", hdev->name, status);
798
799 cp = hci_sent_cmd_data(hdev, HCI_OP_CREATE_CONN);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700800 if (!cp)
801 return;
802
803 hci_dev_lock(hdev);
804
805 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &cp->bdaddr);
806
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200807 BT_DBG("%s bdaddr %s conn %p", hdev->name, batostr(&cp->bdaddr), conn);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700808
809 if (status) {
810 if (conn && conn->state == BT_CONNECT) {
Marcel Holtmann4c67bc72006-10-15 17:30:56 +0200811 if (status != 0x0c || conn->attempt > 2) {
812 conn->state = BT_CLOSED;
813 hci_proto_connect_cfm(conn, status);
814 hci_conn_del(conn);
815 } else
816 conn->state = BT_CONNECT2;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700817 }
818 } else {
819 if (!conn) {
820 conn = hci_conn_add(hdev, ACL_LINK, &cp->bdaddr);
821 if (conn) {
822 conn->out = 1;
823 conn->link_mode |= HCI_LM_MASTER;
824 } else
Gustavo F. Padovan893ef972010-07-18 15:13:37 -0300825 BT_ERR("No memory for new connection");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700826 }
827 }
828
829 hci_dev_unlock(hdev);
830}
831
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200832static void hci_cs_add_sco(struct hci_dev *hdev, __u8 status)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700833{
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200834 struct hci_cp_add_sco *cp;
835 struct hci_conn *acl, *sco;
836 __u16 handle;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700837
Marcel Holtmannb6a0dc82007-10-20 14:55:10 +0200838 BT_DBG("%s status 0x%x", hdev->name, status);
839
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200840 if (!status)
841 return;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700842
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200843 cp = hci_sent_cmd_data(hdev, HCI_OP_ADD_SCO);
844 if (!cp)
845 return;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700846
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200847 handle = __le16_to_cpu(cp->handle);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700848
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200849 BT_DBG("%s handle %d", hdev->name, handle);
Marcel Holtmann6bd57412006-11-18 22:14:22 +0100850
851 hci_dev_lock(hdev);
852
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200853 acl = hci_conn_hash_lookup_handle(hdev, handle);
Andrei Emeltchenko5a08ecc2011-01-11 17:20:20 +0200854 if (acl) {
855 sco = acl->link;
856 if (sco) {
857 sco->state = BT_CLOSED;
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200858
Andrei Emeltchenko5a08ecc2011-01-11 17:20:20 +0200859 hci_proto_connect_cfm(sco, status);
860 hci_conn_del(sco);
861 }
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200862 }
Marcel Holtmann6bd57412006-11-18 22:14:22 +0100863
864 hci_dev_unlock(hdev);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700865}
866
Marcel Holtmannf8558552008-07-14 20:13:49 +0200867static void hci_cs_auth_requested(struct hci_dev *hdev, __u8 status)
868{
869 struct hci_cp_auth_requested *cp;
870 struct hci_conn *conn;
871
872 BT_DBG("%s status 0x%x", hdev->name, status);
873
874 if (!status)
875 return;
876
877 cp = hci_sent_cmd_data(hdev, HCI_OP_AUTH_REQUESTED);
878 if (!cp)
879 return;
880
881 hci_dev_lock(hdev);
882
883 conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(cp->handle));
884 if (conn) {
885 if (conn->state == BT_CONFIG) {
886 hci_proto_connect_cfm(conn, status);
887 hci_conn_put(conn);
888 }
889 }
890
891 hci_dev_unlock(hdev);
892}
893
894static void hci_cs_set_conn_encrypt(struct hci_dev *hdev, __u8 status)
895{
896 struct hci_cp_set_conn_encrypt *cp;
897 struct hci_conn *conn;
898
899 BT_DBG("%s status 0x%x", hdev->name, status);
900
901 if (!status)
902 return;
903
904 cp = hci_sent_cmd_data(hdev, HCI_OP_SET_CONN_ENCRYPT);
905 if (!cp)
906 return;
907
908 hci_dev_lock(hdev);
909
910 conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(cp->handle));
911 if (conn) {
912 if (conn->state == BT_CONFIG) {
913 hci_proto_connect_cfm(conn, status);
914 hci_conn_put(conn);
915 }
916 }
917
918 hci_dev_unlock(hdev);
919}
920
Johan Hedberg127178d2010-11-18 22:22:29 +0200921static int hci_outgoing_auth_needed(struct hci_dev *hdev,
Johan Hedberg392599b2010-11-18 22:22:28 +0200922 struct hci_conn *conn)
923{
Johan Hedberg392599b2010-11-18 22:22:28 +0200924 if (conn->state != BT_CONFIG || !conn->out)
925 return 0;
926
Johan Hedberg765c2a92011-01-19 12:06:52 +0530927 if (conn->pending_sec_level == BT_SECURITY_SDP)
Johan Hedberg392599b2010-11-18 22:22:28 +0200928 return 0;
929
930 /* Only request authentication for SSP connections or non-SSP
931 * devices with sec_level HIGH */
932 if (!(hdev->ssp_mode > 0 && conn->ssp_mode > 0) &&
Johan Hedberg765c2a92011-01-19 12:06:52 +0530933 conn->pending_sec_level != BT_SECURITY_HIGH)
Johan Hedberg392599b2010-11-18 22:22:28 +0200934 return 0;
935
Johan Hedberg392599b2010-11-18 22:22:28 +0200936 return 1;
937}
938
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200939static void hci_cs_remote_name_req(struct hci_dev *hdev, __u8 status)
940{
Johan Hedberg127178d2010-11-18 22:22:29 +0200941 struct hci_cp_remote_name_req *cp;
942 struct hci_conn *conn;
943
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200944 BT_DBG("%s status 0x%x", hdev->name, status);
Johan Hedberg127178d2010-11-18 22:22:29 +0200945
946 /* If successful wait for the name req complete event before
947 * checking for the need to do authentication */
948 if (!status)
949 return;
950
951 cp = hci_sent_cmd_data(hdev, HCI_OP_REMOTE_NAME_REQ);
952 if (!cp)
953 return;
954
955 hci_dev_lock(hdev);
956
957 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &cp->bdaddr);
958 if (conn && hci_outgoing_auth_needed(hdev, conn)) {
959 struct hci_cp_auth_requested cp;
960 cp.handle = __cpu_to_le16(conn->handle);
961 hci_send_cmd(hdev, HCI_OP_AUTH_REQUESTED, sizeof(cp), &cp);
962 }
963
964 hci_dev_unlock(hdev);
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200965}
966
Marcel Holtmann769be972008-07-14 20:13:49 +0200967static void hci_cs_read_remote_features(struct hci_dev *hdev, __u8 status)
968{
969 struct hci_cp_read_remote_features *cp;
970 struct hci_conn *conn;
971
972 BT_DBG("%s status 0x%x", hdev->name, status);
973
974 if (!status)
975 return;
976
977 cp = hci_sent_cmd_data(hdev, HCI_OP_READ_REMOTE_FEATURES);
978 if (!cp)
979 return;
980
981 hci_dev_lock(hdev);
982
983 conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(cp->handle));
984 if (conn) {
985 if (conn->state == BT_CONFIG) {
Marcel Holtmann769be972008-07-14 20:13:49 +0200986 hci_proto_connect_cfm(conn, status);
987 hci_conn_put(conn);
988 }
989 }
990
991 hci_dev_unlock(hdev);
992}
993
994static void hci_cs_read_remote_ext_features(struct hci_dev *hdev, __u8 status)
995{
996 struct hci_cp_read_remote_ext_features *cp;
997 struct hci_conn *conn;
998
999 BT_DBG("%s status 0x%x", hdev->name, status);
1000
1001 if (!status)
1002 return;
1003
1004 cp = hci_sent_cmd_data(hdev, HCI_OP_READ_REMOTE_EXT_FEATURES);
1005 if (!cp)
1006 return;
1007
1008 hci_dev_lock(hdev);
1009
1010 conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(cp->handle));
1011 if (conn) {
1012 if (conn->state == BT_CONFIG) {
Marcel Holtmann769be972008-07-14 20:13:49 +02001013 hci_proto_connect_cfm(conn, status);
1014 hci_conn_put(conn);
1015 }
1016 }
1017
1018 hci_dev_unlock(hdev);
1019}
1020
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001021static void hci_cs_setup_sync_conn(struct hci_dev *hdev, __u8 status)
1022{
Marcel Holtmannb6a0dc82007-10-20 14:55:10 +02001023 struct hci_cp_setup_sync_conn *cp;
1024 struct hci_conn *acl, *sco;
1025 __u16 handle;
1026
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001027 BT_DBG("%s status 0x%x", hdev->name, status);
Marcel Holtmannb6a0dc82007-10-20 14:55:10 +02001028
1029 if (!status)
1030 return;
1031
1032 cp = hci_sent_cmd_data(hdev, HCI_OP_SETUP_SYNC_CONN);
1033 if (!cp)
1034 return;
1035
1036 handle = __le16_to_cpu(cp->handle);
1037
1038 BT_DBG("%s handle %d", hdev->name, handle);
1039
1040 hci_dev_lock(hdev);
1041
1042 acl = hci_conn_hash_lookup_handle(hdev, handle);
Andrei Emeltchenko5a08ecc2011-01-11 17:20:20 +02001043 if (acl) {
1044 sco = acl->link;
1045 if (sco) {
1046 sco->state = BT_CLOSED;
Marcel Holtmannb6a0dc82007-10-20 14:55:10 +02001047
Andrei Emeltchenko5a08ecc2011-01-11 17:20:20 +02001048 hci_proto_connect_cfm(sco, status);
1049 hci_conn_del(sco);
1050 }
Marcel Holtmannb6a0dc82007-10-20 14:55:10 +02001051 }
1052
1053 hci_dev_unlock(hdev);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001054}
1055
1056static void hci_cs_sniff_mode(struct hci_dev *hdev, __u8 status)
1057{
1058 struct hci_cp_sniff_mode *cp;
1059 struct hci_conn *conn;
1060
1061 BT_DBG("%s status 0x%x", hdev->name, status);
1062
1063 if (!status)
1064 return;
1065
1066 cp = hci_sent_cmd_data(hdev, HCI_OP_SNIFF_MODE);
1067 if (!cp)
1068 return;
1069
1070 hci_dev_lock(hdev);
1071
1072 conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(cp->handle));
Marcel Holtmanne73439d2010-07-26 10:06:00 -04001073 if (conn) {
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001074 clear_bit(HCI_CONN_MODE_CHANGE_PEND, &conn->pend);
1075
Marcel Holtmanne73439d2010-07-26 10:06:00 -04001076 if (test_and_clear_bit(HCI_CONN_SCO_SETUP_PEND, &conn->pend))
1077 hci_sco_setup(conn, status);
1078 }
1079
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001080 hci_dev_unlock(hdev);
1081}
1082
1083static void hci_cs_exit_sniff_mode(struct hci_dev *hdev, __u8 status)
1084{
1085 struct hci_cp_exit_sniff_mode *cp;
1086 struct hci_conn *conn;
1087
1088 BT_DBG("%s status 0x%x", hdev->name, status);
1089
1090 if (!status)
1091 return;
1092
1093 cp = hci_sent_cmd_data(hdev, HCI_OP_EXIT_SNIFF_MODE);
1094 if (!cp)
1095 return;
1096
1097 hci_dev_lock(hdev);
1098
1099 conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(cp->handle));
Marcel Holtmanne73439d2010-07-26 10:06:00 -04001100 if (conn) {
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001101 clear_bit(HCI_CONN_MODE_CHANGE_PEND, &conn->pend);
1102
Marcel Holtmanne73439d2010-07-26 10:06:00 -04001103 if (test_and_clear_bit(HCI_CONN_SCO_SETUP_PEND, &conn->pend))
1104 hci_sco_setup(conn, status);
1105 }
1106
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001107 hci_dev_unlock(hdev);
1108}
1109
1110static inline void hci_inquiry_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
1111{
1112 __u8 status = *((__u8 *) skb->data);
1113
1114 BT_DBG("%s status %d", hdev->name, status);
1115
1116 clear_bit(HCI_INQUIRY, &hdev->flags);
1117
Johan Hedberg23bb5762010-12-21 23:01:27 +02001118 hci_req_complete(hdev, HCI_OP_INQUIRY, status);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001119
1120 hci_conn_check_pending(hdev);
1121}
1122
Linus Torvalds1da177e2005-04-16 15:20:36 -07001123static inline void hci_inquiry_result_evt(struct hci_dev *hdev, struct sk_buff *skb)
1124{
Marcel Holtmann45bb4bf2005-08-09 20:27:49 -07001125 struct inquiry_data data;
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001126 struct inquiry_info *info = (void *) (skb->data + 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001127 int num_rsp = *((__u8 *) skb->data);
1128
1129 BT_DBG("%s num_rsp %d", hdev->name, num_rsp);
1130
Marcel Holtmann45bb4bf2005-08-09 20:27:49 -07001131 if (!num_rsp)
1132 return;
1133
Linus Torvalds1da177e2005-04-16 15:20:36 -07001134 hci_dev_lock(hdev);
Marcel Holtmann45bb4bf2005-08-09 20:27:49 -07001135
Linus Torvalds1da177e2005-04-16 15:20:36 -07001136 for (; num_rsp; num_rsp--) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001137 bacpy(&data.bdaddr, &info->bdaddr);
1138 data.pscan_rep_mode = info->pscan_rep_mode;
1139 data.pscan_period_mode = info->pscan_period_mode;
1140 data.pscan_mode = info->pscan_mode;
1141 memcpy(data.dev_class, info->dev_class, 3);
1142 data.clock_offset = info->clock_offset;
1143 data.rssi = 0x00;
Marcel Holtmann41a96212008-07-14 20:13:48 +02001144 data.ssp_mode = 0x00;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001145 info++;
1146 hci_inquiry_cache_update(hdev, &data);
1147 }
Marcel Holtmann45bb4bf2005-08-09 20:27:49 -07001148
Linus Torvalds1da177e2005-04-16 15:20:36 -07001149 hci_dev_unlock(hdev);
1150}
1151
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001152static inline void hci_conn_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001153{
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001154 struct hci_ev_conn_complete *ev = (void *) skb->data;
1155 struct hci_conn *conn;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001156
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001157 BT_DBG("%s", hdev->name);
Marcel Holtmann45bb4bf2005-08-09 20:27:49 -07001158
Linus Torvalds1da177e2005-04-16 15:20:36 -07001159 hci_dev_lock(hdev);
Marcel Holtmann45bb4bf2005-08-09 20:27:49 -07001160
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001161 conn = hci_conn_hash_lookup_ba(hdev, ev->link_type, &ev->bdaddr);
Marcel Holtmann94992372009-04-19 19:30:03 +02001162 if (!conn) {
1163 if (ev->link_type != SCO_LINK)
1164 goto unlock;
1165
1166 conn = hci_conn_hash_lookup_ba(hdev, ESCO_LINK, &ev->bdaddr);
1167 if (!conn)
1168 goto unlock;
1169
1170 conn->type = SCO_LINK;
1171 }
Marcel Holtmann45bb4bf2005-08-09 20:27:49 -07001172
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001173 if (!ev->status) {
1174 conn->handle = __le16_to_cpu(ev->handle);
Marcel Holtmann769be972008-07-14 20:13:49 +02001175
1176 if (conn->type == ACL_LINK) {
1177 conn->state = BT_CONFIG;
1178 hci_conn_hold(conn);
Marcel Holtmann052b30b2009-04-26 20:01:22 +02001179 conn->disc_timeout = HCI_DISCONN_TIMEOUT;
Johan Hedbergf7520542011-01-20 12:34:39 +02001180 mgmt_connected(hdev->id, &ev->bdaddr);
Marcel Holtmann769be972008-07-14 20:13:49 +02001181 } else
1182 conn->state = BT_CONNECTED;
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001183
Marcel Holtmann9eba32b2009-08-22 14:19:26 -07001184 hci_conn_hold_device(conn);
Marcel Holtmann7d0db0a2008-07-14 20:13:51 +02001185 hci_conn_add_sysfs(conn);
1186
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001187 if (test_bit(HCI_AUTH, &hdev->flags))
1188 conn->link_mode |= HCI_LM_AUTH;
1189
1190 if (test_bit(HCI_ENCRYPT, &hdev->flags))
1191 conn->link_mode |= HCI_LM_ENCRYPT;
1192
1193 /* Get remote features */
1194 if (conn->type == ACL_LINK) {
1195 struct hci_cp_read_remote_features cp;
1196 cp.handle = ev->handle;
Marcel Holtmann769be972008-07-14 20:13:49 +02001197 hci_send_cmd(hdev, HCI_OP_READ_REMOTE_FEATURES,
1198 sizeof(cp), &cp);
Marcel Holtmann45bb4bf2005-08-09 20:27:49 -07001199 }
Marcel Holtmann45bb4bf2005-08-09 20:27:49 -07001200
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001201 /* Set packet type for incoming connection */
Marcel Holtmanna8746412008-07-14 20:13:46 +02001202 if (!conn->out && hdev->hci_ver < 3) {
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001203 struct hci_cp_change_conn_ptype cp;
1204 cp.handle = ev->handle;
Marcel Holtmanna8746412008-07-14 20:13:46 +02001205 cp.pkt_type = cpu_to_le16(conn->pkt_type);
1206 hci_send_cmd(hdev, HCI_OP_CHANGE_CONN_PTYPE,
1207 sizeof(cp), &cp);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001208 }
Johan Hedberg17d5c042011-01-22 06:09:08 +02001209 } else {
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001210 conn->state = BT_CLOSED;
Johan Hedberg17d5c042011-01-22 06:09:08 +02001211 if (conn->type == ACL_LINK)
1212 mgmt_connect_failed(hdev->id, &ev->bdaddr, ev->status);
1213 }
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001214
Marcel Holtmanne73439d2010-07-26 10:06:00 -04001215 if (conn->type == ACL_LINK)
1216 hci_sco_setup(conn, ev->status);
Marcel Holtmann45bb4bf2005-08-09 20:27:49 -07001217
Marcel Holtmann769be972008-07-14 20:13:49 +02001218 if (ev->status) {
1219 hci_proto_connect_cfm(conn, ev->status);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001220 hci_conn_del(conn);
Marcel Holtmannc89b6e62009-01-15 21:57:03 +01001221 } else if (ev->link_type != ACL_LINK)
1222 hci_proto_connect_cfm(conn, ev->status);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001223
1224unlock:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001225 hci_dev_unlock(hdev);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001226
1227 hci_conn_check_pending(hdev);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001228}
1229
Linus Torvalds1da177e2005-04-16 15:20:36 -07001230static inline void hci_conn_request_evt(struct hci_dev *hdev, struct sk_buff *skb)
1231{
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001232 struct hci_ev_conn_request *ev = (void *) skb->data;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001233 int mask = hdev->link_mode;
1234
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001235 BT_DBG("%s bdaddr %s type 0x%x", hdev->name,
1236 batostr(&ev->bdaddr), ev->link_type);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001237
1238 mask |= hci_proto_connect_ind(hdev, &ev->bdaddr, ev->link_type);
1239
Johan Hedbergf0358562010-05-18 13:20:32 +02001240 if ((mask & HCI_LM_ACCEPT) && !hci_blacklist_lookup(hdev, &ev->bdaddr)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001241 /* Connection accepted */
Marcel Holtmannc7bdd502008-07-14 20:13:47 +02001242 struct inquiry_entry *ie;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001243 struct hci_conn *conn;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001244
1245 hci_dev_lock(hdev);
Marcel Holtmannb6a0dc82007-10-20 14:55:10 +02001246
Andrei Emeltchenkocc11b9c2010-11-22 13:21:37 +02001247 ie = hci_inquiry_cache_lookup(hdev, &ev->bdaddr);
1248 if (ie)
Marcel Holtmannc7bdd502008-07-14 20:13:47 +02001249 memcpy(ie->data.dev_class, ev->dev_class, 3);
1250
Linus Torvalds1da177e2005-04-16 15:20:36 -07001251 conn = hci_conn_hash_lookup_ba(hdev, ev->link_type, &ev->bdaddr);
1252 if (!conn) {
Andrei Emeltchenkocc11b9c2010-11-22 13:21:37 +02001253 conn = hci_conn_add(hdev, ev->link_type, &ev->bdaddr);
1254 if (!conn) {
Gustavo F. Padovan893ef972010-07-18 15:13:37 -03001255 BT_ERR("No memory for new connection");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001256 hci_dev_unlock(hdev);
1257 return;
1258 }
1259 }
Marcel Holtmannb6a0dc82007-10-20 14:55:10 +02001260
Linus Torvalds1da177e2005-04-16 15:20:36 -07001261 memcpy(conn->dev_class, ev->dev_class, 3);
1262 conn->state = BT_CONNECT;
Marcel Holtmannb6a0dc82007-10-20 14:55:10 +02001263
Linus Torvalds1da177e2005-04-16 15:20:36 -07001264 hci_dev_unlock(hdev);
1265
Marcel Holtmannb6a0dc82007-10-20 14:55:10 +02001266 if (ev->link_type == ACL_LINK || !lmp_esco_capable(hdev)) {
1267 struct hci_cp_accept_conn_req cp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001268
Marcel Holtmannb6a0dc82007-10-20 14:55:10 +02001269 bacpy(&cp.bdaddr, &ev->bdaddr);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001270
Marcel Holtmannb6a0dc82007-10-20 14:55:10 +02001271 if (lmp_rswitch_capable(hdev) && (mask & HCI_LM_MASTER))
1272 cp.role = 0x00; /* Become master */
1273 else
1274 cp.role = 0x01; /* Remain slave */
1275
1276 hci_send_cmd(hdev, HCI_OP_ACCEPT_CONN_REQ,
1277 sizeof(cp), &cp);
1278 } else {
1279 struct hci_cp_accept_sync_conn_req cp;
1280
1281 bacpy(&cp.bdaddr, &ev->bdaddr);
Marcel Holtmanna8746412008-07-14 20:13:46 +02001282 cp.pkt_type = cpu_to_le16(conn->pkt_type);
Marcel Holtmannb6a0dc82007-10-20 14:55:10 +02001283
1284 cp.tx_bandwidth = cpu_to_le32(0x00001f40);
1285 cp.rx_bandwidth = cpu_to_le32(0x00001f40);
1286 cp.max_latency = cpu_to_le16(0xffff);
1287 cp.content_format = cpu_to_le16(hdev->voice_setting);
1288 cp.retrans_effort = 0xff;
1289
1290 hci_send_cmd(hdev, HCI_OP_ACCEPT_SYNC_CONN_REQ,
1291 sizeof(cp), &cp);
1292 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001293 } else {
1294 /* Connection rejected */
1295 struct hci_cp_reject_conn_req cp;
1296
1297 bacpy(&cp.bdaddr, &ev->bdaddr);
1298 cp.reason = 0x0f;
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001299 hci_send_cmd(hdev, HCI_OP_REJECT_CONN_REQ, sizeof(cp), &cp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001300 }
1301}
1302
Linus Torvalds1da177e2005-04-16 15:20:36 -07001303static inline void hci_disconn_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
1304{
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001305 struct hci_ev_disconn_complete *ev = (void *) skb->data;
Marcel Holtmann04837f62006-07-03 10:02:33 +02001306 struct hci_conn *conn;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001307
1308 BT_DBG("%s status %d", hdev->name, ev->status);
1309
Johan Hedberg8962ee72011-01-20 12:40:27 +02001310 if (ev->status) {
1311 mgmt_disconnect_failed(hdev->id);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001312 return;
Johan Hedberg8962ee72011-01-20 12:40:27 +02001313 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001314
1315 hci_dev_lock(hdev);
1316
Marcel Holtmann04837f62006-07-03 10:02:33 +02001317 conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
Johan Hedbergf7520542011-01-20 12:34:39 +02001318 if (!conn)
1319 goto unlock;
Marcel Holtmann7d0db0a2008-07-14 20:13:51 +02001320
Johan Hedbergf7520542011-01-20 12:34:39 +02001321 conn->state = BT_CLOSED;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001322
Johan Hedbergf7520542011-01-20 12:34:39 +02001323 if (conn->type == ACL_LINK)
1324 mgmt_disconnected(hdev->id, &conn->dst);
1325
1326 hci_proto_disconn_cfm(conn, ev->reason);
1327 hci_conn_del(conn);
1328
1329unlock:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001330 hci_dev_unlock(hdev);
1331}
1332
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001333static inline void hci_auth_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
1334{
1335 struct hci_ev_auth_complete *ev = (void *) skb->data;
1336 struct hci_conn *conn;
1337
1338 BT_DBG("%s status %d", hdev->name, ev->status);
1339
1340 hci_dev_lock(hdev);
1341
1342 conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
1343 if (conn) {
Johan Hedberg765c2a92011-01-19 12:06:52 +05301344 if (!ev->status) {
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001345 conn->link_mode |= HCI_LM_AUTH;
Johan Hedberg765c2a92011-01-19 12:06:52 +05301346 conn->sec_level = conn->pending_sec_level;
1347 } else
Johan Hedbergda213f42010-06-18 11:08:56 +03001348 conn->sec_level = BT_SECURITY_LOW;
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001349
1350 clear_bit(HCI_CONN_AUTH_PEND, &conn->pend);
1351
Marcel Holtmannf8558552008-07-14 20:13:49 +02001352 if (conn->state == BT_CONFIG) {
1353 if (!ev->status && hdev->ssp_mode > 0 &&
1354 conn->ssp_mode > 0) {
1355 struct hci_cp_set_conn_encrypt cp;
1356 cp.handle = ev->handle;
1357 cp.encrypt = 0x01;
1358 hci_send_cmd(hdev, HCI_OP_SET_CONN_ENCRYPT,
1359 sizeof(cp), &cp);
1360 } else {
1361 conn->state = BT_CONNECTED;
1362 hci_proto_connect_cfm(conn, ev->status);
1363 hci_conn_put(conn);
1364 }
Marcel Holtmann052b30b2009-04-26 20:01:22 +02001365 } else {
Marcel Holtmannf8558552008-07-14 20:13:49 +02001366 hci_auth_cfm(conn, ev->status);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001367
Marcel Holtmann052b30b2009-04-26 20:01:22 +02001368 hci_conn_hold(conn);
1369 conn->disc_timeout = HCI_DISCONN_TIMEOUT;
1370 hci_conn_put(conn);
1371 }
1372
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001373 if (test_bit(HCI_CONN_ENCRYPT_PEND, &conn->pend)) {
1374 if (!ev->status) {
1375 struct hci_cp_set_conn_encrypt cp;
Marcel Holtmannf8558552008-07-14 20:13:49 +02001376 cp.handle = ev->handle;
1377 cp.encrypt = 0x01;
1378 hci_send_cmd(hdev, HCI_OP_SET_CONN_ENCRYPT,
1379 sizeof(cp), &cp);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001380 } else {
1381 clear_bit(HCI_CONN_ENCRYPT_PEND, &conn->pend);
1382 hci_encrypt_cfm(conn, ev->status, 0x00);
1383 }
1384 }
1385 }
1386
1387 hci_dev_unlock(hdev);
1388}
1389
1390static inline void hci_remote_name_evt(struct hci_dev *hdev, struct sk_buff *skb)
1391{
Johan Hedberg127178d2010-11-18 22:22:29 +02001392 struct hci_ev_remote_name *ev = (void *) skb->data;
1393 struct hci_conn *conn;
1394
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001395 BT_DBG("%s", hdev->name);
1396
1397 hci_conn_check_pending(hdev);
Johan Hedberg127178d2010-11-18 22:22:29 +02001398
1399 hci_dev_lock(hdev);
1400
1401 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
1402 if (conn && hci_outgoing_auth_needed(hdev, conn)) {
1403 struct hci_cp_auth_requested cp;
1404 cp.handle = __cpu_to_le16(conn->handle);
1405 hci_send_cmd(hdev, HCI_OP_AUTH_REQUESTED, sizeof(cp), &cp);
1406 }
1407
1408 hci_dev_unlock(hdev);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001409}
1410
1411static inline void hci_encrypt_change_evt(struct hci_dev *hdev, struct sk_buff *skb)
1412{
1413 struct hci_ev_encrypt_change *ev = (void *) skb->data;
1414 struct hci_conn *conn;
1415
1416 BT_DBG("%s status %d", hdev->name, ev->status);
1417
1418 hci_dev_lock(hdev);
1419
1420 conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
1421 if (conn) {
1422 if (!ev->status) {
Marcel Holtmannae293192008-07-14 20:13:45 +02001423 if (ev->encrypt) {
1424 /* Encryption implies authentication */
1425 conn->link_mode |= HCI_LM_AUTH;
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001426 conn->link_mode |= HCI_LM_ENCRYPT;
Marcel Holtmannae293192008-07-14 20:13:45 +02001427 } else
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001428 conn->link_mode &= ~HCI_LM_ENCRYPT;
1429 }
1430
1431 clear_bit(HCI_CONN_ENCRYPT_PEND, &conn->pend);
1432
Marcel Holtmannf8558552008-07-14 20:13:49 +02001433 if (conn->state == BT_CONFIG) {
1434 if (!ev->status)
1435 conn->state = BT_CONNECTED;
1436
1437 hci_proto_connect_cfm(conn, ev->status);
1438 hci_conn_put(conn);
1439 } else
1440 hci_encrypt_cfm(conn, ev->status, ev->encrypt);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001441 }
1442
1443 hci_dev_unlock(hdev);
1444}
1445
1446static inline void hci_change_link_key_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
1447{
1448 struct hci_ev_change_link_key_complete *ev = (void *) skb->data;
1449 struct hci_conn *conn;
1450
1451 BT_DBG("%s status %d", hdev->name, ev->status);
1452
1453 hci_dev_lock(hdev);
1454
1455 conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
1456 if (conn) {
1457 if (!ev->status)
1458 conn->link_mode |= HCI_LM_SECURE;
1459
1460 clear_bit(HCI_CONN_AUTH_PEND, &conn->pend);
1461
1462 hci_key_change_cfm(conn, ev->status);
1463 }
1464
1465 hci_dev_unlock(hdev);
1466}
1467
1468static inline void hci_remote_features_evt(struct hci_dev *hdev, struct sk_buff *skb)
1469{
1470 struct hci_ev_remote_features *ev = (void *) skb->data;
1471 struct hci_conn *conn;
1472
1473 BT_DBG("%s status %d", hdev->name, ev->status);
1474
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001475 hci_dev_lock(hdev);
1476
1477 conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
Johan Hedbergccd556f2010-11-10 17:11:51 +02001478 if (!conn)
1479 goto unlock;
Marcel Holtmann769be972008-07-14 20:13:49 +02001480
Johan Hedbergccd556f2010-11-10 17:11:51 +02001481 if (!ev->status)
1482 memcpy(conn->features, ev->features, 8);
1483
1484 if (conn->state != BT_CONFIG)
1485 goto unlock;
1486
1487 if (!ev->status && lmp_ssp_capable(hdev) && lmp_ssp_capable(conn)) {
1488 struct hci_cp_read_remote_ext_features cp;
1489 cp.handle = ev->handle;
1490 cp.page = 0x01;
1491 hci_send_cmd(hdev, HCI_OP_READ_REMOTE_EXT_FEATURES,
Marcel Holtmann769be972008-07-14 20:13:49 +02001492 sizeof(cp), &cp);
Johan Hedberg392599b2010-11-18 22:22:28 +02001493 goto unlock;
1494 }
1495
Johan Hedberg127178d2010-11-18 22:22:29 +02001496 if (!ev->status) {
1497 struct hci_cp_remote_name_req cp;
1498 memset(&cp, 0, sizeof(cp));
1499 bacpy(&cp.bdaddr, &conn->dst);
1500 cp.pscan_rep_mode = 0x02;
1501 hci_send_cmd(hdev, HCI_OP_REMOTE_NAME_REQ, sizeof(cp), &cp);
1502 }
Johan Hedberg392599b2010-11-18 22:22:28 +02001503
Johan Hedberg127178d2010-11-18 22:22:29 +02001504 if (!hci_outgoing_auth_needed(hdev, conn)) {
Johan Hedbergccd556f2010-11-10 17:11:51 +02001505 conn->state = BT_CONNECTED;
1506 hci_proto_connect_cfm(conn, ev->status);
1507 hci_conn_put(conn);
Marcel Holtmann769be972008-07-14 20:13:49 +02001508 }
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001509
Johan Hedbergccd556f2010-11-10 17:11:51 +02001510unlock:
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001511 hci_dev_unlock(hdev);
1512}
1513
1514static inline void hci_remote_version_evt(struct hci_dev *hdev, struct sk_buff *skb)
1515{
1516 BT_DBG("%s", hdev->name);
1517}
1518
1519static inline void hci_qos_setup_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
1520{
1521 BT_DBG("%s", hdev->name);
1522}
1523
1524static inline void hci_cmd_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
1525{
1526 struct hci_ev_cmd_complete *ev = (void *) skb->data;
1527 __u16 opcode;
1528
1529 skb_pull(skb, sizeof(*ev));
1530
1531 opcode = __le16_to_cpu(ev->opcode);
1532
1533 switch (opcode) {
1534 case HCI_OP_INQUIRY_CANCEL:
1535 hci_cc_inquiry_cancel(hdev, skb);
1536 break;
1537
1538 case HCI_OP_EXIT_PERIODIC_INQ:
1539 hci_cc_exit_periodic_inq(hdev, skb);
1540 break;
1541
1542 case HCI_OP_REMOTE_NAME_REQ_CANCEL:
1543 hci_cc_remote_name_req_cancel(hdev, skb);
1544 break;
1545
1546 case HCI_OP_ROLE_DISCOVERY:
1547 hci_cc_role_discovery(hdev, skb);
1548 break;
1549
Marcel Holtmanne4e8e372008-07-14 20:13:47 +02001550 case HCI_OP_READ_LINK_POLICY:
1551 hci_cc_read_link_policy(hdev, skb);
1552 break;
1553
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001554 case HCI_OP_WRITE_LINK_POLICY:
1555 hci_cc_write_link_policy(hdev, skb);
1556 break;
1557
Marcel Holtmanne4e8e372008-07-14 20:13:47 +02001558 case HCI_OP_READ_DEF_LINK_POLICY:
1559 hci_cc_read_def_link_policy(hdev, skb);
1560 break;
1561
1562 case HCI_OP_WRITE_DEF_LINK_POLICY:
1563 hci_cc_write_def_link_policy(hdev, skb);
1564 break;
1565
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001566 case HCI_OP_RESET:
1567 hci_cc_reset(hdev, skb);
1568 break;
1569
1570 case HCI_OP_WRITE_LOCAL_NAME:
1571 hci_cc_write_local_name(hdev, skb);
1572 break;
1573
1574 case HCI_OP_READ_LOCAL_NAME:
1575 hci_cc_read_local_name(hdev, skb);
1576 break;
1577
1578 case HCI_OP_WRITE_AUTH_ENABLE:
1579 hci_cc_write_auth_enable(hdev, skb);
1580 break;
1581
1582 case HCI_OP_WRITE_ENCRYPT_MODE:
1583 hci_cc_write_encrypt_mode(hdev, skb);
1584 break;
1585
1586 case HCI_OP_WRITE_SCAN_ENABLE:
1587 hci_cc_write_scan_enable(hdev, skb);
1588 break;
1589
1590 case HCI_OP_READ_CLASS_OF_DEV:
1591 hci_cc_read_class_of_dev(hdev, skb);
1592 break;
1593
1594 case HCI_OP_WRITE_CLASS_OF_DEV:
1595 hci_cc_write_class_of_dev(hdev, skb);
1596 break;
1597
1598 case HCI_OP_READ_VOICE_SETTING:
1599 hci_cc_read_voice_setting(hdev, skb);
1600 break;
1601
1602 case HCI_OP_WRITE_VOICE_SETTING:
1603 hci_cc_write_voice_setting(hdev, skb);
1604 break;
1605
1606 case HCI_OP_HOST_BUFFER_SIZE:
1607 hci_cc_host_buffer_size(hdev, skb);
1608 break;
1609
Marcel Holtmann333140b2008-07-14 20:13:48 +02001610 case HCI_OP_READ_SSP_MODE:
1611 hci_cc_read_ssp_mode(hdev, skb);
1612 break;
1613
1614 case HCI_OP_WRITE_SSP_MODE:
1615 hci_cc_write_ssp_mode(hdev, skb);
1616 break;
1617
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001618 case HCI_OP_READ_LOCAL_VERSION:
1619 hci_cc_read_local_version(hdev, skb);
1620 break;
1621
1622 case HCI_OP_READ_LOCAL_COMMANDS:
1623 hci_cc_read_local_commands(hdev, skb);
1624 break;
1625
1626 case HCI_OP_READ_LOCAL_FEATURES:
1627 hci_cc_read_local_features(hdev, skb);
1628 break;
1629
1630 case HCI_OP_READ_BUFFER_SIZE:
1631 hci_cc_read_buffer_size(hdev, skb);
1632 break;
1633
1634 case HCI_OP_READ_BD_ADDR:
1635 hci_cc_read_bd_addr(hdev, skb);
1636 break;
1637
Johan Hedberg23bb5762010-12-21 23:01:27 +02001638 case HCI_OP_WRITE_CA_TIMEOUT:
1639 hci_cc_write_ca_timeout(hdev, skb);
1640 break;
1641
Johan Hedbergb0916ea2011-01-10 13:44:55 +02001642 case HCI_OP_DELETE_STORED_LINK_KEY:
1643 hci_cc_delete_stored_link_key(hdev, skb);
1644 break;
1645
Johan Hedbergd5859e22011-01-25 01:19:58 +02001646 case HCI_OP_SET_EVENT_MASK:
1647 hci_cc_set_event_mask(hdev, skb);
1648 break;
1649
1650 case HCI_OP_WRITE_INQUIRY_MODE:
1651 hci_cc_write_inquiry_mode(hdev, skb);
1652 break;
1653
1654 case HCI_OP_READ_INQ_RSP_TX_POWER:
1655 hci_cc_read_inq_rsp_tx_power(hdev, skb);
1656 break;
1657
1658 case HCI_OP_SET_EVENT_FLT:
1659 hci_cc_set_event_flt(hdev, skb);
1660 break;
1661
Johan Hedberg980e1a52011-01-22 06:10:07 +02001662 case HCI_OP_PIN_CODE_REPLY:
1663 hci_cc_pin_code_reply(hdev, skb);
1664 break;
1665
1666 case HCI_OP_PIN_CODE_NEG_REPLY:
1667 hci_cc_pin_code_neg_reply(hdev, skb);
1668 break;
1669
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001670 default:
1671 BT_DBG("%s opcode 0x%x", hdev->name, opcode);
1672 break;
1673 }
1674
1675 if (ev->ncmd) {
1676 atomic_set(&hdev->cmd_cnt, 1);
1677 if (!skb_queue_empty(&hdev->cmd_q))
Marcel Holtmannc78ae282009-11-18 01:02:54 +01001678 tasklet_schedule(&hdev->cmd_task);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001679 }
1680}
1681
1682static inline void hci_cmd_status_evt(struct hci_dev *hdev, struct sk_buff *skb)
1683{
1684 struct hci_ev_cmd_status *ev = (void *) skb->data;
1685 __u16 opcode;
1686
1687 skb_pull(skb, sizeof(*ev));
1688
1689 opcode = __le16_to_cpu(ev->opcode);
1690
1691 switch (opcode) {
1692 case HCI_OP_INQUIRY:
1693 hci_cs_inquiry(hdev, ev->status);
1694 break;
1695
1696 case HCI_OP_CREATE_CONN:
1697 hci_cs_create_conn(hdev, ev->status);
1698 break;
1699
1700 case HCI_OP_ADD_SCO:
1701 hci_cs_add_sco(hdev, ev->status);
1702 break;
1703
Marcel Holtmannf8558552008-07-14 20:13:49 +02001704 case HCI_OP_AUTH_REQUESTED:
1705 hci_cs_auth_requested(hdev, ev->status);
1706 break;
1707
1708 case HCI_OP_SET_CONN_ENCRYPT:
1709 hci_cs_set_conn_encrypt(hdev, ev->status);
1710 break;
1711
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001712 case HCI_OP_REMOTE_NAME_REQ:
1713 hci_cs_remote_name_req(hdev, ev->status);
1714 break;
1715
Marcel Holtmann769be972008-07-14 20:13:49 +02001716 case HCI_OP_READ_REMOTE_FEATURES:
1717 hci_cs_read_remote_features(hdev, ev->status);
1718 break;
1719
1720 case HCI_OP_READ_REMOTE_EXT_FEATURES:
1721 hci_cs_read_remote_ext_features(hdev, ev->status);
1722 break;
1723
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001724 case HCI_OP_SETUP_SYNC_CONN:
1725 hci_cs_setup_sync_conn(hdev, ev->status);
1726 break;
1727
1728 case HCI_OP_SNIFF_MODE:
1729 hci_cs_sniff_mode(hdev, ev->status);
1730 break;
1731
1732 case HCI_OP_EXIT_SNIFF_MODE:
1733 hci_cs_exit_sniff_mode(hdev, ev->status);
1734 break;
1735
Johan Hedberg8962ee72011-01-20 12:40:27 +02001736 case HCI_OP_DISCONNECT:
1737 if (ev->status != 0)
1738 mgmt_disconnect_failed(hdev->id);
1739 break;
1740
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001741 default:
1742 BT_DBG("%s opcode 0x%x", hdev->name, opcode);
1743 break;
1744 }
1745
1746 if (ev->ncmd) {
1747 atomic_set(&hdev->cmd_cnt, 1);
1748 if (!skb_queue_empty(&hdev->cmd_q))
Marcel Holtmannc78ae282009-11-18 01:02:54 +01001749 tasklet_schedule(&hdev->cmd_task);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001750 }
1751}
1752
1753static inline void hci_role_change_evt(struct hci_dev *hdev, struct sk_buff *skb)
1754{
1755 struct hci_ev_role_change *ev = (void *) skb->data;
1756 struct hci_conn *conn;
1757
1758 BT_DBG("%s status %d", hdev->name, ev->status);
1759
1760 hci_dev_lock(hdev);
1761
1762 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
1763 if (conn) {
1764 if (!ev->status) {
1765 if (ev->role)
1766 conn->link_mode &= ~HCI_LM_MASTER;
1767 else
1768 conn->link_mode |= HCI_LM_MASTER;
1769 }
1770
1771 clear_bit(HCI_CONN_RSWITCH_PEND, &conn->pend);
1772
1773 hci_role_switch_cfm(conn, ev->status, ev->role);
1774 }
1775
1776 hci_dev_unlock(hdev);
1777}
1778
Linus Torvalds1da177e2005-04-16 15:20:36 -07001779static inline void hci_num_comp_pkts_evt(struct hci_dev *hdev, struct sk_buff *skb)
1780{
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001781 struct hci_ev_num_comp_pkts *ev = (void *) skb->data;
Marcel Holtmann1ebb9252005-11-08 09:57:21 -08001782 __le16 *ptr;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001783 int i;
1784
1785 skb_pull(skb, sizeof(*ev));
1786
1787 BT_DBG("%s num_hndl %d", hdev->name, ev->num_hndl);
1788
1789 if (skb->len < ev->num_hndl * 4) {
1790 BT_DBG("%s bad parameters", hdev->name);
1791 return;
1792 }
1793
1794 tasklet_disable(&hdev->tx_task);
1795
Marcel Holtmann1ebb9252005-11-08 09:57:21 -08001796 for (i = 0, ptr = (__le16 *) skb->data; i < ev->num_hndl; i++) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001797 struct hci_conn *conn;
1798 __u16 handle, count;
1799
Harvey Harrison83985312008-05-02 16:25:46 -07001800 handle = get_unaligned_le16(ptr++);
1801 count = get_unaligned_le16(ptr++);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001802
1803 conn = hci_conn_hash_lookup_handle(hdev, handle);
1804 if (conn) {
1805 conn->sent -= count;
1806
Marcel Holtmann5b7f9902007-07-11 09:51:55 +02001807 if (conn->type == ACL_LINK) {
Andrei Emeltchenko70f230202010-12-01 16:58:25 +02001808 hdev->acl_cnt += count;
1809 if (hdev->acl_cnt > hdev->acl_pkts)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001810 hdev->acl_cnt = hdev->acl_pkts;
Marcel Holtmann5b7f9902007-07-11 09:51:55 +02001811 } else {
Andrei Emeltchenko70f230202010-12-01 16:58:25 +02001812 hdev->sco_cnt += count;
1813 if (hdev->sco_cnt > hdev->sco_pkts)
Marcel Holtmann5b7f9902007-07-11 09:51:55 +02001814 hdev->sco_cnt = hdev->sco_pkts;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001815 }
1816 }
1817 }
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001818
Marcel Holtmannc78ae282009-11-18 01:02:54 +01001819 tasklet_schedule(&hdev->tx_task);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001820
1821 tasklet_enable(&hdev->tx_task);
1822}
1823
Marcel Holtmann04837f62006-07-03 10:02:33 +02001824static inline void hci_mode_change_evt(struct hci_dev *hdev, struct sk_buff *skb)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001825{
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001826 struct hci_ev_mode_change *ev = (void *) skb->data;
Marcel Holtmann04837f62006-07-03 10:02:33 +02001827 struct hci_conn *conn;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001828
1829 BT_DBG("%s status %d", hdev->name, ev->status);
1830
1831 hci_dev_lock(hdev);
1832
Marcel Holtmann04837f62006-07-03 10:02:33 +02001833 conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
1834 if (conn) {
1835 conn->mode = ev->mode;
1836 conn->interval = __le16_to_cpu(ev->interval);
1837
1838 if (!test_and_clear_bit(HCI_CONN_MODE_CHANGE_PEND, &conn->pend)) {
1839 if (conn->mode == HCI_CM_ACTIVE)
1840 conn->power_save = 1;
1841 else
1842 conn->power_save = 0;
1843 }
Marcel Holtmanne73439d2010-07-26 10:06:00 -04001844
1845 if (test_and_clear_bit(HCI_CONN_SCO_SETUP_PEND, &conn->pend))
1846 hci_sco_setup(conn, ev->status);
Marcel Holtmann04837f62006-07-03 10:02:33 +02001847 }
1848
1849 hci_dev_unlock(hdev);
1850}
1851
Linus Torvalds1da177e2005-04-16 15:20:36 -07001852static inline void hci_pin_code_request_evt(struct hci_dev *hdev, struct sk_buff *skb)
1853{
Marcel Holtmann052b30b2009-04-26 20:01:22 +02001854 struct hci_ev_pin_code_req *ev = (void *) skb->data;
1855 struct hci_conn *conn;
1856
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001857 BT_DBG("%s", hdev->name);
Marcel Holtmann052b30b2009-04-26 20:01:22 +02001858
1859 hci_dev_lock(hdev);
1860
1861 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
Marcel Holtmann3d7a9d12009-05-09 12:09:21 -07001862 if (conn && conn->state == BT_CONNECTED) {
Marcel Holtmann052b30b2009-04-26 20:01:22 +02001863 hci_conn_hold(conn);
1864 conn->disc_timeout = HCI_PAIRING_TIMEOUT;
1865 hci_conn_put(conn);
1866 }
1867
Johan Hedberg03b555e2011-01-04 15:40:05 +02001868 if (!test_bit(HCI_PAIRABLE, &hdev->flags))
1869 hci_send_cmd(hdev, HCI_OP_PIN_CODE_NEG_REPLY,
1870 sizeof(ev->bdaddr), &ev->bdaddr);
1871
Johan Hedberg980e1a52011-01-22 06:10:07 +02001872 if (test_bit(HCI_MGMT, &hdev->flags))
1873 mgmt_pin_code_request(hdev->id, &ev->bdaddr);
1874
Marcel Holtmann052b30b2009-04-26 20:01:22 +02001875 hci_dev_unlock(hdev);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001876}
1877
Linus Torvalds1da177e2005-04-16 15:20:36 -07001878static inline void hci_link_key_request_evt(struct hci_dev *hdev, struct sk_buff *skb)
1879{
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02001880 struct hci_ev_link_key_req *ev = (void *) skb->data;
1881 struct hci_cp_link_key_reply cp;
1882 struct hci_conn *conn;
1883 struct link_key *key;
1884
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001885 BT_DBG("%s", hdev->name);
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02001886
1887 if (!test_bit(HCI_LINK_KEYS, &hdev->flags))
1888 return;
1889
1890 hci_dev_lock(hdev);
1891
1892 key = hci_find_link_key(hdev, &ev->bdaddr);
1893 if (!key) {
1894 BT_DBG("%s link key not found for %s", hdev->name,
1895 batostr(&ev->bdaddr));
1896 goto not_found;
1897 }
1898
1899 BT_DBG("%s found key type %u for %s", hdev->name, key->type,
1900 batostr(&ev->bdaddr));
1901
1902 if (!test_bit(HCI_DEBUG_KEYS, &hdev->flags) && key->type == 0x03) {
1903 BT_DBG("%s ignoring debug key", hdev->name);
1904 goto not_found;
1905 }
1906
1907 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
1908
1909 if (key->type == 0x04 && conn && conn->auth_type != 0xff &&
1910 (conn->auth_type & 0x01)) {
1911 BT_DBG("%s ignoring unauthenticated key", hdev->name);
1912 goto not_found;
1913 }
1914
1915 bacpy(&cp.bdaddr, &ev->bdaddr);
1916 memcpy(cp.link_key, key->val, 16);
1917
1918 hci_send_cmd(hdev, HCI_OP_LINK_KEY_REPLY, sizeof(cp), &cp);
1919
1920 hci_dev_unlock(hdev);
1921
1922 return;
1923
1924not_found:
1925 hci_send_cmd(hdev, HCI_OP_LINK_KEY_NEG_REPLY, 6, &ev->bdaddr);
1926 hci_dev_unlock(hdev);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001927}
1928
Linus Torvalds1da177e2005-04-16 15:20:36 -07001929static inline void hci_link_key_notify_evt(struct hci_dev *hdev, struct sk_buff *skb)
1930{
Marcel Holtmann052b30b2009-04-26 20:01:22 +02001931 struct hci_ev_link_key_notify *ev = (void *) skb->data;
1932 struct hci_conn *conn;
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02001933 u8 pin_len = 0;
Marcel Holtmann052b30b2009-04-26 20:01:22 +02001934
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001935 BT_DBG("%s", hdev->name);
Marcel Holtmann052b30b2009-04-26 20:01:22 +02001936
1937 hci_dev_lock(hdev);
1938
1939 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
1940 if (conn) {
1941 hci_conn_hold(conn);
1942 conn->disc_timeout = HCI_DISCONN_TIMEOUT;
Johan Hedberg980e1a52011-01-22 06:10:07 +02001943 pin_len = conn->pin_length;
Marcel Holtmann052b30b2009-04-26 20:01:22 +02001944 hci_conn_put(conn);
1945 }
1946
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02001947 if (test_bit(HCI_LINK_KEYS, &hdev->flags))
1948 hci_add_link_key(hdev, 1, &ev->bdaddr, ev->link_key,
1949 ev->key_type, pin_len);
1950
Marcel Holtmann052b30b2009-04-26 20:01:22 +02001951 hci_dev_unlock(hdev);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001952}
1953
Marcel Holtmann04837f62006-07-03 10:02:33 +02001954static inline void hci_clock_offset_evt(struct hci_dev *hdev, struct sk_buff *skb)
1955{
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001956 struct hci_ev_clock_offset *ev = (void *) skb->data;
Marcel Holtmann04837f62006-07-03 10:02:33 +02001957 struct hci_conn *conn;
1958
1959 BT_DBG("%s status %d", hdev->name, ev->status);
1960
1961 hci_dev_lock(hdev);
1962
1963 conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
Linus Torvalds1da177e2005-04-16 15:20:36 -07001964 if (conn && !ev->status) {
1965 struct inquiry_entry *ie;
1966
Andrei Emeltchenkocc11b9c2010-11-22 13:21:37 +02001967 ie = hci_inquiry_cache_lookup(hdev, &conn->dst);
1968 if (ie) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001969 ie->data.clock_offset = ev->clock_offset;
1970 ie->timestamp = jiffies;
1971 }
1972 }
1973
1974 hci_dev_unlock(hdev);
1975}
1976
Marcel Holtmanna8746412008-07-14 20:13:46 +02001977static inline void hci_pkt_type_change_evt(struct hci_dev *hdev, struct sk_buff *skb)
1978{
1979 struct hci_ev_pkt_type_change *ev = (void *) skb->data;
1980 struct hci_conn *conn;
1981
1982 BT_DBG("%s status %d", hdev->name, ev->status);
1983
1984 hci_dev_lock(hdev);
1985
1986 conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
1987 if (conn && !ev->status)
1988 conn->pkt_type = __le16_to_cpu(ev->pkt_type);
1989
1990 hci_dev_unlock(hdev);
1991}
1992
Marcel Holtmann85a1e932005-08-09 20:28:02 -07001993static inline void hci_pscan_rep_mode_evt(struct hci_dev *hdev, struct sk_buff *skb)
1994{
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001995 struct hci_ev_pscan_rep_mode *ev = (void *) skb->data;
Marcel Holtmann85a1e932005-08-09 20:28:02 -07001996 struct inquiry_entry *ie;
1997
1998 BT_DBG("%s", hdev->name);
1999
2000 hci_dev_lock(hdev);
2001
Andrei Emeltchenkocc11b9c2010-11-22 13:21:37 +02002002 ie = hci_inquiry_cache_lookup(hdev, &ev->bdaddr);
2003 if (ie) {
Marcel Holtmann85a1e932005-08-09 20:28:02 -07002004 ie->data.pscan_rep_mode = ev->pscan_rep_mode;
2005 ie->timestamp = jiffies;
2006 }
2007
2008 hci_dev_unlock(hdev);
2009}
2010
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002011static inline void hci_inquiry_result_with_rssi_evt(struct hci_dev *hdev, struct sk_buff *skb)
2012{
2013 struct inquiry_data data;
2014 int num_rsp = *((__u8 *) skb->data);
2015
2016 BT_DBG("%s num_rsp %d", hdev->name, num_rsp);
2017
2018 if (!num_rsp)
2019 return;
2020
2021 hci_dev_lock(hdev);
2022
2023 if ((skb->len - 1) / num_rsp != sizeof(struct inquiry_info_with_rssi)) {
2024 struct inquiry_info_with_rssi_and_pscan_mode *info = (void *) (skb->data + 1);
2025
2026 for (; num_rsp; num_rsp--) {
2027 bacpy(&data.bdaddr, &info->bdaddr);
2028 data.pscan_rep_mode = info->pscan_rep_mode;
2029 data.pscan_period_mode = info->pscan_period_mode;
2030 data.pscan_mode = info->pscan_mode;
2031 memcpy(data.dev_class, info->dev_class, 3);
2032 data.clock_offset = info->clock_offset;
2033 data.rssi = info->rssi;
Marcel Holtmann41a96212008-07-14 20:13:48 +02002034 data.ssp_mode = 0x00;
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002035 info++;
2036 hci_inquiry_cache_update(hdev, &data);
2037 }
2038 } else {
2039 struct inquiry_info_with_rssi *info = (void *) (skb->data + 1);
2040
2041 for (; num_rsp; num_rsp--) {
2042 bacpy(&data.bdaddr, &info->bdaddr);
2043 data.pscan_rep_mode = info->pscan_rep_mode;
2044 data.pscan_period_mode = info->pscan_period_mode;
2045 data.pscan_mode = 0x00;
2046 memcpy(data.dev_class, info->dev_class, 3);
2047 data.clock_offset = info->clock_offset;
2048 data.rssi = info->rssi;
Marcel Holtmann41a96212008-07-14 20:13:48 +02002049 data.ssp_mode = 0x00;
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002050 info++;
2051 hci_inquiry_cache_update(hdev, &data);
2052 }
2053 }
2054
2055 hci_dev_unlock(hdev);
2056}
2057
2058static inline void hci_remote_ext_features_evt(struct hci_dev *hdev, struct sk_buff *skb)
2059{
Marcel Holtmann41a96212008-07-14 20:13:48 +02002060 struct hci_ev_remote_ext_features *ev = (void *) skb->data;
2061 struct hci_conn *conn;
2062
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002063 BT_DBG("%s", hdev->name);
Marcel Holtmann41a96212008-07-14 20:13:48 +02002064
Marcel Holtmann41a96212008-07-14 20:13:48 +02002065 hci_dev_lock(hdev);
2066
2067 conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
Johan Hedbergccd556f2010-11-10 17:11:51 +02002068 if (!conn)
2069 goto unlock;
Marcel Holtmann41a96212008-07-14 20:13:48 +02002070
Johan Hedbergccd556f2010-11-10 17:11:51 +02002071 if (!ev->status && ev->page == 0x01) {
2072 struct inquiry_entry *ie;
Marcel Holtmann41a96212008-07-14 20:13:48 +02002073
Andrei Emeltchenkocc11b9c2010-11-22 13:21:37 +02002074 ie = hci_inquiry_cache_lookup(hdev, &conn->dst);
2075 if (ie)
Johan Hedbergccd556f2010-11-10 17:11:51 +02002076 ie->data.ssp_mode = (ev->features[0] & 0x01);
Marcel Holtmann769be972008-07-14 20:13:49 +02002077
Johan Hedbergccd556f2010-11-10 17:11:51 +02002078 conn->ssp_mode = (ev->features[0] & 0x01);
Marcel Holtmann41a96212008-07-14 20:13:48 +02002079 }
2080
Johan Hedbergccd556f2010-11-10 17:11:51 +02002081 if (conn->state != BT_CONFIG)
2082 goto unlock;
2083
Johan Hedberg127178d2010-11-18 22:22:29 +02002084 if (!ev->status) {
2085 struct hci_cp_remote_name_req cp;
2086 memset(&cp, 0, sizeof(cp));
2087 bacpy(&cp.bdaddr, &conn->dst);
2088 cp.pscan_rep_mode = 0x02;
2089 hci_send_cmd(hdev, HCI_OP_REMOTE_NAME_REQ, sizeof(cp), &cp);
2090 }
Johan Hedberg392599b2010-11-18 22:22:28 +02002091
Johan Hedberg127178d2010-11-18 22:22:29 +02002092 if (!hci_outgoing_auth_needed(hdev, conn)) {
Johan Hedbergccd556f2010-11-10 17:11:51 +02002093 conn->state = BT_CONNECTED;
2094 hci_proto_connect_cfm(conn, ev->status);
2095 hci_conn_put(conn);
2096 }
2097
2098unlock:
Marcel Holtmann41a96212008-07-14 20:13:48 +02002099 hci_dev_unlock(hdev);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002100}
2101
2102static inline void hci_sync_conn_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
2103{
Marcel Holtmannb6a0dc82007-10-20 14:55:10 +02002104 struct hci_ev_sync_conn_complete *ev = (void *) skb->data;
2105 struct hci_conn *conn;
2106
2107 BT_DBG("%s status %d", hdev->name, ev->status);
2108
2109 hci_dev_lock(hdev);
2110
2111 conn = hci_conn_hash_lookup_ba(hdev, ev->link_type, &ev->bdaddr);
Marcel Holtmann9dc0a3a2008-07-14 20:13:46 +02002112 if (!conn) {
2113 if (ev->link_type == ESCO_LINK)
2114 goto unlock;
2115
2116 conn = hci_conn_hash_lookup_ba(hdev, ESCO_LINK, &ev->bdaddr);
2117 if (!conn)
2118 goto unlock;
2119
2120 conn->type = SCO_LINK;
2121 }
Marcel Holtmannb6a0dc82007-10-20 14:55:10 +02002122
Marcel Holtmann732547f2009-04-19 19:14:14 +02002123 switch (ev->status) {
2124 case 0x00:
Marcel Holtmannb6a0dc82007-10-20 14:55:10 +02002125 conn->handle = __le16_to_cpu(ev->handle);
2126 conn->state = BT_CONNECTED;
Marcel Holtmann7d0db0a2008-07-14 20:13:51 +02002127
Marcel Holtmann9eba32b2009-08-22 14:19:26 -07002128 hci_conn_hold_device(conn);
Marcel Holtmann7d0db0a2008-07-14 20:13:51 +02002129 hci_conn_add_sysfs(conn);
Marcel Holtmann732547f2009-04-19 19:14:14 +02002130 break;
2131
Stephen Coe705e5712010-02-16 11:29:44 -05002132 case 0x11: /* Unsupported Feature or Parameter Value */
Marcel Holtmann732547f2009-04-19 19:14:14 +02002133 case 0x1c: /* SCO interval rejected */
Nick Pelly1038a002010-02-03 11:42:26 -08002134 case 0x1a: /* Unsupported Remote Feature */
Marcel Holtmann732547f2009-04-19 19:14:14 +02002135 case 0x1f: /* Unspecified error */
2136 if (conn->out && conn->attempt < 2) {
2137 conn->pkt_type = (hdev->esco_type & SCO_ESCO_MASK) |
2138 (hdev->esco_type & EDR_ESCO_MASK);
2139 hci_setup_sync(conn, conn->link->handle);
2140 goto unlock;
2141 }
2142 /* fall through */
2143
2144 default:
Marcel Holtmannb6a0dc82007-10-20 14:55:10 +02002145 conn->state = BT_CLOSED;
Marcel Holtmann732547f2009-04-19 19:14:14 +02002146 break;
2147 }
Marcel Holtmannb6a0dc82007-10-20 14:55:10 +02002148
2149 hci_proto_connect_cfm(conn, ev->status);
2150 if (ev->status)
2151 hci_conn_del(conn);
2152
2153unlock:
2154 hci_dev_unlock(hdev);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002155}
2156
2157static inline void hci_sync_conn_changed_evt(struct hci_dev *hdev, struct sk_buff *skb)
2158{
2159 BT_DBG("%s", hdev->name);
2160}
2161
Marcel Holtmann04837f62006-07-03 10:02:33 +02002162static inline void hci_sniff_subrate_evt(struct hci_dev *hdev, struct sk_buff *skb)
2163{
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002164 struct hci_ev_sniff_subrate *ev = (void *) skb->data;
Marcel Holtmann04837f62006-07-03 10:02:33 +02002165 struct hci_conn *conn;
2166
2167 BT_DBG("%s status %d", hdev->name, ev->status);
2168
2169 hci_dev_lock(hdev);
2170
2171 conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
2172 if (conn) {
2173 }
2174
2175 hci_dev_unlock(hdev);
2176}
2177
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002178static inline void hci_extended_inquiry_result_evt(struct hci_dev *hdev, struct sk_buff *skb)
2179{
2180 struct inquiry_data data;
2181 struct extended_inquiry_info *info = (void *) (skb->data + 1);
2182 int num_rsp = *((__u8 *) skb->data);
2183
2184 BT_DBG("%s num_rsp %d", hdev->name, num_rsp);
2185
2186 if (!num_rsp)
2187 return;
2188
2189 hci_dev_lock(hdev);
2190
2191 for (; num_rsp; num_rsp--) {
2192 bacpy(&data.bdaddr, &info->bdaddr);
2193 data.pscan_rep_mode = info->pscan_rep_mode;
2194 data.pscan_period_mode = info->pscan_period_mode;
2195 data.pscan_mode = 0x00;
2196 memcpy(data.dev_class, info->dev_class, 3);
2197 data.clock_offset = info->clock_offset;
2198 data.rssi = info->rssi;
Marcel Holtmann41a96212008-07-14 20:13:48 +02002199 data.ssp_mode = 0x01;
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002200 info++;
2201 hci_inquiry_cache_update(hdev, &data);
2202 }
2203
2204 hci_dev_unlock(hdev);
2205}
2206
Johan Hedberg17fa4b92011-01-25 13:28:33 +02002207static inline u8 hci_get_auth_req(struct hci_conn *conn)
2208{
2209 /* If remote requests dedicated bonding follow that lead */
2210 if (conn->remote_auth == 0x02 || conn->remote_auth == 0x03) {
2211 /* If both remote and local IO capabilities allow MITM
2212 * protection then require it, otherwise don't */
2213 if (conn->remote_cap == 0x03 || conn->io_capability == 0x03)
2214 return 0x02;
2215 else
2216 return 0x03;
2217 }
2218
2219 /* If remote requests no-bonding follow that lead */
2220 if (conn->remote_auth == 0x00 || conn->remote_auth == 0x01)
2221 return 0x00;
2222
2223 return conn->auth_type;
2224}
2225
Marcel Holtmann04936842008-07-14 20:13:48 +02002226static inline void hci_io_capa_request_evt(struct hci_dev *hdev, struct sk_buff *skb)
2227{
2228 struct hci_ev_io_capa_request *ev = (void *) skb->data;
2229 struct hci_conn *conn;
2230
2231 BT_DBG("%s", hdev->name);
2232
2233 hci_dev_lock(hdev);
2234
2235 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
Johan Hedberg03b555e2011-01-04 15:40:05 +02002236 if (!conn)
2237 goto unlock;
Marcel Holtmann04936842008-07-14 20:13:48 +02002238
Johan Hedberg03b555e2011-01-04 15:40:05 +02002239 hci_conn_hold(conn);
2240
2241 if (!test_bit(HCI_MGMT, &hdev->flags))
2242 goto unlock;
2243
2244 if (test_bit(HCI_PAIRABLE, &hdev->flags) ||
2245 (conn->remote_auth & ~0x01) == HCI_AT_NO_BONDING) {
Johan Hedberg17fa4b92011-01-25 13:28:33 +02002246 struct hci_cp_io_capability_reply cp;
2247
2248 bacpy(&cp.bdaddr, &ev->bdaddr);
2249 cp.capability = conn->io_capability;
2250 cp.oob_data = 0;
2251 cp.authentication = hci_get_auth_req(conn);
2252
2253 hci_send_cmd(hdev, HCI_OP_IO_CAPABILITY_REPLY,
2254 sizeof(cp), &cp);
Johan Hedberg03b555e2011-01-04 15:40:05 +02002255 } else {
2256 struct hci_cp_io_capability_neg_reply cp;
2257
2258 bacpy(&cp.bdaddr, &ev->bdaddr);
2259 cp.reason = 0x16; /* Pairing not allowed */
2260
2261 hci_send_cmd(hdev, HCI_OP_IO_CAPABILITY_NEG_REPLY,
2262 sizeof(cp), &cp);
2263 }
2264
2265unlock:
2266 hci_dev_unlock(hdev);
2267}
2268
2269static inline void hci_io_capa_reply_evt(struct hci_dev *hdev, struct sk_buff *skb)
2270{
2271 struct hci_ev_io_capa_reply *ev = (void *) skb->data;
2272 struct hci_conn *conn;
2273
2274 BT_DBG("%s", hdev->name);
2275
2276 hci_dev_lock(hdev);
2277
2278 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
2279 if (!conn)
2280 goto unlock;
2281
2282 hci_conn_hold(conn);
2283
2284 conn->remote_cap = ev->capability;
2285 conn->remote_oob = ev->oob_data;
2286 conn->remote_auth = ev->authentication;
2287
2288unlock:
Marcel Holtmann04936842008-07-14 20:13:48 +02002289 hci_dev_unlock(hdev);
2290}
2291
2292static inline void hci_simple_pair_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
2293{
2294 struct hci_ev_simple_pair_complete *ev = (void *) skb->data;
2295 struct hci_conn *conn;
2296
2297 BT_DBG("%s", hdev->name);
2298
2299 hci_dev_lock(hdev);
2300
2301 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
2302 if (conn)
2303 hci_conn_put(conn);
2304
2305 hci_dev_unlock(hdev);
2306}
2307
Marcel Holtmann41a96212008-07-14 20:13:48 +02002308static inline void hci_remote_host_features_evt(struct hci_dev *hdev, struct sk_buff *skb)
2309{
2310 struct hci_ev_remote_host_features *ev = (void *) skb->data;
2311 struct inquiry_entry *ie;
2312
2313 BT_DBG("%s", hdev->name);
2314
2315 hci_dev_lock(hdev);
2316
Andrei Emeltchenkocc11b9c2010-11-22 13:21:37 +02002317 ie = hci_inquiry_cache_lookup(hdev, &ev->bdaddr);
2318 if (ie)
Marcel Holtmann41a96212008-07-14 20:13:48 +02002319 ie->data.ssp_mode = (ev->features[0] & 0x01);
2320
2321 hci_dev_unlock(hdev);
2322}
2323
Linus Torvalds1da177e2005-04-16 15:20:36 -07002324void hci_event_packet(struct hci_dev *hdev, struct sk_buff *skb)
2325{
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002326 struct hci_event_hdr *hdr = (void *) skb->data;
2327 __u8 event = hdr->evt;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002328
2329 skb_pull(skb, HCI_EVENT_HDR_SIZE);
2330
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002331 switch (event) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002332 case HCI_EV_INQUIRY_COMPLETE:
2333 hci_inquiry_complete_evt(hdev, skb);
2334 break;
2335
2336 case HCI_EV_INQUIRY_RESULT:
2337 hci_inquiry_result_evt(hdev, skb);
2338 break;
2339
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002340 case HCI_EV_CONN_COMPLETE:
2341 hci_conn_complete_evt(hdev, skb);
Marcel Holtmann21d9e302005-09-13 01:32:25 +02002342 break;
2343
Linus Torvalds1da177e2005-04-16 15:20:36 -07002344 case HCI_EV_CONN_REQUEST:
2345 hci_conn_request_evt(hdev, skb);
2346 break;
2347
Linus Torvalds1da177e2005-04-16 15:20:36 -07002348 case HCI_EV_DISCONN_COMPLETE:
2349 hci_disconn_complete_evt(hdev, skb);
2350 break;
2351
Linus Torvalds1da177e2005-04-16 15:20:36 -07002352 case HCI_EV_AUTH_COMPLETE:
2353 hci_auth_complete_evt(hdev, skb);
2354 break;
2355
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002356 case HCI_EV_REMOTE_NAME:
2357 hci_remote_name_evt(hdev, skb);
2358 break;
2359
Linus Torvalds1da177e2005-04-16 15:20:36 -07002360 case HCI_EV_ENCRYPT_CHANGE:
2361 hci_encrypt_change_evt(hdev, skb);
2362 break;
2363
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002364 case HCI_EV_CHANGE_LINK_KEY_COMPLETE:
2365 hci_change_link_key_complete_evt(hdev, skb);
2366 break;
2367
2368 case HCI_EV_REMOTE_FEATURES:
2369 hci_remote_features_evt(hdev, skb);
2370 break;
2371
2372 case HCI_EV_REMOTE_VERSION:
2373 hci_remote_version_evt(hdev, skb);
2374 break;
2375
2376 case HCI_EV_QOS_SETUP_COMPLETE:
2377 hci_qos_setup_complete_evt(hdev, skb);
2378 break;
2379
2380 case HCI_EV_CMD_COMPLETE:
2381 hci_cmd_complete_evt(hdev, skb);
2382 break;
2383
2384 case HCI_EV_CMD_STATUS:
2385 hci_cmd_status_evt(hdev, skb);
2386 break;
2387
2388 case HCI_EV_ROLE_CHANGE:
2389 hci_role_change_evt(hdev, skb);
2390 break;
2391
2392 case HCI_EV_NUM_COMP_PKTS:
2393 hci_num_comp_pkts_evt(hdev, skb);
2394 break;
2395
2396 case HCI_EV_MODE_CHANGE:
2397 hci_mode_change_evt(hdev, skb);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002398 break;
2399
2400 case HCI_EV_PIN_CODE_REQ:
2401 hci_pin_code_request_evt(hdev, skb);
2402 break;
2403
2404 case HCI_EV_LINK_KEY_REQ:
2405 hci_link_key_request_evt(hdev, skb);
2406 break;
2407
2408 case HCI_EV_LINK_KEY_NOTIFY:
2409 hci_link_key_notify_evt(hdev, skb);
2410 break;
2411
2412 case HCI_EV_CLOCK_OFFSET:
2413 hci_clock_offset_evt(hdev, skb);
2414 break;
2415
Marcel Holtmanna8746412008-07-14 20:13:46 +02002416 case HCI_EV_PKT_TYPE_CHANGE:
2417 hci_pkt_type_change_evt(hdev, skb);
2418 break;
2419
Marcel Holtmann85a1e932005-08-09 20:28:02 -07002420 case HCI_EV_PSCAN_REP_MODE:
2421 hci_pscan_rep_mode_evt(hdev, skb);
2422 break;
2423
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002424 case HCI_EV_INQUIRY_RESULT_WITH_RSSI:
2425 hci_inquiry_result_with_rssi_evt(hdev, skb);
2426 break;
2427
2428 case HCI_EV_REMOTE_EXT_FEATURES:
2429 hci_remote_ext_features_evt(hdev, skb);
2430 break;
2431
2432 case HCI_EV_SYNC_CONN_COMPLETE:
2433 hci_sync_conn_complete_evt(hdev, skb);
2434 break;
2435
2436 case HCI_EV_SYNC_CONN_CHANGED:
2437 hci_sync_conn_changed_evt(hdev, skb);
2438 break;
2439
Marcel Holtmann04837f62006-07-03 10:02:33 +02002440 case HCI_EV_SNIFF_SUBRATE:
2441 hci_sniff_subrate_evt(hdev, skb);
2442 break;
2443
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002444 case HCI_EV_EXTENDED_INQUIRY_RESULT:
2445 hci_extended_inquiry_result_evt(hdev, skb);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002446 break;
2447
Marcel Holtmann04936842008-07-14 20:13:48 +02002448 case HCI_EV_IO_CAPA_REQUEST:
2449 hci_io_capa_request_evt(hdev, skb);
2450 break;
2451
Johan Hedberg03b555e2011-01-04 15:40:05 +02002452 case HCI_EV_IO_CAPA_REPLY:
2453 hci_io_capa_reply_evt(hdev, skb);
2454 break;
2455
Marcel Holtmann04936842008-07-14 20:13:48 +02002456 case HCI_EV_SIMPLE_PAIR_COMPLETE:
2457 hci_simple_pair_complete_evt(hdev, skb);
2458 break;
2459
Marcel Holtmann41a96212008-07-14 20:13:48 +02002460 case HCI_EV_REMOTE_HOST_FEATURES:
2461 hci_remote_host_features_evt(hdev, skb);
2462 break;
2463
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002464 default:
2465 BT_DBG("%s event 0x%x", hdev->name, event);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002466 break;
2467 }
2468
2469 kfree_skb(skb);
2470 hdev->stat.evt_rx++;
2471}
2472
2473/* Generate internal stack event */
2474void hci_si_event(struct hci_dev *hdev, int type, int dlen, void *data)
2475{
2476 struct hci_event_hdr *hdr;
2477 struct hci_ev_stack_internal *ev;
2478 struct sk_buff *skb;
2479
2480 skb = bt_skb_alloc(HCI_EVENT_HDR_SIZE + sizeof(*ev) + dlen, GFP_ATOMIC);
2481 if (!skb)
2482 return;
2483
2484 hdr = (void *) skb_put(skb, HCI_EVENT_HDR_SIZE);
2485 hdr->evt = HCI_EV_STACK_INTERNAL;
2486 hdr->plen = sizeof(*ev) + dlen;
2487
2488 ev = (void *) skb_put(skb, sizeof(*ev) + dlen);
2489 ev->type = type;
2490 memcpy(ev->data, data, dlen);
2491
Marcel Holtmann576c7d82005-08-06 12:36:54 +02002492 bt_cb(skb)->incoming = 1;
Patrick McHardya61bbcf2005-08-14 17:24:31 -07002493 __net_timestamp(skb);
Marcel Holtmann576c7d82005-08-06 12:36:54 +02002494
Marcel Holtmann0d48d932005-08-09 20:30:28 -07002495 bt_cb(skb)->pkt_type = HCI_EVENT_PKT;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002496 skb->dev = (void *) hdev;
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02002497 hci_send_to_sock(hdev, skb, NULL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002498 kfree_skb(skb);
2499}