blob: e2d649024a5b3cab4598f4da75e1bf09a0acdc9b [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
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003 Copyright (c) 2000-2001, 2010-2011, 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
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -070059 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
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -070075 clear_bit(HCI_INQUIRY, &hdev->flags);
Marcel Holtmanna9de9242007-10-20 13:33:56 +020076
77 hci_conn_check_pending(hdev);
78}
79
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -070080static void hci_cc_link_key_reply(struct hci_dev *hdev, struct sk_buff *skb)
81{
82 struct hci_rp_link_key_reply *rp = (void *) skb->data;
83 struct hci_conn *conn;
84 struct hci_cp_link_key_reply *cp;
85
86 BT_DBG("%s status 0x%x", hdev->name, rp->status);
87 if (rp->status)
88 return;
89
90 cp = hci_sent_cmd_data(hdev, HCI_OP_LINK_KEY_REPLY);
91 if (!cp)
92 return;
93
94 hci_dev_lock(hdev);
95 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &cp->bdaddr);
96 if (conn) {
97 hci_conn_hold(conn);
98 memcpy(conn->link_key, cp->link_key, sizeof(conn->link_key));
99 conn->key_type = 5;
100 hci_conn_put(conn);
101 }
102 hci_dev_unlock(hdev);
103}
104
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200105static void hci_cc_remote_name_req_cancel(struct hci_dev *hdev, struct sk_buff *skb)
106{
107 BT_DBG("%s", hdev->name);
108}
109
110static void hci_cc_role_discovery(struct hci_dev *hdev, struct sk_buff *skb)
111{
112 struct hci_rp_role_discovery *rp = (void *) skb->data;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700113 struct hci_conn *conn;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700114
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200115 BT_DBG("%s status 0x%x", hdev->name, rp->status);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700116
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200117 if (rp->status)
118 return;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700119
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200120 hci_dev_lock(hdev);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700121
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200122 conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(rp->handle));
123 if (conn) {
124 if (rp->role)
125 conn->link_mode &= ~HCI_LM_MASTER;
126 else
127 conn->link_mode |= HCI_LM_MASTER;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700128 }
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200129
130 hci_dev_unlock(hdev);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700131}
132
Marcel Holtmanne4e8e372008-07-14 20:13:47 +0200133static void hci_cc_read_link_policy(struct hci_dev *hdev, struct sk_buff *skb)
134{
135 struct hci_rp_read_link_policy *rp = (void *) skb->data;
136 struct hci_conn *conn;
137
138 BT_DBG("%s status 0x%x", hdev->name, rp->status);
139
140 if (rp->status)
141 return;
142
143 hci_dev_lock(hdev);
144
145 conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(rp->handle));
146 if (conn)
147 conn->link_policy = __le16_to_cpu(rp->policy);
148
149 hci_dev_unlock(hdev);
150}
151
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200152static void hci_cc_write_link_policy(struct hci_dev *hdev, struct sk_buff *skb)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700153{
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200154 struct hci_rp_write_link_policy *rp = (void *) skb->data;
155 struct hci_conn *conn;
156 void *sent;
157
158 BT_DBG("%s status 0x%x", hdev->name, rp->status);
159
160 if (rp->status)
161 return;
162
163 sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_LINK_POLICY);
164 if (!sent)
165 return;
166
167 hci_dev_lock(hdev);
168
169 conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(rp->handle));
Marcel Holtmanne4e8e372008-07-14 20:13:47 +0200170 if (conn)
Harvey Harrison83985312008-05-02 16:25:46 -0700171 conn->link_policy = get_unaligned_le16(sent + 2);
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200172
173 hci_dev_unlock(hdev);
174}
175
Marcel Holtmanne4e8e372008-07-14 20:13:47 +0200176static void hci_cc_read_def_link_policy(struct hci_dev *hdev, struct sk_buff *skb)
177{
178 struct hci_rp_read_def_link_policy *rp = (void *) skb->data;
179
180 BT_DBG("%s status 0x%x", hdev->name, rp->status);
181
182 if (rp->status)
183 return;
184
185 hdev->link_policy = __le16_to_cpu(rp->policy);
186}
187
188static void hci_cc_write_def_link_policy(struct hci_dev *hdev, struct sk_buff *skb)
189{
190 __u8 status = *((__u8 *) skb->data);
191 void *sent;
192
193 BT_DBG("%s status 0x%x", hdev->name, status);
194
195 sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_DEF_LINK_POLICY);
196 if (!sent)
197 return;
198
199 if (!status)
200 hdev->link_policy = get_unaligned_le16(sent);
201
Johan Hedberg23bb5762010-12-21 23:01:27 +0200202 hci_req_complete(hdev, HCI_OP_WRITE_DEF_LINK_POLICY, status);
Marcel Holtmanne4e8e372008-07-14 20:13:47 +0200203}
204
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200205static void hci_cc_reset(struct hci_dev *hdev, struct sk_buff *skb)
206{
207 __u8 status = *((__u8 *) skb->data);
208
209 BT_DBG("%s status 0x%x", hdev->name, status);
210
Gustavo F. Padovan10572132011-03-16 15:36:29 -0300211 clear_bit(HCI_RESET, &hdev->flags);
212
Johan Hedberg23bb5762010-12-21 23:01:27 +0200213 hci_req_complete(hdev, HCI_OP_RESET, status);
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200214}
215
216static void hci_cc_write_local_name(struct hci_dev *hdev, struct sk_buff *skb)
217{
218 __u8 status = *((__u8 *) skb->data);
219 void *sent;
220
221 BT_DBG("%s status 0x%x", hdev->name, status);
222
223 sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_LOCAL_NAME);
224 if (!sent)
225 return;
226
Johan Hedbergb312b1612011-03-16 14:29:37 +0200227 if (test_bit(HCI_MGMT, &hdev->flags))
228 mgmt_set_local_name_complete(hdev->id, sent, status);
229
230 if (status)
231 return;
232
Johan Hedberg1f6c6372011-03-16 14:29:35 +0200233 memcpy(hdev->dev_name, sent, HCI_MAX_NAME_LENGTH);
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200234}
235
236static void hci_cc_read_local_name(struct hci_dev *hdev, struct sk_buff *skb)
237{
238 struct hci_rp_read_local_name *rp = (void *) skb->data;
239
240 BT_DBG("%s status 0x%x", hdev->name, rp->status);
241
242 if (rp->status)
243 return;
244
Johan Hedberg1f6c6372011-03-16 14:29:35 +0200245 memcpy(hdev->dev_name, rp->name, HCI_MAX_NAME_LENGTH);
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200246}
247
248static void hci_cc_write_auth_enable(struct hci_dev *hdev, struct sk_buff *skb)
249{
250 __u8 status = *((__u8 *) skb->data);
251 void *sent;
252
253 BT_DBG("%s status 0x%x", hdev->name, status);
254
255 sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_AUTH_ENABLE);
256 if (!sent)
257 return;
258
259 if (!status) {
260 __u8 param = *((__u8 *) sent);
261
262 if (param == AUTH_ENABLED)
263 set_bit(HCI_AUTH, &hdev->flags);
264 else
265 clear_bit(HCI_AUTH, &hdev->flags);
266 }
267
Johan Hedberg23bb5762010-12-21 23:01:27 +0200268 hci_req_complete(hdev, HCI_OP_WRITE_AUTH_ENABLE, status);
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200269}
270
271static void hci_cc_write_encrypt_mode(struct hci_dev *hdev, struct sk_buff *skb)
272{
273 __u8 status = *((__u8 *) skb->data);
274 void *sent;
275
276 BT_DBG("%s status 0x%x", hdev->name, status);
277
278 sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_ENCRYPT_MODE);
279 if (!sent)
280 return;
281
282 if (!status) {
283 __u8 param = *((__u8 *) sent);
284
285 if (param)
286 set_bit(HCI_ENCRYPT, &hdev->flags);
287 else
288 clear_bit(HCI_ENCRYPT, &hdev->flags);
289 }
290
Johan Hedberg23bb5762010-12-21 23:01:27 +0200291 hci_req_complete(hdev, HCI_OP_WRITE_ENCRYPT_MODE, status);
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200292}
293
294static void hci_cc_write_scan_enable(struct hci_dev *hdev, struct sk_buff *skb)
295{
296 __u8 status = *((__u8 *) skb->data);
297 void *sent;
298
299 BT_DBG("%s status 0x%x", hdev->name, status);
300
301 sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_SCAN_ENABLE);
302 if (!sent)
303 return;
304
305 if (!status) {
306 __u8 param = *((__u8 *) sent);
Johan Hedberg9fbcbb42010-12-30 00:18:33 +0200307 int old_pscan, old_iscan;
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200308
Johan Hedberg9fbcbb42010-12-30 00:18:33 +0200309 old_pscan = test_and_clear_bit(HCI_PSCAN, &hdev->flags);
310 old_iscan = test_and_clear_bit(HCI_ISCAN, &hdev->flags);
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200311
Johan Hedberg73f22f62010-12-29 16:00:25 +0200312 if (param & SCAN_INQUIRY) {
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200313 set_bit(HCI_ISCAN, &hdev->flags);
Johan Hedberg9fbcbb42010-12-30 00:18:33 +0200314 if (!old_iscan)
315 mgmt_discoverable(hdev->id, 1);
316 } else if (old_iscan)
Johan Hedberg73f22f62010-12-29 16:00:25 +0200317 mgmt_discoverable(hdev->id, 0);
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200318
Johan Hedberg9fbcbb42010-12-30 00:18:33 +0200319 if (param & SCAN_PAGE) {
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200320 set_bit(HCI_PSCAN, &hdev->flags);
Johan Hedberg9fbcbb42010-12-30 00:18:33 +0200321 if (!old_pscan)
322 mgmt_connectable(hdev->id, 1);
323 } else if (old_pscan)
324 mgmt_connectable(hdev->id, 0);
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200325 }
326
Johan Hedberg23bb5762010-12-21 23:01:27 +0200327 hci_req_complete(hdev, HCI_OP_WRITE_SCAN_ENABLE, status);
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200328}
329
330static void hci_cc_read_class_of_dev(struct hci_dev *hdev, struct sk_buff *skb)
331{
332 struct hci_rp_read_class_of_dev *rp = (void *) skb->data;
333
334 BT_DBG("%s status 0x%x", hdev->name, rp->status);
335
336 if (rp->status)
337 return;
338
339 memcpy(hdev->dev_class, rp->dev_class, 3);
340
341 BT_DBG("%s class 0x%.2x%.2x%.2x", hdev->name,
342 hdev->dev_class[2], hdev->dev_class[1], hdev->dev_class[0]);
343}
344
345static void hci_cc_write_class_of_dev(struct hci_dev *hdev, struct sk_buff *skb)
346{
347 __u8 status = *((__u8 *) skb->data);
348 void *sent;
349
350 BT_DBG("%s status 0x%x", hdev->name, status);
351
Marcel Holtmannf383f272008-07-14 20:13:47 +0200352 if (status)
353 return;
354
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200355 sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_CLASS_OF_DEV);
356 if (!sent)
357 return;
358
Marcel Holtmannf383f272008-07-14 20:13:47 +0200359 memcpy(hdev->dev_class, sent, 3);
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200360}
361
362static void hci_cc_read_voice_setting(struct hci_dev *hdev, struct sk_buff *skb)
363{
364 struct hci_rp_read_voice_setting *rp = (void *) skb->data;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700365 __u16 setting;
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200366
367 BT_DBG("%s status 0x%x", hdev->name, rp->status);
368
369 if (rp->status)
370 return;
371
372 setting = __le16_to_cpu(rp->voice_setting);
373
Marcel Holtmannf383f272008-07-14 20:13:47 +0200374 if (hdev->voice_setting == setting)
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200375 return;
376
377 hdev->voice_setting = setting;
378
379 BT_DBG("%s voice setting 0x%04x", hdev->name, setting);
380
381 if (hdev->notify) {
382 tasklet_disable(&hdev->tx_task);
383 hdev->notify(hdev, HCI_NOTIFY_VOICE_SETTING);
384 tasklet_enable(&hdev->tx_task);
385 }
386}
387
388static void hci_cc_write_voice_setting(struct hci_dev *hdev, struct sk_buff *skb)
389{
390 __u8 status = *((__u8 *) skb->data);
Marcel Holtmannf383f272008-07-14 20:13:47 +0200391 __u16 setting;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700392 void *sent;
393
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200394 BT_DBG("%s status 0x%x", hdev->name, status);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700395
Marcel Holtmannf383f272008-07-14 20:13:47 +0200396 if (status)
397 return;
398
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200399 sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_VOICE_SETTING);
400 if (!sent)
401 return;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700402
Marcel Holtmannf383f272008-07-14 20:13:47 +0200403 setting = get_unaligned_le16(sent);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700404
Marcel Holtmannf383f272008-07-14 20:13:47 +0200405 if (hdev->voice_setting == setting)
406 return;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700407
Marcel Holtmannf383f272008-07-14 20:13:47 +0200408 hdev->voice_setting = setting;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700409
Marcel Holtmannf383f272008-07-14 20:13:47 +0200410 BT_DBG("%s voice setting 0x%04x", hdev->name, setting);
411
412 if (hdev->notify) {
413 tasklet_disable(&hdev->tx_task);
414 hdev->notify(hdev, HCI_NOTIFY_VOICE_SETTING);
415 tasklet_enable(&hdev->tx_task);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700416 }
417}
418
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200419static void hci_cc_host_buffer_size(struct hci_dev *hdev, struct sk_buff *skb)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700420{
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200421 __u8 status = *((__u8 *) skb->data);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700422
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200423 BT_DBG("%s status 0x%x", hdev->name, status);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700424
Johan Hedberg23bb5762010-12-21 23:01:27 +0200425 hci_req_complete(hdev, HCI_OP_HOST_BUFFER_SIZE, status);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700426}
427
Marcel Holtmann333140b2008-07-14 20:13:48 +0200428static void hci_cc_read_ssp_mode(struct hci_dev *hdev, struct sk_buff *skb)
429{
430 struct hci_rp_read_ssp_mode *rp = (void *) skb->data;
431
432 BT_DBG("%s status 0x%x", hdev->name, rp->status);
433
434 if (rp->status)
435 return;
436
437 hdev->ssp_mode = rp->mode;
438}
439
440static void hci_cc_write_ssp_mode(struct hci_dev *hdev, struct sk_buff *skb)
441{
442 __u8 status = *((__u8 *) skb->data);
443 void *sent;
444
445 BT_DBG("%s status 0x%x", hdev->name, status);
446
447 if (status)
448 return;
449
450 sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_SSP_MODE);
451 if (!sent)
452 return;
453
454 hdev->ssp_mode = *((__u8 *) sent);
455}
456
Johan Hedbergd5859e22011-01-25 01:19:58 +0200457static u8 hci_get_inquiry_mode(struct hci_dev *hdev)
458{
459 if (hdev->features[6] & LMP_EXT_INQ)
460 return 2;
461
462 if (hdev->features[3] & LMP_RSSI_INQ)
463 return 1;
464
465 if (hdev->manufacturer == 11 && hdev->hci_rev == 0x00 &&
466 hdev->lmp_subver == 0x0757)
467 return 1;
468
469 if (hdev->manufacturer == 15) {
470 if (hdev->hci_rev == 0x03 && hdev->lmp_subver == 0x6963)
471 return 1;
472 if (hdev->hci_rev == 0x09 && hdev->lmp_subver == 0x6963)
473 return 1;
474 if (hdev->hci_rev == 0x00 && hdev->lmp_subver == 0x6965)
475 return 1;
476 }
477
478 if (hdev->manufacturer == 31 && hdev->hci_rev == 0x2005 &&
479 hdev->lmp_subver == 0x1805)
480 return 1;
481
482 return 0;
483}
484
485static void hci_setup_inquiry_mode(struct hci_dev *hdev)
486{
487 u8 mode;
488
489 mode = hci_get_inquiry_mode(hdev);
490
491 hci_send_cmd(hdev, HCI_OP_WRITE_INQUIRY_MODE, 1, &mode);
492}
493
494static void hci_setup_event_mask(struct hci_dev *hdev)
495{
496 /* The second byte is 0xff instead of 0x9f (two reserved bits
497 * disabled) since a Broadcom 1.2 dongle doesn't respond to the
498 * command otherwise */
499 u8 events[8] = { 0xff, 0xff, 0xfb, 0xff, 0x00, 0x00, 0x00, 0x00 };
500
Brian Gixa68668b2011-08-11 15:49:36 -0700501 BT_DBG("");
502
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700503 /* Events for 1.2 and newer controllers */
504 if (hdev->lmp_ver > 1) {
505 events[4] |= 0x01; /* Flow Specification Complete */
506 events[4] |= 0x02; /* Inquiry Result with RSSI */
507 events[4] |= 0x04; /* Read Remote Extended Features Complete */
508 events[5] |= 0x08; /* Synchronous Connection Complete */
509 events[5] |= 0x10; /* Synchronous Connection Changed */
510 }
Johan Hedbergd5859e22011-01-25 01:19:58 +0200511
512 if (hdev->features[3] & LMP_RSSI_INQ)
513 events[4] |= 0x04; /* Inquiry Result with RSSI */
514
515 if (hdev->features[5] & LMP_SNIFF_SUBR)
516 events[5] |= 0x20; /* Sniff Subrating */
517
518 if (hdev->features[5] & LMP_PAUSE_ENC)
519 events[5] |= 0x80; /* Encryption Key Refresh Complete */
520
521 if (hdev->features[6] & LMP_EXT_INQ)
522 events[5] |= 0x40; /* Extended Inquiry Result */
523
524 if (hdev->features[6] & LMP_NO_FLUSH)
525 events[7] |= 0x01; /* Enhanced Flush Complete */
526
527 if (hdev->features[7] & LMP_LSTO)
528 events[6] |= 0x80; /* Link Supervision Timeout Changed */
529
530 if (hdev->features[6] & LMP_SIMPLE_PAIR) {
531 events[6] |= 0x01; /* IO Capability Request */
532 events[6] |= 0x02; /* IO Capability Response */
533 events[6] |= 0x04; /* User Confirmation Request */
534 events[6] |= 0x08; /* User Passkey Request */
535 events[6] |= 0x10; /* Remote OOB Data Request */
536 events[6] |= 0x20; /* Simple Pairing Complete */
537 events[7] |= 0x04; /* User Passkey Notification */
538 events[7] |= 0x08; /* Keypress Notification */
539 events[7] |= 0x10; /* Remote Host Supported
540 * Features Notification */
541 }
542
543 if (hdev->features[4] & LMP_LE)
544 events[7] |= 0x20; /* LE Meta-Event */
545
546 hci_send_cmd(hdev, HCI_OP_SET_EVENT_MASK, sizeof(events), events);
547}
548
549static void hci_setup(struct hci_dev *hdev)
550{
Johan Hedbergd5859e22011-01-25 01:19:58 +0200551 if (hdev->lmp_ver > 1)
552 hci_send_cmd(hdev, HCI_OP_READ_LOCAL_COMMANDS, 0, NULL);
553
554 if (hdev->features[6] & LMP_SIMPLE_PAIR) {
555 u8 mode = 0x01;
556 hci_send_cmd(hdev, HCI_OP_WRITE_SSP_MODE, sizeof(mode), &mode);
557 }
558
559 if (hdev->features[3] & LMP_RSSI_INQ)
560 hci_setup_inquiry_mode(hdev);
561
562 if (hdev->features[7] & LMP_INQ_TX_PWR)
563 hci_send_cmd(hdev, HCI_OP_READ_INQ_RSP_TX_POWER, 0, NULL);
564}
565
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200566static void hci_cc_read_local_version(struct hci_dev *hdev, struct sk_buff *skb)
567{
568 struct hci_rp_read_local_version *rp = (void *) skb->data;
569
570 BT_DBG("%s status 0x%x", hdev->name, rp->status);
571
572 if (rp->status)
573 return;
574
575 hdev->hci_ver = rp->hci_ver;
Marcel Holtmanne4e8e372008-07-14 20:13:47 +0200576 hdev->hci_rev = __le16_to_cpu(rp->hci_rev);
Johan Hedbergd5859e22011-01-25 01:19:58 +0200577 hdev->lmp_ver = rp->lmp_ver;
Marcel Holtmanne4e8e372008-07-14 20:13:47 +0200578 hdev->manufacturer = __le16_to_cpu(rp->manufacturer);
Johan Hedbergd5859e22011-01-25 01:19:58 +0200579 hdev->lmp_subver = __le16_to_cpu(rp->lmp_subver);
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200580
581 BT_DBG("%s manufacturer %d hci ver %d:%d", hdev->name,
582 hdev->manufacturer,
583 hdev->hci_ver, hdev->hci_rev);
Johan Hedbergd5859e22011-01-25 01:19:58 +0200584
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700585 if (hdev->dev_type == HCI_BREDR && test_bit(HCI_INIT, &hdev->flags))
Johan Hedbergd5859e22011-01-25 01:19:58 +0200586 hci_setup(hdev);
587}
588
589static void hci_setup_link_policy(struct hci_dev *hdev)
590{
591 u16 link_policy = 0;
592
593 if (hdev->features[0] & LMP_RSWITCH)
594 link_policy |= HCI_LP_RSWITCH;
595 if (hdev->features[0] & LMP_HOLD)
596 link_policy |= HCI_LP_HOLD;
597 if (hdev->features[0] & LMP_SNIFF)
598 link_policy |= HCI_LP_SNIFF;
599 if (hdev->features[1] & LMP_PARK)
600 link_policy |= HCI_LP_PARK;
601
602 link_policy = cpu_to_le16(link_policy);
603 hci_send_cmd(hdev, HCI_OP_WRITE_DEF_LINK_POLICY,
604 sizeof(link_policy), &link_policy);
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200605}
606
607static void hci_cc_read_local_commands(struct hci_dev *hdev, struct sk_buff *skb)
608{
609 struct hci_rp_read_local_commands *rp = (void *) skb->data;
610
611 BT_DBG("%s status 0x%x", hdev->name, rp->status);
612
613 if (rp->status)
Johan Hedbergd5859e22011-01-25 01:19:58 +0200614 goto done;
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200615
616 memcpy(hdev->commands, rp->commands, sizeof(hdev->commands));
Johan Hedbergd5859e22011-01-25 01:19:58 +0200617
618 if (test_bit(HCI_INIT, &hdev->flags) && (hdev->commands[5] & 0x10))
619 hci_setup_link_policy(hdev);
620
621done:
622 hci_req_complete(hdev, HCI_OP_READ_LOCAL_COMMANDS, rp->status);
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200623}
624
625static void hci_cc_read_local_features(struct hci_dev *hdev, struct sk_buff *skb)
626{
627 struct hci_rp_read_local_features *rp = (void *) skb->data;
628
629 BT_DBG("%s status 0x%x", hdev->name, rp->status);
630
631 if (rp->status)
632 return;
633
634 memcpy(hdev->features, rp->features, 8);
635
Brian Gixa68668b2011-08-11 15:49:36 -0700636 if (hdev->dev_type == HCI_BREDR && test_bit(HCI_INIT, &hdev->flags)) {
637 if (hdev->features[6] & LMP_SIMPLE_PAIR) {
638 u8 mode = 0x01;
639 hci_send_cmd(hdev, HCI_OP_WRITE_SSP_MODE,
640 sizeof(mode), &mode);
641 }
642
643 if (hdev->features[3] & LMP_RSSI_INQ)
644 hci_setup_inquiry_mode(hdev);
645
646 if (hdev->features[7] & LMP_INQ_TX_PWR)
647 hci_send_cmd(hdev, HCI_OP_READ_INQ_RSP_TX_POWER,
648 0, NULL);
649
650 hci_setup_event_mask(hdev);
651 }
652
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200653 /* Adjust default settings according to features
654 * supported by device. */
655
656 if (hdev->features[0] & LMP_3SLOT)
657 hdev->pkt_type |= (HCI_DM3 | HCI_DH3);
658
659 if (hdev->features[0] & LMP_5SLOT)
660 hdev->pkt_type |= (HCI_DM5 | HCI_DH5);
661
662 if (hdev->features[1] & LMP_HV2) {
663 hdev->pkt_type |= (HCI_HV2);
664 hdev->esco_type |= (ESCO_HV2);
665 }
666
667 if (hdev->features[1] & LMP_HV3) {
668 hdev->pkt_type |= (HCI_HV3);
669 hdev->esco_type |= (ESCO_HV3);
670 }
671
672 if (hdev->features[3] & LMP_ESCO)
673 hdev->esco_type |= (ESCO_EV3);
674
675 if (hdev->features[4] & LMP_EV4)
676 hdev->esco_type |= (ESCO_EV4);
677
678 if (hdev->features[4] & LMP_EV5)
679 hdev->esco_type |= (ESCO_EV5);
680
Marcel Holtmannefc76882009-02-06 09:13:37 +0100681 if (hdev->features[5] & LMP_EDR_ESCO_2M)
682 hdev->esco_type |= (ESCO_2EV3);
683
684 if (hdev->features[5] & LMP_EDR_ESCO_3M)
685 hdev->esco_type |= (ESCO_3EV3);
686
687 if (hdev->features[5] & LMP_EDR_3S_ESCO)
688 hdev->esco_type |= (ESCO_2EV5 | ESCO_3EV5);
689
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200690 BT_DBG("%s features 0x%.2x%.2x%.2x%.2x%.2x%.2x%.2x%.2x", hdev->name,
691 hdev->features[0], hdev->features[1],
692 hdev->features[2], hdev->features[3],
693 hdev->features[4], hdev->features[5],
694 hdev->features[6], hdev->features[7]);
695}
696
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700697static void hci_cc_read_flow_control_mode(struct hci_dev *hdev,
698 struct sk_buff *skb)
Andre Guedesd5fa5132011-06-30 19:20:52 -0300699{
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700700 struct hci_rp_read_flow_control_mode *rp = (void *) skb->data;
Andre Guedesd5fa5132011-06-30 19:20:52 -0300701
702 BT_DBG("%s status 0x%x", hdev->name, rp->status);
703
704 if (rp->status)
705 return;
706
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700707 hdev->flow_ctl_mode = rp->mode;
Andre Guedesd5fa5132011-06-30 19:20:52 -0300708}
709
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200710static void hci_cc_read_buffer_size(struct hci_dev *hdev, struct sk_buff *skb)
711{
712 struct hci_rp_read_buffer_size *rp = (void *) skb->data;
713
714 BT_DBG("%s status 0x%x", hdev->name, rp->status);
715
716 if (rp->status)
717 return;
718
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700719 if (hdev->flow_ctl_mode == HCI_PACKET_BASED_FLOW_CTL_MODE) {
720 hdev->acl_mtu = __le16_to_cpu(rp->acl_mtu);
721 hdev->sco_mtu = rp->sco_mtu;
722 hdev->acl_pkts = __le16_to_cpu(rp->acl_max_pkt);
723 hdev->sco_pkts = __le16_to_cpu(rp->sco_max_pkt);
724 hdev->acl_cnt = hdev->acl_pkts;
725 hdev->sco_cnt = hdev->sco_pkts;
726 }
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200727
728 if (test_bit(HCI_QUIRK_FIXUP_BUFFER_SIZE, &hdev->quirks)) {
729 hdev->sco_mtu = 64;
730 hdev->sco_pkts = 8;
731 }
732
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200733
734 BT_DBG("%s acl mtu %d:%d sco mtu %d:%d", hdev->name,
735 hdev->acl_mtu, hdev->acl_pkts,
736 hdev->sco_mtu, hdev->sco_pkts);
737}
738
739static void hci_cc_read_bd_addr(struct hci_dev *hdev, struct sk_buff *skb)
740{
741 struct hci_rp_read_bd_addr *rp = (void *) skb->data;
742
743 BT_DBG("%s status 0x%x", hdev->name, rp->status);
744
745 if (!rp->status)
746 bacpy(&hdev->bdaddr, &rp->bdaddr);
747
Johan Hedberg23bb5762010-12-21 23:01:27 +0200748 hci_req_complete(hdev, HCI_OP_READ_BD_ADDR, rp->status);
749}
750
751static void hci_cc_write_ca_timeout(struct hci_dev *hdev, struct sk_buff *skb)
752{
753 __u8 status = *((__u8 *) skb->data);
754
755 BT_DBG("%s status 0x%x", hdev->name, status);
756
757 hci_req_complete(hdev, HCI_OP_WRITE_CA_TIMEOUT, status);
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200758}
759
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700760static void hci_cc_read_data_block_size(struct hci_dev *hdev,
761 struct sk_buff *skb)
762{
763 struct hci_rp_read_data_block_size *rp = (void *) skb->data;
764
765 BT_DBG("%s status 0x%x", hdev->name, rp->status);
766
767 if (rp->status)
768 return;
769
770 if (hdev->flow_ctl_mode == HCI_BLOCK_BASED_FLOW_CTL_MODE) {
771 hdev->acl_mtu = __le16_to_cpu(rp->max_acl_len);
772 hdev->sco_mtu = 0;
773 hdev->data_block_len = __le16_to_cpu(rp->data_block_len);
774 /* acl_pkts indicates the number of blocks */
775 hdev->acl_pkts = __le16_to_cpu(rp->num_blocks);
776 hdev->sco_pkts = 0;
777 hdev->acl_cnt = hdev->acl_pkts;
778 hdev->sco_cnt = 0;
779 }
780
781 BT_DBG("%s acl mtu %d:%d, data block len %d", hdev->name,
782 hdev->acl_mtu, hdev->acl_cnt, hdev->data_block_len);
783}
784
785static void hci_cc_read_local_amp_info(struct hci_dev *hdev,
786 struct sk_buff *skb)
787{
788 struct hci_rp_read_local_amp_info *rp = (void *) skb->data;
789
790 BT_DBG("%s status 0x%x", hdev->name, rp->status);
791
792 if (rp->status)
793 return;
794
795 hdev->amp_status = rp->amp_status;
796 hdev->amp_total_bw = __le32_to_cpu(rp->total_bw);
797 hdev->amp_max_bw = __le32_to_cpu(rp->max_bw);
798 hdev->amp_min_latency = __le32_to_cpu(rp->min_latency);
799 hdev->amp_max_pdu = __le32_to_cpu(rp->max_pdu);
800 hdev->amp_type = rp->amp_type;
801 hdev->amp_pal_cap = __le16_to_cpu(rp->pal_cap);
802 hdev->amp_assoc_size = __le16_to_cpu(rp->max_assoc_size);
803 hdev->amp_be_flush_to = __le32_to_cpu(rp->be_flush_to);
804 hdev->amp_max_flush_to = __le32_to_cpu(rp->max_flush_to);
805
806 hci_req_complete(hdev, HCI_OP_READ_LOCAL_AMP_INFO, rp->status);
807}
808
Johan Hedbergb0916ea2011-01-10 13:44:55 +0200809static void hci_cc_delete_stored_link_key(struct hci_dev *hdev,
810 struct sk_buff *skb)
811{
812 __u8 status = *((__u8 *) skb->data);
813
814 BT_DBG("%s status 0x%x", hdev->name, status);
815
816 hci_req_complete(hdev, HCI_OP_DELETE_STORED_LINK_KEY, status);
817}
818
Johan Hedbergd5859e22011-01-25 01:19:58 +0200819static void hci_cc_set_event_mask(struct hci_dev *hdev, struct sk_buff *skb)
820{
821 __u8 status = *((__u8 *) skb->data);
822
823 BT_DBG("%s status 0x%x", hdev->name, status);
824
825 hci_req_complete(hdev, HCI_OP_SET_EVENT_MASK, status);
826}
827
828static void hci_cc_write_inquiry_mode(struct hci_dev *hdev,
829 struct sk_buff *skb)
830{
831 __u8 status = *((__u8 *) skb->data);
832
833 BT_DBG("%s status 0x%x", hdev->name, status);
834
835 hci_req_complete(hdev, HCI_OP_WRITE_INQUIRY_MODE, status);
836}
837
838static void hci_cc_read_inq_rsp_tx_power(struct hci_dev *hdev,
839 struct sk_buff *skb)
840{
841 __u8 status = *((__u8 *) skb->data);
842
843 BT_DBG("%s status 0x%x", hdev->name, status);
844
845 hci_req_complete(hdev, HCI_OP_READ_INQ_RSP_TX_POWER, status);
846}
847
848static void hci_cc_set_event_flt(struct hci_dev *hdev, struct sk_buff *skb)
849{
850 __u8 status = *((__u8 *) skb->data);
851
852 BT_DBG("%s status 0x%x", hdev->name, status);
853
854 hci_req_complete(hdev, HCI_OP_SET_EVENT_FLT, status);
855}
856
Johan Hedberg980e1a52011-01-22 06:10:07 +0200857static void hci_cc_pin_code_reply(struct hci_dev *hdev, struct sk_buff *skb)
858{
859 struct hci_rp_pin_code_reply *rp = (void *) skb->data;
860 struct hci_cp_pin_code_reply *cp;
861 struct hci_conn *conn;
862
863 BT_DBG("%s status 0x%x", hdev->name, rp->status);
864
865 if (test_bit(HCI_MGMT, &hdev->flags))
866 mgmt_pin_code_reply_complete(hdev->id, &rp->bdaddr, rp->status);
867
868 if (rp->status != 0)
869 return;
870
871 cp = hci_sent_cmd_data(hdev, HCI_OP_PIN_CODE_REPLY);
872 if (!cp)
873 return;
874
875 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &cp->bdaddr);
876 if (conn)
877 conn->pin_length = cp->pin_len;
878}
879
880static void hci_cc_pin_code_neg_reply(struct hci_dev *hdev, struct sk_buff *skb)
881{
882 struct hci_rp_pin_code_neg_reply *rp = (void *) skb->data;
883
884 BT_DBG("%s status 0x%x", hdev->name, rp->status);
885
886 if (test_bit(HCI_MGMT, &hdev->flags))
887 mgmt_pin_code_neg_reply_complete(hdev->id, &rp->bdaddr,
888 rp->status);
889}
Ville Tervo6ed58ec2011-02-10 22:38:48 -0300890static void hci_cc_le_read_buffer_size(struct hci_dev *hdev,
891 struct sk_buff *skb)
892{
893 struct hci_rp_le_read_buffer_size *rp = (void *) skb->data;
894
895 BT_DBG("%s status 0x%x", hdev->name, rp->status);
896
897 if (rp->status)
898 return;
899
900 hdev->le_mtu = __le16_to_cpu(rp->le_mtu);
901 hdev->le_pkts = rp->le_max_pkt;
902
903 hdev->le_cnt = hdev->le_pkts;
904
905 BT_DBG("%s le mtu %d:%d", hdev->name, hdev->le_mtu, hdev->le_pkts);
906
907 hci_req_complete(hdev, HCI_OP_LE_READ_BUFFER_SIZE, rp->status);
908}
Johan Hedberg980e1a52011-01-22 06:10:07 +0200909
Johan Hedberga5c29682011-02-19 12:05:57 -0300910static void hci_cc_user_confirm_reply(struct hci_dev *hdev, struct sk_buff *skb)
911{
912 struct hci_rp_user_confirm_reply *rp = (void *) skb->data;
913
914 BT_DBG("%s status 0x%x", hdev->name, rp->status);
915
916 if (test_bit(HCI_MGMT, &hdev->flags))
917 mgmt_user_confirm_reply_complete(hdev->id, &rp->bdaddr,
918 rp->status);
919}
920
921static void hci_cc_user_confirm_neg_reply(struct hci_dev *hdev,
922 struct sk_buff *skb)
923{
924 struct hci_rp_user_confirm_reply *rp = (void *) skb->data;
925
926 BT_DBG("%s status 0x%x", hdev->name, rp->status);
927
928 if (test_bit(HCI_MGMT, &hdev->flags))
929 mgmt_user_confirm_neg_reply_complete(hdev->id, &rp->bdaddr,
930 rp->status);
931}
932
Szymon Jancc35938b2011-03-22 13:12:21 +0100933static void hci_cc_read_local_oob_data_reply(struct hci_dev *hdev,
934 struct sk_buff *skb)
935{
936 struct hci_rp_read_local_oob_data *rp = (void *) skb->data;
937
938 BT_DBG("%s status 0x%x", hdev->name, rp->status);
939
940 mgmt_read_local_oob_data_reply_complete(hdev->id, rp->hash,
941 rp->randomizer, rp->status);
942}
943
Vinicius Costa Gomes735038c2011-06-09 18:50:47 -0300944static void hci_cc_le_ltk_reply(struct hci_dev *hdev, struct sk_buff *skb)
945{
946 struct hci_rp_le_ltk_reply *rp = (void *) skb->data;
947
948 BT_DBG("%s status 0x%x", hdev->name, rp->status);
949
950 if (rp->status)
951 return;
952
953 hci_req_complete(hdev, HCI_OP_LE_LTK_REPLY, rp->status);
954}
955
956static void hci_cc_le_ltk_neg_reply(struct hci_dev *hdev, struct sk_buff *skb)
957{
958 struct hci_rp_le_ltk_neg_reply *rp = (void *) skb->data;
959
960 BT_DBG("%s status 0x%x", hdev->name, rp->status);
961
962 if (rp->status)
963 return;
964
965 hci_req_complete(hdev, HCI_OP_LE_LTK_NEG_REPLY, rp->status);
966}
967
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700968static void hci_cc_le_set_scan_enable(struct hci_dev *hdev,
969 struct sk_buff *skb)
Andre Guedese326af42011-06-30 19:20:53 -0300970{
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700971 void *sent;
972 __u8 param_scan_enable;
Andre Guedese326af42011-06-30 19:20:53 -0300973 __u8 status = *((__u8 *) skb->data);
974
Andre Guedese326af42011-06-30 19:20:53 -0300975 if (status)
976 return;
977
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700978 sent = hci_sent_cmd_data(hdev, HCI_OP_LE_SET_SCAN_ENABLE);
979 if (!sent)
980 return;
981
982 param_scan_enable = *((__u8 *) sent);
983 if (param_scan_enable == 0x01) {
984 del_timer(&hdev->adv_timer);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700985 } else if (param_scan_enable == 0x00) {
986 mod_timer(&hdev->adv_timer, jiffies + ADV_CLEAR_TIMEOUT);
987 }
Andre Guedese326af42011-06-30 19:20:53 -0300988}
989
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200990static inline void hci_cs_inquiry(struct hci_dev *hdev, __u8 status)
991{
992 BT_DBG("%s status 0x%x", hdev->name, status);
993
994 if (status) {
Johan Hedberg23bb5762010-12-21 23:01:27 +0200995 hci_req_complete(hdev, HCI_OP_INQUIRY, status);
Johan Hedberg314b2382011-04-27 10:29:57 -0400996
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700997 hci_conn_check_pending(hdev);
Brian Gixa68668b2011-08-11 15:49:36 -0700998 } else {
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700999 set_bit(HCI_INQUIRY, &hdev->flags);
Brian Gixa68668b2011-08-11 15:49:36 -07001000 if (test_bit(HCI_MGMT, &hdev->flags))
1001 mgmt_inquiry_started(hdev->id);
1002 }
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001003}
1004
Linus Torvalds1da177e2005-04-16 15:20:36 -07001005static inline void hci_cs_create_conn(struct hci_dev *hdev, __u8 status)
1006{
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001007 struct hci_cp_create_conn *cp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001008 struct hci_conn *conn;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001009
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001010 BT_DBG("%s status 0x%x", hdev->name, status);
1011
1012 cp = hci_sent_cmd_data(hdev, HCI_OP_CREATE_CONN);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001013 if (!cp)
1014 return;
1015
1016 hci_dev_lock(hdev);
1017
1018 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &cp->bdaddr);
1019
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001020 BT_DBG("%s bdaddr %s conn %p", hdev->name, batostr(&cp->bdaddr), conn);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001021
1022 if (status) {
1023 if (conn && conn->state == BT_CONNECT) {
Marcel Holtmann4c67bc72006-10-15 17:30:56 +02001024 if (status != 0x0c || conn->attempt > 2) {
1025 conn->state = BT_CLOSED;
1026 hci_proto_connect_cfm(conn, status);
1027 hci_conn_del(conn);
1028 } else
1029 conn->state = BT_CONNECT2;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001030 }
1031 } else {
1032 if (!conn) {
Nick Pellybbcda3b2010-02-11 11:54:28 -08001033 conn = hci_conn_add(hdev, ACL_LINK, 0, &cp->bdaddr);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001034 if (conn) {
1035 conn->out = 1;
1036 conn->link_mode |= HCI_LM_MASTER;
1037 } else
Gustavo F. Padovan893ef972010-07-18 15:13:37 -03001038 BT_ERR("No memory for new connection");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001039 }
1040 }
1041
1042 hci_dev_unlock(hdev);
1043}
1044
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001045static void hci_cs_add_sco(struct hci_dev *hdev, __u8 status)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001046{
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001047 struct hci_cp_add_sco *cp;
1048 struct hci_conn *acl, *sco;
1049 __u16 handle;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001050
Marcel Holtmannb6a0dc82007-10-20 14:55:10 +02001051 BT_DBG("%s status 0x%x", hdev->name, status);
1052
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001053 if (!status)
1054 return;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001055
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001056 cp = hci_sent_cmd_data(hdev, HCI_OP_ADD_SCO);
1057 if (!cp)
1058 return;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001059
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001060 handle = __le16_to_cpu(cp->handle);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001061
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001062 BT_DBG("%s handle %d", hdev->name, handle);
Marcel Holtmann6bd57412006-11-18 22:14:22 +01001063
1064 hci_dev_lock(hdev);
1065
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001066 acl = hci_conn_hash_lookup_handle(hdev, handle);
Andrei Emeltchenko5a08ecc2011-01-11 17:20:20 +02001067 if (acl) {
1068 sco = acl->link;
1069 if (sco) {
1070 sco->state = BT_CLOSED;
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001071
Andrei Emeltchenko5a08ecc2011-01-11 17:20:20 +02001072 hci_proto_connect_cfm(sco, status);
1073 hci_conn_del(sco);
1074 }
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001075 }
Marcel Holtmann6bd57412006-11-18 22:14:22 +01001076
1077 hci_dev_unlock(hdev);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001078}
1079
Marcel Holtmannf8558552008-07-14 20:13:49 +02001080static void hci_cs_auth_requested(struct hci_dev *hdev, __u8 status)
1081{
1082 struct hci_cp_auth_requested *cp;
1083 struct hci_conn *conn;
1084
1085 BT_DBG("%s status 0x%x", hdev->name, status);
1086
Marcel Holtmannf8558552008-07-14 20:13:49 +02001087 cp = hci_sent_cmd_data(hdev, HCI_OP_AUTH_REQUESTED);
1088 if (!cp)
1089 return;
1090
1091 hci_dev_lock(hdev);
1092
1093 conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(cp->handle));
1094 if (conn) {
Srinivas Krovvidi9ff51452011-09-27 19:25:02 +05301095 if (status && conn->state == BT_CONFIG) {
Marcel Holtmannf8558552008-07-14 20:13:49 +02001096 hci_proto_connect_cfm(conn, status);
1097 hci_conn_put(conn);
1098 }
Srinivas Krovvidi9ff51452011-09-27 19:25:02 +05301099 conn->auth_initiator = 1;
Marcel Holtmannf8558552008-07-14 20:13:49 +02001100 }
1101
1102 hci_dev_unlock(hdev);
1103}
1104
1105static void hci_cs_set_conn_encrypt(struct hci_dev *hdev, __u8 status)
1106{
1107 struct hci_cp_set_conn_encrypt *cp;
1108 struct hci_conn *conn;
1109
1110 BT_DBG("%s status 0x%x", hdev->name, status);
1111
1112 if (!status)
1113 return;
1114
1115 cp = hci_sent_cmd_data(hdev, HCI_OP_SET_CONN_ENCRYPT);
1116 if (!cp)
1117 return;
1118
1119 hci_dev_lock(hdev);
1120
1121 conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(cp->handle));
1122 if (conn) {
1123 if (conn->state == BT_CONFIG) {
1124 hci_proto_connect_cfm(conn, status);
1125 hci_conn_put(conn);
1126 }
1127 }
1128
1129 hci_dev_unlock(hdev);
1130}
1131
Johan Hedberg127178d2010-11-18 22:22:29 +02001132static int hci_outgoing_auth_needed(struct hci_dev *hdev,
Szymon Janc138d22e2011-02-17 16:44:23 +01001133 struct hci_conn *conn)
Johan Hedberg392599b2010-11-18 22:22:28 +02001134{
Johan Hedberg392599b2010-11-18 22:22:28 +02001135 if (conn->state != BT_CONFIG || !conn->out)
1136 return 0;
1137
Johan Hedberg765c2a92011-01-19 12:06:52 +05301138 if (conn->pending_sec_level == BT_SECURITY_SDP)
Johan Hedberg392599b2010-11-18 22:22:28 +02001139 return 0;
1140
1141 /* Only request authentication for SSP connections or non-SSP
Prabhakaran Mc6001a712011-09-06 11:56:25 +05301142 * devices with sec_level >= BT_SECURITY_MEDIUM*/
1143 BT_DBG("Pending sec level is %d", conn->pending_sec_level);
Johan Hedberg392599b2010-11-18 22:22:28 +02001144 if (!(hdev->ssp_mode > 0 && conn->ssp_mode > 0) &&
Prabhakaran Mc6001a712011-09-06 11:56:25 +05301145 conn->pending_sec_level < BT_SECURITY_MEDIUM)
Johan Hedberg392599b2010-11-18 22:22:28 +02001146 return 0;
1147
Johan Hedberg392599b2010-11-18 22:22:28 +02001148 return 1;
1149}
1150
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001151static void hci_cs_remote_name_req(struct hci_dev *hdev, __u8 status)
1152{
Johan Hedberg127178d2010-11-18 22:22:29 +02001153 struct hci_cp_remote_name_req *cp;
1154 struct hci_conn *conn;
1155
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001156 BT_DBG("%s status 0x%x", hdev->name, status);
Johan Hedberg127178d2010-11-18 22:22:29 +02001157
1158 /* If successful wait for the name req complete event before
1159 * checking for the need to do authentication */
1160 if (!status)
1161 return;
1162
1163 cp = hci_sent_cmd_data(hdev, HCI_OP_REMOTE_NAME_REQ);
1164 if (!cp)
1165 return;
1166
1167 hci_dev_lock(hdev);
1168
1169 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &cp->bdaddr);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001170 if (conn && hci_outgoing_auth_needed(hdev, conn)) {
Johan Hedberg127178d2010-11-18 22:22:29 +02001171 struct hci_cp_auth_requested cp;
1172 cp.handle = __cpu_to_le16(conn->handle);
1173 hci_send_cmd(hdev, HCI_OP_AUTH_REQUESTED, sizeof(cp), &cp);
1174 }
1175
1176 hci_dev_unlock(hdev);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001177}
1178
Marcel Holtmann769be972008-07-14 20:13:49 +02001179static void hci_cs_read_remote_features(struct hci_dev *hdev, __u8 status)
1180{
1181 struct hci_cp_read_remote_features *cp;
1182 struct hci_conn *conn;
1183
1184 BT_DBG("%s status 0x%x", hdev->name, status);
1185
1186 if (!status)
1187 return;
1188
1189 cp = hci_sent_cmd_data(hdev, HCI_OP_READ_REMOTE_FEATURES);
1190 if (!cp)
1191 return;
1192
1193 hci_dev_lock(hdev);
1194
1195 conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(cp->handle));
1196 if (conn) {
1197 if (conn->state == BT_CONFIG) {
Marcel Holtmann769be972008-07-14 20:13:49 +02001198 hci_proto_connect_cfm(conn, status);
1199 hci_conn_put(conn);
1200 }
1201 }
1202
1203 hci_dev_unlock(hdev);
1204}
1205
1206static void hci_cs_read_remote_ext_features(struct hci_dev *hdev, __u8 status)
1207{
1208 struct hci_cp_read_remote_ext_features *cp;
1209 struct hci_conn *conn;
1210
1211 BT_DBG("%s status 0x%x", hdev->name, status);
1212
1213 if (!status)
1214 return;
1215
1216 cp = hci_sent_cmd_data(hdev, HCI_OP_READ_REMOTE_EXT_FEATURES);
1217 if (!cp)
1218 return;
1219
1220 hci_dev_lock(hdev);
1221
1222 conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(cp->handle));
1223 if (conn) {
1224 if (conn->state == BT_CONFIG) {
Marcel Holtmann769be972008-07-14 20:13:49 +02001225 hci_proto_connect_cfm(conn, status);
1226 hci_conn_put(conn);
1227 }
1228 }
1229
1230 hci_dev_unlock(hdev);
1231}
1232
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001233static void hci_cs_setup_sync_conn(struct hci_dev *hdev, __u8 status)
1234{
Marcel Holtmannb6a0dc82007-10-20 14:55:10 +02001235 struct hci_cp_setup_sync_conn *cp;
1236 struct hci_conn *acl, *sco;
1237 __u16 handle;
1238
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001239 BT_DBG("%s status 0x%x", hdev->name, status);
Marcel Holtmannb6a0dc82007-10-20 14:55:10 +02001240
1241 if (!status)
1242 return;
1243
1244 cp = hci_sent_cmd_data(hdev, HCI_OP_SETUP_SYNC_CONN);
1245 if (!cp)
1246 return;
1247
1248 handle = __le16_to_cpu(cp->handle);
1249
1250 BT_DBG("%s handle %d", hdev->name, handle);
1251
1252 hci_dev_lock(hdev);
1253
1254 acl = hci_conn_hash_lookup_handle(hdev, handle);
Andrei Emeltchenko5a08ecc2011-01-11 17:20:20 +02001255 if (acl) {
1256 sco = acl->link;
1257 if (sco) {
1258 sco->state = BT_CLOSED;
Marcel Holtmannb6a0dc82007-10-20 14:55:10 +02001259
Andrei Emeltchenko5a08ecc2011-01-11 17:20:20 +02001260 hci_proto_connect_cfm(sco, status);
1261 hci_conn_del(sco);
1262 }
Marcel Holtmannb6a0dc82007-10-20 14:55:10 +02001263 }
1264
1265 hci_dev_unlock(hdev);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001266}
1267
1268static void hci_cs_sniff_mode(struct hci_dev *hdev, __u8 status)
1269{
1270 struct hci_cp_sniff_mode *cp;
1271 struct hci_conn *conn;
1272
1273 BT_DBG("%s status 0x%x", hdev->name, status);
1274
1275 if (!status)
1276 return;
1277
1278 cp = hci_sent_cmd_data(hdev, HCI_OP_SNIFF_MODE);
1279 if (!cp)
1280 return;
1281
1282 hci_dev_lock(hdev);
1283
1284 conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(cp->handle));
Marcel Holtmanne73439d2010-07-26 10:06:00 -04001285 if (conn) {
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001286 clear_bit(HCI_CONN_MODE_CHANGE_PEND, &conn->pend);
1287
Marcel Holtmanne73439d2010-07-26 10:06:00 -04001288 if (test_and_clear_bit(HCI_CONN_SCO_SETUP_PEND, &conn->pend))
1289 hci_sco_setup(conn, status);
1290 }
1291
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001292 hci_dev_unlock(hdev);
1293}
1294
1295static void hci_cs_exit_sniff_mode(struct hci_dev *hdev, __u8 status)
1296{
1297 struct hci_cp_exit_sniff_mode *cp;
1298 struct hci_conn *conn;
1299
1300 BT_DBG("%s status 0x%x", hdev->name, status);
1301
1302 if (!status)
1303 return;
1304
1305 cp = hci_sent_cmd_data(hdev, HCI_OP_EXIT_SNIFF_MODE);
1306 if (!cp)
1307 return;
1308
1309 hci_dev_lock(hdev);
1310
1311 conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(cp->handle));
Marcel Holtmanne73439d2010-07-26 10:06:00 -04001312 if (conn) {
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001313 clear_bit(HCI_CONN_MODE_CHANGE_PEND, &conn->pend);
1314
Marcel Holtmanne73439d2010-07-26 10:06:00 -04001315 if (test_and_clear_bit(HCI_CONN_SCO_SETUP_PEND, &conn->pend))
1316 hci_sco_setup(conn, status);
1317 }
1318
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001319 hci_dev_unlock(hdev);
1320}
1321
Ville Tervofcd89c02011-02-10 22:38:47 -03001322static void hci_cs_le_create_conn(struct hci_dev *hdev, __u8 status)
1323{
1324 struct hci_cp_le_create_conn *cp;
1325 struct hci_conn *conn;
1326
1327 BT_DBG("%s status 0x%x", hdev->name, status);
1328
1329 cp = hci_sent_cmd_data(hdev, HCI_OP_LE_CREATE_CONN);
1330 if (!cp)
1331 return;
1332
1333 hci_dev_lock(hdev);
1334
1335 conn = hci_conn_hash_lookup_ba(hdev, LE_LINK, &cp->peer_addr);
1336
1337 BT_DBG("%s bdaddr %s conn %p", hdev->name, batostr(&cp->peer_addr),
1338 conn);
1339
1340 if (status) {
1341 if (conn && conn->state == BT_CONNECT) {
1342 conn->state = BT_CLOSED;
1343 hci_proto_connect_cfm(conn, status);
1344 hci_conn_del(conn);
1345 }
1346 } else {
1347 if (!conn) {
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001348 conn = hci_le_conn_add(hdev, &cp->peer_addr,
1349 cp->peer_addr_type);
1350 if (conn)
Ville Tervofcd89c02011-02-10 22:38:47 -03001351 conn->out = 1;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001352 else
Ville Tervofcd89c02011-02-10 22:38:47 -03001353 BT_ERR("No memory for new connection");
1354 }
1355 }
1356
1357 hci_dev_unlock(hdev);
1358}
1359
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001360static void hci_cs_accept_logical_link(struct hci_dev *hdev, __u8 status)
1361{
1362 struct hci_cp_create_logical_link *ap;
1363 struct hci_chan *chan;
1364
1365 BT_DBG("%s status 0x%x", hdev->name, status);
1366
1367 ap = hci_sent_cmd_data(hdev, HCI_OP_ACCEPT_LOGICAL_LINK);
1368 if (!ap)
1369 return;
1370
1371 hci_dev_lock(hdev);
1372
1373 chan = hci_chan_list_lookup_id(hdev, ap->phy_handle);
1374
1375 BT_DBG("%s chan %p", hdev->name, chan);
1376
1377 if (status) {
1378 if (chan && chan->state == BT_CONNECT) {
1379 chan->state = BT_CLOSED;
1380 hci_proto_create_cfm(chan, status);
1381 hci_chan_del(chan);
1382 }
1383 } else if (chan)
1384 chan->state = BT_CONNECT2;
1385
1386 hci_dev_unlock(hdev);
1387}
1388
1389static void hci_cs_create_logical_link(struct hci_dev *hdev, __u8 status)
1390{
1391 struct hci_cp_create_logical_link *cp;
1392 struct hci_chan *chan;
1393
1394 BT_DBG("%s status 0x%x", hdev->name, status);
1395
1396 cp = hci_sent_cmd_data(hdev, HCI_OP_CREATE_LOGICAL_LINK);
1397 if (!cp)
1398 return;
1399
1400 hci_dev_lock(hdev);
1401
1402 chan = hci_chan_list_lookup_id(hdev, cp->phy_handle);
1403
1404 BT_DBG("%s chan %p", hdev->name, chan);
1405
1406 if (status) {
1407 if (chan && chan->state == BT_CONNECT) {
1408 chan->state = BT_CLOSED;
1409 hci_proto_create_cfm(chan, status);
1410 hci_chan_del(chan);
1411 }
1412 } else if (chan)
1413 chan->state = BT_CONNECT2;
1414
1415 hci_dev_unlock(hdev);
1416}
1417
1418static void hci_cs_flow_spec_modify(struct hci_dev *hdev, __u8 status)
1419{
1420 struct hci_cp_flow_spec_modify *cp;
1421 struct hci_chan *chan;
1422
1423 BT_DBG("%s status 0x%x", hdev->name, status);
1424
1425 cp = hci_sent_cmd_data(hdev, HCI_OP_FLOW_SPEC_MODIFY);
1426 if (!cp)
1427 return;
1428
1429 hci_dev_lock(hdev);
1430
1431 chan = hci_chan_list_lookup_handle(hdev, cp->log_handle);
1432 if (chan) {
1433 if (status)
1434 hci_proto_modify_cfm(chan, status);
1435 else {
1436 chan->tx_fs = cp->tx_fs;
1437 chan->rx_fs = cp->rx_fs;
1438 }
1439 }
1440
1441 hci_dev_unlock(hdev);
1442}
1443
1444static void hci_cs_disconn_logical_link(struct hci_dev *hdev, __u8 status)
1445{
1446 struct hci_cp_disconn_logical_link *cp;
1447 struct hci_chan *chan;
1448
1449 if (!status)
1450 return;
1451
1452 BT_DBG("%s status 0x%x", hdev->name, status);
1453
1454 cp = hci_sent_cmd_data(hdev, HCI_OP_DISCONN_LOGICAL_LINK);
1455 if (!cp)
1456 return;
1457
1458 hci_dev_lock(hdev);
1459
1460 chan = hci_chan_list_lookup_handle(hdev, cp->log_handle);
1461 if (chan)
1462 hci_chan_del(chan);
1463
1464 hci_dev_unlock(hdev);
1465}
1466
1467static void hci_cs_disconn_physical_link(struct hci_dev *hdev, __u8 status)
1468{
1469 struct hci_cp_disconn_phys_link *cp;
1470 struct hci_conn *conn;
1471
1472 if (!status)
1473 return;
1474
1475 BT_DBG("%s status 0x%x", hdev->name, status);
1476
1477 cp = hci_sent_cmd_data(hdev, HCI_OP_DISCONN_PHYS_LINK);
1478 if (!cp)
1479 return;
1480
1481 hci_dev_lock(hdev);
1482
1483 conn = hci_conn_hash_lookup_handle(hdev, cp->phy_handle);
1484 if (conn) {
1485 conn->state = BT_CLOSED;
1486 hci_conn_del(conn);
1487 }
1488
1489 hci_dev_unlock(hdev);
1490}
1491
Vinicius Costa Gomes735038c2011-06-09 18:50:47 -03001492static void hci_cs_le_start_enc(struct hci_dev *hdev, u8 status)
1493{
1494 BT_DBG("%s status 0x%x", hdev->name, status);
1495}
1496
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001497static inline void hci_inquiry_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
1498{
1499 __u8 status = *((__u8 *) skb->data);
1500
1501 BT_DBG("%s status %d", hdev->name, status);
1502
Brian Gixa68668b2011-08-11 15:49:36 -07001503 if (!lmp_le_capable(hdev))
1504 clear_bit(HCI_INQUIRY, &hdev->flags);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001505
Johan Hedberg23bb5762010-12-21 23:01:27 +02001506 hci_req_complete(hdev, HCI_OP_INQUIRY, status);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001507
Brian Gixa68668b2011-08-11 15:49:36 -07001508 if (test_bit(HCI_MGMT, &hdev->flags))
1509 mgmt_inquiry_complete_evt(hdev->id, status);
1510
1511 if (!lmp_le_capable(hdev))
1512 hci_conn_check_pending(hdev);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001513}
1514
Linus Torvalds1da177e2005-04-16 15:20:36 -07001515static inline void hci_inquiry_result_evt(struct hci_dev *hdev, struct sk_buff *skb)
1516{
Marcel Holtmann45bb4bf2005-08-09 20:27:49 -07001517 struct inquiry_data data;
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001518 struct inquiry_info *info = (void *) (skb->data + 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001519 int num_rsp = *((__u8 *) skb->data);
1520
1521 BT_DBG("%s num_rsp %d", hdev->name, num_rsp);
1522
Marcel Holtmann45bb4bf2005-08-09 20:27:49 -07001523 if (!num_rsp)
1524 return;
1525
Linus Torvalds1da177e2005-04-16 15:20:36 -07001526 hci_dev_lock(hdev);
Marcel Holtmann45bb4bf2005-08-09 20:27:49 -07001527
Johan Hedberge17acd42011-03-30 23:57:16 +03001528 for (; num_rsp; num_rsp--, info++) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001529 bacpy(&data.bdaddr, &info->bdaddr);
1530 data.pscan_rep_mode = info->pscan_rep_mode;
1531 data.pscan_period_mode = info->pscan_period_mode;
1532 data.pscan_mode = info->pscan_mode;
1533 memcpy(data.dev_class, info->dev_class, 3);
1534 data.clock_offset = info->clock_offset;
1535 data.rssi = 0x00;
Marcel Holtmann41a96212008-07-14 20:13:48 +02001536 data.ssp_mode = 0x00;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001537 hci_inquiry_cache_update(hdev, &data);
Brian Gixa68668b2011-08-11 15:49:36 -07001538 mgmt_device_found(hdev->id, &info->bdaddr, 0, 0,
1539 info->dev_class, 0, 0, NULL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001540 }
Marcel Holtmann45bb4bf2005-08-09 20:27:49 -07001541
Linus Torvalds1da177e2005-04-16 15:20:36 -07001542 hci_dev_unlock(hdev);
1543}
1544
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001545static inline void hci_conn_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001546{
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001547 struct hci_ev_conn_complete *ev = (void *) skb->data;
1548 struct hci_conn *conn;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001549
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001550 BT_DBG("%s", hdev->name);
Marcel Holtmann45bb4bf2005-08-09 20:27:49 -07001551
Linus Torvalds1da177e2005-04-16 15:20:36 -07001552 hci_dev_lock(hdev);
Marcel Holtmann45bb4bf2005-08-09 20:27:49 -07001553
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001554 conn = hci_conn_hash_lookup_ba(hdev, ev->link_type, &ev->bdaddr);
Marcel Holtmann94992372009-04-19 19:30:03 +02001555 if (!conn) {
1556 if (ev->link_type != SCO_LINK)
1557 goto unlock;
1558
1559 conn = hci_conn_hash_lookup_ba(hdev, ESCO_LINK, &ev->bdaddr);
1560 if (!conn)
1561 goto unlock;
1562
1563 conn->type = SCO_LINK;
1564 }
Marcel Holtmann45bb4bf2005-08-09 20:27:49 -07001565
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001566 if (!ev->status) {
1567 conn->handle = __le16_to_cpu(ev->handle);
Marcel Holtmann769be972008-07-14 20:13:49 +02001568
1569 if (conn->type == ACL_LINK) {
1570 conn->state = BT_CONFIG;
1571 hci_conn_hold(conn);
Marcel Holtmann052b30b2009-04-26 20:01:22 +02001572 conn->disc_timeout = HCI_DISCONN_TIMEOUT;
Brian Gix2e2f50d2011-09-13 12:36:04 -07001573 mgmt_connected(hdev->id, &ev->bdaddr, 0);
Brian Gixa68668b2011-08-11 15:49:36 -07001574 } else if (conn->type == LE_LINK) {
1575 conn->state = BT_CONNECTED;
1576 conn->disc_timeout = HCI_DISCONN_TIMEOUT;
Brian Gix2e2f50d2011-09-13 12:36:04 -07001577 mgmt_connected(hdev->id, &ev->bdaddr, 1);
Marcel Holtmann769be972008-07-14 20:13:49 +02001578 } else
1579 conn->state = BT_CONNECTED;
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001580
Marcel Holtmann9eba32b2009-08-22 14:19:26 -07001581 hci_conn_hold_device(conn);
Marcel Holtmann7d0db0a2008-07-14 20:13:51 +02001582 hci_conn_add_sysfs(conn);
1583
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001584 if (test_bit(HCI_AUTH, &hdev->flags))
1585 conn->link_mode |= HCI_LM_AUTH;
1586
1587 if (test_bit(HCI_ENCRYPT, &hdev->flags))
1588 conn->link_mode |= HCI_LM_ENCRYPT;
1589
1590 /* Get remote features */
1591 if (conn->type == ACL_LINK) {
1592 struct hci_cp_read_remote_features cp;
1593 cp.handle = ev->handle;
Marcel Holtmann769be972008-07-14 20:13:49 +02001594 hci_send_cmd(hdev, HCI_OP_READ_REMOTE_FEATURES,
1595 sizeof(cp), &cp);
Marcel Holtmann45bb4bf2005-08-09 20:27:49 -07001596 }
Marcel Holtmann45bb4bf2005-08-09 20:27:49 -07001597
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001598 /* Set packet type for incoming connection */
Marcel Holtmanna8746412008-07-14 20:13:46 +02001599 if (!conn->out && hdev->hci_ver < 3) {
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001600 struct hci_cp_change_conn_ptype cp;
1601 cp.handle = ev->handle;
Marcel Holtmanna8746412008-07-14 20:13:46 +02001602 cp.pkt_type = cpu_to_le16(conn->pkt_type);
1603 hci_send_cmd(hdev, HCI_OP_CHANGE_CONN_PTYPE,
1604 sizeof(cp), &cp);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001605 }
Johan Hedberg17d5c042011-01-22 06:09:08 +02001606 } else {
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001607 conn->state = BT_CLOSED;
Brian Gixa68668b2011-08-11 15:49:36 -07001608 if (conn->type == ACL_LINK || conn->type == LE_LINK)
Johan Hedberg17d5c042011-01-22 06:09:08 +02001609 mgmt_connect_failed(hdev->id, &ev->bdaddr, ev->status);
1610 }
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001611
Marcel Holtmanne73439d2010-07-26 10:06:00 -04001612 if (conn->type == ACL_LINK)
1613 hci_sco_setup(conn, ev->status);
Marcel Holtmann45bb4bf2005-08-09 20:27:49 -07001614
Marcel Holtmann769be972008-07-14 20:13:49 +02001615 if (ev->status) {
1616 hci_proto_connect_cfm(conn, ev->status);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001617 hci_conn_del(conn);
Marcel Holtmannc89b6e62009-01-15 21:57:03 +01001618 } else if (ev->link_type != ACL_LINK)
1619 hci_proto_connect_cfm(conn, ev->status);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001620
1621unlock:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001622 hci_dev_unlock(hdev);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001623
1624 hci_conn_check_pending(hdev);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001625}
1626
Linus Torvalds1da177e2005-04-16 15:20:36 -07001627static inline void hci_conn_request_evt(struct hci_dev *hdev, struct sk_buff *skb)
1628{
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001629 struct hci_ev_conn_request *ev = (void *) skb->data;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001630 int mask = hdev->link_mode;
1631
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001632 BT_DBG("%s bdaddr %s type 0x%x", hdev->name,
1633 batostr(&ev->bdaddr), ev->link_type);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001634
1635 mask |= hci_proto_connect_ind(hdev, &ev->bdaddr, ev->link_type);
1636
Szymon Janc138d22e2011-02-17 16:44:23 +01001637 if ((mask & HCI_LM_ACCEPT) &&
1638 !hci_blacklist_lookup(hdev, &ev->bdaddr)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001639 /* Connection accepted */
Marcel Holtmannc7bdd502008-07-14 20:13:47 +02001640 struct inquiry_entry *ie;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001641 struct hci_conn *conn;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001642
1643 hci_dev_lock(hdev);
Marcel Holtmannb6a0dc82007-10-20 14:55:10 +02001644
Andrei Emeltchenkocc11b9c2010-11-22 13:21:37 +02001645 ie = hci_inquiry_cache_lookup(hdev, &ev->bdaddr);
1646 if (ie)
Marcel Holtmannc7bdd502008-07-14 20:13:47 +02001647 memcpy(ie->data.dev_class, ev->dev_class, 3);
1648
Linus Torvalds1da177e2005-04-16 15:20:36 -07001649 conn = hci_conn_hash_lookup_ba(hdev, ev->link_type, &ev->bdaddr);
1650 if (!conn) {
Nick Pellybbcda3b2010-02-11 11:54:28 -08001651 /* pkt_type not yet used for incoming connections */
1652 conn = hci_conn_add(hdev, ev->link_type, 0, &ev->bdaddr);
Andrei Emeltchenkocc11b9c2010-11-22 13:21:37 +02001653 if (!conn) {
Gustavo F. Padovan893ef972010-07-18 15:13:37 -03001654 BT_ERR("No memory for new connection");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001655 hci_dev_unlock(hdev);
1656 return;
1657 }
1658 }
Marcel Holtmannb6a0dc82007-10-20 14:55:10 +02001659
Linus Torvalds1da177e2005-04-16 15:20:36 -07001660 memcpy(conn->dev_class, ev->dev_class, 3);
1661 conn->state = BT_CONNECT;
Marcel Holtmannb6a0dc82007-10-20 14:55:10 +02001662
Linus Torvalds1da177e2005-04-16 15:20:36 -07001663 hci_dev_unlock(hdev);
1664
Marcel Holtmannb6a0dc82007-10-20 14:55:10 +02001665 if (ev->link_type == ACL_LINK || !lmp_esco_capable(hdev)) {
1666 struct hci_cp_accept_conn_req cp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001667
Marcel Holtmannb6a0dc82007-10-20 14:55:10 +02001668 bacpy(&cp.bdaddr, &ev->bdaddr);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001669
Marcel Holtmannb6a0dc82007-10-20 14:55:10 +02001670 if (lmp_rswitch_capable(hdev) && (mask & HCI_LM_MASTER))
1671 cp.role = 0x00; /* Become master */
1672 else
1673 cp.role = 0x01; /* Remain slave */
1674
1675 hci_send_cmd(hdev, HCI_OP_ACCEPT_CONN_REQ,
1676 sizeof(cp), &cp);
1677 } else {
1678 struct hci_cp_accept_sync_conn_req cp;
1679
1680 bacpy(&cp.bdaddr, &ev->bdaddr);
Marcel Holtmanna8746412008-07-14 20:13:46 +02001681 cp.pkt_type = cpu_to_le16(conn->pkt_type);
Marcel Holtmannb6a0dc82007-10-20 14:55:10 +02001682
1683 cp.tx_bandwidth = cpu_to_le32(0x00001f40);
1684 cp.rx_bandwidth = cpu_to_le32(0x00001f40);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001685 cp.max_latency = cpu_to_le16(0x000A);
Marcel Holtmannb6a0dc82007-10-20 14:55:10 +02001686 cp.content_format = cpu_to_le16(hdev->voice_setting);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001687 cp.retrans_effort = 0x01;
Marcel Holtmannb6a0dc82007-10-20 14:55:10 +02001688
1689 hci_send_cmd(hdev, HCI_OP_ACCEPT_SYNC_CONN_REQ,
1690 sizeof(cp), &cp);
1691 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001692 } else {
1693 /* Connection rejected */
1694 struct hci_cp_reject_conn_req cp;
1695
1696 bacpy(&cp.bdaddr, &ev->bdaddr);
1697 cp.reason = 0x0f;
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001698 hci_send_cmd(hdev, HCI_OP_REJECT_CONN_REQ, sizeof(cp), &cp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001699 }
1700}
1701
Linus Torvalds1da177e2005-04-16 15:20:36 -07001702static inline void hci_disconn_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
1703{
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001704 struct hci_ev_disconn_complete *ev = (void *) skb->data;
Marcel Holtmann04837f62006-07-03 10:02:33 +02001705 struct hci_conn *conn;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001706
1707 BT_DBG("%s status %d", hdev->name, ev->status);
1708
Johan Hedberg8962ee72011-01-20 12:40:27 +02001709 if (ev->status) {
1710 mgmt_disconnect_failed(hdev->id);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001711 return;
Johan Hedberg8962ee72011-01-20 12:40:27 +02001712 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001713
1714 hci_dev_lock(hdev);
1715
Marcel Holtmann04837f62006-07-03 10:02:33 +02001716 conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
Johan Hedbergf7520542011-01-20 12:34:39 +02001717 if (!conn)
1718 goto unlock;
Marcel Holtmann7d0db0a2008-07-14 20:13:51 +02001719
Johan Hedbergf7520542011-01-20 12:34:39 +02001720 conn->state = BT_CLOSED;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001721
Brian Gixa68668b2011-08-11 15:49:36 -07001722 if (conn->type == ACL_LINK || conn->type == LE_LINK)
Johan Hedbergf7520542011-01-20 12:34:39 +02001723 mgmt_disconnected(hdev->id, &conn->dst);
1724
Brian Gixe9ceb522011-09-22 10:46:35 -07001725 if (conn->type == LE_LINK)
1726 del_timer(&conn->smp_timer);
1727
Johan Hedbergf7520542011-01-20 12:34:39 +02001728 hci_proto_disconn_cfm(conn, ev->reason);
1729 hci_conn_del(conn);
1730
1731unlock:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001732 hci_dev_unlock(hdev);
1733}
1734
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001735static inline void hci_auth_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
1736{
1737 struct hci_ev_auth_complete *ev = (void *) skb->data;
1738 struct hci_conn *conn;
1739
1740 BT_DBG("%s status %d", hdev->name, ev->status);
1741
1742 hci_dev_lock(hdev);
1743
1744 conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001745 if (conn) {
1746 if (ev->status == 0x06 && hdev->ssp_mode > 0 &&
1747 conn->ssp_mode > 0) {
1748 struct hci_cp_auth_requested cp;
Prabhakaran Mcb04401d2011-09-20 17:37:55 +05301749 hci_remove_link_key(hdev, &conn->dst);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001750 cp.handle = cpu_to_le16(conn->handle);
1751 hci_send_cmd(conn->hdev, HCI_OP_AUTH_REQUESTED,
1752 sizeof(cp), &cp);
1753 hci_dev_unlock(hdev);
1754 BT_INFO("Pin or key missing");
1755 return;
1756 }
Waldemar Rymarkiewicz54444292011-05-31 15:49:26 +02001757
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001758 if (!ev->status) {
Waldemar Rymarkiewicz54444292011-05-31 15:49:26 +02001759 conn->link_mode |= HCI_LM_AUTH;
1760 conn->sec_level = conn->pending_sec_level;
Marcel Holtmann052b30b2009-04-26 20:01:22 +02001761 } else {
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001762 mgmt_auth_failed(hdev->id, &conn->dst, ev->status);
1763 conn->sec_level = BT_SECURITY_LOW;
1764 }
1765
1766 clear_bit(HCI_CONN_AUTH_PEND, &conn->pend);
1767
1768 if (conn->state == BT_CONFIG) {
1769 if (!ev->status && hdev->ssp_mode > 0 &&
1770 conn->ssp_mode > 0) {
1771 struct hci_cp_set_conn_encrypt cp;
1772 cp.handle = ev->handle;
1773 cp.encrypt = 0x01;
1774 hci_send_cmd(hdev, HCI_OP_SET_CONN_ENCRYPT,
1775 sizeof(cp), &cp);
1776 } else {
1777 conn->state = BT_CONNECTED;
1778 hci_proto_connect_cfm(conn, ev->status);
1779 hci_conn_put(conn);
1780 }
1781 } else {
1782 hci_auth_cfm(conn, ev->status);
1783
1784 hci_conn_hold(conn);
1785 conn->disc_timeout = HCI_DISCONN_TIMEOUT;
Marcel Holtmann052b30b2009-04-26 20:01:22 +02001786 hci_conn_put(conn);
1787 }
1788
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001789 if (test_bit(HCI_CONN_ENCRYPT_PEND, &conn->pend)) {
1790 if (!ev->status) {
1791 struct hci_cp_set_conn_encrypt cp;
1792 cp.handle = ev->handle;
1793 cp.encrypt = 0x01;
1794 hci_send_cmd(hdev, HCI_OP_SET_CONN_ENCRYPT,
1795 sizeof(cp), &cp);
1796 } else {
1797 clear_bit(HCI_CONN_ENCRYPT_PEND, &conn->pend);
1798 hci_encrypt_cfm(conn, ev->status, 0x00);
1799 }
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001800 }
1801 }
1802
1803 hci_dev_unlock(hdev);
1804}
1805
1806static inline void hci_remote_name_evt(struct hci_dev *hdev, struct sk_buff *skb)
1807{
Johan Hedberg127178d2010-11-18 22:22:29 +02001808 struct hci_ev_remote_name *ev = (void *) skb->data;
1809 struct hci_conn *conn;
1810
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001811 BT_DBG("%s", hdev->name);
1812
1813 hci_conn_check_pending(hdev);
Johan Hedberg127178d2010-11-18 22:22:29 +02001814
1815 hci_dev_lock(hdev);
1816
Brian Gixa68668b2011-08-11 15:49:36 -07001817 if (test_bit(HCI_MGMT, &hdev->flags))
1818 mgmt_remote_name(hdev->id, &ev->bdaddr, ev->status, ev->name);
Johan Hedberga88a9652011-03-30 13:18:12 +03001819
Johan Hedberg127178d2010-11-18 22:22:29 +02001820 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001821 if (conn && hci_outgoing_auth_needed(hdev, conn)) {
Johan Hedberg127178d2010-11-18 22:22:29 +02001822 struct hci_cp_auth_requested cp;
1823 cp.handle = __cpu_to_le16(conn->handle);
1824 hci_send_cmd(hdev, HCI_OP_AUTH_REQUESTED, sizeof(cp), &cp);
1825 }
1826
1827 hci_dev_unlock(hdev);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001828}
1829
1830static inline void hci_encrypt_change_evt(struct hci_dev *hdev, struct sk_buff *skb)
1831{
1832 struct hci_ev_encrypt_change *ev = (void *) skb->data;
1833 struct hci_conn *conn;
1834
1835 BT_DBG("%s status %d", hdev->name, ev->status);
1836
1837 hci_dev_lock(hdev);
1838
1839 conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
1840 if (conn) {
1841 if (!ev->status) {
Marcel Holtmannae293192008-07-14 20:13:45 +02001842 if (ev->encrypt) {
1843 /* Encryption implies authentication */
1844 conn->link_mode |= HCI_LM_AUTH;
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001845 conn->link_mode |= HCI_LM_ENCRYPT;
Vinicius Costa Gomes64532ec2011-06-09 18:50:53 -03001846 conn->sec_level = conn->pending_sec_level;
Marcel Holtmannae293192008-07-14 20:13:45 +02001847 } else
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001848 conn->link_mode &= ~HCI_LM_ENCRYPT;
1849 }
1850
1851 clear_bit(HCI_CONN_ENCRYPT_PEND, &conn->pend);
1852
Marcel Holtmannf8558552008-07-14 20:13:49 +02001853 if (conn->state == BT_CONFIG) {
1854 if (!ev->status)
1855 conn->state = BT_CONNECTED;
1856
1857 hci_proto_connect_cfm(conn, ev->status);
1858 hci_conn_put(conn);
1859 } else
1860 hci_encrypt_cfm(conn, ev->status, ev->encrypt);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001861 }
1862
1863 hci_dev_unlock(hdev);
1864}
1865
1866static inline void hci_change_link_key_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
1867{
1868 struct hci_ev_change_link_key_complete *ev = (void *) skb->data;
1869 struct hci_conn *conn;
1870
1871 BT_DBG("%s status %d", hdev->name, ev->status);
1872
1873 hci_dev_lock(hdev);
1874
1875 conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
1876 if (conn) {
1877 if (!ev->status)
1878 conn->link_mode |= HCI_LM_SECURE;
1879
1880 clear_bit(HCI_CONN_AUTH_PEND, &conn->pend);
1881
1882 hci_key_change_cfm(conn, ev->status);
1883 }
1884
1885 hci_dev_unlock(hdev);
1886}
1887
1888static inline void hci_remote_features_evt(struct hci_dev *hdev, struct sk_buff *skb)
1889{
1890 struct hci_ev_remote_features *ev = (void *) skb->data;
1891 struct hci_conn *conn;
1892
1893 BT_DBG("%s status %d", hdev->name, ev->status);
1894
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001895 hci_dev_lock(hdev);
1896
1897 conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
Johan Hedbergccd556f2010-11-10 17:11:51 +02001898 if (!conn)
1899 goto unlock;
Marcel Holtmann769be972008-07-14 20:13:49 +02001900
Johan Hedbergccd556f2010-11-10 17:11:51 +02001901 if (!ev->status)
1902 memcpy(conn->features, ev->features, 8);
1903
1904 if (conn->state != BT_CONFIG)
1905 goto unlock;
1906
1907 if (!ev->status && lmp_ssp_capable(hdev) && lmp_ssp_capable(conn)) {
1908 struct hci_cp_read_remote_ext_features cp;
1909 cp.handle = ev->handle;
1910 cp.page = 0x01;
1911 hci_send_cmd(hdev, HCI_OP_READ_REMOTE_EXT_FEATURES,
Marcel Holtmann769be972008-07-14 20:13:49 +02001912 sizeof(cp), &cp);
Johan Hedberg392599b2010-11-18 22:22:28 +02001913 goto unlock;
1914 }
1915
Johan Hedberg127178d2010-11-18 22:22:29 +02001916 if (!ev->status) {
1917 struct hci_cp_remote_name_req cp;
1918 memset(&cp, 0, sizeof(cp));
1919 bacpy(&cp.bdaddr, &conn->dst);
1920 cp.pscan_rep_mode = 0x02;
1921 hci_send_cmd(hdev, HCI_OP_REMOTE_NAME_REQ, sizeof(cp), &cp);
1922 }
Johan Hedberg392599b2010-11-18 22:22:28 +02001923
Johan Hedberg127178d2010-11-18 22:22:29 +02001924 if (!hci_outgoing_auth_needed(hdev, conn)) {
Johan Hedbergccd556f2010-11-10 17:11:51 +02001925 conn->state = BT_CONNECTED;
1926 hci_proto_connect_cfm(conn, ev->status);
1927 hci_conn_put(conn);
Marcel Holtmann769be972008-07-14 20:13:49 +02001928 }
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001929
Johan Hedbergccd556f2010-11-10 17:11:51 +02001930unlock:
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001931 hci_dev_unlock(hdev);
1932}
1933
1934static inline void hci_remote_version_evt(struct hci_dev *hdev, struct sk_buff *skb)
1935{
1936 BT_DBG("%s", hdev->name);
1937}
1938
1939static inline void hci_qos_setup_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
1940{
1941 BT_DBG("%s", hdev->name);
1942}
1943
1944static inline void hci_cmd_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
1945{
1946 struct hci_ev_cmd_complete *ev = (void *) skb->data;
1947 __u16 opcode;
1948
1949 skb_pull(skb, sizeof(*ev));
1950
1951 opcode = __le16_to_cpu(ev->opcode);
1952
1953 switch (opcode) {
1954 case HCI_OP_INQUIRY_CANCEL:
1955 hci_cc_inquiry_cancel(hdev, skb);
1956 break;
1957
1958 case HCI_OP_EXIT_PERIODIC_INQ:
1959 hci_cc_exit_periodic_inq(hdev, skb);
1960 break;
1961
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001962 case HCI_OP_LINK_KEY_REPLY:
1963 hci_cc_link_key_reply(hdev, skb);
1964 break;
1965
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001966 case HCI_OP_REMOTE_NAME_REQ_CANCEL:
1967 hci_cc_remote_name_req_cancel(hdev, skb);
1968 break;
1969
1970 case HCI_OP_ROLE_DISCOVERY:
1971 hci_cc_role_discovery(hdev, skb);
1972 break;
1973
Marcel Holtmanne4e8e372008-07-14 20:13:47 +02001974 case HCI_OP_READ_LINK_POLICY:
1975 hci_cc_read_link_policy(hdev, skb);
1976 break;
1977
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001978 case HCI_OP_WRITE_LINK_POLICY:
1979 hci_cc_write_link_policy(hdev, skb);
1980 break;
1981
Marcel Holtmanne4e8e372008-07-14 20:13:47 +02001982 case HCI_OP_READ_DEF_LINK_POLICY:
1983 hci_cc_read_def_link_policy(hdev, skb);
1984 break;
1985
1986 case HCI_OP_WRITE_DEF_LINK_POLICY:
1987 hci_cc_write_def_link_policy(hdev, skb);
1988 break;
1989
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001990 case HCI_OP_RESET:
1991 hci_cc_reset(hdev, skb);
1992 break;
1993
1994 case HCI_OP_WRITE_LOCAL_NAME:
1995 hci_cc_write_local_name(hdev, skb);
1996 break;
1997
1998 case HCI_OP_READ_LOCAL_NAME:
1999 hci_cc_read_local_name(hdev, skb);
2000 break;
2001
2002 case HCI_OP_WRITE_AUTH_ENABLE:
2003 hci_cc_write_auth_enable(hdev, skb);
2004 break;
2005
2006 case HCI_OP_WRITE_ENCRYPT_MODE:
2007 hci_cc_write_encrypt_mode(hdev, skb);
2008 break;
2009
2010 case HCI_OP_WRITE_SCAN_ENABLE:
2011 hci_cc_write_scan_enable(hdev, skb);
2012 break;
2013
2014 case HCI_OP_READ_CLASS_OF_DEV:
2015 hci_cc_read_class_of_dev(hdev, skb);
2016 break;
2017
2018 case HCI_OP_WRITE_CLASS_OF_DEV:
2019 hci_cc_write_class_of_dev(hdev, skb);
2020 break;
2021
2022 case HCI_OP_READ_VOICE_SETTING:
2023 hci_cc_read_voice_setting(hdev, skb);
2024 break;
2025
2026 case HCI_OP_WRITE_VOICE_SETTING:
2027 hci_cc_write_voice_setting(hdev, skb);
2028 break;
2029
2030 case HCI_OP_HOST_BUFFER_SIZE:
2031 hci_cc_host_buffer_size(hdev, skb);
2032 break;
2033
Marcel Holtmann333140b2008-07-14 20:13:48 +02002034 case HCI_OP_READ_SSP_MODE:
2035 hci_cc_read_ssp_mode(hdev, skb);
2036 break;
2037
2038 case HCI_OP_WRITE_SSP_MODE:
2039 hci_cc_write_ssp_mode(hdev, skb);
2040 break;
2041
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002042 case HCI_OP_READ_LOCAL_VERSION:
2043 hci_cc_read_local_version(hdev, skb);
2044 break;
2045
2046 case HCI_OP_READ_LOCAL_COMMANDS:
2047 hci_cc_read_local_commands(hdev, skb);
2048 break;
2049
2050 case HCI_OP_READ_LOCAL_FEATURES:
2051 hci_cc_read_local_features(hdev, skb);
2052 break;
2053
2054 case HCI_OP_READ_BUFFER_SIZE:
2055 hci_cc_read_buffer_size(hdev, skb);
2056 break;
2057
2058 case HCI_OP_READ_BD_ADDR:
2059 hci_cc_read_bd_addr(hdev, skb);
2060 break;
2061
Johan Hedberg23bb5762010-12-21 23:01:27 +02002062 case HCI_OP_WRITE_CA_TIMEOUT:
2063 hci_cc_write_ca_timeout(hdev, skb);
2064 break;
2065
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002066 case HCI_OP_READ_FLOW_CONTROL_MODE:
2067 hci_cc_read_flow_control_mode(hdev, skb);
2068 break;
2069
2070 case HCI_OP_READ_DATA_BLOCK_SIZE:
2071 hci_cc_read_data_block_size(hdev, skb);
2072 break;
2073
2074 case HCI_OP_READ_LOCAL_AMP_INFO:
2075 hci_cc_read_local_amp_info(hdev, skb);
2076 break;
2077
2078 case HCI_OP_READ_LOCAL_AMP_ASSOC:
2079 case HCI_OP_WRITE_REMOTE_AMP_ASSOC:
2080 hci_amp_cmd_complete(hdev, opcode, skb);
2081 break;
2082
Johan Hedbergb0916ea2011-01-10 13:44:55 +02002083 case HCI_OP_DELETE_STORED_LINK_KEY:
2084 hci_cc_delete_stored_link_key(hdev, skb);
2085 break;
2086
Johan Hedbergd5859e22011-01-25 01:19:58 +02002087 case HCI_OP_SET_EVENT_MASK:
2088 hci_cc_set_event_mask(hdev, skb);
2089 break;
2090
2091 case HCI_OP_WRITE_INQUIRY_MODE:
2092 hci_cc_write_inquiry_mode(hdev, skb);
2093 break;
2094
2095 case HCI_OP_READ_INQ_RSP_TX_POWER:
2096 hci_cc_read_inq_rsp_tx_power(hdev, skb);
2097 break;
2098
2099 case HCI_OP_SET_EVENT_FLT:
2100 hci_cc_set_event_flt(hdev, skb);
2101 break;
2102
Johan Hedberg980e1a52011-01-22 06:10:07 +02002103 case HCI_OP_PIN_CODE_REPLY:
2104 hci_cc_pin_code_reply(hdev, skb);
2105 break;
2106
2107 case HCI_OP_PIN_CODE_NEG_REPLY:
2108 hci_cc_pin_code_neg_reply(hdev, skb);
2109 break;
2110
Szymon Jancc35938b2011-03-22 13:12:21 +01002111 case HCI_OP_READ_LOCAL_OOB_DATA:
2112 hci_cc_read_local_oob_data_reply(hdev, skb);
2113 break;
2114
Ville Tervo6ed58ec2011-02-10 22:38:48 -03002115 case HCI_OP_LE_READ_BUFFER_SIZE:
2116 hci_cc_le_read_buffer_size(hdev, skb);
2117 break;
2118
Johan Hedberga5c29682011-02-19 12:05:57 -03002119 case HCI_OP_USER_CONFIRM_REPLY:
2120 hci_cc_user_confirm_reply(hdev, skb);
2121 break;
2122
2123 case HCI_OP_USER_CONFIRM_NEG_REPLY:
2124 hci_cc_user_confirm_neg_reply(hdev, skb);
2125 break;
2126
Vinicius Costa Gomes735038c2011-06-09 18:50:47 -03002127 case HCI_OP_LE_LTK_REPLY:
2128 hci_cc_le_ltk_reply(hdev, skb);
2129 break;
2130
2131 case HCI_OP_LE_LTK_NEG_REPLY:
2132 hci_cc_le_ltk_neg_reply(hdev, skb);
2133 break;
2134
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002135 case HCI_OP_LE_SET_SCAN_ENABLE:
2136 hci_cc_le_set_scan_enable(hdev, skb);
Andre Guedese326af42011-06-30 19:20:53 -03002137 break;
2138
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002139 default:
2140 BT_DBG("%s opcode 0x%x", hdev->name, opcode);
2141 break;
2142 }
2143
Ville Tervo6bd32322011-02-16 16:32:41 +02002144 if (ev->opcode != HCI_OP_NOP)
2145 del_timer(&hdev->cmd_timer);
2146
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002147 if (ev->ncmd) {
2148 atomic_set(&hdev->cmd_cnt, 1);
2149 if (!skb_queue_empty(&hdev->cmd_q))
Marcel Holtmannc78ae282009-11-18 01:02:54 +01002150 tasklet_schedule(&hdev->cmd_task);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002151 }
2152}
2153
2154static inline void hci_cmd_status_evt(struct hci_dev *hdev, struct sk_buff *skb)
2155{
2156 struct hci_ev_cmd_status *ev = (void *) skb->data;
2157 __u16 opcode;
2158
2159 skb_pull(skb, sizeof(*ev));
2160
2161 opcode = __le16_to_cpu(ev->opcode);
2162
2163 switch (opcode) {
2164 case HCI_OP_INQUIRY:
2165 hci_cs_inquiry(hdev, ev->status);
2166 break;
2167
2168 case HCI_OP_CREATE_CONN:
2169 hci_cs_create_conn(hdev, ev->status);
2170 break;
2171
2172 case HCI_OP_ADD_SCO:
2173 hci_cs_add_sco(hdev, ev->status);
2174 break;
2175
Marcel Holtmannf8558552008-07-14 20:13:49 +02002176 case HCI_OP_AUTH_REQUESTED:
2177 hci_cs_auth_requested(hdev, ev->status);
2178 break;
2179
2180 case HCI_OP_SET_CONN_ENCRYPT:
2181 hci_cs_set_conn_encrypt(hdev, ev->status);
2182 break;
2183
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002184 case HCI_OP_REMOTE_NAME_REQ:
2185 hci_cs_remote_name_req(hdev, ev->status);
2186 break;
2187
Marcel Holtmann769be972008-07-14 20:13:49 +02002188 case HCI_OP_READ_REMOTE_FEATURES:
2189 hci_cs_read_remote_features(hdev, ev->status);
2190 break;
2191
2192 case HCI_OP_READ_REMOTE_EXT_FEATURES:
2193 hci_cs_read_remote_ext_features(hdev, ev->status);
2194 break;
2195
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002196 case HCI_OP_SETUP_SYNC_CONN:
2197 hci_cs_setup_sync_conn(hdev, ev->status);
2198 break;
2199
2200 case HCI_OP_SNIFF_MODE:
2201 hci_cs_sniff_mode(hdev, ev->status);
2202 break;
2203
2204 case HCI_OP_EXIT_SNIFF_MODE:
2205 hci_cs_exit_sniff_mode(hdev, ev->status);
2206 break;
2207
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002208 case HCI_OP_CREATE_LOGICAL_LINK:
2209 hci_cs_create_logical_link(hdev, ev->status);
2210 break;
2211
2212 case HCI_OP_ACCEPT_LOGICAL_LINK:
2213 hci_cs_accept_logical_link(hdev, ev->status);
2214 break;
2215
2216 case HCI_OP_DISCONN_LOGICAL_LINK:
2217 hci_cs_disconn_logical_link(hdev, ev->status);
2218 break;
2219
2220 case HCI_OP_FLOW_SPEC_MODIFY:
2221 hci_cs_flow_spec_modify(hdev, ev->status);
2222 break;
2223
2224 case HCI_OP_CREATE_PHYS_LINK:
2225 case HCI_OP_ACCEPT_PHYS_LINK:
2226 hci_amp_cmd_status(hdev, opcode, ev->status);
2227 break;
2228
2229 case HCI_OP_DISCONN_PHYS_LINK:
2230 hci_cs_disconn_physical_link(hdev, ev->status);
2231
Johan Hedberg8962ee72011-01-20 12:40:27 +02002232 case HCI_OP_DISCONNECT:
2233 if (ev->status != 0)
2234 mgmt_disconnect_failed(hdev->id);
2235 break;
2236
Ville Tervofcd89c02011-02-10 22:38:47 -03002237 case HCI_OP_LE_CREATE_CONN:
2238 hci_cs_le_create_conn(hdev, ev->status);
2239 break;
2240
Vinicius Costa Gomes735038c2011-06-09 18:50:47 -03002241 case HCI_OP_LE_START_ENC:
2242 hci_cs_le_start_enc(hdev, ev->status);
2243 break;
2244
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002245 default:
2246 BT_DBG("%s opcode 0x%x", hdev->name, opcode);
2247 break;
2248 }
2249
Ville Tervo6bd32322011-02-16 16:32:41 +02002250 if (ev->opcode != HCI_OP_NOP)
2251 del_timer(&hdev->cmd_timer);
2252
Gustavo F. Padovan10572132011-03-16 15:36:29 -03002253 if (ev->ncmd && !test_bit(HCI_RESET, &hdev->flags)) {
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002254 atomic_set(&hdev->cmd_cnt, 1);
2255 if (!skb_queue_empty(&hdev->cmd_q))
Marcel Holtmannc78ae282009-11-18 01:02:54 +01002256 tasklet_schedule(&hdev->cmd_task);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002257 }
2258}
2259
2260static inline void hci_role_change_evt(struct hci_dev *hdev, struct sk_buff *skb)
2261{
2262 struct hci_ev_role_change *ev = (void *) skb->data;
2263 struct hci_conn *conn;
2264
2265 BT_DBG("%s status %d", hdev->name, ev->status);
2266
2267 hci_dev_lock(hdev);
2268
2269 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
2270 if (conn) {
2271 if (!ev->status) {
2272 if (ev->role)
2273 conn->link_mode &= ~HCI_LM_MASTER;
2274 else
2275 conn->link_mode |= HCI_LM_MASTER;
2276 }
2277
2278 clear_bit(HCI_CONN_RSWITCH_PEND, &conn->pend);
2279
2280 hci_role_switch_cfm(conn, ev->status, ev->role);
2281 }
2282
2283 hci_dev_unlock(hdev);
2284}
2285
Linus Torvalds1da177e2005-04-16 15:20:36 -07002286static inline void hci_num_comp_pkts_evt(struct hci_dev *hdev, struct sk_buff *skb)
2287{
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002288 struct hci_ev_num_comp_pkts *ev = (void *) skb->data;
Marcel Holtmann1ebb9252005-11-08 09:57:21 -08002289 __le16 *ptr;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002290 int i;
2291
2292 skb_pull(skb, sizeof(*ev));
2293
2294 BT_DBG("%s num_hndl %d", hdev->name, ev->num_hndl);
2295
2296 if (skb->len < ev->num_hndl * 4) {
2297 BT_DBG("%s bad parameters", hdev->name);
2298 return;
2299 }
2300
2301 tasklet_disable(&hdev->tx_task);
2302
Marcel Holtmann1ebb9252005-11-08 09:57:21 -08002303 for (i = 0, ptr = (__le16 *) skb->data; i < ev->num_hndl; i++) {
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002304 struct hci_conn *conn = NULL;
2305 struct hci_chan *chan;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002306 __u16 handle, count;
2307
Harvey Harrison83985312008-05-02 16:25:46 -07002308 handle = get_unaligned_le16(ptr++);
2309 count = get_unaligned_le16(ptr++);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002310
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002311 if (hdev->dev_type == HCI_BREDR)
2312 conn = hci_conn_hash_lookup_handle(hdev, handle);
2313 else {
2314 chan = hci_chan_list_lookup_handle(hdev, handle);
2315 if (chan)
2316 conn = chan->conn;
2317 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002318 if (conn) {
2319 conn->sent -= count;
2320
Marcel Holtmann5b7f9902007-07-11 09:51:55 +02002321 if (conn->type == ACL_LINK) {
Andrei Emeltchenko70f230202010-12-01 16:58:25 +02002322 hdev->acl_cnt += count;
2323 if (hdev->acl_cnt > hdev->acl_pkts)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002324 hdev->acl_cnt = hdev->acl_pkts;
Ville Tervo6ed58ec2011-02-10 22:38:48 -03002325 } else if (conn->type == LE_LINK) {
2326 if (hdev->le_pkts) {
2327 hdev->le_cnt += count;
2328 if (hdev->le_cnt > hdev->le_pkts)
2329 hdev->le_cnt = hdev->le_pkts;
2330 } else {
2331 hdev->acl_cnt += count;
2332 if (hdev->acl_cnt > hdev->acl_pkts)
2333 hdev->acl_cnt = hdev->acl_pkts;
2334 }
Marcel Holtmann5b7f9902007-07-11 09:51:55 +02002335 } else {
Andrei Emeltchenko70f230202010-12-01 16:58:25 +02002336 hdev->sco_cnt += count;
2337 if (hdev->sco_cnt > hdev->sco_pkts)
Marcel Holtmann5b7f9902007-07-11 09:51:55 +02002338 hdev->sco_cnt = hdev->sco_pkts;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002339 }
2340 }
2341 }
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002342
Marcel Holtmannc78ae282009-11-18 01:02:54 +01002343 tasklet_schedule(&hdev->tx_task);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002344
2345 tasklet_enable(&hdev->tx_task);
2346}
2347
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002348static inline void hci_num_comp_blocks_evt(struct hci_dev *hdev,
2349 struct sk_buff *skb)
2350{
2351 struct hci_ev_num_comp_blocks *ev = (void *) skb->data;
2352 __le16 *ptr;
2353 int i;
2354
2355 skb_pull(skb, sizeof(*ev));
2356
2357 BT_DBG("%s total_num_blocks %d num_hndl %d",
2358 hdev->name, ev->total_num_blocks, ev->num_hndl);
2359
2360 if (skb->len < ev->num_hndl * 6) {
2361 BT_DBG("%s bad parameters", hdev->name);
2362 return;
2363 }
2364
2365 tasklet_disable(&hdev->tx_task);
2366
2367 for (i = 0, ptr = (__le16 *) skb->data; i < ev->num_hndl; i++) {
2368 struct hci_conn *conn = NULL;
2369 struct hci_chan *chan;
2370 __u16 handle, block_count;
2371
2372 handle = get_unaligned_le16(ptr++);
2373
2374 /* Skip packet count */
2375 ptr++;
2376 block_count = get_unaligned_le16(ptr++);
2377
2378 BT_DBG("%s handle %d count %d", hdev->name, handle,
2379 block_count);
2380
2381 if (hdev->dev_type == HCI_BREDR)
2382 conn = hci_conn_hash_lookup_handle(hdev, handle);
2383 else {
2384 chan = hci_chan_list_lookup_handle(hdev, handle);
2385 if (chan)
2386 conn = chan->conn;
2387 }
2388 if (conn) {
2389 BT_DBG("%s conn %p sent %d", hdev->name,
2390 conn, conn->sent);
2391
2392 conn->sent -= block_count;
2393
2394 if (conn->type == ACL_LINK) {
2395 hdev->acl_cnt += block_count;
2396 if (hdev->acl_cnt > hdev->acl_pkts)
2397 hdev->acl_cnt = hdev->acl_pkts;
2398 } else {
2399 /* We should not find ourselves here */
2400 BT_DBG("Unexpected event for SCO connection");
2401 }
2402 }
2403 }
2404
2405 tasklet_schedule(&hdev->tx_task);
2406
2407 tasklet_enable(&hdev->tx_task);
2408}
2409
Marcel Holtmann04837f62006-07-03 10:02:33 +02002410static inline void hci_mode_change_evt(struct hci_dev *hdev, struct sk_buff *skb)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002411{
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002412 struct hci_ev_mode_change *ev = (void *) skb->data;
Marcel Holtmann04837f62006-07-03 10:02:33 +02002413 struct hci_conn *conn;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002414
2415 BT_DBG("%s status %d", hdev->name, ev->status);
2416
2417 hci_dev_lock(hdev);
2418
Marcel Holtmann04837f62006-07-03 10:02:33 +02002419 conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
2420 if (conn) {
2421 conn->mode = ev->mode;
2422 conn->interval = __le16_to_cpu(ev->interval);
2423
2424 if (!test_and_clear_bit(HCI_CONN_MODE_CHANGE_PEND, &conn->pend)) {
2425 if (conn->mode == HCI_CM_ACTIVE)
2426 conn->power_save = 1;
2427 else
2428 conn->power_save = 0;
2429 }
Marcel Holtmanne73439d2010-07-26 10:06:00 -04002430
2431 if (test_and_clear_bit(HCI_CONN_SCO_SETUP_PEND, &conn->pend))
2432 hci_sco_setup(conn, ev->status);
Marcel Holtmann04837f62006-07-03 10:02:33 +02002433 }
2434
2435 hci_dev_unlock(hdev);
2436}
2437
Linus Torvalds1da177e2005-04-16 15:20:36 -07002438static inline void hci_pin_code_request_evt(struct hci_dev *hdev, struct sk_buff *skb)
2439{
Marcel Holtmann052b30b2009-04-26 20:01:22 +02002440 struct hci_ev_pin_code_req *ev = (void *) skb->data;
2441 struct hci_conn *conn;
2442
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002443 BT_DBG("%s", hdev->name);
Marcel Holtmann052b30b2009-04-26 20:01:22 +02002444
2445 hci_dev_lock(hdev);
2446
2447 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
Marcel Holtmann3d7a9d12009-05-09 12:09:21 -07002448 if (conn && conn->state == BT_CONNECTED) {
Marcel Holtmann052b30b2009-04-26 20:01:22 +02002449 hci_conn_hold(conn);
2450 conn->disc_timeout = HCI_PAIRING_TIMEOUT;
2451 hci_conn_put(conn);
2452 }
2453
Johan Hedberg03b555e2011-01-04 15:40:05 +02002454 if (!test_bit(HCI_PAIRABLE, &hdev->flags))
2455 hci_send_cmd(hdev, HCI_OP_PIN_CODE_NEG_REPLY,
2456 sizeof(ev->bdaddr), &ev->bdaddr);
Waldemar Rymarkiewicza770bb52011-04-28 12:07:59 +02002457
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002458 if (test_bit(HCI_MGMT, &hdev->flags))
2459 mgmt_pin_code_request(hdev->id, &ev->bdaddr);
Johan Hedberg980e1a52011-01-22 06:10:07 +02002460
Marcel Holtmann052b30b2009-04-26 20:01:22 +02002461 hci_dev_unlock(hdev);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002462}
2463
Linus Torvalds1da177e2005-04-16 15:20:36 -07002464static inline void hci_link_key_request_evt(struct hci_dev *hdev, struct sk_buff *skb)
2465{
Johan Hedberg55ed8ca2011-01-17 14:41:05 +02002466 struct hci_ev_link_key_req *ev = (void *) skb->data;
2467 struct hci_cp_link_key_reply cp;
2468 struct hci_conn *conn;
2469 struct link_key *key;
2470
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002471 BT_DBG("%s", hdev->name);
Johan Hedberg55ed8ca2011-01-17 14:41:05 +02002472
2473 if (!test_bit(HCI_LINK_KEYS, &hdev->flags))
2474 return;
2475
2476 hci_dev_lock(hdev);
2477
2478 key = hci_find_link_key(hdev, &ev->bdaddr);
2479 if (!key) {
2480 BT_DBG("%s link key not found for %s", hdev->name,
2481 batostr(&ev->bdaddr));
2482 goto not_found;
2483 }
2484
2485 BT_DBG("%s found key type %u for %s", hdev->name, key->type,
2486 batostr(&ev->bdaddr));
2487
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002488 if (!test_bit(HCI_DEBUG_KEYS, &hdev->flags) && key->type == 0x03) {
Johan Hedberg55ed8ca2011-01-17 14:41:05 +02002489 BT_DBG("%s ignoring debug key", hdev->name);
2490 goto not_found;
2491 }
2492
2493 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
2494
Prabhakaran Mc6001a712011-09-06 11:56:25 +05302495 if (conn) {
2496 BT_DBG("Conn pending sec level is %d, ssp is %d, key len is %d",
2497 conn->pending_sec_level, conn->ssp_mode, key->pin_len);
2498 }
2499 if (conn && (conn->ssp_mode == 0) &&
2500 (conn->pending_sec_level == BT_SECURITY_HIGH) &&
2501 (key->pin_len != 16)) {
2502 BT_DBG("Security is high ignoring this key");
2503 goto not_found;
2504 }
2505
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002506 if (key->type == 0x04 && conn && conn->auth_type != 0xff &&
2507 (conn->auth_type & 0x01)) {
2508 BT_DBG("%s ignoring unauthenticated key", hdev->name);
2509 goto not_found;
Johan Hedberg55ed8ca2011-01-17 14:41:05 +02002510 }
2511
2512 bacpy(&cp.bdaddr, &ev->bdaddr);
2513 memcpy(cp.link_key, key->val, 16);
2514
2515 hci_send_cmd(hdev, HCI_OP_LINK_KEY_REPLY, sizeof(cp), &cp);
2516
2517 hci_dev_unlock(hdev);
2518
2519 return;
2520
2521not_found:
2522 hci_send_cmd(hdev, HCI_OP_LINK_KEY_NEG_REPLY, 6, &ev->bdaddr);
2523 hci_dev_unlock(hdev);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002524}
2525
Linus Torvalds1da177e2005-04-16 15:20:36 -07002526static inline void hci_link_key_notify_evt(struct hci_dev *hdev, struct sk_buff *skb)
2527{
Marcel Holtmann052b30b2009-04-26 20:01:22 +02002528 struct hci_ev_link_key_notify *ev = (void *) skb->data;
2529 struct hci_conn *conn;
Johan Hedberg55ed8ca2011-01-17 14:41:05 +02002530 u8 pin_len = 0;
Marcel Holtmann052b30b2009-04-26 20:01:22 +02002531
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002532 BT_DBG("%s type %d", hdev->name, ev->key_type);
Marcel Holtmann052b30b2009-04-26 20:01:22 +02002533
2534 hci_dev_lock(hdev);
2535
2536 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
2537 if (conn) {
2538 hci_conn_hold(conn);
2539 conn->disc_timeout = HCI_DISCONN_TIMEOUT;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002540
2541 memcpy(conn->link_key, ev->link_key, 16);
2542 conn->key_type = ev->key_type;
2543 hci_disconnect_amp(conn, 0x06);
2544
Johan Hedberg980e1a52011-01-22 06:10:07 +02002545 pin_len = conn->pin_length;
Marcel Holtmann052b30b2009-04-26 20:01:22 +02002546 hci_conn_put(conn);
2547 }
2548
Johan Hedberg55ed8ca2011-01-17 14:41:05 +02002549 if (test_bit(HCI_LINK_KEYS, &hdev->flags))
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002550 hci_add_link_key(hdev, 1, &ev->bdaddr, ev->link_key,
Johan Hedberg55ed8ca2011-01-17 14:41:05 +02002551 ev->key_type, pin_len);
2552
Marcel Holtmann052b30b2009-04-26 20:01:22 +02002553 hci_dev_unlock(hdev);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002554}
2555
Marcel Holtmann04837f62006-07-03 10:02:33 +02002556static inline void hci_clock_offset_evt(struct hci_dev *hdev, struct sk_buff *skb)
2557{
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002558 struct hci_ev_clock_offset *ev = (void *) skb->data;
Marcel Holtmann04837f62006-07-03 10:02:33 +02002559 struct hci_conn *conn;
2560
2561 BT_DBG("%s status %d", hdev->name, ev->status);
2562
2563 hci_dev_lock(hdev);
2564
2565 conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
Linus Torvalds1da177e2005-04-16 15:20:36 -07002566 if (conn && !ev->status) {
2567 struct inquiry_entry *ie;
2568
Andrei Emeltchenkocc11b9c2010-11-22 13:21:37 +02002569 ie = hci_inquiry_cache_lookup(hdev, &conn->dst);
2570 if (ie) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002571 ie->data.clock_offset = ev->clock_offset;
2572 ie->timestamp = jiffies;
2573 }
2574 }
2575
2576 hci_dev_unlock(hdev);
2577}
2578
Marcel Holtmanna8746412008-07-14 20:13:46 +02002579static inline void hci_pkt_type_change_evt(struct hci_dev *hdev, struct sk_buff *skb)
2580{
2581 struct hci_ev_pkt_type_change *ev = (void *) skb->data;
2582 struct hci_conn *conn;
2583
2584 BT_DBG("%s status %d", hdev->name, ev->status);
2585
2586 hci_dev_lock(hdev);
2587
2588 conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
2589 if (conn && !ev->status)
2590 conn->pkt_type = __le16_to_cpu(ev->pkt_type);
2591
2592 hci_dev_unlock(hdev);
2593}
2594
Marcel Holtmann85a1e932005-08-09 20:28:02 -07002595static inline void hci_pscan_rep_mode_evt(struct hci_dev *hdev, struct sk_buff *skb)
2596{
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002597 struct hci_ev_pscan_rep_mode *ev = (void *) skb->data;
Marcel Holtmann85a1e932005-08-09 20:28:02 -07002598 struct inquiry_entry *ie;
2599
2600 BT_DBG("%s", hdev->name);
2601
2602 hci_dev_lock(hdev);
2603
Andrei Emeltchenkocc11b9c2010-11-22 13:21:37 +02002604 ie = hci_inquiry_cache_lookup(hdev, &ev->bdaddr);
2605 if (ie) {
Marcel Holtmann85a1e932005-08-09 20:28:02 -07002606 ie->data.pscan_rep_mode = ev->pscan_rep_mode;
2607 ie->timestamp = jiffies;
2608 }
2609
2610 hci_dev_unlock(hdev);
2611}
2612
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002613static inline void hci_inquiry_result_with_rssi_evt(struct hci_dev *hdev, struct sk_buff *skb)
2614{
2615 struct inquiry_data data;
2616 int num_rsp = *((__u8 *) skb->data);
2617
2618 BT_DBG("%s num_rsp %d", hdev->name, num_rsp);
2619
2620 if (!num_rsp)
2621 return;
2622
2623 hci_dev_lock(hdev);
2624
2625 if ((skb->len - 1) / num_rsp != sizeof(struct inquiry_info_with_rssi)) {
Szymon Janc138d22e2011-02-17 16:44:23 +01002626 struct inquiry_info_with_rssi_and_pscan_mode *info;
2627 info = (void *) (skb->data + 1);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002628
Johan Hedberge17acd42011-03-30 23:57:16 +03002629 for (; num_rsp; num_rsp--, info++) {
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002630 bacpy(&data.bdaddr, &info->bdaddr);
2631 data.pscan_rep_mode = info->pscan_rep_mode;
2632 data.pscan_period_mode = info->pscan_period_mode;
2633 data.pscan_mode = info->pscan_mode;
2634 memcpy(data.dev_class, info->dev_class, 3);
2635 data.clock_offset = info->clock_offset;
2636 data.rssi = info->rssi;
Marcel Holtmann41a96212008-07-14 20:13:48 +02002637 data.ssp_mode = 0x00;
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002638 hci_inquiry_cache_update(hdev, &data);
Brian Gixa68668b2011-08-11 15:49:36 -07002639 mgmt_device_found(hdev->id, &info->bdaddr, 0, 0,
Johan Hedberge17acd42011-03-30 23:57:16 +03002640 info->dev_class, info->rssi,
Brian Gixa68668b2011-08-11 15:49:36 -07002641 0, NULL);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002642 }
2643 } else {
2644 struct inquiry_info_with_rssi *info = (void *) (skb->data + 1);
2645
Johan Hedberge17acd42011-03-30 23:57:16 +03002646 for (; num_rsp; num_rsp--, info++) {
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002647 bacpy(&data.bdaddr, &info->bdaddr);
2648 data.pscan_rep_mode = info->pscan_rep_mode;
2649 data.pscan_period_mode = info->pscan_period_mode;
2650 data.pscan_mode = 0x00;
2651 memcpy(data.dev_class, info->dev_class, 3);
2652 data.clock_offset = info->clock_offset;
2653 data.rssi = info->rssi;
Marcel Holtmann41a96212008-07-14 20:13:48 +02002654 data.ssp_mode = 0x00;
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002655 hci_inquiry_cache_update(hdev, &data);
Brian Gixa68668b2011-08-11 15:49:36 -07002656 mgmt_device_found(hdev->id, &info->bdaddr, 0, 0,
Johan Hedberge17acd42011-03-30 23:57:16 +03002657 info->dev_class, info->rssi,
Brian Gixa68668b2011-08-11 15:49:36 -07002658 0, NULL);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002659 }
2660 }
2661
2662 hci_dev_unlock(hdev);
2663}
2664
2665static inline void hci_remote_ext_features_evt(struct hci_dev *hdev, struct sk_buff *skb)
2666{
Marcel Holtmann41a96212008-07-14 20:13:48 +02002667 struct hci_ev_remote_ext_features *ev = (void *) skb->data;
2668 struct hci_conn *conn;
2669
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002670 BT_DBG("%s", hdev->name);
Marcel Holtmann41a96212008-07-14 20:13:48 +02002671
Marcel Holtmann41a96212008-07-14 20:13:48 +02002672 hci_dev_lock(hdev);
2673
2674 conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
Johan Hedbergccd556f2010-11-10 17:11:51 +02002675 if (!conn)
2676 goto unlock;
Marcel Holtmann41a96212008-07-14 20:13:48 +02002677
Johan Hedbergccd556f2010-11-10 17:11:51 +02002678 if (!ev->status && ev->page == 0x01) {
2679 struct inquiry_entry *ie;
Marcel Holtmann41a96212008-07-14 20:13:48 +02002680
Andrei Emeltchenkocc11b9c2010-11-22 13:21:37 +02002681 ie = hci_inquiry_cache_lookup(hdev, &conn->dst);
2682 if (ie)
Johan Hedbergccd556f2010-11-10 17:11:51 +02002683 ie->data.ssp_mode = (ev->features[0] & 0x01);
Marcel Holtmann769be972008-07-14 20:13:49 +02002684
Johan Hedbergccd556f2010-11-10 17:11:51 +02002685 conn->ssp_mode = (ev->features[0] & 0x01);
Marcel Holtmann41a96212008-07-14 20:13:48 +02002686 }
2687
Johan Hedbergccd556f2010-11-10 17:11:51 +02002688 if (conn->state != BT_CONFIG)
2689 goto unlock;
2690
Johan Hedberg127178d2010-11-18 22:22:29 +02002691 if (!ev->status) {
2692 struct hci_cp_remote_name_req cp;
2693 memset(&cp, 0, sizeof(cp));
2694 bacpy(&cp.bdaddr, &conn->dst);
2695 cp.pscan_rep_mode = 0x02;
2696 hci_send_cmd(hdev, HCI_OP_REMOTE_NAME_REQ, sizeof(cp), &cp);
2697 }
Johan Hedberg392599b2010-11-18 22:22:28 +02002698
Johan Hedberg127178d2010-11-18 22:22:29 +02002699 if (!hci_outgoing_auth_needed(hdev, conn)) {
Johan Hedbergccd556f2010-11-10 17:11:51 +02002700 conn->state = BT_CONNECTED;
2701 hci_proto_connect_cfm(conn, ev->status);
2702 hci_conn_put(conn);
2703 }
2704
2705unlock:
Marcel Holtmann41a96212008-07-14 20:13:48 +02002706 hci_dev_unlock(hdev);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002707}
2708
2709static inline void hci_sync_conn_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
2710{
Marcel Holtmannb6a0dc82007-10-20 14:55:10 +02002711 struct hci_ev_sync_conn_complete *ev = (void *) skb->data;
2712 struct hci_conn *conn;
2713
2714 BT_DBG("%s status %d", hdev->name, ev->status);
2715
2716 hci_dev_lock(hdev);
2717
2718 conn = hci_conn_hash_lookup_ba(hdev, ev->link_type, &ev->bdaddr);
Marcel Holtmann9dc0a3a2008-07-14 20:13:46 +02002719 if (!conn) {
2720 if (ev->link_type == ESCO_LINK)
2721 goto unlock;
2722
2723 conn = hci_conn_hash_lookup_ba(hdev, ESCO_LINK, &ev->bdaddr);
2724 if (!conn)
2725 goto unlock;
2726
2727 conn->type = SCO_LINK;
2728 }
Marcel Holtmannb6a0dc82007-10-20 14:55:10 +02002729
Marcel Holtmann732547f2009-04-19 19:14:14 +02002730 switch (ev->status) {
2731 case 0x00:
Marcel Holtmannb6a0dc82007-10-20 14:55:10 +02002732 conn->handle = __le16_to_cpu(ev->handle);
2733 conn->state = BT_CONNECTED;
Marcel Holtmann7d0db0a2008-07-14 20:13:51 +02002734
Marcel Holtmann9eba32b2009-08-22 14:19:26 -07002735 hci_conn_hold_device(conn);
Marcel Holtmann7d0db0a2008-07-14 20:13:51 +02002736 hci_conn_add_sysfs(conn);
Marcel Holtmann732547f2009-04-19 19:14:14 +02002737 break;
2738
Stephen Coe705e5712010-02-16 11:29:44 -05002739 case 0x11: /* Unsupported Feature or Parameter Value */
Marcel Holtmann732547f2009-04-19 19:14:14 +02002740 case 0x1c: /* SCO interval rejected */
Nick Pelly1038a002010-02-03 11:42:26 -08002741 case 0x1a: /* Unsupported Remote Feature */
Marcel Holtmann732547f2009-04-19 19:14:14 +02002742 case 0x1f: /* Unspecified error */
2743 if (conn->out && conn->attempt < 2) {
Kun Han Kim15b911f2011-07-08 09:30:28 -07002744 if (!conn->hdev->is_wbs)
2745 conn->pkt_type =
2746 (hdev->esco_type & SCO_ESCO_MASK) |
Marcel Holtmann732547f2009-04-19 19:14:14 +02002747 (hdev->esco_type & EDR_ESCO_MASK);
2748 hci_setup_sync(conn, conn->link->handle);
2749 goto unlock;
2750 }
2751 /* fall through */
2752
2753 default:
Marcel Holtmannb6a0dc82007-10-20 14:55:10 +02002754 conn->state = BT_CLOSED;
Marcel Holtmann732547f2009-04-19 19:14:14 +02002755 break;
2756 }
Marcel Holtmannb6a0dc82007-10-20 14:55:10 +02002757
2758 hci_proto_connect_cfm(conn, ev->status);
2759 if (ev->status)
2760 hci_conn_del(conn);
2761
2762unlock:
2763 hci_dev_unlock(hdev);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002764}
2765
2766static inline void hci_sync_conn_changed_evt(struct hci_dev *hdev, struct sk_buff *skb)
2767{
2768 BT_DBG("%s", hdev->name);
2769}
2770
Marcel Holtmann04837f62006-07-03 10:02:33 +02002771static inline void hci_sniff_subrate_evt(struct hci_dev *hdev, struct sk_buff *skb)
2772{
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002773 struct hci_ev_sniff_subrate *ev = (void *) skb->data;
Marcel Holtmann04837f62006-07-03 10:02:33 +02002774
2775 BT_DBG("%s status %d", hdev->name, ev->status);
Marcel Holtmann04837f62006-07-03 10:02:33 +02002776}
2777
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002778static inline void hci_extended_inquiry_result_evt(struct hci_dev *hdev, struct sk_buff *skb)
2779{
2780 struct inquiry_data data;
2781 struct extended_inquiry_info *info = (void *) (skb->data + 1);
2782 int num_rsp = *((__u8 *) skb->data);
2783
2784 BT_DBG("%s num_rsp %d", hdev->name, num_rsp);
2785
2786 if (!num_rsp)
2787 return;
2788
2789 hci_dev_lock(hdev);
2790
Johan Hedberge17acd42011-03-30 23:57:16 +03002791 for (; num_rsp; num_rsp--, info++) {
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002792 bacpy(&data.bdaddr, &info->bdaddr);
Szymon Janc138d22e2011-02-17 16:44:23 +01002793 data.pscan_rep_mode = info->pscan_rep_mode;
2794 data.pscan_period_mode = info->pscan_period_mode;
2795 data.pscan_mode = 0x00;
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002796 memcpy(data.dev_class, info->dev_class, 3);
Szymon Janc138d22e2011-02-17 16:44:23 +01002797 data.clock_offset = info->clock_offset;
2798 data.rssi = info->rssi;
Marcel Holtmann41a96212008-07-14 20:13:48 +02002799 data.ssp_mode = 0x01;
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002800 hci_inquiry_cache_update(hdev, &data);
Brian Gixa68668b2011-08-11 15:49:36 -07002801 mgmt_device_found(hdev->id, &info->bdaddr, 0, 0,
2802 info->dev_class, info->rssi,
2803 HCI_MAX_EIR_LENGTH, info->data);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002804 }
2805
2806 hci_dev_unlock(hdev);
2807}
2808
Johan Hedberg17fa4b92011-01-25 13:28:33 +02002809static inline u8 hci_get_auth_req(struct hci_conn *conn)
2810{
Brian Gixa68668b2011-08-11 15:49:36 -07002811 BT_DBG("%p", conn);
2812
Johan Hedberg17fa4b92011-01-25 13:28:33 +02002813 /* If remote requests dedicated bonding follow that lead */
2814 if (conn->remote_auth == 0x02 || conn->remote_auth == 0x03) {
2815 /* If both remote and local IO capabilities allow MITM
2816 * protection then require it, otherwise don't */
Brian Gixa68668b2011-08-11 15:49:36 -07002817 if (conn->remote_cap == 0x03 || conn->io_capability == 0x03) {
Johan Hedberg17fa4b92011-01-25 13:28:33 +02002818 return 0x02;
Brian Gixa68668b2011-08-11 15:49:36 -07002819 } else {
2820 conn->auth_type |= 0x01;
Johan Hedberg17fa4b92011-01-25 13:28:33 +02002821 return 0x03;
Brian Gixa68668b2011-08-11 15:49:36 -07002822 }
Johan Hedberg17fa4b92011-01-25 13:28:33 +02002823 }
2824
2825 /* If remote requests no-bonding follow that lead */
Brian Gixa68668b2011-08-11 15:49:36 -07002826 if (conn->remote_auth <= 0x01)
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002827 return 0x00;
Johan Hedberg17fa4b92011-01-25 13:28:33 +02002828
2829 return conn->auth_type;
2830}
2831
Marcel Holtmann04936842008-07-14 20:13:48 +02002832static inline void hci_io_capa_request_evt(struct hci_dev *hdev, struct sk_buff *skb)
2833{
2834 struct hci_ev_io_capa_request *ev = (void *) skb->data;
2835 struct hci_conn *conn;
2836
2837 BT_DBG("%s", hdev->name);
2838
2839 hci_dev_lock(hdev);
2840
2841 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
Johan Hedberg03b555e2011-01-04 15:40:05 +02002842 if (!conn)
2843 goto unlock;
Marcel Holtmann04936842008-07-14 20:13:48 +02002844
Johan Hedberg03b555e2011-01-04 15:40:05 +02002845 hci_conn_hold(conn);
2846
2847 if (!test_bit(HCI_MGMT, &hdev->flags))
2848 goto unlock;
2849
2850 if (test_bit(HCI_PAIRABLE, &hdev->flags) ||
2851 (conn->remote_auth & ~0x01) == HCI_AT_NO_BONDING) {
Johan Hedberg17fa4b92011-01-25 13:28:33 +02002852 struct hci_cp_io_capability_reply cp;
Brian Gixa68668b2011-08-11 15:49:36 -07002853 u8 io_cap = conn->io_capability;
Johan Hedberg17fa4b92011-01-25 13:28:33 +02002854
Brian Gixa68668b2011-08-11 15:49:36 -07002855 /* ACL-SSP does not support IO CAP 0x04 */
2856 cp.capability = (io_cap == 0x04) ? 0x01 : io_cap;
Johan Hedberg17fa4b92011-01-25 13:28:33 +02002857 bacpy(&cp.bdaddr, &ev->bdaddr);
Brian Gixa68668b2011-08-11 15:49:36 -07002858 if (conn->auth_initiator)
2859 cp.authentication = conn->auth_type;
2860 else
2861 cp.authentication = hci_get_auth_req(conn);
Johan Hedberg17fa4b92011-01-25 13:28:33 +02002862
Szymon Jancce85ee12011-03-22 13:12:23 +01002863 if ((conn->out == 0x01 || conn->remote_oob == 0x01) &&
2864 hci_find_remote_oob_data(hdev, &conn->dst))
2865 cp.oob_data = 0x01;
2866 else
2867 cp.oob_data = 0x00;
2868
Johan Hedberg17fa4b92011-01-25 13:28:33 +02002869 hci_send_cmd(hdev, HCI_OP_IO_CAPABILITY_REPLY,
2870 sizeof(cp), &cp);
Johan Hedberg03b555e2011-01-04 15:40:05 +02002871 } else {
2872 struct hci_cp_io_capability_neg_reply cp;
2873
2874 bacpy(&cp.bdaddr, &ev->bdaddr);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002875 cp.reason = 0x16; /* Pairing not allowed */
Johan Hedberg03b555e2011-01-04 15:40:05 +02002876
2877 hci_send_cmd(hdev, HCI_OP_IO_CAPABILITY_NEG_REPLY,
2878 sizeof(cp), &cp);
2879 }
2880
2881unlock:
2882 hci_dev_unlock(hdev);
2883}
2884
2885static inline void hci_io_capa_reply_evt(struct hci_dev *hdev, struct sk_buff *skb)
2886{
2887 struct hci_ev_io_capa_reply *ev = (void *) skb->data;
2888 struct hci_conn *conn;
2889
2890 BT_DBG("%s", hdev->name);
2891
2892 hci_dev_lock(hdev);
2893
2894 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
2895 if (!conn)
2896 goto unlock;
2897
Johan Hedberg03b555e2011-01-04 15:40:05 +02002898 conn->remote_cap = ev->capability;
2899 conn->remote_oob = ev->oob_data;
2900 conn->remote_auth = ev->authentication;
2901
2902unlock:
Marcel Holtmann04936842008-07-14 20:13:48 +02002903 hci_dev_unlock(hdev);
2904}
2905
Brian Gixa68668b2011-08-11 15:49:36 -07002906static inline void hci_user_ssp_confirmation_evt(struct hci_dev *hdev,
2907 u8 event, struct sk_buff *skb)
Johan Hedberga5c29682011-02-19 12:05:57 -03002908{
2909 struct hci_ev_user_confirm_req *ev = (void *) skb->data;
2910
2911 BT_DBG("%s", hdev->name);
2912
2913 hci_dev_lock(hdev);
2914
Brian Gixa68668b2011-08-11 15:49:36 -07002915 if (test_bit(HCI_MGMT, &hdev->flags)) {
2916 if (event == HCI_EV_USER_PASSKEY_REQUEST)
2917 mgmt_user_confirm_request(hdev->id, event,
2918 &ev->bdaddr, 0);
2919 else
2920 mgmt_user_confirm_request(hdev->id, event,
2921 &ev->bdaddr, ev->passkey);
2922 }
Johan Hedberga5c29682011-02-19 12:05:57 -03002923
2924 hci_dev_unlock(hdev);
2925}
2926
Marcel Holtmann04936842008-07-14 20:13:48 +02002927static inline void hci_simple_pair_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
2928{
2929 struct hci_ev_simple_pair_complete *ev = (void *) skb->data;
2930 struct hci_conn *conn;
2931
2932 BT_DBG("%s", hdev->name);
2933
2934 hci_dev_lock(hdev);
2935
2936 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
Johan Hedberg2a611692011-02-19 12:06:00 -03002937 if (!conn)
2938 goto unlock;
Marcel Holtmann04936842008-07-14 20:13:48 +02002939
Johan Hedberg2a611692011-02-19 12:06:00 -03002940 /* To avoid duplicate auth_failed events to user space we check
2941 * the HCI_CONN_AUTH_PEND flag which will be set if we
2942 * initiated the authentication. A traditional auth_complete
2943 * event gets always produced as initiator and is also mapped to
2944 * the mgmt_auth_failed event */
2945 if (!test_bit(HCI_CONN_AUTH_PEND, &conn->pend) && ev->status != 0)
2946 mgmt_auth_failed(hdev->id, &conn->dst, ev->status);
2947
2948 hci_conn_put(conn);
2949
2950unlock:
Marcel Holtmann04936842008-07-14 20:13:48 +02002951 hci_dev_unlock(hdev);
2952}
2953
Marcel Holtmann41a96212008-07-14 20:13:48 +02002954static inline void hci_remote_host_features_evt(struct hci_dev *hdev, struct sk_buff *skb)
2955{
2956 struct hci_ev_remote_host_features *ev = (void *) skb->data;
2957 struct inquiry_entry *ie;
2958
2959 BT_DBG("%s", hdev->name);
2960
2961 hci_dev_lock(hdev);
2962
Andrei Emeltchenkocc11b9c2010-11-22 13:21:37 +02002963 ie = hci_inquiry_cache_lookup(hdev, &ev->bdaddr);
2964 if (ie)
Marcel Holtmann41a96212008-07-14 20:13:48 +02002965 ie->data.ssp_mode = (ev->features[0] & 0x01);
2966
2967 hci_dev_unlock(hdev);
2968}
2969
Szymon Janc2763eda2011-03-22 13:12:22 +01002970static inline void hci_remote_oob_data_request_evt(struct hci_dev *hdev,
2971 struct sk_buff *skb)
2972{
2973 struct hci_ev_remote_oob_data_request *ev = (void *) skb->data;
2974 struct oob_data *data;
2975
2976 BT_DBG("%s", hdev->name);
2977
2978 hci_dev_lock(hdev);
2979
Szymon Jance1ba1f12011-04-06 13:01:59 +02002980 if (!test_bit(HCI_MGMT, &hdev->flags))
2981 goto unlock;
2982
Szymon Janc2763eda2011-03-22 13:12:22 +01002983 data = hci_find_remote_oob_data(hdev, &ev->bdaddr);
2984 if (data) {
2985 struct hci_cp_remote_oob_data_reply cp;
2986
2987 bacpy(&cp.bdaddr, &ev->bdaddr);
2988 memcpy(cp.hash, data->hash, sizeof(cp.hash));
2989 memcpy(cp.randomizer, data->randomizer, sizeof(cp.randomizer));
2990
2991 hci_send_cmd(hdev, HCI_OP_REMOTE_OOB_DATA_REPLY, sizeof(cp),
2992 &cp);
2993 } else {
2994 struct hci_cp_remote_oob_data_neg_reply cp;
2995
2996 bacpy(&cp.bdaddr, &ev->bdaddr);
2997 hci_send_cmd(hdev, HCI_OP_REMOTE_OOB_DATA_NEG_REPLY, sizeof(cp),
2998 &cp);
2999 }
3000
Szymon Jance1ba1f12011-04-06 13:01:59 +02003001unlock:
Szymon Janc2763eda2011-03-22 13:12:22 +01003002 hci_dev_unlock(hdev);
3003}
3004
Ville Tervofcd89c02011-02-10 22:38:47 -03003005static inline void hci_le_conn_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
3006{
3007 struct hci_ev_le_conn_complete *ev = (void *) skb->data;
3008 struct hci_conn *conn;
3009
3010 BT_DBG("%s status %d", hdev->name, ev->status);
3011
3012 hci_dev_lock(hdev);
3013
3014 conn = hci_conn_hash_lookup_ba(hdev, LE_LINK, &ev->bdaddr);
Ville Tervob62f3282011-02-10 22:38:50 -03003015 if (!conn) {
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003016 conn = hci_le_conn_add(hdev, &ev->bdaddr, ev->bdaddr_type);
Ville Tervob62f3282011-02-10 22:38:50 -03003017 if (!conn) {
3018 BT_ERR("No memory for new connection");
3019 hci_dev_unlock(hdev);
3020 return;
3021 }
3022 }
Ville Tervofcd89c02011-02-10 22:38:47 -03003023
3024 if (ev->status) {
3025 hci_proto_connect_cfm(conn, ev->status);
3026 conn->state = BT_CLOSED;
3027 hci_conn_del(conn);
3028 goto unlock;
3029 }
3030
Vinicius Costa Gomes403d2c82011-06-09 18:50:50 -03003031 conn->sec_level = BT_SECURITY_LOW;
Ville Tervofcd89c02011-02-10 22:38:47 -03003032 conn->handle = __le16_to_cpu(ev->handle);
3033 conn->state = BT_CONNECTED;
Brian Gixa68668b2011-08-11 15:49:36 -07003034 conn->disc_timeout = HCI_DISCONN_TIMEOUT;
Brian Gix2e2f50d2011-09-13 12:36:04 -07003035 mgmt_connected(hdev->id, &ev->bdaddr, 1);
Ville Tervofcd89c02011-02-10 22:38:47 -03003036
Brian Gix6d5fb8a2011-09-09 14:53:04 -07003037 hci_conn_hold(conn);
Ville Tervofcd89c02011-02-10 22:38:47 -03003038 hci_conn_hold_device(conn);
3039 hci_conn_add_sysfs(conn);
3040
3041 hci_proto_connect_cfm(conn, ev->status);
3042
3043unlock:
3044 hci_dev_unlock(hdev);
3045}
3046
Vinicius Costa Gomes735038c2011-06-09 18:50:47 -03003047static inline void hci_le_ltk_request_evt(struct hci_dev *hdev,
3048 struct sk_buff *skb)
3049{
3050 struct hci_ev_le_ltk_req *ev = (void *) skb->data;
3051 struct hci_cp_le_ltk_reply cp;
Vinicius Costa Gomes60e56472011-07-07 18:59:37 -03003052 struct hci_cp_le_ltk_neg_reply neg;
Vinicius Costa Gomes735038c2011-06-09 18:50:47 -03003053 struct hci_conn *conn;
Vinicius Costa Gomes60e56472011-07-07 18:59:37 -03003054 struct link_key *ltk;
Vinicius Costa Gomes735038c2011-06-09 18:50:47 -03003055
3056 BT_DBG("%s handle %d", hdev->name, cpu_to_le16(ev->handle));
3057
3058 hci_dev_lock(hdev);
3059
3060 conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
Vinicius Costa Gomes60e56472011-07-07 18:59:37 -03003061 if (conn == NULL)
3062 goto not_found;
Vinicius Costa Gomes735038c2011-06-09 18:50:47 -03003063
Vinicius Costa Gomes60e56472011-07-07 18:59:37 -03003064 ltk = hci_find_ltk(hdev, ev->ediv, ev->random);
3065 if (ltk == NULL)
3066 goto not_found;
3067
3068 memcpy(cp.ltk, ltk->val, sizeof(ltk->val));
Vinicius Costa Gomes735038c2011-06-09 18:50:47 -03003069 cp.handle = cpu_to_le16(conn->handle);
Vinicius Costa Gomes1fa2de32011-07-08 18:31:45 -03003070 conn->pin_length = ltk->pin_len;
Vinicius Costa Gomes735038c2011-06-09 18:50:47 -03003071
3072 hci_send_cmd(hdev, HCI_OP_LE_LTK_REPLY, sizeof(cp), &cp);
3073
3074 hci_dev_unlock(hdev);
Vinicius Costa Gomes60e56472011-07-07 18:59:37 -03003075
3076 return;
3077
3078not_found:
3079 neg.handle = ev->handle;
3080 hci_send_cmd(hdev, HCI_OP_LE_LTK_NEG_REPLY, sizeof(neg), &neg);
3081 hci_dev_unlock(hdev);
Vinicius Costa Gomes735038c2011-06-09 18:50:47 -03003082}
3083
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003084static inline void hci_le_adv_report_evt(struct hci_dev *hdev,
3085 struct sk_buff *skb)
3086{
3087 struct hci_ev_le_advertising_info *ev;
3088 u8 num_reports;
3089
3090 num_reports = skb->data[0];
3091 ev = (void *) &skb->data[1];
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003092
Brian Gix3dd70172011-09-16 21:38:54 -07003093 hci_dev_lock(hdev);
3094
Brian Gixa68668b2011-08-11 15:49:36 -07003095 while (num_reports--) {
3096 mgmt_device_found(hdev->id, &ev->bdaddr, ev->bdaddr_type,
3097 1, NULL, 0, ev->length, ev->data);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003098 hci_add_adv_entry(hdev, ev);
Brian Gixa68668b2011-08-11 15:49:36 -07003099 ev = (void *) (ev->data + ev->length + 1);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003100 }
Brian Gix3dd70172011-09-16 21:38:54 -07003101
3102 hci_dev_unlock(hdev);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003103}
3104
Ville Tervofcd89c02011-02-10 22:38:47 -03003105static inline void hci_le_meta_evt(struct hci_dev *hdev, struct sk_buff *skb)
3106{
3107 struct hci_ev_le_meta *le_ev = (void *) skb->data;
3108
3109 skb_pull(skb, sizeof(*le_ev));
3110
3111 switch (le_ev->subevent) {
3112 case HCI_EV_LE_CONN_COMPLETE:
3113 hci_le_conn_complete_evt(hdev, skb);
3114 break;
3115
Vinicius Costa Gomes735038c2011-06-09 18:50:47 -03003116 case HCI_EV_LE_LTK_REQ:
3117 hci_le_ltk_request_evt(hdev, skb);
3118 break;
3119
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003120 case HCI_EV_LE_ADVERTISING_REPORT:
3121 hci_le_adv_report_evt(hdev, skb);
3122 break;
3123
Ville Tervofcd89c02011-02-10 22:38:47 -03003124 default:
3125 break;
3126 }
3127}
3128
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003129static inline void hci_phy_link_complete(struct hci_dev *hdev,
3130 struct sk_buff *skb)
3131{
3132 struct hci_ev_phys_link_complete *ev = (void *) skb->data;
3133 struct hci_conn *conn;
3134
3135 BT_DBG("%s handle %d status %d", hdev->name, ev->phy_handle,
3136 ev->status);
3137
3138 hci_dev_lock(hdev);
3139
3140 if (ev->status == 0) {
3141 conn = hci_conn_add(hdev, ACL_LINK, 0, BDADDR_ANY);
3142 if (conn) {
3143 conn->handle = ev->phy_handle;
3144 conn->state = BT_CONNECTED;
3145
3146 hci_conn_hold(conn);
3147 conn->disc_timeout = HCI_DISCONN_TIMEOUT/2;
3148 hci_conn_put(conn);
3149
3150 hci_conn_hold_device(conn);
3151 hci_conn_add_sysfs(conn);
3152 } else
3153 BT_ERR("No memory for new connection");
3154 }
3155
3156 hci_dev_unlock(hdev);
3157}
3158
3159static inline void hci_log_link_complete(struct hci_dev *hdev,
3160 struct sk_buff *skb)
3161{
3162 struct hci_ev_log_link_complete *ev = (void *) skb->data;
3163 struct hci_chan *chan;
3164
3165 BT_DBG("%s handle %d status %d", hdev->name,
3166 __le16_to_cpu(ev->log_handle), ev->status);
3167
3168 hci_dev_lock(hdev);
3169
3170 chan = hci_chan_list_lookup_id(hdev, ev->phy_handle);
3171
3172 if (ev->status == 0) {
3173 if (chan) {
3174 chan->ll_handle = __le16_to_cpu(ev->log_handle);
3175 chan->state = BT_CONNECTED;
3176 hci_proto_create_cfm(chan, ev->status);
3177 hci_chan_hold(chan);
3178 }
3179 } else {
3180 if (chan) {
3181 chan->state = BT_CLOSED;
3182 hci_proto_create_cfm(chan, ev->status);
3183 hci_chan_del(chan);
3184 }
3185 }
3186
3187 hci_dev_unlock(hdev);
3188}
3189
3190static inline void hci_flow_spec_modify_complete(struct hci_dev *hdev,
3191 struct sk_buff *skb)
3192{
3193 struct hci_ev_flow_spec_modify_complete *ev = (void *) skb->data;
3194 struct hci_chan *chan;
3195
3196 BT_DBG("%s handle %d status %d", hdev->name,
3197 __le16_to_cpu(ev->log_handle), ev->status);
3198
3199 hci_dev_lock(hdev);
3200
3201 chan = hci_chan_list_lookup_handle(hdev, ev->log_handle);
3202 if (chan)
3203 hci_proto_modify_cfm(chan, ev->status);
3204
3205 hci_dev_unlock(hdev);
3206}
3207
3208static inline void hci_disconn_log_link_complete_evt(struct hci_dev *hdev,
3209 struct sk_buff *skb)
3210{
3211 struct hci_ev_disconn_log_link_complete *ev = (void *) skb->data;
3212 struct hci_chan *chan;
3213
3214 BT_DBG("%s handle %d status %d", hdev->name,
3215 __le16_to_cpu(ev->log_handle), ev->status);
3216
3217 if (ev->status)
3218 return;
3219
3220 hci_dev_lock(hdev);
3221
3222 chan = hci_chan_list_lookup_handle(hdev, __le16_to_cpu(ev->log_handle));
3223 if (chan) {
3224 hci_proto_destroy_cfm(chan, ev->reason);
3225 hci_chan_del(chan);
3226 }
3227
3228 hci_dev_unlock(hdev);
3229}
3230
3231static inline void hci_disconn_phy_link_complete_evt(struct hci_dev *hdev,
3232 struct sk_buff *skb)
3233{
3234 struct hci_ev_disconn_phys_link_complete *ev = (void *) skb->data;
3235 struct hci_conn *conn;
3236
3237 BT_DBG("%s status %d", hdev->name, ev->status);
3238
3239 if (ev->status)
3240 return;
3241
3242 hci_dev_lock(hdev);
3243
3244 conn = hci_conn_hash_lookup_handle(hdev, ev->phy_handle);
3245 if (conn) {
3246 conn->state = BT_CLOSED;
3247
3248 hci_proto_disconn_cfm(conn, ev->reason);
3249 hci_conn_del(conn);
3250 }
3251
3252 hci_dev_unlock(hdev);
3253}
3254
Linus Torvalds1da177e2005-04-16 15:20:36 -07003255void hci_event_packet(struct hci_dev *hdev, struct sk_buff *skb)
3256{
Marcel Holtmanna9de9242007-10-20 13:33:56 +02003257 struct hci_event_hdr *hdr = (void *) skb->data;
3258 __u8 event = hdr->evt;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003259
Brian Gixdfdd9362011-08-18 09:58:02 -07003260 BT_DBG("");
3261
Linus Torvalds1da177e2005-04-16 15:20:36 -07003262 skb_pull(skb, HCI_EVENT_HDR_SIZE);
3263
Marcel Holtmanna9de9242007-10-20 13:33:56 +02003264 switch (event) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003265 case HCI_EV_INQUIRY_COMPLETE:
3266 hci_inquiry_complete_evt(hdev, skb);
3267 break;
3268
3269 case HCI_EV_INQUIRY_RESULT:
3270 hci_inquiry_result_evt(hdev, skb);
3271 break;
3272
Marcel Holtmanna9de9242007-10-20 13:33:56 +02003273 case HCI_EV_CONN_COMPLETE:
3274 hci_conn_complete_evt(hdev, skb);
Marcel Holtmann21d9e302005-09-13 01:32:25 +02003275 break;
3276
Linus Torvalds1da177e2005-04-16 15:20:36 -07003277 case HCI_EV_CONN_REQUEST:
3278 hci_conn_request_evt(hdev, skb);
3279 break;
3280
Linus Torvalds1da177e2005-04-16 15:20:36 -07003281 case HCI_EV_DISCONN_COMPLETE:
3282 hci_disconn_complete_evt(hdev, skb);
3283 break;
3284
Linus Torvalds1da177e2005-04-16 15:20:36 -07003285 case HCI_EV_AUTH_COMPLETE:
3286 hci_auth_complete_evt(hdev, skb);
3287 break;
3288
Marcel Holtmanna9de9242007-10-20 13:33:56 +02003289 case HCI_EV_REMOTE_NAME:
3290 hci_remote_name_evt(hdev, skb);
3291 break;
3292
Linus Torvalds1da177e2005-04-16 15:20:36 -07003293 case HCI_EV_ENCRYPT_CHANGE:
3294 hci_encrypt_change_evt(hdev, skb);
3295 break;
3296
Marcel Holtmanna9de9242007-10-20 13:33:56 +02003297 case HCI_EV_CHANGE_LINK_KEY_COMPLETE:
3298 hci_change_link_key_complete_evt(hdev, skb);
3299 break;
3300
3301 case HCI_EV_REMOTE_FEATURES:
3302 hci_remote_features_evt(hdev, skb);
3303 break;
3304
3305 case HCI_EV_REMOTE_VERSION:
3306 hci_remote_version_evt(hdev, skb);
3307 break;
3308
3309 case HCI_EV_QOS_SETUP_COMPLETE:
3310 hci_qos_setup_complete_evt(hdev, skb);
3311 break;
3312
3313 case HCI_EV_CMD_COMPLETE:
3314 hci_cmd_complete_evt(hdev, skb);
3315 break;
3316
3317 case HCI_EV_CMD_STATUS:
3318 hci_cmd_status_evt(hdev, skb);
3319 break;
3320
3321 case HCI_EV_ROLE_CHANGE:
3322 hci_role_change_evt(hdev, skb);
3323 break;
3324
3325 case HCI_EV_NUM_COMP_PKTS:
3326 hci_num_comp_pkts_evt(hdev, skb);
3327 break;
3328
3329 case HCI_EV_MODE_CHANGE:
3330 hci_mode_change_evt(hdev, skb);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003331 break;
3332
3333 case HCI_EV_PIN_CODE_REQ:
3334 hci_pin_code_request_evt(hdev, skb);
3335 break;
3336
3337 case HCI_EV_LINK_KEY_REQ:
3338 hci_link_key_request_evt(hdev, skb);
3339 break;
3340
3341 case HCI_EV_LINK_KEY_NOTIFY:
3342 hci_link_key_notify_evt(hdev, skb);
3343 break;
3344
3345 case HCI_EV_CLOCK_OFFSET:
3346 hci_clock_offset_evt(hdev, skb);
3347 break;
3348
Marcel Holtmanna8746412008-07-14 20:13:46 +02003349 case HCI_EV_PKT_TYPE_CHANGE:
3350 hci_pkt_type_change_evt(hdev, skb);
3351 break;
3352
Marcel Holtmann85a1e932005-08-09 20:28:02 -07003353 case HCI_EV_PSCAN_REP_MODE:
3354 hci_pscan_rep_mode_evt(hdev, skb);
3355 break;
3356
Marcel Holtmanna9de9242007-10-20 13:33:56 +02003357 case HCI_EV_INQUIRY_RESULT_WITH_RSSI:
3358 hci_inquiry_result_with_rssi_evt(hdev, skb);
3359 break;
3360
3361 case HCI_EV_REMOTE_EXT_FEATURES:
3362 hci_remote_ext_features_evt(hdev, skb);
3363 break;
3364
3365 case HCI_EV_SYNC_CONN_COMPLETE:
3366 hci_sync_conn_complete_evt(hdev, skb);
3367 break;
3368
3369 case HCI_EV_SYNC_CONN_CHANGED:
3370 hci_sync_conn_changed_evt(hdev, skb);
3371 break;
3372
Marcel Holtmann04837f62006-07-03 10:02:33 +02003373 case HCI_EV_SNIFF_SUBRATE:
3374 hci_sniff_subrate_evt(hdev, skb);
3375 break;
3376
Marcel Holtmanna9de9242007-10-20 13:33:56 +02003377 case HCI_EV_EXTENDED_INQUIRY_RESULT:
3378 hci_extended_inquiry_result_evt(hdev, skb);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003379 break;
3380
Marcel Holtmann04936842008-07-14 20:13:48 +02003381 case HCI_EV_IO_CAPA_REQUEST:
3382 hci_io_capa_request_evt(hdev, skb);
3383 break;
3384
Johan Hedberg03b555e2011-01-04 15:40:05 +02003385 case HCI_EV_IO_CAPA_REPLY:
3386 hci_io_capa_reply_evt(hdev, skb);
3387 break;
3388
Brian Gixa68668b2011-08-11 15:49:36 -07003389 case HCI_EV_USER_PASSKEY_REQUEST:
3390 case HCI_EV_USER_PASSKEY_NOTIFICATION:
Johan Hedberga5c29682011-02-19 12:05:57 -03003391 case HCI_EV_USER_CONFIRM_REQUEST:
Brian Gixa68668b2011-08-11 15:49:36 -07003392 hci_user_ssp_confirmation_evt(hdev, event, skb);
Johan Hedberga5c29682011-02-19 12:05:57 -03003393 break;
3394
Marcel Holtmann04936842008-07-14 20:13:48 +02003395 case HCI_EV_SIMPLE_PAIR_COMPLETE:
3396 hci_simple_pair_complete_evt(hdev, skb);
3397 break;
3398
Marcel Holtmann41a96212008-07-14 20:13:48 +02003399 case HCI_EV_REMOTE_HOST_FEATURES:
3400 hci_remote_host_features_evt(hdev, skb);
3401 break;
3402
Ville Tervofcd89c02011-02-10 22:38:47 -03003403 case HCI_EV_LE_META:
3404 hci_le_meta_evt(hdev, skb);
3405 break;
3406
Szymon Janc2763eda2011-03-22 13:12:22 +01003407 case HCI_EV_REMOTE_OOB_DATA_REQUEST:
3408 hci_remote_oob_data_request_evt(hdev, skb);
3409 break;
3410
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003411 case HCI_EV_PHYS_LINK_COMPLETE:
3412 hci_phy_link_complete(hdev, skb);
3413 hci_amp_event_packet(hdev, event, skb);
3414 break;
3415
3416 case HCI_EV_LOG_LINK_COMPLETE:
3417 hci_log_link_complete(hdev, skb);
3418 break;
3419
3420 case HCI_EV_FLOW_SPEC_MODIFY_COMPLETE:
3421 hci_flow_spec_modify_complete(hdev, skb);
3422 break;
3423
3424 case HCI_EV_DISCONN_LOG_LINK_COMPLETE:
3425 hci_disconn_log_link_complete_evt(hdev, skb);
3426 break;
3427
3428 case HCI_EV_DISCONN_PHYS_LINK_COMPLETE:
3429 hci_disconn_phy_link_complete_evt(hdev, skb);
3430 hci_amp_event_packet(hdev, event, skb);
3431 break;
3432
3433 case HCI_EV_NUM_COMP_BLOCKS:
3434 hci_num_comp_blocks_evt(hdev, skb);
3435 break;
3436
3437 case HCI_EV_CHANNEL_SELECTED:
3438 hci_amp_event_packet(hdev, event, skb);
3439 break;
3440
3441 case HCI_EV_AMP_STATUS_CHANGE:
3442 hci_amp_event_packet(hdev, event, skb);
3443 break;
3444
Marcel Holtmanna9de9242007-10-20 13:33:56 +02003445 default:
3446 BT_DBG("%s event 0x%x", hdev->name, event);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003447 break;
3448 }
3449
3450 kfree_skb(skb);
3451 hdev->stat.evt_rx++;
3452}
3453
3454/* Generate internal stack event */
3455void hci_si_event(struct hci_dev *hdev, int type, int dlen, void *data)
3456{
3457 struct hci_event_hdr *hdr;
3458 struct hci_ev_stack_internal *ev;
3459 struct sk_buff *skb;
3460
3461 skb = bt_skb_alloc(HCI_EVENT_HDR_SIZE + sizeof(*ev) + dlen, GFP_ATOMIC);
3462 if (!skb)
3463 return;
3464
3465 hdr = (void *) skb_put(skb, HCI_EVENT_HDR_SIZE);
3466 hdr->evt = HCI_EV_STACK_INTERNAL;
3467 hdr->plen = sizeof(*ev) + dlen;
3468
3469 ev = (void *) skb_put(skb, sizeof(*ev) + dlen);
3470 ev->type = type;
3471 memcpy(ev->data, data, dlen);
3472
Marcel Holtmann576c7d82005-08-06 12:36:54 +02003473 bt_cb(skb)->incoming = 1;
Patrick McHardya61bbcf2005-08-14 17:24:31 -07003474 __net_timestamp(skb);
Marcel Holtmann576c7d82005-08-06 12:36:54 +02003475
Marcel Holtmann0d48d932005-08-09 20:30:28 -07003476 bt_cb(skb)->pkt_type = HCI_EVENT_PKT;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003477 skb->dev = (void *) hdev;
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02003478 hci_send_to_sock(hdev, skb, NULL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003479 kfree_skb(skb);
3480}