blob: 3155ad588076b583d4c66ac72461e8cee5baaa67 [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}
Ville Tervo6ed58ec2011-02-10 22:38:48 -0300779static void hci_cc_le_read_buffer_size(struct hci_dev *hdev,
780 struct sk_buff *skb)
781{
782 struct hci_rp_le_read_buffer_size *rp = (void *) skb->data;
783
784 BT_DBG("%s status 0x%x", hdev->name, rp->status);
785
786 if (rp->status)
787 return;
788
789 hdev->le_mtu = __le16_to_cpu(rp->le_mtu);
790 hdev->le_pkts = rp->le_max_pkt;
791
792 hdev->le_cnt = hdev->le_pkts;
793
794 BT_DBG("%s le mtu %d:%d", hdev->name, hdev->le_mtu, hdev->le_pkts);
795
796 hci_req_complete(hdev, HCI_OP_LE_READ_BUFFER_SIZE, rp->status);
797}
Johan Hedberg980e1a52011-01-22 06:10:07 +0200798
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200799static inline void hci_cs_inquiry(struct hci_dev *hdev, __u8 status)
800{
801 BT_DBG("%s status 0x%x", hdev->name, status);
802
803 if (status) {
Johan Hedberg23bb5762010-12-21 23:01:27 +0200804 hci_req_complete(hdev, HCI_OP_INQUIRY, status);
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200805
806 hci_conn_check_pending(hdev);
807 } else
808 set_bit(HCI_INQUIRY, &hdev->flags);
809}
810
Linus Torvalds1da177e2005-04-16 15:20:36 -0700811static inline void hci_cs_create_conn(struct hci_dev *hdev, __u8 status)
812{
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200813 struct hci_cp_create_conn *cp;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700814 struct hci_conn *conn;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700815
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200816 BT_DBG("%s status 0x%x", hdev->name, status);
817
818 cp = hci_sent_cmd_data(hdev, HCI_OP_CREATE_CONN);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700819 if (!cp)
820 return;
821
822 hci_dev_lock(hdev);
823
824 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &cp->bdaddr);
825
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200826 BT_DBG("%s bdaddr %s conn %p", hdev->name, batostr(&cp->bdaddr), conn);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700827
828 if (status) {
829 if (conn && conn->state == BT_CONNECT) {
Marcel Holtmann4c67bc72006-10-15 17:30:56 +0200830 if (status != 0x0c || conn->attempt > 2) {
831 conn->state = BT_CLOSED;
832 hci_proto_connect_cfm(conn, status);
833 hci_conn_del(conn);
834 } else
835 conn->state = BT_CONNECT2;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700836 }
837 } else {
838 if (!conn) {
839 conn = hci_conn_add(hdev, ACL_LINK, &cp->bdaddr);
840 if (conn) {
841 conn->out = 1;
842 conn->link_mode |= HCI_LM_MASTER;
843 } else
Gustavo F. Padovan893ef972010-07-18 15:13:37 -0300844 BT_ERR("No memory for new connection");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700845 }
846 }
847
848 hci_dev_unlock(hdev);
849}
850
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200851static void hci_cs_add_sco(struct hci_dev *hdev, __u8 status)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700852{
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200853 struct hci_cp_add_sco *cp;
854 struct hci_conn *acl, *sco;
855 __u16 handle;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700856
Marcel Holtmannb6a0dc82007-10-20 14:55:10 +0200857 BT_DBG("%s status 0x%x", hdev->name, status);
858
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200859 if (!status)
860 return;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700861
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200862 cp = hci_sent_cmd_data(hdev, HCI_OP_ADD_SCO);
863 if (!cp)
864 return;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700865
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200866 handle = __le16_to_cpu(cp->handle);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700867
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200868 BT_DBG("%s handle %d", hdev->name, handle);
Marcel Holtmann6bd57412006-11-18 22:14:22 +0100869
870 hci_dev_lock(hdev);
871
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200872 acl = hci_conn_hash_lookup_handle(hdev, handle);
Andrei Emeltchenko5a08ecc2011-01-11 17:20:20 +0200873 if (acl) {
874 sco = acl->link;
875 if (sco) {
876 sco->state = BT_CLOSED;
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200877
Andrei Emeltchenko5a08ecc2011-01-11 17:20:20 +0200878 hci_proto_connect_cfm(sco, status);
879 hci_conn_del(sco);
880 }
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200881 }
Marcel Holtmann6bd57412006-11-18 22:14:22 +0100882
883 hci_dev_unlock(hdev);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700884}
885
Marcel Holtmannf8558552008-07-14 20:13:49 +0200886static void hci_cs_auth_requested(struct hci_dev *hdev, __u8 status)
887{
888 struct hci_cp_auth_requested *cp;
889 struct hci_conn *conn;
890
891 BT_DBG("%s status 0x%x", hdev->name, status);
892
893 if (!status)
894 return;
895
896 cp = hci_sent_cmd_data(hdev, HCI_OP_AUTH_REQUESTED);
897 if (!cp)
898 return;
899
900 hci_dev_lock(hdev);
901
902 conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(cp->handle));
903 if (conn) {
904 if (conn->state == BT_CONFIG) {
905 hci_proto_connect_cfm(conn, status);
906 hci_conn_put(conn);
907 }
908 }
909
910 hci_dev_unlock(hdev);
911}
912
913static void hci_cs_set_conn_encrypt(struct hci_dev *hdev, __u8 status)
914{
915 struct hci_cp_set_conn_encrypt *cp;
916 struct hci_conn *conn;
917
918 BT_DBG("%s status 0x%x", hdev->name, status);
919
920 if (!status)
921 return;
922
923 cp = hci_sent_cmd_data(hdev, HCI_OP_SET_CONN_ENCRYPT);
924 if (!cp)
925 return;
926
927 hci_dev_lock(hdev);
928
929 conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(cp->handle));
930 if (conn) {
931 if (conn->state == BT_CONFIG) {
932 hci_proto_connect_cfm(conn, status);
933 hci_conn_put(conn);
934 }
935 }
936
937 hci_dev_unlock(hdev);
938}
939
Johan Hedberg127178d2010-11-18 22:22:29 +0200940static int hci_outgoing_auth_needed(struct hci_dev *hdev,
Johan Hedberg392599b2010-11-18 22:22:28 +0200941 struct hci_conn *conn)
942{
Johan Hedberg392599b2010-11-18 22:22:28 +0200943 if (conn->state != BT_CONFIG || !conn->out)
944 return 0;
945
Johan Hedberg765c2a92011-01-19 12:06:52 +0530946 if (conn->pending_sec_level == BT_SECURITY_SDP)
Johan Hedberg392599b2010-11-18 22:22:28 +0200947 return 0;
948
949 /* Only request authentication for SSP connections or non-SSP
950 * devices with sec_level HIGH */
951 if (!(hdev->ssp_mode > 0 && conn->ssp_mode > 0) &&
Johan Hedberg765c2a92011-01-19 12:06:52 +0530952 conn->pending_sec_level != BT_SECURITY_HIGH)
Johan Hedberg392599b2010-11-18 22:22:28 +0200953 return 0;
954
Johan Hedberg392599b2010-11-18 22:22:28 +0200955 return 1;
956}
957
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200958static void hci_cs_remote_name_req(struct hci_dev *hdev, __u8 status)
959{
Johan Hedberg127178d2010-11-18 22:22:29 +0200960 struct hci_cp_remote_name_req *cp;
961 struct hci_conn *conn;
962
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200963 BT_DBG("%s status 0x%x", hdev->name, status);
Johan Hedberg127178d2010-11-18 22:22:29 +0200964
965 /* If successful wait for the name req complete event before
966 * checking for the need to do authentication */
967 if (!status)
968 return;
969
970 cp = hci_sent_cmd_data(hdev, HCI_OP_REMOTE_NAME_REQ);
971 if (!cp)
972 return;
973
974 hci_dev_lock(hdev);
975
976 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &cp->bdaddr);
977 if (conn && hci_outgoing_auth_needed(hdev, conn)) {
978 struct hci_cp_auth_requested cp;
979 cp.handle = __cpu_to_le16(conn->handle);
980 hci_send_cmd(hdev, HCI_OP_AUTH_REQUESTED, sizeof(cp), &cp);
981 }
982
983 hci_dev_unlock(hdev);
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200984}
985
Marcel Holtmann769be972008-07-14 20:13:49 +0200986static void hci_cs_read_remote_features(struct hci_dev *hdev, __u8 status)
987{
988 struct hci_cp_read_remote_features *cp;
989 struct hci_conn *conn;
990
991 BT_DBG("%s status 0x%x", hdev->name, status);
992
993 if (!status)
994 return;
995
996 cp = hci_sent_cmd_data(hdev, HCI_OP_READ_REMOTE_FEATURES);
997 if (!cp)
998 return;
999
1000 hci_dev_lock(hdev);
1001
1002 conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(cp->handle));
1003 if (conn) {
1004 if (conn->state == BT_CONFIG) {
Marcel Holtmann769be972008-07-14 20:13:49 +02001005 hci_proto_connect_cfm(conn, status);
1006 hci_conn_put(conn);
1007 }
1008 }
1009
1010 hci_dev_unlock(hdev);
1011}
1012
1013static void hci_cs_read_remote_ext_features(struct hci_dev *hdev, __u8 status)
1014{
1015 struct hci_cp_read_remote_ext_features *cp;
1016 struct hci_conn *conn;
1017
1018 BT_DBG("%s status 0x%x", hdev->name, status);
1019
1020 if (!status)
1021 return;
1022
1023 cp = hci_sent_cmd_data(hdev, HCI_OP_READ_REMOTE_EXT_FEATURES);
1024 if (!cp)
1025 return;
1026
1027 hci_dev_lock(hdev);
1028
1029 conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(cp->handle));
1030 if (conn) {
1031 if (conn->state == BT_CONFIG) {
Marcel Holtmann769be972008-07-14 20:13:49 +02001032 hci_proto_connect_cfm(conn, status);
1033 hci_conn_put(conn);
1034 }
1035 }
1036
1037 hci_dev_unlock(hdev);
1038}
1039
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001040static void hci_cs_setup_sync_conn(struct hci_dev *hdev, __u8 status)
1041{
Marcel Holtmannb6a0dc82007-10-20 14:55:10 +02001042 struct hci_cp_setup_sync_conn *cp;
1043 struct hci_conn *acl, *sco;
1044 __u16 handle;
1045
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001046 BT_DBG("%s status 0x%x", hdev->name, status);
Marcel Holtmannb6a0dc82007-10-20 14:55:10 +02001047
1048 if (!status)
1049 return;
1050
1051 cp = hci_sent_cmd_data(hdev, HCI_OP_SETUP_SYNC_CONN);
1052 if (!cp)
1053 return;
1054
1055 handle = __le16_to_cpu(cp->handle);
1056
1057 BT_DBG("%s handle %d", hdev->name, handle);
1058
1059 hci_dev_lock(hdev);
1060
1061 acl = hci_conn_hash_lookup_handle(hdev, handle);
Andrei Emeltchenko5a08ecc2011-01-11 17:20:20 +02001062 if (acl) {
1063 sco = acl->link;
1064 if (sco) {
1065 sco->state = BT_CLOSED;
Marcel Holtmannb6a0dc82007-10-20 14:55:10 +02001066
Andrei Emeltchenko5a08ecc2011-01-11 17:20:20 +02001067 hci_proto_connect_cfm(sco, status);
1068 hci_conn_del(sco);
1069 }
Marcel Holtmannb6a0dc82007-10-20 14:55:10 +02001070 }
1071
1072 hci_dev_unlock(hdev);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001073}
1074
1075static void hci_cs_sniff_mode(struct hci_dev *hdev, __u8 status)
1076{
1077 struct hci_cp_sniff_mode *cp;
1078 struct hci_conn *conn;
1079
1080 BT_DBG("%s status 0x%x", hdev->name, status);
1081
1082 if (!status)
1083 return;
1084
1085 cp = hci_sent_cmd_data(hdev, HCI_OP_SNIFF_MODE);
1086 if (!cp)
1087 return;
1088
1089 hci_dev_lock(hdev);
1090
1091 conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(cp->handle));
Marcel Holtmanne73439d2010-07-26 10:06:00 -04001092 if (conn) {
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001093 clear_bit(HCI_CONN_MODE_CHANGE_PEND, &conn->pend);
1094
Marcel Holtmanne73439d2010-07-26 10:06:00 -04001095 if (test_and_clear_bit(HCI_CONN_SCO_SETUP_PEND, &conn->pend))
1096 hci_sco_setup(conn, status);
1097 }
1098
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001099 hci_dev_unlock(hdev);
1100}
1101
1102static void hci_cs_exit_sniff_mode(struct hci_dev *hdev, __u8 status)
1103{
1104 struct hci_cp_exit_sniff_mode *cp;
1105 struct hci_conn *conn;
1106
1107 BT_DBG("%s status 0x%x", hdev->name, status);
1108
1109 if (!status)
1110 return;
1111
1112 cp = hci_sent_cmd_data(hdev, HCI_OP_EXIT_SNIFF_MODE);
1113 if (!cp)
1114 return;
1115
1116 hci_dev_lock(hdev);
1117
1118 conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(cp->handle));
Marcel Holtmanne73439d2010-07-26 10:06:00 -04001119 if (conn) {
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001120 clear_bit(HCI_CONN_MODE_CHANGE_PEND, &conn->pend);
1121
Marcel Holtmanne73439d2010-07-26 10:06:00 -04001122 if (test_and_clear_bit(HCI_CONN_SCO_SETUP_PEND, &conn->pend))
1123 hci_sco_setup(conn, status);
1124 }
1125
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001126 hci_dev_unlock(hdev);
1127}
1128
Ville Tervofcd89c02011-02-10 22:38:47 -03001129static void hci_cs_le_create_conn(struct hci_dev *hdev, __u8 status)
1130{
1131 struct hci_cp_le_create_conn *cp;
1132 struct hci_conn *conn;
1133
1134 BT_DBG("%s status 0x%x", hdev->name, status);
1135
1136 cp = hci_sent_cmd_data(hdev, HCI_OP_LE_CREATE_CONN);
1137 if (!cp)
1138 return;
1139
1140 hci_dev_lock(hdev);
1141
1142 conn = hci_conn_hash_lookup_ba(hdev, LE_LINK, &cp->peer_addr);
1143
1144 BT_DBG("%s bdaddr %s conn %p", hdev->name, batostr(&cp->peer_addr),
1145 conn);
1146
1147 if (status) {
1148 if (conn && conn->state == BT_CONNECT) {
1149 conn->state = BT_CLOSED;
1150 hci_proto_connect_cfm(conn, status);
1151 hci_conn_del(conn);
1152 }
1153 } else {
1154 if (!conn) {
1155 conn = hci_conn_add(hdev, LE_LINK, &cp->peer_addr);
1156 if (conn)
1157 conn->out = 1;
1158 else
1159 BT_ERR("No memory for new connection");
1160 }
1161 }
1162
1163 hci_dev_unlock(hdev);
1164}
1165
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001166static inline void hci_inquiry_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
1167{
1168 __u8 status = *((__u8 *) skb->data);
1169
1170 BT_DBG("%s status %d", hdev->name, status);
1171
1172 clear_bit(HCI_INQUIRY, &hdev->flags);
1173
Johan Hedberg23bb5762010-12-21 23:01:27 +02001174 hci_req_complete(hdev, HCI_OP_INQUIRY, status);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001175
1176 hci_conn_check_pending(hdev);
1177}
1178
Linus Torvalds1da177e2005-04-16 15:20:36 -07001179static inline void hci_inquiry_result_evt(struct hci_dev *hdev, struct sk_buff *skb)
1180{
Marcel Holtmann45bb4bf2005-08-09 20:27:49 -07001181 struct inquiry_data data;
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001182 struct inquiry_info *info = (void *) (skb->data + 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001183 int num_rsp = *((__u8 *) skb->data);
1184
1185 BT_DBG("%s num_rsp %d", hdev->name, num_rsp);
1186
Marcel Holtmann45bb4bf2005-08-09 20:27:49 -07001187 if (!num_rsp)
1188 return;
1189
Linus Torvalds1da177e2005-04-16 15:20:36 -07001190 hci_dev_lock(hdev);
Marcel Holtmann45bb4bf2005-08-09 20:27:49 -07001191
Linus Torvalds1da177e2005-04-16 15:20:36 -07001192 for (; num_rsp; num_rsp--) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001193 bacpy(&data.bdaddr, &info->bdaddr);
1194 data.pscan_rep_mode = info->pscan_rep_mode;
1195 data.pscan_period_mode = info->pscan_period_mode;
1196 data.pscan_mode = info->pscan_mode;
1197 memcpy(data.dev_class, info->dev_class, 3);
1198 data.clock_offset = info->clock_offset;
1199 data.rssi = 0x00;
Marcel Holtmann41a96212008-07-14 20:13:48 +02001200 data.ssp_mode = 0x00;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001201 info++;
1202 hci_inquiry_cache_update(hdev, &data);
1203 }
Marcel Holtmann45bb4bf2005-08-09 20:27:49 -07001204
Linus Torvalds1da177e2005-04-16 15:20:36 -07001205 hci_dev_unlock(hdev);
1206}
1207
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001208static inline void hci_conn_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001209{
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001210 struct hci_ev_conn_complete *ev = (void *) skb->data;
1211 struct hci_conn *conn;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001212
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001213 BT_DBG("%s", hdev->name);
Marcel Holtmann45bb4bf2005-08-09 20:27:49 -07001214
Linus Torvalds1da177e2005-04-16 15:20:36 -07001215 hci_dev_lock(hdev);
Marcel Holtmann45bb4bf2005-08-09 20:27:49 -07001216
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001217 conn = hci_conn_hash_lookup_ba(hdev, ev->link_type, &ev->bdaddr);
Marcel Holtmann94992372009-04-19 19:30:03 +02001218 if (!conn) {
1219 if (ev->link_type != SCO_LINK)
1220 goto unlock;
1221
1222 conn = hci_conn_hash_lookup_ba(hdev, ESCO_LINK, &ev->bdaddr);
1223 if (!conn)
1224 goto unlock;
1225
1226 conn->type = SCO_LINK;
1227 }
Marcel Holtmann45bb4bf2005-08-09 20:27:49 -07001228
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001229 if (!ev->status) {
1230 conn->handle = __le16_to_cpu(ev->handle);
Marcel Holtmann769be972008-07-14 20:13:49 +02001231
1232 if (conn->type == ACL_LINK) {
1233 conn->state = BT_CONFIG;
1234 hci_conn_hold(conn);
Marcel Holtmann052b30b2009-04-26 20:01:22 +02001235 conn->disc_timeout = HCI_DISCONN_TIMEOUT;
Johan Hedbergf7520542011-01-20 12:34:39 +02001236 mgmt_connected(hdev->id, &ev->bdaddr);
Marcel Holtmann769be972008-07-14 20:13:49 +02001237 } else
1238 conn->state = BT_CONNECTED;
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001239
Marcel Holtmann9eba32b2009-08-22 14:19:26 -07001240 hci_conn_hold_device(conn);
Marcel Holtmann7d0db0a2008-07-14 20:13:51 +02001241 hci_conn_add_sysfs(conn);
1242
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001243 if (test_bit(HCI_AUTH, &hdev->flags))
1244 conn->link_mode |= HCI_LM_AUTH;
1245
1246 if (test_bit(HCI_ENCRYPT, &hdev->flags))
1247 conn->link_mode |= HCI_LM_ENCRYPT;
1248
1249 /* Get remote features */
1250 if (conn->type == ACL_LINK) {
1251 struct hci_cp_read_remote_features cp;
1252 cp.handle = ev->handle;
Marcel Holtmann769be972008-07-14 20:13:49 +02001253 hci_send_cmd(hdev, HCI_OP_READ_REMOTE_FEATURES,
1254 sizeof(cp), &cp);
Marcel Holtmann45bb4bf2005-08-09 20:27:49 -07001255 }
Marcel Holtmann45bb4bf2005-08-09 20:27:49 -07001256
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001257 /* Set packet type for incoming connection */
Marcel Holtmanna8746412008-07-14 20:13:46 +02001258 if (!conn->out && hdev->hci_ver < 3) {
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001259 struct hci_cp_change_conn_ptype cp;
1260 cp.handle = ev->handle;
Marcel Holtmanna8746412008-07-14 20:13:46 +02001261 cp.pkt_type = cpu_to_le16(conn->pkt_type);
1262 hci_send_cmd(hdev, HCI_OP_CHANGE_CONN_PTYPE,
1263 sizeof(cp), &cp);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001264 }
Johan Hedberg17d5c042011-01-22 06:09:08 +02001265 } else {
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001266 conn->state = BT_CLOSED;
Johan Hedberg17d5c042011-01-22 06:09:08 +02001267 if (conn->type == ACL_LINK)
1268 mgmt_connect_failed(hdev->id, &ev->bdaddr, ev->status);
1269 }
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001270
Marcel Holtmanne73439d2010-07-26 10:06:00 -04001271 if (conn->type == ACL_LINK)
1272 hci_sco_setup(conn, ev->status);
Marcel Holtmann45bb4bf2005-08-09 20:27:49 -07001273
Marcel Holtmann769be972008-07-14 20:13:49 +02001274 if (ev->status) {
1275 hci_proto_connect_cfm(conn, ev->status);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001276 hci_conn_del(conn);
Marcel Holtmannc89b6e62009-01-15 21:57:03 +01001277 } else if (ev->link_type != ACL_LINK)
1278 hci_proto_connect_cfm(conn, ev->status);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001279
1280unlock:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001281 hci_dev_unlock(hdev);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001282
1283 hci_conn_check_pending(hdev);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001284}
1285
Linus Torvalds1da177e2005-04-16 15:20:36 -07001286static inline void hci_conn_request_evt(struct hci_dev *hdev, struct sk_buff *skb)
1287{
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001288 struct hci_ev_conn_request *ev = (void *) skb->data;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001289 int mask = hdev->link_mode;
1290
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001291 BT_DBG("%s bdaddr %s type 0x%x", hdev->name,
1292 batostr(&ev->bdaddr), ev->link_type);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001293
1294 mask |= hci_proto_connect_ind(hdev, &ev->bdaddr, ev->link_type);
1295
Johan Hedbergf0358562010-05-18 13:20:32 +02001296 if ((mask & HCI_LM_ACCEPT) && !hci_blacklist_lookup(hdev, &ev->bdaddr)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001297 /* Connection accepted */
Marcel Holtmannc7bdd502008-07-14 20:13:47 +02001298 struct inquiry_entry *ie;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001299 struct hci_conn *conn;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001300
1301 hci_dev_lock(hdev);
Marcel Holtmannb6a0dc82007-10-20 14:55:10 +02001302
Andrei Emeltchenkocc11b9c2010-11-22 13:21:37 +02001303 ie = hci_inquiry_cache_lookup(hdev, &ev->bdaddr);
1304 if (ie)
Marcel Holtmannc7bdd502008-07-14 20:13:47 +02001305 memcpy(ie->data.dev_class, ev->dev_class, 3);
1306
Linus Torvalds1da177e2005-04-16 15:20:36 -07001307 conn = hci_conn_hash_lookup_ba(hdev, ev->link_type, &ev->bdaddr);
1308 if (!conn) {
Andrei Emeltchenkocc11b9c2010-11-22 13:21:37 +02001309 conn = hci_conn_add(hdev, ev->link_type, &ev->bdaddr);
1310 if (!conn) {
Gustavo F. Padovan893ef972010-07-18 15:13:37 -03001311 BT_ERR("No memory for new connection");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001312 hci_dev_unlock(hdev);
1313 return;
1314 }
1315 }
Marcel Holtmannb6a0dc82007-10-20 14:55:10 +02001316
Linus Torvalds1da177e2005-04-16 15:20:36 -07001317 memcpy(conn->dev_class, ev->dev_class, 3);
1318 conn->state = BT_CONNECT;
Marcel Holtmannb6a0dc82007-10-20 14:55:10 +02001319
Linus Torvalds1da177e2005-04-16 15:20:36 -07001320 hci_dev_unlock(hdev);
1321
Marcel Holtmannb6a0dc82007-10-20 14:55:10 +02001322 if (ev->link_type == ACL_LINK || !lmp_esco_capable(hdev)) {
1323 struct hci_cp_accept_conn_req cp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001324
Marcel Holtmannb6a0dc82007-10-20 14:55:10 +02001325 bacpy(&cp.bdaddr, &ev->bdaddr);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001326
Marcel Holtmannb6a0dc82007-10-20 14:55:10 +02001327 if (lmp_rswitch_capable(hdev) && (mask & HCI_LM_MASTER))
1328 cp.role = 0x00; /* Become master */
1329 else
1330 cp.role = 0x01; /* Remain slave */
1331
1332 hci_send_cmd(hdev, HCI_OP_ACCEPT_CONN_REQ,
1333 sizeof(cp), &cp);
1334 } else {
1335 struct hci_cp_accept_sync_conn_req cp;
1336
1337 bacpy(&cp.bdaddr, &ev->bdaddr);
Marcel Holtmanna8746412008-07-14 20:13:46 +02001338 cp.pkt_type = cpu_to_le16(conn->pkt_type);
Marcel Holtmannb6a0dc82007-10-20 14:55:10 +02001339
1340 cp.tx_bandwidth = cpu_to_le32(0x00001f40);
1341 cp.rx_bandwidth = cpu_to_le32(0x00001f40);
1342 cp.max_latency = cpu_to_le16(0xffff);
1343 cp.content_format = cpu_to_le16(hdev->voice_setting);
1344 cp.retrans_effort = 0xff;
1345
1346 hci_send_cmd(hdev, HCI_OP_ACCEPT_SYNC_CONN_REQ,
1347 sizeof(cp), &cp);
1348 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001349 } else {
1350 /* Connection rejected */
1351 struct hci_cp_reject_conn_req cp;
1352
1353 bacpy(&cp.bdaddr, &ev->bdaddr);
1354 cp.reason = 0x0f;
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001355 hci_send_cmd(hdev, HCI_OP_REJECT_CONN_REQ, sizeof(cp), &cp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001356 }
1357}
1358
Linus Torvalds1da177e2005-04-16 15:20:36 -07001359static inline void hci_disconn_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
1360{
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001361 struct hci_ev_disconn_complete *ev = (void *) skb->data;
Marcel Holtmann04837f62006-07-03 10:02:33 +02001362 struct hci_conn *conn;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001363
1364 BT_DBG("%s status %d", hdev->name, ev->status);
1365
Johan Hedberg8962ee72011-01-20 12:40:27 +02001366 if (ev->status) {
1367 mgmt_disconnect_failed(hdev->id);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001368 return;
Johan Hedberg8962ee72011-01-20 12:40:27 +02001369 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001370
1371 hci_dev_lock(hdev);
1372
Marcel Holtmann04837f62006-07-03 10:02:33 +02001373 conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
Johan Hedbergf7520542011-01-20 12:34:39 +02001374 if (!conn)
1375 goto unlock;
Marcel Holtmann7d0db0a2008-07-14 20:13:51 +02001376
Johan Hedbergf7520542011-01-20 12:34:39 +02001377 conn->state = BT_CLOSED;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001378
Johan Hedbergf7520542011-01-20 12:34:39 +02001379 if (conn->type == ACL_LINK)
1380 mgmt_disconnected(hdev->id, &conn->dst);
1381
1382 hci_proto_disconn_cfm(conn, ev->reason);
1383 hci_conn_del(conn);
1384
1385unlock:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001386 hci_dev_unlock(hdev);
1387}
1388
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001389static inline void hci_auth_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
1390{
1391 struct hci_ev_auth_complete *ev = (void *) skb->data;
1392 struct hci_conn *conn;
1393
1394 BT_DBG("%s status %d", hdev->name, ev->status);
1395
1396 hci_dev_lock(hdev);
1397
1398 conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
1399 if (conn) {
Johan Hedberg765c2a92011-01-19 12:06:52 +05301400 if (!ev->status) {
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001401 conn->link_mode |= HCI_LM_AUTH;
Johan Hedberg765c2a92011-01-19 12:06:52 +05301402 conn->sec_level = conn->pending_sec_level;
1403 } else
Johan Hedbergda213f42010-06-18 11:08:56 +03001404 conn->sec_level = BT_SECURITY_LOW;
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001405
1406 clear_bit(HCI_CONN_AUTH_PEND, &conn->pend);
1407
Marcel Holtmannf8558552008-07-14 20:13:49 +02001408 if (conn->state == BT_CONFIG) {
1409 if (!ev->status && hdev->ssp_mode > 0 &&
1410 conn->ssp_mode > 0) {
1411 struct hci_cp_set_conn_encrypt cp;
1412 cp.handle = ev->handle;
1413 cp.encrypt = 0x01;
1414 hci_send_cmd(hdev, HCI_OP_SET_CONN_ENCRYPT,
1415 sizeof(cp), &cp);
1416 } else {
1417 conn->state = BT_CONNECTED;
1418 hci_proto_connect_cfm(conn, ev->status);
1419 hci_conn_put(conn);
1420 }
Marcel Holtmann052b30b2009-04-26 20:01:22 +02001421 } else {
Marcel Holtmannf8558552008-07-14 20:13:49 +02001422 hci_auth_cfm(conn, ev->status);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001423
Marcel Holtmann052b30b2009-04-26 20:01:22 +02001424 hci_conn_hold(conn);
1425 conn->disc_timeout = HCI_DISCONN_TIMEOUT;
1426 hci_conn_put(conn);
1427 }
1428
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001429 if (test_bit(HCI_CONN_ENCRYPT_PEND, &conn->pend)) {
1430 if (!ev->status) {
1431 struct hci_cp_set_conn_encrypt cp;
Marcel Holtmannf8558552008-07-14 20:13:49 +02001432 cp.handle = ev->handle;
1433 cp.encrypt = 0x01;
1434 hci_send_cmd(hdev, HCI_OP_SET_CONN_ENCRYPT,
1435 sizeof(cp), &cp);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001436 } else {
1437 clear_bit(HCI_CONN_ENCRYPT_PEND, &conn->pend);
1438 hci_encrypt_cfm(conn, ev->status, 0x00);
1439 }
1440 }
1441 }
1442
1443 hci_dev_unlock(hdev);
1444}
1445
1446static inline void hci_remote_name_evt(struct hci_dev *hdev, struct sk_buff *skb)
1447{
Johan Hedberg127178d2010-11-18 22:22:29 +02001448 struct hci_ev_remote_name *ev = (void *) skb->data;
1449 struct hci_conn *conn;
1450
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001451 BT_DBG("%s", hdev->name);
1452
1453 hci_conn_check_pending(hdev);
Johan Hedberg127178d2010-11-18 22:22:29 +02001454
1455 hci_dev_lock(hdev);
1456
1457 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
1458 if (conn && hci_outgoing_auth_needed(hdev, conn)) {
1459 struct hci_cp_auth_requested cp;
1460 cp.handle = __cpu_to_le16(conn->handle);
1461 hci_send_cmd(hdev, HCI_OP_AUTH_REQUESTED, sizeof(cp), &cp);
1462 }
1463
1464 hci_dev_unlock(hdev);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001465}
1466
1467static inline void hci_encrypt_change_evt(struct hci_dev *hdev, struct sk_buff *skb)
1468{
1469 struct hci_ev_encrypt_change *ev = (void *) skb->data;
1470 struct hci_conn *conn;
1471
1472 BT_DBG("%s status %d", hdev->name, ev->status);
1473
1474 hci_dev_lock(hdev);
1475
1476 conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
1477 if (conn) {
1478 if (!ev->status) {
Marcel Holtmannae293192008-07-14 20:13:45 +02001479 if (ev->encrypt) {
1480 /* Encryption implies authentication */
1481 conn->link_mode |= HCI_LM_AUTH;
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001482 conn->link_mode |= HCI_LM_ENCRYPT;
Marcel Holtmannae293192008-07-14 20:13:45 +02001483 } else
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001484 conn->link_mode &= ~HCI_LM_ENCRYPT;
1485 }
1486
1487 clear_bit(HCI_CONN_ENCRYPT_PEND, &conn->pend);
1488
Marcel Holtmannf8558552008-07-14 20:13:49 +02001489 if (conn->state == BT_CONFIG) {
1490 if (!ev->status)
1491 conn->state = BT_CONNECTED;
1492
1493 hci_proto_connect_cfm(conn, ev->status);
1494 hci_conn_put(conn);
1495 } else
1496 hci_encrypt_cfm(conn, ev->status, ev->encrypt);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001497 }
1498
1499 hci_dev_unlock(hdev);
1500}
1501
1502static inline void hci_change_link_key_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
1503{
1504 struct hci_ev_change_link_key_complete *ev = (void *) skb->data;
1505 struct hci_conn *conn;
1506
1507 BT_DBG("%s status %d", hdev->name, ev->status);
1508
1509 hci_dev_lock(hdev);
1510
1511 conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
1512 if (conn) {
1513 if (!ev->status)
1514 conn->link_mode |= HCI_LM_SECURE;
1515
1516 clear_bit(HCI_CONN_AUTH_PEND, &conn->pend);
1517
1518 hci_key_change_cfm(conn, ev->status);
1519 }
1520
1521 hci_dev_unlock(hdev);
1522}
1523
1524static inline void hci_remote_features_evt(struct hci_dev *hdev, struct sk_buff *skb)
1525{
1526 struct hci_ev_remote_features *ev = (void *) skb->data;
1527 struct hci_conn *conn;
1528
1529 BT_DBG("%s status %d", hdev->name, ev->status);
1530
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001531 hci_dev_lock(hdev);
1532
1533 conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
Johan Hedbergccd556f2010-11-10 17:11:51 +02001534 if (!conn)
1535 goto unlock;
Marcel Holtmann769be972008-07-14 20:13:49 +02001536
Johan Hedbergccd556f2010-11-10 17:11:51 +02001537 if (!ev->status)
1538 memcpy(conn->features, ev->features, 8);
1539
1540 if (conn->state != BT_CONFIG)
1541 goto unlock;
1542
1543 if (!ev->status && lmp_ssp_capable(hdev) && lmp_ssp_capable(conn)) {
1544 struct hci_cp_read_remote_ext_features cp;
1545 cp.handle = ev->handle;
1546 cp.page = 0x01;
1547 hci_send_cmd(hdev, HCI_OP_READ_REMOTE_EXT_FEATURES,
Marcel Holtmann769be972008-07-14 20:13:49 +02001548 sizeof(cp), &cp);
Johan Hedberg392599b2010-11-18 22:22:28 +02001549 goto unlock;
1550 }
1551
Johan Hedberg127178d2010-11-18 22:22:29 +02001552 if (!ev->status) {
1553 struct hci_cp_remote_name_req cp;
1554 memset(&cp, 0, sizeof(cp));
1555 bacpy(&cp.bdaddr, &conn->dst);
1556 cp.pscan_rep_mode = 0x02;
1557 hci_send_cmd(hdev, HCI_OP_REMOTE_NAME_REQ, sizeof(cp), &cp);
1558 }
Johan Hedberg392599b2010-11-18 22:22:28 +02001559
Johan Hedberg127178d2010-11-18 22:22:29 +02001560 if (!hci_outgoing_auth_needed(hdev, conn)) {
Johan Hedbergccd556f2010-11-10 17:11:51 +02001561 conn->state = BT_CONNECTED;
1562 hci_proto_connect_cfm(conn, ev->status);
1563 hci_conn_put(conn);
Marcel Holtmann769be972008-07-14 20:13:49 +02001564 }
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001565
Johan Hedbergccd556f2010-11-10 17:11:51 +02001566unlock:
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001567 hci_dev_unlock(hdev);
1568}
1569
1570static inline void hci_remote_version_evt(struct hci_dev *hdev, struct sk_buff *skb)
1571{
1572 BT_DBG("%s", hdev->name);
1573}
1574
1575static inline void hci_qos_setup_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
1576{
1577 BT_DBG("%s", hdev->name);
1578}
1579
1580static inline void hci_cmd_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
1581{
1582 struct hci_ev_cmd_complete *ev = (void *) skb->data;
1583 __u16 opcode;
1584
1585 skb_pull(skb, sizeof(*ev));
1586
1587 opcode = __le16_to_cpu(ev->opcode);
1588
1589 switch (opcode) {
1590 case HCI_OP_INQUIRY_CANCEL:
1591 hci_cc_inquiry_cancel(hdev, skb);
1592 break;
1593
1594 case HCI_OP_EXIT_PERIODIC_INQ:
1595 hci_cc_exit_periodic_inq(hdev, skb);
1596 break;
1597
1598 case HCI_OP_REMOTE_NAME_REQ_CANCEL:
1599 hci_cc_remote_name_req_cancel(hdev, skb);
1600 break;
1601
1602 case HCI_OP_ROLE_DISCOVERY:
1603 hci_cc_role_discovery(hdev, skb);
1604 break;
1605
Marcel Holtmanne4e8e372008-07-14 20:13:47 +02001606 case HCI_OP_READ_LINK_POLICY:
1607 hci_cc_read_link_policy(hdev, skb);
1608 break;
1609
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001610 case HCI_OP_WRITE_LINK_POLICY:
1611 hci_cc_write_link_policy(hdev, skb);
1612 break;
1613
Marcel Holtmanne4e8e372008-07-14 20:13:47 +02001614 case HCI_OP_READ_DEF_LINK_POLICY:
1615 hci_cc_read_def_link_policy(hdev, skb);
1616 break;
1617
1618 case HCI_OP_WRITE_DEF_LINK_POLICY:
1619 hci_cc_write_def_link_policy(hdev, skb);
1620 break;
1621
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001622 case HCI_OP_RESET:
1623 hci_cc_reset(hdev, skb);
1624 break;
1625
1626 case HCI_OP_WRITE_LOCAL_NAME:
1627 hci_cc_write_local_name(hdev, skb);
1628 break;
1629
1630 case HCI_OP_READ_LOCAL_NAME:
1631 hci_cc_read_local_name(hdev, skb);
1632 break;
1633
1634 case HCI_OP_WRITE_AUTH_ENABLE:
1635 hci_cc_write_auth_enable(hdev, skb);
1636 break;
1637
1638 case HCI_OP_WRITE_ENCRYPT_MODE:
1639 hci_cc_write_encrypt_mode(hdev, skb);
1640 break;
1641
1642 case HCI_OP_WRITE_SCAN_ENABLE:
1643 hci_cc_write_scan_enable(hdev, skb);
1644 break;
1645
1646 case HCI_OP_READ_CLASS_OF_DEV:
1647 hci_cc_read_class_of_dev(hdev, skb);
1648 break;
1649
1650 case HCI_OP_WRITE_CLASS_OF_DEV:
1651 hci_cc_write_class_of_dev(hdev, skb);
1652 break;
1653
1654 case HCI_OP_READ_VOICE_SETTING:
1655 hci_cc_read_voice_setting(hdev, skb);
1656 break;
1657
1658 case HCI_OP_WRITE_VOICE_SETTING:
1659 hci_cc_write_voice_setting(hdev, skb);
1660 break;
1661
1662 case HCI_OP_HOST_BUFFER_SIZE:
1663 hci_cc_host_buffer_size(hdev, skb);
1664 break;
1665
Marcel Holtmann333140b2008-07-14 20:13:48 +02001666 case HCI_OP_READ_SSP_MODE:
1667 hci_cc_read_ssp_mode(hdev, skb);
1668 break;
1669
1670 case HCI_OP_WRITE_SSP_MODE:
1671 hci_cc_write_ssp_mode(hdev, skb);
1672 break;
1673
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001674 case HCI_OP_READ_LOCAL_VERSION:
1675 hci_cc_read_local_version(hdev, skb);
1676 break;
1677
1678 case HCI_OP_READ_LOCAL_COMMANDS:
1679 hci_cc_read_local_commands(hdev, skb);
1680 break;
1681
1682 case HCI_OP_READ_LOCAL_FEATURES:
1683 hci_cc_read_local_features(hdev, skb);
1684 break;
1685
1686 case HCI_OP_READ_BUFFER_SIZE:
1687 hci_cc_read_buffer_size(hdev, skb);
1688 break;
1689
1690 case HCI_OP_READ_BD_ADDR:
1691 hci_cc_read_bd_addr(hdev, skb);
1692 break;
1693
Johan Hedberg23bb5762010-12-21 23:01:27 +02001694 case HCI_OP_WRITE_CA_TIMEOUT:
1695 hci_cc_write_ca_timeout(hdev, skb);
1696 break;
1697
Johan Hedbergb0916ea2011-01-10 13:44:55 +02001698 case HCI_OP_DELETE_STORED_LINK_KEY:
1699 hci_cc_delete_stored_link_key(hdev, skb);
1700 break;
1701
Johan Hedbergd5859e22011-01-25 01:19:58 +02001702 case HCI_OP_SET_EVENT_MASK:
1703 hci_cc_set_event_mask(hdev, skb);
1704 break;
1705
1706 case HCI_OP_WRITE_INQUIRY_MODE:
1707 hci_cc_write_inquiry_mode(hdev, skb);
1708 break;
1709
1710 case HCI_OP_READ_INQ_RSP_TX_POWER:
1711 hci_cc_read_inq_rsp_tx_power(hdev, skb);
1712 break;
1713
1714 case HCI_OP_SET_EVENT_FLT:
1715 hci_cc_set_event_flt(hdev, skb);
1716 break;
1717
Johan Hedberg980e1a52011-01-22 06:10:07 +02001718 case HCI_OP_PIN_CODE_REPLY:
1719 hci_cc_pin_code_reply(hdev, skb);
1720 break;
1721
1722 case HCI_OP_PIN_CODE_NEG_REPLY:
1723 hci_cc_pin_code_neg_reply(hdev, skb);
1724 break;
1725
Ville Tervo6ed58ec2011-02-10 22:38:48 -03001726 case HCI_OP_LE_READ_BUFFER_SIZE:
1727 hci_cc_le_read_buffer_size(hdev, skb);
1728 break;
1729
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001730 default:
1731 BT_DBG("%s opcode 0x%x", hdev->name, opcode);
1732 break;
1733 }
1734
1735 if (ev->ncmd) {
1736 atomic_set(&hdev->cmd_cnt, 1);
1737 if (!skb_queue_empty(&hdev->cmd_q))
Marcel Holtmannc78ae282009-11-18 01:02:54 +01001738 tasklet_schedule(&hdev->cmd_task);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001739 }
1740}
1741
1742static inline void hci_cmd_status_evt(struct hci_dev *hdev, struct sk_buff *skb)
1743{
1744 struct hci_ev_cmd_status *ev = (void *) skb->data;
1745 __u16 opcode;
1746
1747 skb_pull(skb, sizeof(*ev));
1748
1749 opcode = __le16_to_cpu(ev->opcode);
1750
1751 switch (opcode) {
1752 case HCI_OP_INQUIRY:
1753 hci_cs_inquiry(hdev, ev->status);
1754 break;
1755
1756 case HCI_OP_CREATE_CONN:
1757 hci_cs_create_conn(hdev, ev->status);
1758 break;
1759
1760 case HCI_OP_ADD_SCO:
1761 hci_cs_add_sco(hdev, ev->status);
1762 break;
1763
Marcel Holtmannf8558552008-07-14 20:13:49 +02001764 case HCI_OP_AUTH_REQUESTED:
1765 hci_cs_auth_requested(hdev, ev->status);
1766 break;
1767
1768 case HCI_OP_SET_CONN_ENCRYPT:
1769 hci_cs_set_conn_encrypt(hdev, ev->status);
1770 break;
1771
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001772 case HCI_OP_REMOTE_NAME_REQ:
1773 hci_cs_remote_name_req(hdev, ev->status);
1774 break;
1775
Marcel Holtmann769be972008-07-14 20:13:49 +02001776 case HCI_OP_READ_REMOTE_FEATURES:
1777 hci_cs_read_remote_features(hdev, ev->status);
1778 break;
1779
1780 case HCI_OP_READ_REMOTE_EXT_FEATURES:
1781 hci_cs_read_remote_ext_features(hdev, ev->status);
1782 break;
1783
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001784 case HCI_OP_SETUP_SYNC_CONN:
1785 hci_cs_setup_sync_conn(hdev, ev->status);
1786 break;
1787
1788 case HCI_OP_SNIFF_MODE:
1789 hci_cs_sniff_mode(hdev, ev->status);
1790 break;
1791
1792 case HCI_OP_EXIT_SNIFF_MODE:
1793 hci_cs_exit_sniff_mode(hdev, ev->status);
1794 break;
1795
Johan Hedberg8962ee72011-01-20 12:40:27 +02001796 case HCI_OP_DISCONNECT:
1797 if (ev->status != 0)
1798 mgmt_disconnect_failed(hdev->id);
1799 break;
1800
Ville Tervofcd89c02011-02-10 22:38:47 -03001801 case HCI_OP_LE_CREATE_CONN:
1802 hci_cs_le_create_conn(hdev, ev->status);
1803 break;
1804
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001805 default:
1806 BT_DBG("%s opcode 0x%x", hdev->name, opcode);
1807 break;
1808 }
1809
1810 if (ev->ncmd) {
1811 atomic_set(&hdev->cmd_cnt, 1);
1812 if (!skb_queue_empty(&hdev->cmd_q))
Marcel Holtmannc78ae282009-11-18 01:02:54 +01001813 tasklet_schedule(&hdev->cmd_task);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001814 }
1815}
1816
1817static inline void hci_role_change_evt(struct hci_dev *hdev, struct sk_buff *skb)
1818{
1819 struct hci_ev_role_change *ev = (void *) skb->data;
1820 struct hci_conn *conn;
1821
1822 BT_DBG("%s status %d", hdev->name, ev->status);
1823
1824 hci_dev_lock(hdev);
1825
1826 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
1827 if (conn) {
1828 if (!ev->status) {
1829 if (ev->role)
1830 conn->link_mode &= ~HCI_LM_MASTER;
1831 else
1832 conn->link_mode |= HCI_LM_MASTER;
1833 }
1834
1835 clear_bit(HCI_CONN_RSWITCH_PEND, &conn->pend);
1836
1837 hci_role_switch_cfm(conn, ev->status, ev->role);
1838 }
1839
1840 hci_dev_unlock(hdev);
1841}
1842
Linus Torvalds1da177e2005-04-16 15:20:36 -07001843static inline void hci_num_comp_pkts_evt(struct hci_dev *hdev, struct sk_buff *skb)
1844{
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001845 struct hci_ev_num_comp_pkts *ev = (void *) skb->data;
Marcel Holtmann1ebb9252005-11-08 09:57:21 -08001846 __le16 *ptr;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001847 int i;
1848
1849 skb_pull(skb, sizeof(*ev));
1850
1851 BT_DBG("%s num_hndl %d", hdev->name, ev->num_hndl);
1852
1853 if (skb->len < ev->num_hndl * 4) {
1854 BT_DBG("%s bad parameters", hdev->name);
1855 return;
1856 }
1857
1858 tasklet_disable(&hdev->tx_task);
1859
Marcel Holtmann1ebb9252005-11-08 09:57:21 -08001860 for (i = 0, ptr = (__le16 *) skb->data; i < ev->num_hndl; i++) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001861 struct hci_conn *conn;
1862 __u16 handle, count;
1863
Harvey Harrison83985312008-05-02 16:25:46 -07001864 handle = get_unaligned_le16(ptr++);
1865 count = get_unaligned_le16(ptr++);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001866
1867 conn = hci_conn_hash_lookup_handle(hdev, handle);
1868 if (conn) {
1869 conn->sent -= count;
1870
Marcel Holtmann5b7f9902007-07-11 09:51:55 +02001871 if (conn->type == ACL_LINK) {
Andrei Emeltchenko70f230202010-12-01 16:58:25 +02001872 hdev->acl_cnt += count;
1873 if (hdev->acl_cnt > hdev->acl_pkts)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001874 hdev->acl_cnt = hdev->acl_pkts;
Ville Tervo6ed58ec2011-02-10 22:38:48 -03001875 } else if (conn->type == LE_LINK) {
1876 if (hdev->le_pkts) {
1877 hdev->le_cnt += count;
1878 if (hdev->le_cnt > hdev->le_pkts)
1879 hdev->le_cnt = hdev->le_pkts;
1880 } else {
1881 hdev->acl_cnt += count;
1882 if (hdev->acl_cnt > hdev->acl_pkts)
1883 hdev->acl_cnt = hdev->acl_pkts;
1884 }
Marcel Holtmann5b7f9902007-07-11 09:51:55 +02001885 } else {
Andrei Emeltchenko70f230202010-12-01 16:58:25 +02001886 hdev->sco_cnt += count;
1887 if (hdev->sco_cnt > hdev->sco_pkts)
Marcel Holtmann5b7f9902007-07-11 09:51:55 +02001888 hdev->sco_cnt = hdev->sco_pkts;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001889 }
1890 }
1891 }
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001892
Marcel Holtmannc78ae282009-11-18 01:02:54 +01001893 tasklet_schedule(&hdev->tx_task);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001894
1895 tasklet_enable(&hdev->tx_task);
1896}
1897
Marcel Holtmann04837f62006-07-03 10:02:33 +02001898static inline void hci_mode_change_evt(struct hci_dev *hdev, struct sk_buff *skb)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001899{
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001900 struct hci_ev_mode_change *ev = (void *) skb->data;
Marcel Holtmann04837f62006-07-03 10:02:33 +02001901 struct hci_conn *conn;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001902
1903 BT_DBG("%s status %d", hdev->name, ev->status);
1904
1905 hci_dev_lock(hdev);
1906
Marcel Holtmann04837f62006-07-03 10:02:33 +02001907 conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
1908 if (conn) {
1909 conn->mode = ev->mode;
1910 conn->interval = __le16_to_cpu(ev->interval);
1911
1912 if (!test_and_clear_bit(HCI_CONN_MODE_CHANGE_PEND, &conn->pend)) {
1913 if (conn->mode == HCI_CM_ACTIVE)
1914 conn->power_save = 1;
1915 else
1916 conn->power_save = 0;
1917 }
Marcel Holtmanne73439d2010-07-26 10:06:00 -04001918
1919 if (test_and_clear_bit(HCI_CONN_SCO_SETUP_PEND, &conn->pend))
1920 hci_sco_setup(conn, ev->status);
Marcel Holtmann04837f62006-07-03 10:02:33 +02001921 }
1922
1923 hci_dev_unlock(hdev);
1924}
1925
Linus Torvalds1da177e2005-04-16 15:20:36 -07001926static inline void hci_pin_code_request_evt(struct hci_dev *hdev, struct sk_buff *skb)
1927{
Marcel Holtmann052b30b2009-04-26 20:01:22 +02001928 struct hci_ev_pin_code_req *ev = (void *) skb->data;
1929 struct hci_conn *conn;
1930
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001931 BT_DBG("%s", hdev->name);
Marcel Holtmann052b30b2009-04-26 20:01:22 +02001932
1933 hci_dev_lock(hdev);
1934
1935 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
Marcel Holtmann3d7a9d12009-05-09 12:09:21 -07001936 if (conn && conn->state == BT_CONNECTED) {
Marcel Holtmann052b30b2009-04-26 20:01:22 +02001937 hci_conn_hold(conn);
1938 conn->disc_timeout = HCI_PAIRING_TIMEOUT;
1939 hci_conn_put(conn);
1940 }
1941
Johan Hedberg03b555e2011-01-04 15:40:05 +02001942 if (!test_bit(HCI_PAIRABLE, &hdev->flags))
1943 hci_send_cmd(hdev, HCI_OP_PIN_CODE_NEG_REPLY,
1944 sizeof(ev->bdaddr), &ev->bdaddr);
1945
Johan Hedberg980e1a52011-01-22 06:10:07 +02001946 if (test_bit(HCI_MGMT, &hdev->flags))
1947 mgmt_pin_code_request(hdev->id, &ev->bdaddr);
1948
Marcel Holtmann052b30b2009-04-26 20:01:22 +02001949 hci_dev_unlock(hdev);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001950}
1951
Linus Torvalds1da177e2005-04-16 15:20:36 -07001952static inline void hci_link_key_request_evt(struct hci_dev *hdev, struct sk_buff *skb)
1953{
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02001954 struct hci_ev_link_key_req *ev = (void *) skb->data;
1955 struct hci_cp_link_key_reply cp;
1956 struct hci_conn *conn;
1957 struct link_key *key;
1958
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001959 BT_DBG("%s", hdev->name);
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02001960
1961 if (!test_bit(HCI_LINK_KEYS, &hdev->flags))
1962 return;
1963
1964 hci_dev_lock(hdev);
1965
1966 key = hci_find_link_key(hdev, &ev->bdaddr);
1967 if (!key) {
1968 BT_DBG("%s link key not found for %s", hdev->name,
1969 batostr(&ev->bdaddr));
1970 goto not_found;
1971 }
1972
1973 BT_DBG("%s found key type %u for %s", hdev->name, key->type,
1974 batostr(&ev->bdaddr));
1975
1976 if (!test_bit(HCI_DEBUG_KEYS, &hdev->flags) && key->type == 0x03) {
1977 BT_DBG("%s ignoring debug key", hdev->name);
1978 goto not_found;
1979 }
1980
1981 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
1982
1983 if (key->type == 0x04 && conn && conn->auth_type != 0xff &&
1984 (conn->auth_type & 0x01)) {
1985 BT_DBG("%s ignoring unauthenticated key", hdev->name);
1986 goto not_found;
1987 }
1988
1989 bacpy(&cp.bdaddr, &ev->bdaddr);
1990 memcpy(cp.link_key, key->val, 16);
1991
1992 hci_send_cmd(hdev, HCI_OP_LINK_KEY_REPLY, sizeof(cp), &cp);
1993
1994 hci_dev_unlock(hdev);
1995
1996 return;
1997
1998not_found:
1999 hci_send_cmd(hdev, HCI_OP_LINK_KEY_NEG_REPLY, 6, &ev->bdaddr);
2000 hci_dev_unlock(hdev);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002001}
2002
Linus Torvalds1da177e2005-04-16 15:20:36 -07002003static inline void hci_link_key_notify_evt(struct hci_dev *hdev, struct sk_buff *skb)
2004{
Marcel Holtmann052b30b2009-04-26 20:01:22 +02002005 struct hci_ev_link_key_notify *ev = (void *) skb->data;
2006 struct hci_conn *conn;
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002007 u8 pin_len = 0;
Marcel Holtmann052b30b2009-04-26 20:01:22 +02002008
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002009 BT_DBG("%s", hdev->name);
Marcel Holtmann052b30b2009-04-26 20:01:22 +02002010
2011 hci_dev_lock(hdev);
2012
2013 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
2014 if (conn) {
2015 hci_conn_hold(conn);
2016 conn->disc_timeout = HCI_DISCONN_TIMEOUT;
Johan Hedberg980e1a52011-01-22 06:10:07 +02002017 pin_len = conn->pin_length;
Marcel Holtmann052b30b2009-04-26 20:01:22 +02002018 hci_conn_put(conn);
2019 }
2020
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002021 if (test_bit(HCI_LINK_KEYS, &hdev->flags))
2022 hci_add_link_key(hdev, 1, &ev->bdaddr, ev->link_key,
2023 ev->key_type, pin_len);
2024
Marcel Holtmann052b30b2009-04-26 20:01:22 +02002025 hci_dev_unlock(hdev);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002026}
2027
Marcel Holtmann04837f62006-07-03 10:02:33 +02002028static inline void hci_clock_offset_evt(struct hci_dev *hdev, struct sk_buff *skb)
2029{
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002030 struct hci_ev_clock_offset *ev = (void *) skb->data;
Marcel Holtmann04837f62006-07-03 10:02:33 +02002031 struct hci_conn *conn;
2032
2033 BT_DBG("%s status %d", hdev->name, ev->status);
2034
2035 hci_dev_lock(hdev);
2036
2037 conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
Linus Torvalds1da177e2005-04-16 15:20:36 -07002038 if (conn && !ev->status) {
2039 struct inquiry_entry *ie;
2040
Andrei Emeltchenkocc11b9c2010-11-22 13:21:37 +02002041 ie = hci_inquiry_cache_lookup(hdev, &conn->dst);
2042 if (ie) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002043 ie->data.clock_offset = ev->clock_offset;
2044 ie->timestamp = jiffies;
2045 }
2046 }
2047
2048 hci_dev_unlock(hdev);
2049}
2050
Marcel Holtmanna8746412008-07-14 20:13:46 +02002051static inline void hci_pkt_type_change_evt(struct hci_dev *hdev, struct sk_buff *skb)
2052{
2053 struct hci_ev_pkt_type_change *ev = (void *) skb->data;
2054 struct hci_conn *conn;
2055
2056 BT_DBG("%s status %d", hdev->name, ev->status);
2057
2058 hci_dev_lock(hdev);
2059
2060 conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
2061 if (conn && !ev->status)
2062 conn->pkt_type = __le16_to_cpu(ev->pkt_type);
2063
2064 hci_dev_unlock(hdev);
2065}
2066
Marcel Holtmann85a1e932005-08-09 20:28:02 -07002067static inline void hci_pscan_rep_mode_evt(struct hci_dev *hdev, struct sk_buff *skb)
2068{
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002069 struct hci_ev_pscan_rep_mode *ev = (void *) skb->data;
Marcel Holtmann85a1e932005-08-09 20:28:02 -07002070 struct inquiry_entry *ie;
2071
2072 BT_DBG("%s", hdev->name);
2073
2074 hci_dev_lock(hdev);
2075
Andrei Emeltchenkocc11b9c2010-11-22 13:21:37 +02002076 ie = hci_inquiry_cache_lookup(hdev, &ev->bdaddr);
2077 if (ie) {
Marcel Holtmann85a1e932005-08-09 20:28:02 -07002078 ie->data.pscan_rep_mode = ev->pscan_rep_mode;
2079 ie->timestamp = jiffies;
2080 }
2081
2082 hci_dev_unlock(hdev);
2083}
2084
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002085static inline void hci_inquiry_result_with_rssi_evt(struct hci_dev *hdev, struct sk_buff *skb)
2086{
2087 struct inquiry_data data;
2088 int num_rsp = *((__u8 *) skb->data);
2089
2090 BT_DBG("%s num_rsp %d", hdev->name, num_rsp);
2091
2092 if (!num_rsp)
2093 return;
2094
2095 hci_dev_lock(hdev);
2096
2097 if ((skb->len - 1) / num_rsp != sizeof(struct inquiry_info_with_rssi)) {
2098 struct inquiry_info_with_rssi_and_pscan_mode *info = (void *) (skb->data + 1);
2099
2100 for (; num_rsp; num_rsp--) {
2101 bacpy(&data.bdaddr, &info->bdaddr);
2102 data.pscan_rep_mode = info->pscan_rep_mode;
2103 data.pscan_period_mode = info->pscan_period_mode;
2104 data.pscan_mode = info->pscan_mode;
2105 memcpy(data.dev_class, info->dev_class, 3);
2106 data.clock_offset = info->clock_offset;
2107 data.rssi = info->rssi;
Marcel Holtmann41a96212008-07-14 20:13:48 +02002108 data.ssp_mode = 0x00;
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002109 info++;
2110 hci_inquiry_cache_update(hdev, &data);
2111 }
2112 } else {
2113 struct inquiry_info_with_rssi *info = (void *) (skb->data + 1);
2114
2115 for (; num_rsp; num_rsp--) {
2116 bacpy(&data.bdaddr, &info->bdaddr);
2117 data.pscan_rep_mode = info->pscan_rep_mode;
2118 data.pscan_period_mode = info->pscan_period_mode;
2119 data.pscan_mode = 0x00;
2120 memcpy(data.dev_class, info->dev_class, 3);
2121 data.clock_offset = info->clock_offset;
2122 data.rssi = info->rssi;
Marcel Holtmann41a96212008-07-14 20:13:48 +02002123 data.ssp_mode = 0x00;
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002124 info++;
2125 hci_inquiry_cache_update(hdev, &data);
2126 }
2127 }
2128
2129 hci_dev_unlock(hdev);
2130}
2131
2132static inline void hci_remote_ext_features_evt(struct hci_dev *hdev, struct sk_buff *skb)
2133{
Marcel Holtmann41a96212008-07-14 20:13:48 +02002134 struct hci_ev_remote_ext_features *ev = (void *) skb->data;
2135 struct hci_conn *conn;
2136
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002137 BT_DBG("%s", hdev->name);
Marcel Holtmann41a96212008-07-14 20:13:48 +02002138
Marcel Holtmann41a96212008-07-14 20:13:48 +02002139 hci_dev_lock(hdev);
2140
2141 conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
Johan Hedbergccd556f2010-11-10 17:11:51 +02002142 if (!conn)
2143 goto unlock;
Marcel Holtmann41a96212008-07-14 20:13:48 +02002144
Johan Hedbergccd556f2010-11-10 17:11:51 +02002145 if (!ev->status && ev->page == 0x01) {
2146 struct inquiry_entry *ie;
Marcel Holtmann41a96212008-07-14 20:13:48 +02002147
Andrei Emeltchenkocc11b9c2010-11-22 13:21:37 +02002148 ie = hci_inquiry_cache_lookup(hdev, &conn->dst);
2149 if (ie)
Johan Hedbergccd556f2010-11-10 17:11:51 +02002150 ie->data.ssp_mode = (ev->features[0] & 0x01);
Marcel Holtmann769be972008-07-14 20:13:49 +02002151
Johan Hedbergccd556f2010-11-10 17:11:51 +02002152 conn->ssp_mode = (ev->features[0] & 0x01);
Marcel Holtmann41a96212008-07-14 20:13:48 +02002153 }
2154
Johan Hedbergccd556f2010-11-10 17:11:51 +02002155 if (conn->state != BT_CONFIG)
2156 goto unlock;
2157
Johan Hedberg127178d2010-11-18 22:22:29 +02002158 if (!ev->status) {
2159 struct hci_cp_remote_name_req cp;
2160 memset(&cp, 0, sizeof(cp));
2161 bacpy(&cp.bdaddr, &conn->dst);
2162 cp.pscan_rep_mode = 0x02;
2163 hci_send_cmd(hdev, HCI_OP_REMOTE_NAME_REQ, sizeof(cp), &cp);
2164 }
Johan Hedberg392599b2010-11-18 22:22:28 +02002165
Johan Hedberg127178d2010-11-18 22:22:29 +02002166 if (!hci_outgoing_auth_needed(hdev, conn)) {
Johan Hedbergccd556f2010-11-10 17:11:51 +02002167 conn->state = BT_CONNECTED;
2168 hci_proto_connect_cfm(conn, ev->status);
2169 hci_conn_put(conn);
2170 }
2171
2172unlock:
Marcel Holtmann41a96212008-07-14 20:13:48 +02002173 hci_dev_unlock(hdev);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002174}
2175
2176static inline void hci_sync_conn_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
2177{
Marcel Holtmannb6a0dc82007-10-20 14:55:10 +02002178 struct hci_ev_sync_conn_complete *ev = (void *) skb->data;
2179 struct hci_conn *conn;
2180
2181 BT_DBG("%s status %d", hdev->name, ev->status);
2182
2183 hci_dev_lock(hdev);
2184
2185 conn = hci_conn_hash_lookup_ba(hdev, ev->link_type, &ev->bdaddr);
Marcel Holtmann9dc0a3a2008-07-14 20:13:46 +02002186 if (!conn) {
2187 if (ev->link_type == ESCO_LINK)
2188 goto unlock;
2189
2190 conn = hci_conn_hash_lookup_ba(hdev, ESCO_LINK, &ev->bdaddr);
2191 if (!conn)
2192 goto unlock;
2193
2194 conn->type = SCO_LINK;
2195 }
Marcel Holtmannb6a0dc82007-10-20 14:55:10 +02002196
Marcel Holtmann732547f2009-04-19 19:14:14 +02002197 switch (ev->status) {
2198 case 0x00:
Marcel Holtmannb6a0dc82007-10-20 14:55:10 +02002199 conn->handle = __le16_to_cpu(ev->handle);
2200 conn->state = BT_CONNECTED;
Marcel Holtmann7d0db0a2008-07-14 20:13:51 +02002201
Marcel Holtmann9eba32b2009-08-22 14:19:26 -07002202 hci_conn_hold_device(conn);
Marcel Holtmann7d0db0a2008-07-14 20:13:51 +02002203 hci_conn_add_sysfs(conn);
Marcel Holtmann732547f2009-04-19 19:14:14 +02002204 break;
2205
Stephen Coe705e5712010-02-16 11:29:44 -05002206 case 0x11: /* Unsupported Feature or Parameter Value */
Marcel Holtmann732547f2009-04-19 19:14:14 +02002207 case 0x1c: /* SCO interval rejected */
Nick Pelly1038a002010-02-03 11:42:26 -08002208 case 0x1a: /* Unsupported Remote Feature */
Marcel Holtmann732547f2009-04-19 19:14:14 +02002209 case 0x1f: /* Unspecified error */
2210 if (conn->out && conn->attempt < 2) {
2211 conn->pkt_type = (hdev->esco_type & SCO_ESCO_MASK) |
2212 (hdev->esco_type & EDR_ESCO_MASK);
2213 hci_setup_sync(conn, conn->link->handle);
2214 goto unlock;
2215 }
2216 /* fall through */
2217
2218 default:
Marcel Holtmannb6a0dc82007-10-20 14:55:10 +02002219 conn->state = BT_CLOSED;
Marcel Holtmann732547f2009-04-19 19:14:14 +02002220 break;
2221 }
Marcel Holtmannb6a0dc82007-10-20 14:55:10 +02002222
2223 hci_proto_connect_cfm(conn, ev->status);
2224 if (ev->status)
2225 hci_conn_del(conn);
2226
2227unlock:
2228 hci_dev_unlock(hdev);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002229}
2230
2231static inline void hci_sync_conn_changed_evt(struct hci_dev *hdev, struct sk_buff *skb)
2232{
2233 BT_DBG("%s", hdev->name);
2234}
2235
Marcel Holtmann04837f62006-07-03 10:02:33 +02002236static inline void hci_sniff_subrate_evt(struct hci_dev *hdev, struct sk_buff *skb)
2237{
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002238 struct hci_ev_sniff_subrate *ev = (void *) skb->data;
Marcel Holtmann04837f62006-07-03 10:02:33 +02002239 struct hci_conn *conn;
2240
2241 BT_DBG("%s status %d", hdev->name, ev->status);
2242
2243 hci_dev_lock(hdev);
2244
2245 conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
2246 if (conn) {
2247 }
2248
2249 hci_dev_unlock(hdev);
2250}
2251
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002252static inline void hci_extended_inquiry_result_evt(struct hci_dev *hdev, struct sk_buff *skb)
2253{
2254 struct inquiry_data data;
2255 struct extended_inquiry_info *info = (void *) (skb->data + 1);
2256 int num_rsp = *((__u8 *) skb->data);
2257
2258 BT_DBG("%s num_rsp %d", hdev->name, num_rsp);
2259
2260 if (!num_rsp)
2261 return;
2262
2263 hci_dev_lock(hdev);
2264
2265 for (; num_rsp; num_rsp--) {
2266 bacpy(&data.bdaddr, &info->bdaddr);
2267 data.pscan_rep_mode = info->pscan_rep_mode;
2268 data.pscan_period_mode = info->pscan_period_mode;
2269 data.pscan_mode = 0x00;
2270 memcpy(data.dev_class, info->dev_class, 3);
2271 data.clock_offset = info->clock_offset;
2272 data.rssi = info->rssi;
Marcel Holtmann41a96212008-07-14 20:13:48 +02002273 data.ssp_mode = 0x01;
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002274 info++;
2275 hci_inquiry_cache_update(hdev, &data);
2276 }
2277
2278 hci_dev_unlock(hdev);
2279}
2280
Johan Hedberg17fa4b92011-01-25 13:28:33 +02002281static inline u8 hci_get_auth_req(struct hci_conn *conn)
2282{
2283 /* If remote requests dedicated bonding follow that lead */
2284 if (conn->remote_auth == 0x02 || conn->remote_auth == 0x03) {
2285 /* If both remote and local IO capabilities allow MITM
2286 * protection then require it, otherwise don't */
2287 if (conn->remote_cap == 0x03 || conn->io_capability == 0x03)
2288 return 0x02;
2289 else
2290 return 0x03;
2291 }
2292
2293 /* If remote requests no-bonding follow that lead */
2294 if (conn->remote_auth == 0x00 || conn->remote_auth == 0x01)
2295 return 0x00;
2296
2297 return conn->auth_type;
2298}
2299
Marcel Holtmann04936842008-07-14 20:13:48 +02002300static inline void hci_io_capa_request_evt(struct hci_dev *hdev, struct sk_buff *skb)
2301{
2302 struct hci_ev_io_capa_request *ev = (void *) skb->data;
2303 struct hci_conn *conn;
2304
2305 BT_DBG("%s", hdev->name);
2306
2307 hci_dev_lock(hdev);
2308
2309 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
Johan Hedberg03b555e2011-01-04 15:40:05 +02002310 if (!conn)
2311 goto unlock;
Marcel Holtmann04936842008-07-14 20:13:48 +02002312
Johan Hedberg03b555e2011-01-04 15:40:05 +02002313 hci_conn_hold(conn);
2314
2315 if (!test_bit(HCI_MGMT, &hdev->flags))
2316 goto unlock;
2317
2318 if (test_bit(HCI_PAIRABLE, &hdev->flags) ||
2319 (conn->remote_auth & ~0x01) == HCI_AT_NO_BONDING) {
Johan Hedberg17fa4b92011-01-25 13:28:33 +02002320 struct hci_cp_io_capability_reply cp;
2321
2322 bacpy(&cp.bdaddr, &ev->bdaddr);
2323 cp.capability = conn->io_capability;
2324 cp.oob_data = 0;
2325 cp.authentication = hci_get_auth_req(conn);
2326
2327 hci_send_cmd(hdev, HCI_OP_IO_CAPABILITY_REPLY,
2328 sizeof(cp), &cp);
Johan Hedberg03b555e2011-01-04 15:40:05 +02002329 } else {
2330 struct hci_cp_io_capability_neg_reply cp;
2331
2332 bacpy(&cp.bdaddr, &ev->bdaddr);
2333 cp.reason = 0x16; /* Pairing not allowed */
2334
2335 hci_send_cmd(hdev, HCI_OP_IO_CAPABILITY_NEG_REPLY,
2336 sizeof(cp), &cp);
2337 }
2338
2339unlock:
2340 hci_dev_unlock(hdev);
2341}
2342
2343static inline void hci_io_capa_reply_evt(struct hci_dev *hdev, struct sk_buff *skb)
2344{
2345 struct hci_ev_io_capa_reply *ev = (void *) skb->data;
2346 struct hci_conn *conn;
2347
2348 BT_DBG("%s", hdev->name);
2349
2350 hci_dev_lock(hdev);
2351
2352 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
2353 if (!conn)
2354 goto unlock;
2355
2356 hci_conn_hold(conn);
2357
2358 conn->remote_cap = ev->capability;
2359 conn->remote_oob = ev->oob_data;
2360 conn->remote_auth = ev->authentication;
2361
2362unlock:
Marcel Holtmann04936842008-07-14 20:13:48 +02002363 hci_dev_unlock(hdev);
2364}
2365
2366static inline void hci_simple_pair_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
2367{
2368 struct hci_ev_simple_pair_complete *ev = (void *) skb->data;
2369 struct hci_conn *conn;
2370
2371 BT_DBG("%s", hdev->name);
2372
2373 hci_dev_lock(hdev);
2374
2375 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
2376 if (conn)
2377 hci_conn_put(conn);
2378
2379 hci_dev_unlock(hdev);
2380}
2381
Marcel Holtmann41a96212008-07-14 20:13:48 +02002382static inline void hci_remote_host_features_evt(struct hci_dev *hdev, struct sk_buff *skb)
2383{
2384 struct hci_ev_remote_host_features *ev = (void *) skb->data;
2385 struct inquiry_entry *ie;
2386
2387 BT_DBG("%s", hdev->name);
2388
2389 hci_dev_lock(hdev);
2390
Andrei Emeltchenkocc11b9c2010-11-22 13:21:37 +02002391 ie = hci_inquiry_cache_lookup(hdev, &ev->bdaddr);
2392 if (ie)
Marcel Holtmann41a96212008-07-14 20:13:48 +02002393 ie->data.ssp_mode = (ev->features[0] & 0x01);
2394
2395 hci_dev_unlock(hdev);
2396}
2397
Ville Tervofcd89c02011-02-10 22:38:47 -03002398static inline void hci_le_conn_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
2399{
2400 struct hci_ev_le_conn_complete *ev = (void *) skb->data;
2401 struct hci_conn *conn;
2402
2403 BT_DBG("%s status %d", hdev->name, ev->status);
2404
2405 hci_dev_lock(hdev);
2406
2407 conn = hci_conn_hash_lookup_ba(hdev, LE_LINK, &ev->bdaddr);
2408 if (!conn)
2409 goto unlock;
2410
2411 if (ev->status) {
2412 hci_proto_connect_cfm(conn, ev->status);
2413 conn->state = BT_CLOSED;
2414 hci_conn_del(conn);
2415 goto unlock;
2416 }
2417
2418 conn->handle = __le16_to_cpu(ev->handle);
2419 conn->state = BT_CONNECTED;
2420
2421 hci_conn_hold_device(conn);
2422 hci_conn_add_sysfs(conn);
2423
2424 hci_proto_connect_cfm(conn, ev->status);
2425
2426unlock:
2427 hci_dev_unlock(hdev);
2428}
2429
2430static inline void hci_le_meta_evt(struct hci_dev *hdev, struct sk_buff *skb)
2431{
2432 struct hci_ev_le_meta *le_ev = (void *) skb->data;
2433
2434 skb_pull(skb, sizeof(*le_ev));
2435
2436 switch (le_ev->subevent) {
2437 case HCI_EV_LE_CONN_COMPLETE:
2438 hci_le_conn_complete_evt(hdev, skb);
2439 break;
2440
2441 default:
2442 break;
2443 }
2444}
2445
Linus Torvalds1da177e2005-04-16 15:20:36 -07002446void hci_event_packet(struct hci_dev *hdev, struct sk_buff *skb)
2447{
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002448 struct hci_event_hdr *hdr = (void *) skb->data;
2449 __u8 event = hdr->evt;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002450
2451 skb_pull(skb, HCI_EVENT_HDR_SIZE);
2452
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002453 switch (event) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002454 case HCI_EV_INQUIRY_COMPLETE:
2455 hci_inquiry_complete_evt(hdev, skb);
2456 break;
2457
2458 case HCI_EV_INQUIRY_RESULT:
2459 hci_inquiry_result_evt(hdev, skb);
2460 break;
2461
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002462 case HCI_EV_CONN_COMPLETE:
2463 hci_conn_complete_evt(hdev, skb);
Marcel Holtmann21d9e302005-09-13 01:32:25 +02002464 break;
2465
Linus Torvalds1da177e2005-04-16 15:20:36 -07002466 case HCI_EV_CONN_REQUEST:
2467 hci_conn_request_evt(hdev, skb);
2468 break;
2469
Linus Torvalds1da177e2005-04-16 15:20:36 -07002470 case HCI_EV_DISCONN_COMPLETE:
2471 hci_disconn_complete_evt(hdev, skb);
2472 break;
2473
Linus Torvalds1da177e2005-04-16 15:20:36 -07002474 case HCI_EV_AUTH_COMPLETE:
2475 hci_auth_complete_evt(hdev, skb);
2476 break;
2477
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002478 case HCI_EV_REMOTE_NAME:
2479 hci_remote_name_evt(hdev, skb);
2480 break;
2481
Linus Torvalds1da177e2005-04-16 15:20:36 -07002482 case HCI_EV_ENCRYPT_CHANGE:
2483 hci_encrypt_change_evt(hdev, skb);
2484 break;
2485
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002486 case HCI_EV_CHANGE_LINK_KEY_COMPLETE:
2487 hci_change_link_key_complete_evt(hdev, skb);
2488 break;
2489
2490 case HCI_EV_REMOTE_FEATURES:
2491 hci_remote_features_evt(hdev, skb);
2492 break;
2493
2494 case HCI_EV_REMOTE_VERSION:
2495 hci_remote_version_evt(hdev, skb);
2496 break;
2497
2498 case HCI_EV_QOS_SETUP_COMPLETE:
2499 hci_qos_setup_complete_evt(hdev, skb);
2500 break;
2501
2502 case HCI_EV_CMD_COMPLETE:
2503 hci_cmd_complete_evt(hdev, skb);
2504 break;
2505
2506 case HCI_EV_CMD_STATUS:
2507 hci_cmd_status_evt(hdev, skb);
2508 break;
2509
2510 case HCI_EV_ROLE_CHANGE:
2511 hci_role_change_evt(hdev, skb);
2512 break;
2513
2514 case HCI_EV_NUM_COMP_PKTS:
2515 hci_num_comp_pkts_evt(hdev, skb);
2516 break;
2517
2518 case HCI_EV_MODE_CHANGE:
2519 hci_mode_change_evt(hdev, skb);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002520 break;
2521
2522 case HCI_EV_PIN_CODE_REQ:
2523 hci_pin_code_request_evt(hdev, skb);
2524 break;
2525
2526 case HCI_EV_LINK_KEY_REQ:
2527 hci_link_key_request_evt(hdev, skb);
2528 break;
2529
2530 case HCI_EV_LINK_KEY_NOTIFY:
2531 hci_link_key_notify_evt(hdev, skb);
2532 break;
2533
2534 case HCI_EV_CLOCK_OFFSET:
2535 hci_clock_offset_evt(hdev, skb);
2536 break;
2537
Marcel Holtmanna8746412008-07-14 20:13:46 +02002538 case HCI_EV_PKT_TYPE_CHANGE:
2539 hci_pkt_type_change_evt(hdev, skb);
2540 break;
2541
Marcel Holtmann85a1e932005-08-09 20:28:02 -07002542 case HCI_EV_PSCAN_REP_MODE:
2543 hci_pscan_rep_mode_evt(hdev, skb);
2544 break;
2545
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002546 case HCI_EV_INQUIRY_RESULT_WITH_RSSI:
2547 hci_inquiry_result_with_rssi_evt(hdev, skb);
2548 break;
2549
2550 case HCI_EV_REMOTE_EXT_FEATURES:
2551 hci_remote_ext_features_evt(hdev, skb);
2552 break;
2553
2554 case HCI_EV_SYNC_CONN_COMPLETE:
2555 hci_sync_conn_complete_evt(hdev, skb);
2556 break;
2557
2558 case HCI_EV_SYNC_CONN_CHANGED:
2559 hci_sync_conn_changed_evt(hdev, skb);
2560 break;
2561
Marcel Holtmann04837f62006-07-03 10:02:33 +02002562 case HCI_EV_SNIFF_SUBRATE:
2563 hci_sniff_subrate_evt(hdev, skb);
2564 break;
2565
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002566 case HCI_EV_EXTENDED_INQUIRY_RESULT:
2567 hci_extended_inquiry_result_evt(hdev, skb);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002568 break;
2569
Marcel Holtmann04936842008-07-14 20:13:48 +02002570 case HCI_EV_IO_CAPA_REQUEST:
2571 hci_io_capa_request_evt(hdev, skb);
2572 break;
2573
Johan Hedberg03b555e2011-01-04 15:40:05 +02002574 case HCI_EV_IO_CAPA_REPLY:
2575 hci_io_capa_reply_evt(hdev, skb);
2576 break;
2577
Marcel Holtmann04936842008-07-14 20:13:48 +02002578 case HCI_EV_SIMPLE_PAIR_COMPLETE:
2579 hci_simple_pair_complete_evt(hdev, skb);
2580 break;
2581
Marcel Holtmann41a96212008-07-14 20:13:48 +02002582 case HCI_EV_REMOTE_HOST_FEATURES:
2583 hci_remote_host_features_evt(hdev, skb);
2584 break;
2585
Ville Tervofcd89c02011-02-10 22:38:47 -03002586 case HCI_EV_LE_META:
2587 hci_le_meta_evt(hdev, skb);
2588 break;
2589
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002590 default:
2591 BT_DBG("%s event 0x%x", hdev->name, event);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002592 break;
2593 }
2594
2595 kfree_skb(skb);
2596 hdev->stat.evt_rx++;
2597}
2598
2599/* Generate internal stack event */
2600void hci_si_event(struct hci_dev *hdev, int type, int dlen, void *data)
2601{
2602 struct hci_event_hdr *hdr;
2603 struct hci_ev_stack_internal *ev;
2604 struct sk_buff *skb;
2605
2606 skb = bt_skb_alloc(HCI_EVENT_HDR_SIZE + sizeof(*ev) + dlen, GFP_ATOMIC);
2607 if (!skb)
2608 return;
2609
2610 hdr = (void *) skb_put(skb, HCI_EVENT_HDR_SIZE);
2611 hdr->evt = HCI_EV_STACK_INTERNAL;
2612 hdr->plen = sizeof(*ev) + dlen;
2613
2614 ev = (void *) skb_put(skb, sizeof(*ev) + dlen);
2615 ev->type = type;
2616 memcpy(ev->data, data, dlen);
2617
Marcel Holtmann576c7d82005-08-06 12:36:54 +02002618 bt_cb(skb)->incoming = 1;
Patrick McHardya61bbcf2005-08-14 17:24:31 -07002619 __net_timestamp(skb);
Marcel Holtmann576c7d82005-08-06 12:36:54 +02002620
Marcel Holtmann0d48d932005-08-09 20:30:28 -07002621 bt_cb(skb)->pkt_type = HCI_EVENT_PKT;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002622 skb->dev = (void *) hdev;
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02002623 hci_send_to_sock(hdev, skb, NULL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002624 kfree_skb(skb);
2625}