blob: da8b78096345442cae14c6524f0a5bac32faa98f [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 }
Brian Gix114f3a62011-09-27 14:02:20 -07001355
1356 if (conn)
1357 mod_timer(&conn->disc_timer,
1358 jiffies + msecs_to_jiffies(5000));
Ville Tervofcd89c02011-02-10 22:38:47 -03001359 }
1360
1361 hci_dev_unlock(hdev);
1362}
1363
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001364static void hci_cs_accept_logical_link(struct hci_dev *hdev, __u8 status)
1365{
1366 struct hci_cp_create_logical_link *ap;
1367 struct hci_chan *chan;
1368
1369 BT_DBG("%s status 0x%x", hdev->name, status);
1370
1371 ap = hci_sent_cmd_data(hdev, HCI_OP_ACCEPT_LOGICAL_LINK);
1372 if (!ap)
1373 return;
1374
1375 hci_dev_lock(hdev);
1376
1377 chan = hci_chan_list_lookup_id(hdev, ap->phy_handle);
1378
1379 BT_DBG("%s chan %p", hdev->name, chan);
1380
1381 if (status) {
1382 if (chan && chan->state == BT_CONNECT) {
1383 chan->state = BT_CLOSED;
1384 hci_proto_create_cfm(chan, status);
1385 hci_chan_del(chan);
1386 }
1387 } else if (chan)
1388 chan->state = BT_CONNECT2;
1389
1390 hci_dev_unlock(hdev);
1391}
1392
1393static void hci_cs_create_logical_link(struct hci_dev *hdev, __u8 status)
1394{
1395 struct hci_cp_create_logical_link *cp;
1396 struct hci_chan *chan;
1397
1398 BT_DBG("%s status 0x%x", hdev->name, status);
1399
1400 cp = hci_sent_cmd_data(hdev, HCI_OP_CREATE_LOGICAL_LINK);
1401 if (!cp)
1402 return;
1403
1404 hci_dev_lock(hdev);
1405
1406 chan = hci_chan_list_lookup_id(hdev, cp->phy_handle);
1407
1408 BT_DBG("%s chan %p", hdev->name, chan);
1409
1410 if (status) {
1411 if (chan && chan->state == BT_CONNECT) {
1412 chan->state = BT_CLOSED;
1413 hci_proto_create_cfm(chan, status);
1414 hci_chan_del(chan);
1415 }
1416 } else if (chan)
1417 chan->state = BT_CONNECT2;
1418
1419 hci_dev_unlock(hdev);
1420}
1421
1422static void hci_cs_flow_spec_modify(struct hci_dev *hdev, __u8 status)
1423{
1424 struct hci_cp_flow_spec_modify *cp;
1425 struct hci_chan *chan;
1426
1427 BT_DBG("%s status 0x%x", hdev->name, status);
1428
1429 cp = hci_sent_cmd_data(hdev, HCI_OP_FLOW_SPEC_MODIFY);
1430 if (!cp)
1431 return;
1432
1433 hci_dev_lock(hdev);
1434
1435 chan = hci_chan_list_lookup_handle(hdev, cp->log_handle);
1436 if (chan) {
1437 if (status)
1438 hci_proto_modify_cfm(chan, status);
1439 else {
1440 chan->tx_fs = cp->tx_fs;
1441 chan->rx_fs = cp->rx_fs;
1442 }
1443 }
1444
1445 hci_dev_unlock(hdev);
1446}
1447
1448static void hci_cs_disconn_logical_link(struct hci_dev *hdev, __u8 status)
1449{
1450 struct hci_cp_disconn_logical_link *cp;
1451 struct hci_chan *chan;
1452
1453 if (!status)
1454 return;
1455
1456 BT_DBG("%s status 0x%x", hdev->name, status);
1457
1458 cp = hci_sent_cmd_data(hdev, HCI_OP_DISCONN_LOGICAL_LINK);
1459 if (!cp)
1460 return;
1461
1462 hci_dev_lock(hdev);
1463
1464 chan = hci_chan_list_lookup_handle(hdev, cp->log_handle);
1465 if (chan)
1466 hci_chan_del(chan);
1467
1468 hci_dev_unlock(hdev);
1469}
1470
1471static void hci_cs_disconn_physical_link(struct hci_dev *hdev, __u8 status)
1472{
1473 struct hci_cp_disconn_phys_link *cp;
1474 struct hci_conn *conn;
1475
1476 if (!status)
1477 return;
1478
1479 BT_DBG("%s status 0x%x", hdev->name, status);
1480
1481 cp = hci_sent_cmd_data(hdev, HCI_OP_DISCONN_PHYS_LINK);
1482 if (!cp)
1483 return;
1484
1485 hci_dev_lock(hdev);
1486
1487 conn = hci_conn_hash_lookup_handle(hdev, cp->phy_handle);
1488 if (conn) {
1489 conn->state = BT_CLOSED;
1490 hci_conn_del(conn);
1491 }
1492
1493 hci_dev_unlock(hdev);
1494}
1495
Vinicius Costa Gomes735038c2011-06-09 18:50:47 -03001496static void hci_cs_le_start_enc(struct hci_dev *hdev, u8 status)
1497{
1498 BT_DBG("%s status 0x%x", hdev->name, status);
1499}
1500
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001501static inline void hci_inquiry_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
1502{
1503 __u8 status = *((__u8 *) skb->data);
1504
1505 BT_DBG("%s status %d", hdev->name, status);
1506
Brian Gixa68668b2011-08-11 15:49:36 -07001507 if (!lmp_le_capable(hdev))
1508 clear_bit(HCI_INQUIRY, &hdev->flags);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001509
Johan Hedberg23bb5762010-12-21 23:01:27 +02001510 hci_req_complete(hdev, HCI_OP_INQUIRY, status);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001511
Brian Gixa68668b2011-08-11 15:49:36 -07001512 if (test_bit(HCI_MGMT, &hdev->flags))
1513 mgmt_inquiry_complete_evt(hdev->id, status);
1514
1515 if (!lmp_le_capable(hdev))
1516 hci_conn_check_pending(hdev);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001517}
1518
Linus Torvalds1da177e2005-04-16 15:20:36 -07001519static inline void hci_inquiry_result_evt(struct hci_dev *hdev, struct sk_buff *skb)
1520{
Marcel Holtmann45bb4bf2005-08-09 20:27:49 -07001521 struct inquiry_data data;
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001522 struct inquiry_info *info = (void *) (skb->data + 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001523 int num_rsp = *((__u8 *) skb->data);
1524
1525 BT_DBG("%s num_rsp %d", hdev->name, num_rsp);
1526
Marcel Holtmann45bb4bf2005-08-09 20:27:49 -07001527 if (!num_rsp)
1528 return;
1529
Linus Torvalds1da177e2005-04-16 15:20:36 -07001530 hci_dev_lock(hdev);
Marcel Holtmann45bb4bf2005-08-09 20:27:49 -07001531
Johan Hedberge17acd42011-03-30 23:57:16 +03001532 for (; num_rsp; num_rsp--, info++) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001533 bacpy(&data.bdaddr, &info->bdaddr);
1534 data.pscan_rep_mode = info->pscan_rep_mode;
1535 data.pscan_period_mode = info->pscan_period_mode;
1536 data.pscan_mode = info->pscan_mode;
1537 memcpy(data.dev_class, info->dev_class, 3);
1538 data.clock_offset = info->clock_offset;
1539 data.rssi = 0x00;
Marcel Holtmann41a96212008-07-14 20:13:48 +02001540 data.ssp_mode = 0x00;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001541 hci_inquiry_cache_update(hdev, &data);
Brian Gixa68668b2011-08-11 15:49:36 -07001542 mgmt_device_found(hdev->id, &info->bdaddr, 0, 0,
1543 info->dev_class, 0, 0, NULL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001544 }
Marcel Holtmann45bb4bf2005-08-09 20:27:49 -07001545
Linus Torvalds1da177e2005-04-16 15:20:36 -07001546 hci_dev_unlock(hdev);
1547}
1548
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001549static inline void hci_conn_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001550{
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001551 struct hci_ev_conn_complete *ev = (void *) skb->data;
1552 struct hci_conn *conn;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001553
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001554 BT_DBG("%s", hdev->name);
Marcel Holtmann45bb4bf2005-08-09 20:27:49 -07001555
Linus Torvalds1da177e2005-04-16 15:20:36 -07001556 hci_dev_lock(hdev);
Marcel Holtmann45bb4bf2005-08-09 20:27:49 -07001557
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001558 conn = hci_conn_hash_lookup_ba(hdev, ev->link_type, &ev->bdaddr);
Marcel Holtmann94992372009-04-19 19:30:03 +02001559 if (!conn) {
1560 if (ev->link_type != SCO_LINK)
1561 goto unlock;
1562
1563 conn = hci_conn_hash_lookup_ba(hdev, ESCO_LINK, &ev->bdaddr);
1564 if (!conn)
1565 goto unlock;
1566
1567 conn->type = SCO_LINK;
1568 }
Marcel Holtmann45bb4bf2005-08-09 20:27:49 -07001569
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001570 if (!ev->status) {
1571 conn->handle = __le16_to_cpu(ev->handle);
Marcel Holtmann769be972008-07-14 20:13:49 +02001572
1573 if (conn->type == ACL_LINK) {
1574 conn->state = BT_CONFIG;
1575 hci_conn_hold(conn);
Marcel Holtmann052b30b2009-04-26 20:01:22 +02001576 conn->disc_timeout = HCI_DISCONN_TIMEOUT;
Brian Gix2e2f50d2011-09-13 12:36:04 -07001577 mgmt_connected(hdev->id, &ev->bdaddr, 0);
Brian Gixa68668b2011-08-11 15:49:36 -07001578 } else if (conn->type == LE_LINK) {
1579 conn->state = BT_CONNECTED;
1580 conn->disc_timeout = HCI_DISCONN_TIMEOUT;
Brian Gix2e2f50d2011-09-13 12:36:04 -07001581 mgmt_connected(hdev->id, &ev->bdaddr, 1);
Marcel Holtmann769be972008-07-14 20:13:49 +02001582 } else
1583 conn->state = BT_CONNECTED;
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001584
Marcel Holtmann9eba32b2009-08-22 14:19:26 -07001585 hci_conn_hold_device(conn);
Marcel Holtmann7d0db0a2008-07-14 20:13:51 +02001586 hci_conn_add_sysfs(conn);
1587
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001588 if (test_bit(HCI_AUTH, &hdev->flags))
1589 conn->link_mode |= HCI_LM_AUTH;
1590
1591 if (test_bit(HCI_ENCRYPT, &hdev->flags))
1592 conn->link_mode |= HCI_LM_ENCRYPT;
1593
1594 /* Get remote features */
1595 if (conn->type == ACL_LINK) {
1596 struct hci_cp_read_remote_features cp;
1597 cp.handle = ev->handle;
Marcel Holtmann769be972008-07-14 20:13:49 +02001598 hci_send_cmd(hdev, HCI_OP_READ_REMOTE_FEATURES,
1599 sizeof(cp), &cp);
Marcel Holtmann45bb4bf2005-08-09 20:27:49 -07001600 }
Marcel Holtmann45bb4bf2005-08-09 20:27:49 -07001601
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001602 /* Set packet type for incoming connection */
Marcel Holtmanna8746412008-07-14 20:13:46 +02001603 if (!conn->out && hdev->hci_ver < 3) {
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001604 struct hci_cp_change_conn_ptype cp;
1605 cp.handle = ev->handle;
Marcel Holtmanna8746412008-07-14 20:13:46 +02001606 cp.pkt_type = cpu_to_le16(conn->pkt_type);
1607 hci_send_cmd(hdev, HCI_OP_CHANGE_CONN_PTYPE,
1608 sizeof(cp), &cp);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001609 }
Johan Hedberg17d5c042011-01-22 06:09:08 +02001610 } else {
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001611 conn->state = BT_CLOSED;
Brian Gixa68668b2011-08-11 15:49:36 -07001612 if (conn->type == ACL_LINK || conn->type == LE_LINK)
Johan Hedberg17d5c042011-01-22 06:09:08 +02001613 mgmt_connect_failed(hdev->id, &ev->bdaddr, ev->status);
1614 }
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001615
Marcel Holtmanne73439d2010-07-26 10:06:00 -04001616 if (conn->type == ACL_LINK)
1617 hci_sco_setup(conn, ev->status);
Marcel Holtmann45bb4bf2005-08-09 20:27:49 -07001618
Marcel Holtmann769be972008-07-14 20:13:49 +02001619 if (ev->status) {
1620 hci_proto_connect_cfm(conn, ev->status);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001621 hci_conn_del(conn);
Marcel Holtmannc89b6e62009-01-15 21:57:03 +01001622 } else if (ev->link_type != ACL_LINK)
1623 hci_proto_connect_cfm(conn, ev->status);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001624
1625unlock:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001626 hci_dev_unlock(hdev);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001627
1628 hci_conn_check_pending(hdev);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001629}
1630
Linus Torvalds1da177e2005-04-16 15:20:36 -07001631static inline void hci_conn_request_evt(struct hci_dev *hdev, struct sk_buff *skb)
1632{
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001633 struct hci_ev_conn_request *ev = (void *) skb->data;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001634 int mask = hdev->link_mode;
1635
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001636 BT_DBG("%s bdaddr %s type 0x%x", hdev->name,
1637 batostr(&ev->bdaddr), ev->link_type);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001638
1639 mask |= hci_proto_connect_ind(hdev, &ev->bdaddr, ev->link_type);
1640
Szymon Janc138d22e2011-02-17 16:44:23 +01001641 if ((mask & HCI_LM_ACCEPT) &&
1642 !hci_blacklist_lookup(hdev, &ev->bdaddr)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001643 /* Connection accepted */
Marcel Holtmannc7bdd502008-07-14 20:13:47 +02001644 struct inquiry_entry *ie;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001645 struct hci_conn *conn;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001646
1647 hci_dev_lock(hdev);
Marcel Holtmannb6a0dc82007-10-20 14:55:10 +02001648
Andrei Emeltchenkocc11b9c2010-11-22 13:21:37 +02001649 ie = hci_inquiry_cache_lookup(hdev, &ev->bdaddr);
1650 if (ie)
Marcel Holtmannc7bdd502008-07-14 20:13:47 +02001651 memcpy(ie->data.dev_class, ev->dev_class, 3);
1652
Linus Torvalds1da177e2005-04-16 15:20:36 -07001653 conn = hci_conn_hash_lookup_ba(hdev, ev->link_type, &ev->bdaddr);
1654 if (!conn) {
Nick Pellybbcda3b2010-02-11 11:54:28 -08001655 /* pkt_type not yet used for incoming connections */
1656 conn = hci_conn_add(hdev, ev->link_type, 0, &ev->bdaddr);
Andrei Emeltchenkocc11b9c2010-11-22 13:21:37 +02001657 if (!conn) {
Gustavo F. Padovan893ef972010-07-18 15:13:37 -03001658 BT_ERR("No memory for new connection");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001659 hci_dev_unlock(hdev);
1660 return;
1661 }
1662 }
Marcel Holtmannb6a0dc82007-10-20 14:55:10 +02001663
Linus Torvalds1da177e2005-04-16 15:20:36 -07001664 memcpy(conn->dev_class, ev->dev_class, 3);
1665 conn->state = BT_CONNECT;
Marcel Holtmannb6a0dc82007-10-20 14:55:10 +02001666
Linus Torvalds1da177e2005-04-16 15:20:36 -07001667 hci_dev_unlock(hdev);
1668
Marcel Holtmannb6a0dc82007-10-20 14:55:10 +02001669 if (ev->link_type == ACL_LINK || !lmp_esco_capable(hdev)) {
1670 struct hci_cp_accept_conn_req cp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001671
Marcel Holtmannb6a0dc82007-10-20 14:55:10 +02001672 bacpy(&cp.bdaddr, &ev->bdaddr);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001673
Marcel Holtmannb6a0dc82007-10-20 14:55:10 +02001674 if (lmp_rswitch_capable(hdev) && (mask & HCI_LM_MASTER))
1675 cp.role = 0x00; /* Become master */
1676 else
1677 cp.role = 0x01; /* Remain slave */
1678
1679 hci_send_cmd(hdev, HCI_OP_ACCEPT_CONN_REQ,
1680 sizeof(cp), &cp);
1681 } else {
1682 struct hci_cp_accept_sync_conn_req cp;
1683
1684 bacpy(&cp.bdaddr, &ev->bdaddr);
Marcel Holtmanna8746412008-07-14 20:13:46 +02001685 cp.pkt_type = cpu_to_le16(conn->pkt_type);
Marcel Holtmannb6a0dc82007-10-20 14:55:10 +02001686
1687 cp.tx_bandwidth = cpu_to_le32(0x00001f40);
1688 cp.rx_bandwidth = cpu_to_le32(0x00001f40);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001689 cp.max_latency = cpu_to_le16(0x000A);
Marcel Holtmannb6a0dc82007-10-20 14:55:10 +02001690 cp.content_format = cpu_to_le16(hdev->voice_setting);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001691 cp.retrans_effort = 0x01;
Marcel Holtmannb6a0dc82007-10-20 14:55:10 +02001692
1693 hci_send_cmd(hdev, HCI_OP_ACCEPT_SYNC_CONN_REQ,
1694 sizeof(cp), &cp);
1695 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001696 } else {
1697 /* Connection rejected */
1698 struct hci_cp_reject_conn_req cp;
1699
1700 bacpy(&cp.bdaddr, &ev->bdaddr);
1701 cp.reason = 0x0f;
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001702 hci_send_cmd(hdev, HCI_OP_REJECT_CONN_REQ, sizeof(cp), &cp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001703 }
1704}
1705
Linus Torvalds1da177e2005-04-16 15:20:36 -07001706static inline void hci_disconn_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
1707{
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001708 struct hci_ev_disconn_complete *ev = (void *) skb->data;
Marcel Holtmann04837f62006-07-03 10:02:33 +02001709 struct hci_conn *conn;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001710
1711 BT_DBG("%s status %d", hdev->name, ev->status);
1712
Johan Hedberg8962ee72011-01-20 12:40:27 +02001713 if (ev->status) {
1714 mgmt_disconnect_failed(hdev->id);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001715 return;
Johan Hedberg8962ee72011-01-20 12:40:27 +02001716 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001717
1718 hci_dev_lock(hdev);
1719
Marcel Holtmann04837f62006-07-03 10:02:33 +02001720 conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
Johan Hedbergf7520542011-01-20 12:34:39 +02001721 if (!conn)
1722 goto unlock;
Marcel Holtmann7d0db0a2008-07-14 20:13:51 +02001723
Johan Hedbergf7520542011-01-20 12:34:39 +02001724 conn->state = BT_CLOSED;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001725
Brian Gixa68668b2011-08-11 15:49:36 -07001726 if (conn->type == ACL_LINK || conn->type == LE_LINK)
Johan Hedbergf7520542011-01-20 12:34:39 +02001727 mgmt_disconnected(hdev->id, &conn->dst);
1728
Brian Gixe9ceb522011-09-22 10:46:35 -07001729 if (conn->type == LE_LINK)
1730 del_timer(&conn->smp_timer);
1731
Johan Hedbergf7520542011-01-20 12:34:39 +02001732 hci_proto_disconn_cfm(conn, ev->reason);
1733 hci_conn_del(conn);
1734
1735unlock:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001736 hci_dev_unlock(hdev);
1737}
1738
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001739static inline void hci_auth_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
1740{
1741 struct hci_ev_auth_complete *ev = (void *) skb->data;
1742 struct hci_conn *conn;
1743
1744 BT_DBG("%s status %d", hdev->name, ev->status);
1745
1746 hci_dev_lock(hdev);
1747
1748 conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001749 if (conn) {
1750 if (ev->status == 0x06 && hdev->ssp_mode > 0 &&
1751 conn->ssp_mode > 0) {
1752 struct hci_cp_auth_requested cp;
Prabhakaran Mcb04401d2011-09-20 17:37:55 +05301753 hci_remove_link_key(hdev, &conn->dst);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001754 cp.handle = cpu_to_le16(conn->handle);
1755 hci_send_cmd(conn->hdev, HCI_OP_AUTH_REQUESTED,
1756 sizeof(cp), &cp);
1757 hci_dev_unlock(hdev);
1758 BT_INFO("Pin or key missing");
1759 return;
1760 }
Waldemar Rymarkiewicz54444292011-05-31 15:49:26 +02001761
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001762 if (!ev->status) {
Waldemar Rymarkiewicz54444292011-05-31 15:49:26 +02001763 conn->link_mode |= HCI_LM_AUTH;
1764 conn->sec_level = conn->pending_sec_level;
Marcel Holtmann052b30b2009-04-26 20:01:22 +02001765 } else {
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001766 mgmt_auth_failed(hdev->id, &conn->dst, ev->status);
1767 conn->sec_level = BT_SECURITY_LOW;
1768 }
1769
1770 clear_bit(HCI_CONN_AUTH_PEND, &conn->pend);
1771
1772 if (conn->state == BT_CONFIG) {
1773 if (!ev->status && hdev->ssp_mode > 0 &&
1774 conn->ssp_mode > 0) {
1775 struct hci_cp_set_conn_encrypt cp;
1776 cp.handle = ev->handle;
1777 cp.encrypt = 0x01;
1778 hci_send_cmd(hdev, HCI_OP_SET_CONN_ENCRYPT,
1779 sizeof(cp), &cp);
1780 } else {
1781 conn->state = BT_CONNECTED;
1782 hci_proto_connect_cfm(conn, ev->status);
1783 hci_conn_put(conn);
1784 }
1785 } else {
1786 hci_auth_cfm(conn, ev->status);
1787
1788 hci_conn_hold(conn);
1789 conn->disc_timeout = HCI_DISCONN_TIMEOUT;
Marcel Holtmann052b30b2009-04-26 20:01:22 +02001790 hci_conn_put(conn);
1791 }
1792
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001793 if (test_bit(HCI_CONN_ENCRYPT_PEND, &conn->pend)) {
1794 if (!ev->status) {
1795 struct hci_cp_set_conn_encrypt cp;
1796 cp.handle = ev->handle;
1797 cp.encrypt = 0x01;
1798 hci_send_cmd(hdev, HCI_OP_SET_CONN_ENCRYPT,
1799 sizeof(cp), &cp);
1800 } else {
1801 clear_bit(HCI_CONN_ENCRYPT_PEND, &conn->pend);
1802 hci_encrypt_cfm(conn, ev->status, 0x00);
1803 }
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001804 }
1805 }
1806
1807 hci_dev_unlock(hdev);
1808}
1809
1810static inline void hci_remote_name_evt(struct hci_dev *hdev, struct sk_buff *skb)
1811{
Johan Hedberg127178d2010-11-18 22:22:29 +02001812 struct hci_ev_remote_name *ev = (void *) skb->data;
1813 struct hci_conn *conn;
1814
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001815 BT_DBG("%s", hdev->name);
1816
1817 hci_conn_check_pending(hdev);
Johan Hedberg127178d2010-11-18 22:22:29 +02001818
1819 hci_dev_lock(hdev);
1820
Brian Gixa68668b2011-08-11 15:49:36 -07001821 if (test_bit(HCI_MGMT, &hdev->flags))
1822 mgmt_remote_name(hdev->id, &ev->bdaddr, ev->status, ev->name);
Johan Hedberga88a9652011-03-30 13:18:12 +03001823
Johan Hedberg127178d2010-11-18 22:22:29 +02001824 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001825 if (conn && hci_outgoing_auth_needed(hdev, conn)) {
Johan Hedberg127178d2010-11-18 22:22:29 +02001826 struct hci_cp_auth_requested cp;
1827 cp.handle = __cpu_to_le16(conn->handle);
1828 hci_send_cmd(hdev, HCI_OP_AUTH_REQUESTED, sizeof(cp), &cp);
1829 }
1830
1831 hci_dev_unlock(hdev);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001832}
1833
1834static inline void hci_encrypt_change_evt(struct hci_dev *hdev, struct sk_buff *skb)
1835{
1836 struct hci_ev_encrypt_change *ev = (void *) skb->data;
1837 struct hci_conn *conn;
1838
1839 BT_DBG("%s status %d", hdev->name, ev->status);
1840
1841 hci_dev_lock(hdev);
1842
1843 conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
1844 if (conn) {
1845 if (!ev->status) {
Marcel Holtmannae293192008-07-14 20:13:45 +02001846 if (ev->encrypt) {
1847 /* Encryption implies authentication */
1848 conn->link_mode |= HCI_LM_AUTH;
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001849 conn->link_mode |= HCI_LM_ENCRYPT;
Vinicius Costa Gomes64532ec2011-06-09 18:50:53 -03001850 conn->sec_level = conn->pending_sec_level;
Marcel Holtmannae293192008-07-14 20:13:45 +02001851 } else
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001852 conn->link_mode &= ~HCI_LM_ENCRYPT;
1853 }
1854
1855 clear_bit(HCI_CONN_ENCRYPT_PEND, &conn->pend);
1856
Marcel Holtmannf8558552008-07-14 20:13:49 +02001857 if (conn->state == BT_CONFIG) {
1858 if (!ev->status)
1859 conn->state = BT_CONNECTED;
1860
1861 hci_proto_connect_cfm(conn, ev->status);
1862 hci_conn_put(conn);
1863 } else
1864 hci_encrypt_cfm(conn, ev->status, ev->encrypt);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001865 }
1866
1867 hci_dev_unlock(hdev);
1868}
1869
1870static inline void hci_change_link_key_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
1871{
1872 struct hci_ev_change_link_key_complete *ev = (void *) skb->data;
1873 struct hci_conn *conn;
1874
1875 BT_DBG("%s status %d", hdev->name, ev->status);
1876
1877 hci_dev_lock(hdev);
1878
1879 conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
1880 if (conn) {
1881 if (!ev->status)
1882 conn->link_mode |= HCI_LM_SECURE;
1883
1884 clear_bit(HCI_CONN_AUTH_PEND, &conn->pend);
1885
1886 hci_key_change_cfm(conn, ev->status);
1887 }
1888
1889 hci_dev_unlock(hdev);
1890}
1891
1892static inline void hci_remote_features_evt(struct hci_dev *hdev, struct sk_buff *skb)
1893{
1894 struct hci_ev_remote_features *ev = (void *) skb->data;
1895 struct hci_conn *conn;
1896
1897 BT_DBG("%s status %d", hdev->name, ev->status);
1898
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001899 hci_dev_lock(hdev);
1900
1901 conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
Johan Hedbergccd556f2010-11-10 17:11:51 +02001902 if (!conn)
1903 goto unlock;
Marcel Holtmann769be972008-07-14 20:13:49 +02001904
Johan Hedbergccd556f2010-11-10 17:11:51 +02001905 if (!ev->status)
1906 memcpy(conn->features, ev->features, 8);
1907
1908 if (conn->state != BT_CONFIG)
1909 goto unlock;
1910
1911 if (!ev->status && lmp_ssp_capable(hdev) && lmp_ssp_capable(conn)) {
1912 struct hci_cp_read_remote_ext_features cp;
1913 cp.handle = ev->handle;
1914 cp.page = 0x01;
1915 hci_send_cmd(hdev, HCI_OP_READ_REMOTE_EXT_FEATURES,
Marcel Holtmann769be972008-07-14 20:13:49 +02001916 sizeof(cp), &cp);
Johan Hedberg392599b2010-11-18 22:22:28 +02001917 goto unlock;
1918 }
1919
Johan Hedberg127178d2010-11-18 22:22:29 +02001920 if (!ev->status) {
1921 struct hci_cp_remote_name_req cp;
1922 memset(&cp, 0, sizeof(cp));
1923 bacpy(&cp.bdaddr, &conn->dst);
1924 cp.pscan_rep_mode = 0x02;
1925 hci_send_cmd(hdev, HCI_OP_REMOTE_NAME_REQ, sizeof(cp), &cp);
1926 }
Johan Hedberg392599b2010-11-18 22:22:28 +02001927
Johan Hedberg127178d2010-11-18 22:22:29 +02001928 if (!hci_outgoing_auth_needed(hdev, conn)) {
Johan Hedbergccd556f2010-11-10 17:11:51 +02001929 conn->state = BT_CONNECTED;
1930 hci_proto_connect_cfm(conn, ev->status);
1931 hci_conn_put(conn);
Marcel Holtmann769be972008-07-14 20:13:49 +02001932 }
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001933
Johan Hedbergccd556f2010-11-10 17:11:51 +02001934unlock:
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001935 hci_dev_unlock(hdev);
1936}
1937
1938static inline void hci_remote_version_evt(struct hci_dev *hdev, struct sk_buff *skb)
1939{
1940 BT_DBG("%s", hdev->name);
1941}
1942
1943static inline void hci_qos_setup_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
1944{
1945 BT_DBG("%s", hdev->name);
1946}
1947
1948static inline void hci_cmd_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
1949{
1950 struct hci_ev_cmd_complete *ev = (void *) skb->data;
1951 __u16 opcode;
1952
1953 skb_pull(skb, sizeof(*ev));
1954
1955 opcode = __le16_to_cpu(ev->opcode);
1956
1957 switch (opcode) {
1958 case HCI_OP_INQUIRY_CANCEL:
1959 hci_cc_inquiry_cancel(hdev, skb);
1960 break;
1961
1962 case HCI_OP_EXIT_PERIODIC_INQ:
1963 hci_cc_exit_periodic_inq(hdev, skb);
1964 break;
1965
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001966 case HCI_OP_LINK_KEY_REPLY:
1967 hci_cc_link_key_reply(hdev, skb);
1968 break;
1969
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001970 case HCI_OP_REMOTE_NAME_REQ_CANCEL:
1971 hci_cc_remote_name_req_cancel(hdev, skb);
1972 break;
1973
1974 case HCI_OP_ROLE_DISCOVERY:
1975 hci_cc_role_discovery(hdev, skb);
1976 break;
1977
Marcel Holtmanne4e8e372008-07-14 20:13:47 +02001978 case HCI_OP_READ_LINK_POLICY:
1979 hci_cc_read_link_policy(hdev, skb);
1980 break;
1981
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001982 case HCI_OP_WRITE_LINK_POLICY:
1983 hci_cc_write_link_policy(hdev, skb);
1984 break;
1985
Marcel Holtmanne4e8e372008-07-14 20:13:47 +02001986 case HCI_OP_READ_DEF_LINK_POLICY:
1987 hci_cc_read_def_link_policy(hdev, skb);
1988 break;
1989
1990 case HCI_OP_WRITE_DEF_LINK_POLICY:
1991 hci_cc_write_def_link_policy(hdev, skb);
1992 break;
1993
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001994 case HCI_OP_RESET:
1995 hci_cc_reset(hdev, skb);
1996 break;
1997
1998 case HCI_OP_WRITE_LOCAL_NAME:
1999 hci_cc_write_local_name(hdev, skb);
2000 break;
2001
2002 case HCI_OP_READ_LOCAL_NAME:
2003 hci_cc_read_local_name(hdev, skb);
2004 break;
2005
2006 case HCI_OP_WRITE_AUTH_ENABLE:
2007 hci_cc_write_auth_enable(hdev, skb);
2008 break;
2009
2010 case HCI_OP_WRITE_ENCRYPT_MODE:
2011 hci_cc_write_encrypt_mode(hdev, skb);
2012 break;
2013
2014 case HCI_OP_WRITE_SCAN_ENABLE:
2015 hci_cc_write_scan_enable(hdev, skb);
2016 break;
2017
2018 case HCI_OP_READ_CLASS_OF_DEV:
2019 hci_cc_read_class_of_dev(hdev, skb);
2020 break;
2021
2022 case HCI_OP_WRITE_CLASS_OF_DEV:
2023 hci_cc_write_class_of_dev(hdev, skb);
2024 break;
2025
2026 case HCI_OP_READ_VOICE_SETTING:
2027 hci_cc_read_voice_setting(hdev, skb);
2028 break;
2029
2030 case HCI_OP_WRITE_VOICE_SETTING:
2031 hci_cc_write_voice_setting(hdev, skb);
2032 break;
2033
2034 case HCI_OP_HOST_BUFFER_SIZE:
2035 hci_cc_host_buffer_size(hdev, skb);
2036 break;
2037
Marcel Holtmann333140b2008-07-14 20:13:48 +02002038 case HCI_OP_READ_SSP_MODE:
2039 hci_cc_read_ssp_mode(hdev, skb);
2040 break;
2041
2042 case HCI_OP_WRITE_SSP_MODE:
2043 hci_cc_write_ssp_mode(hdev, skb);
2044 break;
2045
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002046 case HCI_OP_READ_LOCAL_VERSION:
2047 hci_cc_read_local_version(hdev, skb);
2048 break;
2049
2050 case HCI_OP_READ_LOCAL_COMMANDS:
2051 hci_cc_read_local_commands(hdev, skb);
2052 break;
2053
2054 case HCI_OP_READ_LOCAL_FEATURES:
2055 hci_cc_read_local_features(hdev, skb);
2056 break;
2057
2058 case HCI_OP_READ_BUFFER_SIZE:
2059 hci_cc_read_buffer_size(hdev, skb);
2060 break;
2061
2062 case HCI_OP_READ_BD_ADDR:
2063 hci_cc_read_bd_addr(hdev, skb);
2064 break;
2065
Johan Hedberg23bb5762010-12-21 23:01:27 +02002066 case HCI_OP_WRITE_CA_TIMEOUT:
2067 hci_cc_write_ca_timeout(hdev, skb);
2068 break;
2069
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002070 case HCI_OP_READ_FLOW_CONTROL_MODE:
2071 hci_cc_read_flow_control_mode(hdev, skb);
2072 break;
2073
2074 case HCI_OP_READ_DATA_BLOCK_SIZE:
2075 hci_cc_read_data_block_size(hdev, skb);
2076 break;
2077
2078 case HCI_OP_READ_LOCAL_AMP_INFO:
2079 hci_cc_read_local_amp_info(hdev, skb);
2080 break;
2081
2082 case HCI_OP_READ_LOCAL_AMP_ASSOC:
2083 case HCI_OP_WRITE_REMOTE_AMP_ASSOC:
2084 hci_amp_cmd_complete(hdev, opcode, skb);
2085 break;
2086
Johan Hedbergb0916ea2011-01-10 13:44:55 +02002087 case HCI_OP_DELETE_STORED_LINK_KEY:
2088 hci_cc_delete_stored_link_key(hdev, skb);
2089 break;
2090
Johan Hedbergd5859e22011-01-25 01:19:58 +02002091 case HCI_OP_SET_EVENT_MASK:
2092 hci_cc_set_event_mask(hdev, skb);
2093 break;
2094
2095 case HCI_OP_WRITE_INQUIRY_MODE:
2096 hci_cc_write_inquiry_mode(hdev, skb);
2097 break;
2098
2099 case HCI_OP_READ_INQ_RSP_TX_POWER:
2100 hci_cc_read_inq_rsp_tx_power(hdev, skb);
2101 break;
2102
2103 case HCI_OP_SET_EVENT_FLT:
2104 hci_cc_set_event_flt(hdev, skb);
2105 break;
2106
Johan Hedberg980e1a52011-01-22 06:10:07 +02002107 case HCI_OP_PIN_CODE_REPLY:
2108 hci_cc_pin_code_reply(hdev, skb);
2109 break;
2110
2111 case HCI_OP_PIN_CODE_NEG_REPLY:
2112 hci_cc_pin_code_neg_reply(hdev, skb);
2113 break;
2114
Szymon Jancc35938b2011-03-22 13:12:21 +01002115 case HCI_OP_READ_LOCAL_OOB_DATA:
2116 hci_cc_read_local_oob_data_reply(hdev, skb);
2117 break;
2118
Ville Tervo6ed58ec2011-02-10 22:38:48 -03002119 case HCI_OP_LE_READ_BUFFER_SIZE:
2120 hci_cc_le_read_buffer_size(hdev, skb);
2121 break;
2122
Johan Hedberga5c29682011-02-19 12:05:57 -03002123 case HCI_OP_USER_CONFIRM_REPLY:
2124 hci_cc_user_confirm_reply(hdev, skb);
2125 break;
2126
2127 case HCI_OP_USER_CONFIRM_NEG_REPLY:
2128 hci_cc_user_confirm_neg_reply(hdev, skb);
2129 break;
2130
Vinicius Costa Gomes735038c2011-06-09 18:50:47 -03002131 case HCI_OP_LE_LTK_REPLY:
2132 hci_cc_le_ltk_reply(hdev, skb);
2133 break;
2134
2135 case HCI_OP_LE_LTK_NEG_REPLY:
2136 hci_cc_le_ltk_neg_reply(hdev, skb);
2137 break;
2138
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002139 case HCI_OP_LE_SET_SCAN_ENABLE:
2140 hci_cc_le_set_scan_enable(hdev, skb);
Andre Guedese326af42011-06-30 19:20:53 -03002141 break;
2142
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002143 default:
2144 BT_DBG("%s opcode 0x%x", hdev->name, opcode);
2145 break;
2146 }
2147
Ville Tervo6bd32322011-02-16 16:32:41 +02002148 if (ev->opcode != HCI_OP_NOP)
2149 del_timer(&hdev->cmd_timer);
2150
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002151 if (ev->ncmd) {
2152 atomic_set(&hdev->cmd_cnt, 1);
2153 if (!skb_queue_empty(&hdev->cmd_q))
Marcel Holtmannc78ae282009-11-18 01:02:54 +01002154 tasklet_schedule(&hdev->cmd_task);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002155 }
2156}
2157
2158static inline void hci_cmd_status_evt(struct hci_dev *hdev, struct sk_buff *skb)
2159{
2160 struct hci_ev_cmd_status *ev = (void *) skb->data;
2161 __u16 opcode;
2162
2163 skb_pull(skb, sizeof(*ev));
2164
2165 opcode = __le16_to_cpu(ev->opcode);
2166
2167 switch (opcode) {
2168 case HCI_OP_INQUIRY:
2169 hci_cs_inquiry(hdev, ev->status);
2170 break;
2171
2172 case HCI_OP_CREATE_CONN:
2173 hci_cs_create_conn(hdev, ev->status);
2174 break;
2175
2176 case HCI_OP_ADD_SCO:
2177 hci_cs_add_sco(hdev, ev->status);
2178 break;
2179
Marcel Holtmannf8558552008-07-14 20:13:49 +02002180 case HCI_OP_AUTH_REQUESTED:
2181 hci_cs_auth_requested(hdev, ev->status);
2182 break;
2183
2184 case HCI_OP_SET_CONN_ENCRYPT:
2185 hci_cs_set_conn_encrypt(hdev, ev->status);
2186 break;
2187
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002188 case HCI_OP_REMOTE_NAME_REQ:
2189 hci_cs_remote_name_req(hdev, ev->status);
2190 break;
2191
Marcel Holtmann769be972008-07-14 20:13:49 +02002192 case HCI_OP_READ_REMOTE_FEATURES:
2193 hci_cs_read_remote_features(hdev, ev->status);
2194 break;
2195
2196 case HCI_OP_READ_REMOTE_EXT_FEATURES:
2197 hci_cs_read_remote_ext_features(hdev, ev->status);
2198 break;
2199
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002200 case HCI_OP_SETUP_SYNC_CONN:
2201 hci_cs_setup_sync_conn(hdev, ev->status);
2202 break;
2203
2204 case HCI_OP_SNIFF_MODE:
2205 hci_cs_sniff_mode(hdev, ev->status);
2206 break;
2207
2208 case HCI_OP_EXIT_SNIFF_MODE:
2209 hci_cs_exit_sniff_mode(hdev, ev->status);
2210 break;
2211
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002212 case HCI_OP_CREATE_LOGICAL_LINK:
2213 hci_cs_create_logical_link(hdev, ev->status);
2214 break;
2215
2216 case HCI_OP_ACCEPT_LOGICAL_LINK:
2217 hci_cs_accept_logical_link(hdev, ev->status);
2218 break;
2219
2220 case HCI_OP_DISCONN_LOGICAL_LINK:
2221 hci_cs_disconn_logical_link(hdev, ev->status);
2222 break;
2223
2224 case HCI_OP_FLOW_SPEC_MODIFY:
2225 hci_cs_flow_spec_modify(hdev, ev->status);
2226 break;
2227
2228 case HCI_OP_CREATE_PHYS_LINK:
2229 case HCI_OP_ACCEPT_PHYS_LINK:
2230 hci_amp_cmd_status(hdev, opcode, ev->status);
2231 break;
2232
2233 case HCI_OP_DISCONN_PHYS_LINK:
2234 hci_cs_disconn_physical_link(hdev, ev->status);
2235
Johan Hedberg8962ee72011-01-20 12:40:27 +02002236 case HCI_OP_DISCONNECT:
2237 if (ev->status != 0)
2238 mgmt_disconnect_failed(hdev->id);
2239 break;
2240
Ville Tervofcd89c02011-02-10 22:38:47 -03002241 case HCI_OP_LE_CREATE_CONN:
2242 hci_cs_le_create_conn(hdev, ev->status);
2243 break;
2244
Vinicius Costa Gomes735038c2011-06-09 18:50:47 -03002245 case HCI_OP_LE_START_ENC:
2246 hci_cs_le_start_enc(hdev, ev->status);
2247 break;
2248
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002249 default:
2250 BT_DBG("%s opcode 0x%x", hdev->name, opcode);
2251 break;
2252 }
2253
Ville Tervo6bd32322011-02-16 16:32:41 +02002254 if (ev->opcode != HCI_OP_NOP)
2255 del_timer(&hdev->cmd_timer);
2256
Gustavo F. Padovan10572132011-03-16 15:36:29 -03002257 if (ev->ncmd && !test_bit(HCI_RESET, &hdev->flags)) {
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002258 atomic_set(&hdev->cmd_cnt, 1);
2259 if (!skb_queue_empty(&hdev->cmd_q))
Marcel Holtmannc78ae282009-11-18 01:02:54 +01002260 tasklet_schedule(&hdev->cmd_task);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002261 }
2262}
2263
2264static inline void hci_role_change_evt(struct hci_dev *hdev, struct sk_buff *skb)
2265{
2266 struct hci_ev_role_change *ev = (void *) skb->data;
2267 struct hci_conn *conn;
2268
2269 BT_DBG("%s status %d", hdev->name, ev->status);
2270
2271 hci_dev_lock(hdev);
2272
2273 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
2274 if (conn) {
2275 if (!ev->status) {
2276 if (ev->role)
2277 conn->link_mode &= ~HCI_LM_MASTER;
2278 else
2279 conn->link_mode |= HCI_LM_MASTER;
2280 }
2281
2282 clear_bit(HCI_CONN_RSWITCH_PEND, &conn->pend);
2283
2284 hci_role_switch_cfm(conn, ev->status, ev->role);
2285 }
2286
2287 hci_dev_unlock(hdev);
2288}
2289
Linus Torvalds1da177e2005-04-16 15:20:36 -07002290static inline void hci_num_comp_pkts_evt(struct hci_dev *hdev, struct sk_buff *skb)
2291{
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002292 struct hci_ev_num_comp_pkts *ev = (void *) skb->data;
Marcel Holtmann1ebb9252005-11-08 09:57:21 -08002293 __le16 *ptr;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002294 int i;
2295
2296 skb_pull(skb, sizeof(*ev));
2297
2298 BT_DBG("%s num_hndl %d", hdev->name, ev->num_hndl);
2299
2300 if (skb->len < ev->num_hndl * 4) {
2301 BT_DBG("%s bad parameters", hdev->name);
2302 return;
2303 }
2304
2305 tasklet_disable(&hdev->tx_task);
2306
Marcel Holtmann1ebb9252005-11-08 09:57:21 -08002307 for (i = 0, ptr = (__le16 *) skb->data; i < ev->num_hndl; i++) {
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002308 struct hci_conn *conn = NULL;
2309 struct hci_chan *chan;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002310 __u16 handle, count;
2311
Harvey Harrison83985312008-05-02 16:25:46 -07002312 handle = get_unaligned_le16(ptr++);
2313 count = get_unaligned_le16(ptr++);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002314
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002315 if (hdev->dev_type == HCI_BREDR)
2316 conn = hci_conn_hash_lookup_handle(hdev, handle);
2317 else {
2318 chan = hci_chan_list_lookup_handle(hdev, handle);
2319 if (chan)
2320 conn = chan->conn;
2321 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002322 if (conn) {
2323 conn->sent -= count;
2324
Marcel Holtmann5b7f9902007-07-11 09:51:55 +02002325 if (conn->type == ACL_LINK) {
Andrei Emeltchenko70f230202010-12-01 16:58:25 +02002326 hdev->acl_cnt += count;
2327 if (hdev->acl_cnt > hdev->acl_pkts)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002328 hdev->acl_cnt = hdev->acl_pkts;
Ville Tervo6ed58ec2011-02-10 22:38:48 -03002329 } else if (conn->type == LE_LINK) {
2330 if (hdev->le_pkts) {
2331 hdev->le_cnt += count;
2332 if (hdev->le_cnt > hdev->le_pkts)
2333 hdev->le_cnt = hdev->le_pkts;
2334 } else {
2335 hdev->acl_cnt += count;
2336 if (hdev->acl_cnt > hdev->acl_pkts)
2337 hdev->acl_cnt = hdev->acl_pkts;
2338 }
Marcel Holtmann5b7f9902007-07-11 09:51:55 +02002339 } else {
Andrei Emeltchenko70f230202010-12-01 16:58:25 +02002340 hdev->sco_cnt += count;
2341 if (hdev->sco_cnt > hdev->sco_pkts)
Marcel Holtmann5b7f9902007-07-11 09:51:55 +02002342 hdev->sco_cnt = hdev->sco_pkts;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002343 }
2344 }
2345 }
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002346
Marcel Holtmannc78ae282009-11-18 01:02:54 +01002347 tasklet_schedule(&hdev->tx_task);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002348
2349 tasklet_enable(&hdev->tx_task);
2350}
2351
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002352static inline void hci_num_comp_blocks_evt(struct hci_dev *hdev,
2353 struct sk_buff *skb)
2354{
2355 struct hci_ev_num_comp_blocks *ev = (void *) skb->data;
2356 __le16 *ptr;
2357 int i;
2358
2359 skb_pull(skb, sizeof(*ev));
2360
2361 BT_DBG("%s total_num_blocks %d num_hndl %d",
2362 hdev->name, ev->total_num_blocks, ev->num_hndl);
2363
2364 if (skb->len < ev->num_hndl * 6) {
2365 BT_DBG("%s bad parameters", hdev->name);
2366 return;
2367 }
2368
2369 tasklet_disable(&hdev->tx_task);
2370
2371 for (i = 0, ptr = (__le16 *) skb->data; i < ev->num_hndl; i++) {
2372 struct hci_conn *conn = NULL;
2373 struct hci_chan *chan;
2374 __u16 handle, block_count;
2375
2376 handle = get_unaligned_le16(ptr++);
2377
2378 /* Skip packet count */
2379 ptr++;
2380 block_count = get_unaligned_le16(ptr++);
2381
2382 BT_DBG("%s handle %d count %d", hdev->name, handle,
2383 block_count);
2384
2385 if (hdev->dev_type == HCI_BREDR)
2386 conn = hci_conn_hash_lookup_handle(hdev, handle);
2387 else {
2388 chan = hci_chan_list_lookup_handle(hdev, handle);
2389 if (chan)
2390 conn = chan->conn;
2391 }
2392 if (conn) {
2393 BT_DBG("%s conn %p sent %d", hdev->name,
2394 conn, conn->sent);
2395
2396 conn->sent -= block_count;
2397
2398 if (conn->type == ACL_LINK) {
2399 hdev->acl_cnt += block_count;
2400 if (hdev->acl_cnt > hdev->acl_pkts)
2401 hdev->acl_cnt = hdev->acl_pkts;
2402 } else {
2403 /* We should not find ourselves here */
2404 BT_DBG("Unexpected event for SCO connection");
2405 }
2406 }
2407 }
2408
2409 tasklet_schedule(&hdev->tx_task);
2410
2411 tasklet_enable(&hdev->tx_task);
2412}
2413
Marcel Holtmann04837f62006-07-03 10:02:33 +02002414static inline void hci_mode_change_evt(struct hci_dev *hdev, struct sk_buff *skb)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002415{
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002416 struct hci_ev_mode_change *ev = (void *) skb->data;
Marcel Holtmann04837f62006-07-03 10:02:33 +02002417 struct hci_conn *conn;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002418
2419 BT_DBG("%s status %d", hdev->name, ev->status);
2420
2421 hci_dev_lock(hdev);
2422
Marcel Holtmann04837f62006-07-03 10:02:33 +02002423 conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
2424 if (conn) {
2425 conn->mode = ev->mode;
2426 conn->interval = __le16_to_cpu(ev->interval);
2427
2428 if (!test_and_clear_bit(HCI_CONN_MODE_CHANGE_PEND, &conn->pend)) {
2429 if (conn->mode == HCI_CM_ACTIVE)
2430 conn->power_save = 1;
2431 else
2432 conn->power_save = 0;
2433 }
Marcel Holtmanne73439d2010-07-26 10:06:00 -04002434
2435 if (test_and_clear_bit(HCI_CONN_SCO_SETUP_PEND, &conn->pend))
2436 hci_sco_setup(conn, ev->status);
Marcel Holtmann04837f62006-07-03 10:02:33 +02002437 }
2438
2439 hci_dev_unlock(hdev);
2440}
2441
Linus Torvalds1da177e2005-04-16 15:20:36 -07002442static inline void hci_pin_code_request_evt(struct hci_dev *hdev, struct sk_buff *skb)
2443{
Marcel Holtmann052b30b2009-04-26 20:01:22 +02002444 struct hci_ev_pin_code_req *ev = (void *) skb->data;
2445 struct hci_conn *conn;
2446
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002447 BT_DBG("%s", hdev->name);
Marcel Holtmann052b30b2009-04-26 20:01:22 +02002448
2449 hci_dev_lock(hdev);
2450
2451 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
Marcel Holtmann3d7a9d12009-05-09 12:09:21 -07002452 if (conn && conn->state == BT_CONNECTED) {
Marcel Holtmann052b30b2009-04-26 20:01:22 +02002453 hci_conn_hold(conn);
2454 conn->disc_timeout = HCI_PAIRING_TIMEOUT;
2455 hci_conn_put(conn);
2456 }
2457
Johan Hedberg03b555e2011-01-04 15:40:05 +02002458 if (!test_bit(HCI_PAIRABLE, &hdev->flags))
2459 hci_send_cmd(hdev, HCI_OP_PIN_CODE_NEG_REPLY,
2460 sizeof(ev->bdaddr), &ev->bdaddr);
Waldemar Rymarkiewicza770bb52011-04-28 12:07:59 +02002461
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002462 if (test_bit(HCI_MGMT, &hdev->flags))
2463 mgmt_pin_code_request(hdev->id, &ev->bdaddr);
Johan Hedberg980e1a52011-01-22 06:10:07 +02002464
Marcel Holtmann052b30b2009-04-26 20:01:22 +02002465 hci_dev_unlock(hdev);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002466}
2467
Linus Torvalds1da177e2005-04-16 15:20:36 -07002468static inline void hci_link_key_request_evt(struct hci_dev *hdev, struct sk_buff *skb)
2469{
Johan Hedberg55ed8ca2011-01-17 14:41:05 +02002470 struct hci_ev_link_key_req *ev = (void *) skb->data;
2471 struct hci_cp_link_key_reply cp;
2472 struct hci_conn *conn;
2473 struct link_key *key;
2474
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002475 BT_DBG("%s", hdev->name);
Johan Hedberg55ed8ca2011-01-17 14:41:05 +02002476
2477 if (!test_bit(HCI_LINK_KEYS, &hdev->flags))
2478 return;
2479
2480 hci_dev_lock(hdev);
2481
2482 key = hci_find_link_key(hdev, &ev->bdaddr);
2483 if (!key) {
2484 BT_DBG("%s link key not found for %s", hdev->name,
2485 batostr(&ev->bdaddr));
2486 goto not_found;
2487 }
2488
2489 BT_DBG("%s found key type %u for %s", hdev->name, key->type,
2490 batostr(&ev->bdaddr));
2491
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002492 if (!test_bit(HCI_DEBUG_KEYS, &hdev->flags) && key->type == 0x03) {
Johan Hedberg55ed8ca2011-01-17 14:41:05 +02002493 BT_DBG("%s ignoring debug key", hdev->name);
2494 goto not_found;
2495 }
2496
2497 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
2498
Prabhakaran Mc6001a712011-09-06 11:56:25 +05302499 if (conn) {
2500 BT_DBG("Conn pending sec level is %d, ssp is %d, key len is %d",
2501 conn->pending_sec_level, conn->ssp_mode, key->pin_len);
2502 }
2503 if (conn && (conn->ssp_mode == 0) &&
2504 (conn->pending_sec_level == BT_SECURITY_HIGH) &&
2505 (key->pin_len != 16)) {
2506 BT_DBG("Security is high ignoring this key");
2507 goto not_found;
2508 }
2509
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002510 if (key->type == 0x04 && conn && conn->auth_type != 0xff &&
2511 (conn->auth_type & 0x01)) {
2512 BT_DBG("%s ignoring unauthenticated key", hdev->name);
2513 goto not_found;
Johan Hedberg55ed8ca2011-01-17 14:41:05 +02002514 }
2515
2516 bacpy(&cp.bdaddr, &ev->bdaddr);
2517 memcpy(cp.link_key, key->val, 16);
2518
2519 hci_send_cmd(hdev, HCI_OP_LINK_KEY_REPLY, sizeof(cp), &cp);
2520
2521 hci_dev_unlock(hdev);
2522
2523 return;
2524
2525not_found:
2526 hci_send_cmd(hdev, HCI_OP_LINK_KEY_NEG_REPLY, 6, &ev->bdaddr);
2527 hci_dev_unlock(hdev);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002528}
2529
Linus Torvalds1da177e2005-04-16 15:20:36 -07002530static inline void hci_link_key_notify_evt(struct hci_dev *hdev, struct sk_buff *skb)
2531{
Marcel Holtmann052b30b2009-04-26 20:01:22 +02002532 struct hci_ev_link_key_notify *ev = (void *) skb->data;
2533 struct hci_conn *conn;
Johan Hedberg55ed8ca2011-01-17 14:41:05 +02002534 u8 pin_len = 0;
Marcel Holtmann052b30b2009-04-26 20:01:22 +02002535
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002536 BT_DBG("%s type %d", hdev->name, ev->key_type);
Marcel Holtmann052b30b2009-04-26 20:01:22 +02002537
2538 hci_dev_lock(hdev);
2539
2540 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
2541 if (conn) {
2542 hci_conn_hold(conn);
2543 conn->disc_timeout = HCI_DISCONN_TIMEOUT;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002544
2545 memcpy(conn->link_key, ev->link_key, 16);
2546 conn->key_type = ev->key_type;
2547 hci_disconnect_amp(conn, 0x06);
2548
Johan Hedberg980e1a52011-01-22 06:10:07 +02002549 pin_len = conn->pin_length;
Marcel Holtmann052b30b2009-04-26 20:01:22 +02002550 hci_conn_put(conn);
2551 }
2552
Johan Hedberg55ed8ca2011-01-17 14:41:05 +02002553 if (test_bit(HCI_LINK_KEYS, &hdev->flags))
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002554 hci_add_link_key(hdev, 1, &ev->bdaddr, ev->link_key,
Johan Hedberg55ed8ca2011-01-17 14:41:05 +02002555 ev->key_type, pin_len);
2556
Marcel Holtmann052b30b2009-04-26 20:01:22 +02002557 hci_dev_unlock(hdev);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002558}
2559
Marcel Holtmann04837f62006-07-03 10:02:33 +02002560static inline void hci_clock_offset_evt(struct hci_dev *hdev, struct sk_buff *skb)
2561{
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002562 struct hci_ev_clock_offset *ev = (void *) skb->data;
Marcel Holtmann04837f62006-07-03 10:02:33 +02002563 struct hci_conn *conn;
2564
2565 BT_DBG("%s status %d", hdev->name, ev->status);
2566
2567 hci_dev_lock(hdev);
2568
2569 conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
Linus Torvalds1da177e2005-04-16 15:20:36 -07002570 if (conn && !ev->status) {
2571 struct inquiry_entry *ie;
2572
Andrei Emeltchenkocc11b9c2010-11-22 13:21:37 +02002573 ie = hci_inquiry_cache_lookup(hdev, &conn->dst);
2574 if (ie) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002575 ie->data.clock_offset = ev->clock_offset;
2576 ie->timestamp = jiffies;
2577 }
2578 }
2579
2580 hci_dev_unlock(hdev);
2581}
2582
Marcel Holtmanna8746412008-07-14 20:13:46 +02002583static inline void hci_pkt_type_change_evt(struct hci_dev *hdev, struct sk_buff *skb)
2584{
2585 struct hci_ev_pkt_type_change *ev = (void *) skb->data;
2586 struct hci_conn *conn;
2587
2588 BT_DBG("%s status %d", hdev->name, ev->status);
2589
2590 hci_dev_lock(hdev);
2591
2592 conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
2593 if (conn && !ev->status)
2594 conn->pkt_type = __le16_to_cpu(ev->pkt_type);
2595
2596 hci_dev_unlock(hdev);
2597}
2598
Marcel Holtmann85a1e932005-08-09 20:28:02 -07002599static inline void hci_pscan_rep_mode_evt(struct hci_dev *hdev, struct sk_buff *skb)
2600{
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002601 struct hci_ev_pscan_rep_mode *ev = (void *) skb->data;
Marcel Holtmann85a1e932005-08-09 20:28:02 -07002602 struct inquiry_entry *ie;
2603
2604 BT_DBG("%s", hdev->name);
2605
2606 hci_dev_lock(hdev);
2607
Andrei Emeltchenkocc11b9c2010-11-22 13:21:37 +02002608 ie = hci_inquiry_cache_lookup(hdev, &ev->bdaddr);
2609 if (ie) {
Marcel Holtmann85a1e932005-08-09 20:28:02 -07002610 ie->data.pscan_rep_mode = ev->pscan_rep_mode;
2611 ie->timestamp = jiffies;
2612 }
2613
2614 hci_dev_unlock(hdev);
2615}
2616
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002617static inline void hci_inquiry_result_with_rssi_evt(struct hci_dev *hdev, struct sk_buff *skb)
2618{
2619 struct inquiry_data data;
2620 int num_rsp = *((__u8 *) skb->data);
2621
2622 BT_DBG("%s num_rsp %d", hdev->name, num_rsp);
2623
2624 if (!num_rsp)
2625 return;
2626
2627 hci_dev_lock(hdev);
2628
2629 if ((skb->len - 1) / num_rsp != sizeof(struct inquiry_info_with_rssi)) {
Szymon Janc138d22e2011-02-17 16:44:23 +01002630 struct inquiry_info_with_rssi_and_pscan_mode *info;
2631 info = (void *) (skb->data + 1);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002632
Johan Hedberge17acd42011-03-30 23:57:16 +03002633 for (; num_rsp; num_rsp--, info++) {
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002634 bacpy(&data.bdaddr, &info->bdaddr);
2635 data.pscan_rep_mode = info->pscan_rep_mode;
2636 data.pscan_period_mode = info->pscan_period_mode;
2637 data.pscan_mode = info->pscan_mode;
2638 memcpy(data.dev_class, info->dev_class, 3);
2639 data.clock_offset = info->clock_offset;
2640 data.rssi = info->rssi;
Marcel Holtmann41a96212008-07-14 20:13:48 +02002641 data.ssp_mode = 0x00;
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002642 hci_inquiry_cache_update(hdev, &data);
Brian Gixa68668b2011-08-11 15:49:36 -07002643 mgmt_device_found(hdev->id, &info->bdaddr, 0, 0,
Johan Hedberge17acd42011-03-30 23:57:16 +03002644 info->dev_class, info->rssi,
Brian Gixa68668b2011-08-11 15:49:36 -07002645 0, NULL);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002646 }
2647 } else {
2648 struct inquiry_info_with_rssi *info = (void *) (skb->data + 1);
2649
Johan Hedberge17acd42011-03-30 23:57:16 +03002650 for (; num_rsp; num_rsp--, info++) {
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002651 bacpy(&data.bdaddr, &info->bdaddr);
2652 data.pscan_rep_mode = info->pscan_rep_mode;
2653 data.pscan_period_mode = info->pscan_period_mode;
2654 data.pscan_mode = 0x00;
2655 memcpy(data.dev_class, info->dev_class, 3);
2656 data.clock_offset = info->clock_offset;
2657 data.rssi = info->rssi;
Marcel Holtmann41a96212008-07-14 20:13:48 +02002658 data.ssp_mode = 0x00;
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002659 hci_inquiry_cache_update(hdev, &data);
Brian Gixa68668b2011-08-11 15:49:36 -07002660 mgmt_device_found(hdev->id, &info->bdaddr, 0, 0,
Johan Hedberge17acd42011-03-30 23:57:16 +03002661 info->dev_class, info->rssi,
Brian Gixa68668b2011-08-11 15:49:36 -07002662 0, NULL);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002663 }
2664 }
2665
2666 hci_dev_unlock(hdev);
2667}
2668
2669static inline void hci_remote_ext_features_evt(struct hci_dev *hdev, struct sk_buff *skb)
2670{
Marcel Holtmann41a96212008-07-14 20:13:48 +02002671 struct hci_ev_remote_ext_features *ev = (void *) skb->data;
2672 struct hci_conn *conn;
2673
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002674 BT_DBG("%s", hdev->name);
Marcel Holtmann41a96212008-07-14 20:13:48 +02002675
Marcel Holtmann41a96212008-07-14 20:13:48 +02002676 hci_dev_lock(hdev);
2677
2678 conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
Johan Hedbergccd556f2010-11-10 17:11:51 +02002679 if (!conn)
2680 goto unlock;
Marcel Holtmann41a96212008-07-14 20:13:48 +02002681
Johan Hedbergccd556f2010-11-10 17:11:51 +02002682 if (!ev->status && ev->page == 0x01) {
2683 struct inquiry_entry *ie;
Marcel Holtmann41a96212008-07-14 20:13:48 +02002684
Andrei Emeltchenkocc11b9c2010-11-22 13:21:37 +02002685 ie = hci_inquiry_cache_lookup(hdev, &conn->dst);
2686 if (ie)
Johan Hedbergccd556f2010-11-10 17:11:51 +02002687 ie->data.ssp_mode = (ev->features[0] & 0x01);
Marcel Holtmann769be972008-07-14 20:13:49 +02002688
Johan Hedbergccd556f2010-11-10 17:11:51 +02002689 conn->ssp_mode = (ev->features[0] & 0x01);
Marcel Holtmann41a96212008-07-14 20:13:48 +02002690 }
2691
Johan Hedbergccd556f2010-11-10 17:11:51 +02002692 if (conn->state != BT_CONFIG)
2693 goto unlock;
2694
Johan Hedberg127178d2010-11-18 22:22:29 +02002695 if (!ev->status) {
2696 struct hci_cp_remote_name_req cp;
2697 memset(&cp, 0, sizeof(cp));
2698 bacpy(&cp.bdaddr, &conn->dst);
2699 cp.pscan_rep_mode = 0x02;
2700 hci_send_cmd(hdev, HCI_OP_REMOTE_NAME_REQ, sizeof(cp), &cp);
2701 }
Johan Hedberg392599b2010-11-18 22:22:28 +02002702
Johan Hedberg127178d2010-11-18 22:22:29 +02002703 if (!hci_outgoing_auth_needed(hdev, conn)) {
Johan Hedbergccd556f2010-11-10 17:11:51 +02002704 conn->state = BT_CONNECTED;
2705 hci_proto_connect_cfm(conn, ev->status);
2706 hci_conn_put(conn);
2707 }
2708
2709unlock:
Marcel Holtmann41a96212008-07-14 20:13:48 +02002710 hci_dev_unlock(hdev);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002711}
2712
2713static inline void hci_sync_conn_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
2714{
Marcel Holtmannb6a0dc82007-10-20 14:55:10 +02002715 struct hci_ev_sync_conn_complete *ev = (void *) skb->data;
2716 struct hci_conn *conn;
2717
2718 BT_DBG("%s status %d", hdev->name, ev->status);
2719
2720 hci_dev_lock(hdev);
2721
2722 conn = hci_conn_hash_lookup_ba(hdev, ev->link_type, &ev->bdaddr);
Marcel Holtmann9dc0a3a2008-07-14 20:13:46 +02002723 if (!conn) {
2724 if (ev->link_type == ESCO_LINK)
2725 goto unlock;
2726
2727 conn = hci_conn_hash_lookup_ba(hdev, ESCO_LINK, &ev->bdaddr);
2728 if (!conn)
2729 goto unlock;
2730
2731 conn->type = SCO_LINK;
2732 }
Marcel Holtmannb6a0dc82007-10-20 14:55:10 +02002733
Marcel Holtmann732547f2009-04-19 19:14:14 +02002734 switch (ev->status) {
2735 case 0x00:
Marcel Holtmannb6a0dc82007-10-20 14:55:10 +02002736 conn->handle = __le16_to_cpu(ev->handle);
2737 conn->state = BT_CONNECTED;
Marcel Holtmann7d0db0a2008-07-14 20:13:51 +02002738
Marcel Holtmann9eba32b2009-08-22 14:19:26 -07002739 hci_conn_hold_device(conn);
Marcel Holtmann7d0db0a2008-07-14 20:13:51 +02002740 hci_conn_add_sysfs(conn);
Marcel Holtmann732547f2009-04-19 19:14:14 +02002741 break;
2742
Stephen Coe705e5712010-02-16 11:29:44 -05002743 case 0x11: /* Unsupported Feature or Parameter Value */
Marcel Holtmann732547f2009-04-19 19:14:14 +02002744 case 0x1c: /* SCO interval rejected */
Nick Pelly1038a002010-02-03 11:42:26 -08002745 case 0x1a: /* Unsupported Remote Feature */
Marcel Holtmann732547f2009-04-19 19:14:14 +02002746 case 0x1f: /* Unspecified error */
2747 if (conn->out && conn->attempt < 2) {
Kun Han Kim15b911f2011-07-08 09:30:28 -07002748 if (!conn->hdev->is_wbs)
2749 conn->pkt_type =
2750 (hdev->esco_type & SCO_ESCO_MASK) |
Marcel Holtmann732547f2009-04-19 19:14:14 +02002751 (hdev->esco_type & EDR_ESCO_MASK);
2752 hci_setup_sync(conn, conn->link->handle);
2753 goto unlock;
2754 }
2755 /* fall through */
2756
2757 default:
Marcel Holtmannb6a0dc82007-10-20 14:55:10 +02002758 conn->state = BT_CLOSED;
Marcel Holtmann732547f2009-04-19 19:14:14 +02002759 break;
2760 }
Marcel Holtmannb6a0dc82007-10-20 14:55:10 +02002761
2762 hci_proto_connect_cfm(conn, ev->status);
2763 if (ev->status)
2764 hci_conn_del(conn);
2765
2766unlock:
2767 hci_dev_unlock(hdev);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002768}
2769
2770static inline void hci_sync_conn_changed_evt(struct hci_dev *hdev, struct sk_buff *skb)
2771{
2772 BT_DBG("%s", hdev->name);
2773}
2774
Marcel Holtmann04837f62006-07-03 10:02:33 +02002775static inline void hci_sniff_subrate_evt(struct hci_dev *hdev, struct sk_buff *skb)
2776{
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002777 struct hci_ev_sniff_subrate *ev = (void *) skb->data;
Marcel Holtmann04837f62006-07-03 10:02:33 +02002778
2779 BT_DBG("%s status %d", hdev->name, ev->status);
Marcel Holtmann04837f62006-07-03 10:02:33 +02002780}
2781
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002782static inline void hci_extended_inquiry_result_evt(struct hci_dev *hdev, struct sk_buff *skb)
2783{
2784 struct inquiry_data data;
2785 struct extended_inquiry_info *info = (void *) (skb->data + 1);
2786 int num_rsp = *((__u8 *) skb->data);
2787
2788 BT_DBG("%s num_rsp %d", hdev->name, num_rsp);
2789
2790 if (!num_rsp)
2791 return;
2792
2793 hci_dev_lock(hdev);
2794
Johan Hedberge17acd42011-03-30 23:57:16 +03002795 for (; num_rsp; num_rsp--, info++) {
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002796 bacpy(&data.bdaddr, &info->bdaddr);
Szymon Janc138d22e2011-02-17 16:44:23 +01002797 data.pscan_rep_mode = info->pscan_rep_mode;
2798 data.pscan_period_mode = info->pscan_period_mode;
2799 data.pscan_mode = 0x00;
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002800 memcpy(data.dev_class, info->dev_class, 3);
Szymon Janc138d22e2011-02-17 16:44:23 +01002801 data.clock_offset = info->clock_offset;
2802 data.rssi = info->rssi;
Marcel Holtmann41a96212008-07-14 20:13:48 +02002803 data.ssp_mode = 0x01;
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002804 hci_inquiry_cache_update(hdev, &data);
Brian Gixa68668b2011-08-11 15:49:36 -07002805 mgmt_device_found(hdev->id, &info->bdaddr, 0, 0,
2806 info->dev_class, info->rssi,
2807 HCI_MAX_EIR_LENGTH, info->data);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002808 }
2809
2810 hci_dev_unlock(hdev);
2811}
2812
Johan Hedberg17fa4b92011-01-25 13:28:33 +02002813static inline u8 hci_get_auth_req(struct hci_conn *conn)
2814{
Brian Gixa68668b2011-08-11 15:49:36 -07002815 BT_DBG("%p", conn);
2816
Johan Hedberg17fa4b92011-01-25 13:28:33 +02002817 /* If remote requests dedicated bonding follow that lead */
2818 if (conn->remote_auth == 0x02 || conn->remote_auth == 0x03) {
2819 /* If both remote and local IO capabilities allow MITM
2820 * protection then require it, otherwise don't */
Brian Gixa68668b2011-08-11 15:49:36 -07002821 if (conn->remote_cap == 0x03 || conn->io_capability == 0x03) {
Johan Hedberg17fa4b92011-01-25 13:28:33 +02002822 return 0x02;
Brian Gixa68668b2011-08-11 15:49:36 -07002823 } else {
2824 conn->auth_type |= 0x01;
Johan Hedberg17fa4b92011-01-25 13:28:33 +02002825 return 0x03;
Brian Gixa68668b2011-08-11 15:49:36 -07002826 }
Johan Hedberg17fa4b92011-01-25 13:28:33 +02002827 }
2828
2829 /* If remote requests no-bonding follow that lead */
Brian Gixa68668b2011-08-11 15:49:36 -07002830 if (conn->remote_auth <= 0x01)
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002831 return 0x00;
Johan Hedberg17fa4b92011-01-25 13:28:33 +02002832
2833 return conn->auth_type;
2834}
2835
Marcel Holtmann04936842008-07-14 20:13:48 +02002836static inline void hci_io_capa_request_evt(struct hci_dev *hdev, struct sk_buff *skb)
2837{
2838 struct hci_ev_io_capa_request *ev = (void *) skb->data;
2839 struct hci_conn *conn;
2840
2841 BT_DBG("%s", hdev->name);
2842
2843 hci_dev_lock(hdev);
2844
2845 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
Johan Hedberg03b555e2011-01-04 15:40:05 +02002846 if (!conn)
2847 goto unlock;
Marcel Holtmann04936842008-07-14 20:13:48 +02002848
Johan Hedberg03b555e2011-01-04 15:40:05 +02002849 hci_conn_hold(conn);
2850
2851 if (!test_bit(HCI_MGMT, &hdev->flags))
2852 goto unlock;
2853
2854 if (test_bit(HCI_PAIRABLE, &hdev->flags) ||
2855 (conn->remote_auth & ~0x01) == HCI_AT_NO_BONDING) {
Johan Hedberg17fa4b92011-01-25 13:28:33 +02002856 struct hci_cp_io_capability_reply cp;
Brian Gixa68668b2011-08-11 15:49:36 -07002857 u8 io_cap = conn->io_capability;
Johan Hedberg17fa4b92011-01-25 13:28:33 +02002858
Brian Gixa68668b2011-08-11 15:49:36 -07002859 /* ACL-SSP does not support IO CAP 0x04 */
2860 cp.capability = (io_cap == 0x04) ? 0x01 : io_cap;
Johan Hedberg17fa4b92011-01-25 13:28:33 +02002861 bacpy(&cp.bdaddr, &ev->bdaddr);
Brian Gixa68668b2011-08-11 15:49:36 -07002862 if (conn->auth_initiator)
2863 cp.authentication = conn->auth_type;
2864 else
2865 cp.authentication = hci_get_auth_req(conn);
Johan Hedberg17fa4b92011-01-25 13:28:33 +02002866
Szymon Jancce85ee12011-03-22 13:12:23 +01002867 if ((conn->out == 0x01 || conn->remote_oob == 0x01) &&
2868 hci_find_remote_oob_data(hdev, &conn->dst))
2869 cp.oob_data = 0x01;
2870 else
2871 cp.oob_data = 0x00;
2872
Johan Hedberg17fa4b92011-01-25 13:28:33 +02002873 hci_send_cmd(hdev, HCI_OP_IO_CAPABILITY_REPLY,
2874 sizeof(cp), &cp);
Johan Hedberg03b555e2011-01-04 15:40:05 +02002875 } else {
2876 struct hci_cp_io_capability_neg_reply cp;
2877
2878 bacpy(&cp.bdaddr, &ev->bdaddr);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002879 cp.reason = 0x16; /* Pairing not allowed */
Johan Hedberg03b555e2011-01-04 15:40:05 +02002880
2881 hci_send_cmd(hdev, HCI_OP_IO_CAPABILITY_NEG_REPLY,
2882 sizeof(cp), &cp);
2883 }
2884
2885unlock:
2886 hci_dev_unlock(hdev);
2887}
2888
2889static inline void hci_io_capa_reply_evt(struct hci_dev *hdev, struct sk_buff *skb)
2890{
2891 struct hci_ev_io_capa_reply *ev = (void *) skb->data;
2892 struct hci_conn *conn;
2893
2894 BT_DBG("%s", hdev->name);
2895
2896 hci_dev_lock(hdev);
2897
2898 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
2899 if (!conn)
2900 goto unlock;
2901
Johan Hedberg03b555e2011-01-04 15:40:05 +02002902 conn->remote_cap = ev->capability;
2903 conn->remote_oob = ev->oob_data;
2904 conn->remote_auth = ev->authentication;
2905
2906unlock:
Marcel Holtmann04936842008-07-14 20:13:48 +02002907 hci_dev_unlock(hdev);
2908}
2909
Brian Gixa68668b2011-08-11 15:49:36 -07002910static inline void hci_user_ssp_confirmation_evt(struct hci_dev *hdev,
2911 u8 event, struct sk_buff *skb)
Johan Hedberga5c29682011-02-19 12:05:57 -03002912{
2913 struct hci_ev_user_confirm_req *ev = (void *) skb->data;
2914
2915 BT_DBG("%s", hdev->name);
2916
2917 hci_dev_lock(hdev);
2918
Brian Gixa68668b2011-08-11 15:49:36 -07002919 if (test_bit(HCI_MGMT, &hdev->flags)) {
2920 if (event == HCI_EV_USER_PASSKEY_REQUEST)
2921 mgmt_user_confirm_request(hdev->id, event,
2922 &ev->bdaddr, 0);
2923 else
2924 mgmt_user_confirm_request(hdev->id, event,
2925 &ev->bdaddr, ev->passkey);
2926 }
Johan Hedberga5c29682011-02-19 12:05:57 -03002927
2928 hci_dev_unlock(hdev);
2929}
2930
Marcel Holtmann04936842008-07-14 20:13:48 +02002931static inline void hci_simple_pair_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
2932{
2933 struct hci_ev_simple_pair_complete *ev = (void *) skb->data;
2934 struct hci_conn *conn;
2935
2936 BT_DBG("%s", hdev->name);
2937
2938 hci_dev_lock(hdev);
2939
2940 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
Johan Hedberg2a611692011-02-19 12:06:00 -03002941 if (!conn)
2942 goto unlock;
Marcel Holtmann04936842008-07-14 20:13:48 +02002943
Johan Hedberg2a611692011-02-19 12:06:00 -03002944 /* To avoid duplicate auth_failed events to user space we check
2945 * the HCI_CONN_AUTH_PEND flag which will be set if we
2946 * initiated the authentication. A traditional auth_complete
2947 * event gets always produced as initiator and is also mapped to
2948 * the mgmt_auth_failed event */
2949 if (!test_bit(HCI_CONN_AUTH_PEND, &conn->pend) && ev->status != 0)
2950 mgmt_auth_failed(hdev->id, &conn->dst, ev->status);
2951
2952 hci_conn_put(conn);
2953
2954unlock:
Marcel Holtmann04936842008-07-14 20:13:48 +02002955 hci_dev_unlock(hdev);
2956}
2957
Marcel Holtmann41a96212008-07-14 20:13:48 +02002958static inline void hci_remote_host_features_evt(struct hci_dev *hdev, struct sk_buff *skb)
2959{
2960 struct hci_ev_remote_host_features *ev = (void *) skb->data;
2961 struct inquiry_entry *ie;
2962
2963 BT_DBG("%s", hdev->name);
2964
2965 hci_dev_lock(hdev);
2966
Andrei Emeltchenkocc11b9c2010-11-22 13:21:37 +02002967 ie = hci_inquiry_cache_lookup(hdev, &ev->bdaddr);
2968 if (ie)
Marcel Holtmann41a96212008-07-14 20:13:48 +02002969 ie->data.ssp_mode = (ev->features[0] & 0x01);
2970
2971 hci_dev_unlock(hdev);
2972}
2973
Szymon Janc2763eda2011-03-22 13:12:22 +01002974static inline void hci_remote_oob_data_request_evt(struct hci_dev *hdev,
2975 struct sk_buff *skb)
2976{
2977 struct hci_ev_remote_oob_data_request *ev = (void *) skb->data;
2978 struct oob_data *data;
2979
2980 BT_DBG("%s", hdev->name);
2981
2982 hci_dev_lock(hdev);
2983
Szymon Jance1ba1f12011-04-06 13:01:59 +02002984 if (!test_bit(HCI_MGMT, &hdev->flags))
2985 goto unlock;
2986
Szymon Janc2763eda2011-03-22 13:12:22 +01002987 data = hci_find_remote_oob_data(hdev, &ev->bdaddr);
2988 if (data) {
2989 struct hci_cp_remote_oob_data_reply cp;
2990
2991 bacpy(&cp.bdaddr, &ev->bdaddr);
2992 memcpy(cp.hash, data->hash, sizeof(cp.hash));
2993 memcpy(cp.randomizer, data->randomizer, sizeof(cp.randomizer));
2994
2995 hci_send_cmd(hdev, HCI_OP_REMOTE_OOB_DATA_REPLY, sizeof(cp),
2996 &cp);
2997 } else {
2998 struct hci_cp_remote_oob_data_neg_reply cp;
2999
3000 bacpy(&cp.bdaddr, &ev->bdaddr);
3001 hci_send_cmd(hdev, HCI_OP_REMOTE_OOB_DATA_NEG_REPLY, sizeof(cp),
3002 &cp);
3003 }
3004
Szymon Jance1ba1f12011-04-06 13:01:59 +02003005unlock:
Szymon Janc2763eda2011-03-22 13:12:22 +01003006 hci_dev_unlock(hdev);
3007}
3008
Ville Tervofcd89c02011-02-10 22:38:47 -03003009static inline void hci_le_conn_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
3010{
3011 struct hci_ev_le_conn_complete *ev = (void *) skb->data;
3012 struct hci_conn *conn;
3013
3014 BT_DBG("%s status %d", hdev->name, ev->status);
3015
3016 hci_dev_lock(hdev);
3017
3018 conn = hci_conn_hash_lookup_ba(hdev, LE_LINK, &ev->bdaddr);
Ville Tervob62f3282011-02-10 22:38:50 -03003019 if (!conn) {
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003020 conn = hci_le_conn_add(hdev, &ev->bdaddr, ev->bdaddr_type);
Ville Tervob62f3282011-02-10 22:38:50 -03003021 if (!conn) {
3022 BT_ERR("No memory for new connection");
3023 hci_dev_unlock(hdev);
3024 return;
3025 }
3026 }
Ville Tervofcd89c02011-02-10 22:38:47 -03003027
3028 if (ev->status) {
3029 hci_proto_connect_cfm(conn, ev->status);
3030 conn->state = BT_CLOSED;
3031 hci_conn_del(conn);
3032 goto unlock;
3033 }
3034
Vinicius Costa Gomes403d2c82011-06-09 18:50:50 -03003035 conn->sec_level = BT_SECURITY_LOW;
Ville Tervofcd89c02011-02-10 22:38:47 -03003036 conn->handle = __le16_to_cpu(ev->handle);
3037 conn->state = BT_CONNECTED;
Brian Gixa68668b2011-08-11 15:49:36 -07003038 conn->disc_timeout = HCI_DISCONN_TIMEOUT;
Brian Gix2e2f50d2011-09-13 12:36:04 -07003039 mgmt_connected(hdev->id, &ev->bdaddr, 1);
Ville Tervofcd89c02011-02-10 22:38:47 -03003040
Brian Gix6d5fb8a2011-09-09 14:53:04 -07003041 hci_conn_hold(conn);
Ville Tervofcd89c02011-02-10 22:38:47 -03003042 hci_conn_hold_device(conn);
3043 hci_conn_add_sysfs(conn);
3044
3045 hci_proto_connect_cfm(conn, ev->status);
3046
3047unlock:
3048 hci_dev_unlock(hdev);
3049}
3050
Vinicius Costa Gomes735038c2011-06-09 18:50:47 -03003051static inline void hci_le_ltk_request_evt(struct hci_dev *hdev,
3052 struct sk_buff *skb)
3053{
3054 struct hci_ev_le_ltk_req *ev = (void *) skb->data;
3055 struct hci_cp_le_ltk_reply cp;
Vinicius Costa Gomes60e56472011-07-07 18:59:37 -03003056 struct hci_cp_le_ltk_neg_reply neg;
Vinicius Costa Gomes735038c2011-06-09 18:50:47 -03003057 struct hci_conn *conn;
Vinicius Costa Gomes60e56472011-07-07 18:59:37 -03003058 struct link_key *ltk;
Vinicius Costa Gomes735038c2011-06-09 18:50:47 -03003059
3060 BT_DBG("%s handle %d", hdev->name, cpu_to_le16(ev->handle));
3061
3062 hci_dev_lock(hdev);
3063
3064 conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
Vinicius Costa Gomes60e56472011-07-07 18:59:37 -03003065 if (conn == NULL)
3066 goto not_found;
Vinicius Costa Gomes735038c2011-06-09 18:50:47 -03003067
Vinicius Costa Gomes60e56472011-07-07 18:59:37 -03003068 ltk = hci_find_ltk(hdev, ev->ediv, ev->random);
3069 if (ltk == NULL)
3070 goto not_found;
3071
3072 memcpy(cp.ltk, ltk->val, sizeof(ltk->val));
Vinicius Costa Gomes735038c2011-06-09 18:50:47 -03003073 cp.handle = cpu_to_le16(conn->handle);
Vinicius Costa Gomes1fa2de32011-07-08 18:31:45 -03003074 conn->pin_length = ltk->pin_len;
Vinicius Costa Gomes735038c2011-06-09 18:50:47 -03003075
3076 hci_send_cmd(hdev, HCI_OP_LE_LTK_REPLY, sizeof(cp), &cp);
3077
3078 hci_dev_unlock(hdev);
Vinicius Costa Gomes60e56472011-07-07 18:59:37 -03003079
3080 return;
3081
3082not_found:
3083 neg.handle = ev->handle;
3084 hci_send_cmd(hdev, HCI_OP_LE_LTK_NEG_REPLY, sizeof(neg), &neg);
3085 hci_dev_unlock(hdev);
Vinicius Costa Gomes735038c2011-06-09 18:50:47 -03003086}
3087
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003088static inline void hci_le_adv_report_evt(struct hci_dev *hdev,
3089 struct sk_buff *skb)
3090{
3091 struct hci_ev_le_advertising_info *ev;
3092 u8 num_reports;
3093
3094 num_reports = skb->data[0];
3095 ev = (void *) &skb->data[1];
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003096
Brian Gix3dd70172011-09-16 21:38:54 -07003097 hci_dev_lock(hdev);
3098
Brian Gixa68668b2011-08-11 15:49:36 -07003099 while (num_reports--) {
3100 mgmt_device_found(hdev->id, &ev->bdaddr, ev->bdaddr_type,
3101 1, NULL, 0, ev->length, ev->data);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003102 hci_add_adv_entry(hdev, ev);
Brian Gixa68668b2011-08-11 15:49:36 -07003103 ev = (void *) (ev->data + ev->length + 1);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003104 }
Brian Gix3dd70172011-09-16 21:38:54 -07003105
3106 hci_dev_unlock(hdev);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003107}
3108
Ville Tervofcd89c02011-02-10 22:38:47 -03003109static inline void hci_le_meta_evt(struct hci_dev *hdev, struct sk_buff *skb)
3110{
3111 struct hci_ev_le_meta *le_ev = (void *) skb->data;
3112
3113 skb_pull(skb, sizeof(*le_ev));
3114
3115 switch (le_ev->subevent) {
3116 case HCI_EV_LE_CONN_COMPLETE:
3117 hci_le_conn_complete_evt(hdev, skb);
3118 break;
3119
Vinicius Costa Gomes735038c2011-06-09 18:50:47 -03003120 case HCI_EV_LE_LTK_REQ:
3121 hci_le_ltk_request_evt(hdev, skb);
3122 break;
3123
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003124 case HCI_EV_LE_ADVERTISING_REPORT:
3125 hci_le_adv_report_evt(hdev, skb);
3126 break;
3127
Ville Tervofcd89c02011-02-10 22:38:47 -03003128 default:
3129 break;
3130 }
3131}
3132
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003133static inline void hci_phy_link_complete(struct hci_dev *hdev,
3134 struct sk_buff *skb)
3135{
3136 struct hci_ev_phys_link_complete *ev = (void *) skb->data;
3137 struct hci_conn *conn;
3138
3139 BT_DBG("%s handle %d status %d", hdev->name, ev->phy_handle,
3140 ev->status);
3141
3142 hci_dev_lock(hdev);
3143
3144 if (ev->status == 0) {
3145 conn = hci_conn_add(hdev, ACL_LINK, 0, BDADDR_ANY);
3146 if (conn) {
3147 conn->handle = ev->phy_handle;
3148 conn->state = BT_CONNECTED;
3149
3150 hci_conn_hold(conn);
3151 conn->disc_timeout = HCI_DISCONN_TIMEOUT/2;
3152 hci_conn_put(conn);
3153
3154 hci_conn_hold_device(conn);
3155 hci_conn_add_sysfs(conn);
3156 } else
3157 BT_ERR("No memory for new connection");
3158 }
3159
3160 hci_dev_unlock(hdev);
3161}
3162
3163static inline void hci_log_link_complete(struct hci_dev *hdev,
3164 struct sk_buff *skb)
3165{
3166 struct hci_ev_log_link_complete *ev = (void *) skb->data;
3167 struct hci_chan *chan;
3168
3169 BT_DBG("%s handle %d status %d", hdev->name,
3170 __le16_to_cpu(ev->log_handle), ev->status);
3171
3172 hci_dev_lock(hdev);
3173
3174 chan = hci_chan_list_lookup_id(hdev, ev->phy_handle);
3175
3176 if (ev->status == 0) {
3177 if (chan) {
3178 chan->ll_handle = __le16_to_cpu(ev->log_handle);
3179 chan->state = BT_CONNECTED;
3180 hci_proto_create_cfm(chan, ev->status);
3181 hci_chan_hold(chan);
3182 }
3183 } else {
3184 if (chan) {
3185 chan->state = BT_CLOSED;
3186 hci_proto_create_cfm(chan, ev->status);
3187 hci_chan_del(chan);
3188 }
3189 }
3190
3191 hci_dev_unlock(hdev);
3192}
3193
3194static inline void hci_flow_spec_modify_complete(struct hci_dev *hdev,
3195 struct sk_buff *skb)
3196{
3197 struct hci_ev_flow_spec_modify_complete *ev = (void *) skb->data;
3198 struct hci_chan *chan;
3199
3200 BT_DBG("%s handle %d status %d", hdev->name,
3201 __le16_to_cpu(ev->log_handle), ev->status);
3202
3203 hci_dev_lock(hdev);
3204
3205 chan = hci_chan_list_lookup_handle(hdev, ev->log_handle);
3206 if (chan)
3207 hci_proto_modify_cfm(chan, ev->status);
3208
3209 hci_dev_unlock(hdev);
3210}
3211
3212static inline void hci_disconn_log_link_complete_evt(struct hci_dev *hdev,
3213 struct sk_buff *skb)
3214{
3215 struct hci_ev_disconn_log_link_complete *ev = (void *) skb->data;
3216 struct hci_chan *chan;
3217
3218 BT_DBG("%s handle %d status %d", hdev->name,
3219 __le16_to_cpu(ev->log_handle), ev->status);
3220
3221 if (ev->status)
3222 return;
3223
3224 hci_dev_lock(hdev);
3225
3226 chan = hci_chan_list_lookup_handle(hdev, __le16_to_cpu(ev->log_handle));
3227 if (chan) {
3228 hci_proto_destroy_cfm(chan, ev->reason);
3229 hci_chan_del(chan);
3230 }
3231
3232 hci_dev_unlock(hdev);
3233}
3234
3235static inline void hci_disconn_phy_link_complete_evt(struct hci_dev *hdev,
3236 struct sk_buff *skb)
3237{
3238 struct hci_ev_disconn_phys_link_complete *ev = (void *) skb->data;
3239 struct hci_conn *conn;
3240
3241 BT_DBG("%s status %d", hdev->name, ev->status);
3242
3243 if (ev->status)
3244 return;
3245
3246 hci_dev_lock(hdev);
3247
3248 conn = hci_conn_hash_lookup_handle(hdev, ev->phy_handle);
3249 if (conn) {
3250 conn->state = BT_CLOSED;
3251
3252 hci_proto_disconn_cfm(conn, ev->reason);
3253 hci_conn_del(conn);
3254 }
3255
3256 hci_dev_unlock(hdev);
3257}
3258
Linus Torvalds1da177e2005-04-16 15:20:36 -07003259void hci_event_packet(struct hci_dev *hdev, struct sk_buff *skb)
3260{
Marcel Holtmanna9de9242007-10-20 13:33:56 +02003261 struct hci_event_hdr *hdr = (void *) skb->data;
3262 __u8 event = hdr->evt;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003263
Brian Gixdfdd9362011-08-18 09:58:02 -07003264 BT_DBG("");
3265
Linus Torvalds1da177e2005-04-16 15:20:36 -07003266 skb_pull(skb, HCI_EVENT_HDR_SIZE);
3267
Marcel Holtmanna9de9242007-10-20 13:33:56 +02003268 switch (event) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003269 case HCI_EV_INQUIRY_COMPLETE:
3270 hci_inquiry_complete_evt(hdev, skb);
3271 break;
3272
3273 case HCI_EV_INQUIRY_RESULT:
3274 hci_inquiry_result_evt(hdev, skb);
3275 break;
3276
Marcel Holtmanna9de9242007-10-20 13:33:56 +02003277 case HCI_EV_CONN_COMPLETE:
3278 hci_conn_complete_evt(hdev, skb);
Marcel Holtmann21d9e302005-09-13 01:32:25 +02003279 break;
3280
Linus Torvalds1da177e2005-04-16 15:20:36 -07003281 case HCI_EV_CONN_REQUEST:
3282 hci_conn_request_evt(hdev, skb);
3283 break;
3284
Linus Torvalds1da177e2005-04-16 15:20:36 -07003285 case HCI_EV_DISCONN_COMPLETE:
3286 hci_disconn_complete_evt(hdev, skb);
3287 break;
3288
Linus Torvalds1da177e2005-04-16 15:20:36 -07003289 case HCI_EV_AUTH_COMPLETE:
3290 hci_auth_complete_evt(hdev, skb);
3291 break;
3292
Marcel Holtmanna9de9242007-10-20 13:33:56 +02003293 case HCI_EV_REMOTE_NAME:
3294 hci_remote_name_evt(hdev, skb);
3295 break;
3296
Linus Torvalds1da177e2005-04-16 15:20:36 -07003297 case HCI_EV_ENCRYPT_CHANGE:
3298 hci_encrypt_change_evt(hdev, skb);
3299 break;
3300
Marcel Holtmanna9de9242007-10-20 13:33:56 +02003301 case HCI_EV_CHANGE_LINK_KEY_COMPLETE:
3302 hci_change_link_key_complete_evt(hdev, skb);
3303 break;
3304
3305 case HCI_EV_REMOTE_FEATURES:
3306 hci_remote_features_evt(hdev, skb);
3307 break;
3308
3309 case HCI_EV_REMOTE_VERSION:
3310 hci_remote_version_evt(hdev, skb);
3311 break;
3312
3313 case HCI_EV_QOS_SETUP_COMPLETE:
3314 hci_qos_setup_complete_evt(hdev, skb);
3315 break;
3316
3317 case HCI_EV_CMD_COMPLETE:
3318 hci_cmd_complete_evt(hdev, skb);
3319 break;
3320
3321 case HCI_EV_CMD_STATUS:
3322 hci_cmd_status_evt(hdev, skb);
3323 break;
3324
3325 case HCI_EV_ROLE_CHANGE:
3326 hci_role_change_evt(hdev, skb);
3327 break;
3328
3329 case HCI_EV_NUM_COMP_PKTS:
3330 hci_num_comp_pkts_evt(hdev, skb);
3331 break;
3332
3333 case HCI_EV_MODE_CHANGE:
3334 hci_mode_change_evt(hdev, skb);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003335 break;
3336
3337 case HCI_EV_PIN_CODE_REQ:
3338 hci_pin_code_request_evt(hdev, skb);
3339 break;
3340
3341 case HCI_EV_LINK_KEY_REQ:
3342 hci_link_key_request_evt(hdev, skb);
3343 break;
3344
3345 case HCI_EV_LINK_KEY_NOTIFY:
3346 hci_link_key_notify_evt(hdev, skb);
3347 break;
3348
3349 case HCI_EV_CLOCK_OFFSET:
3350 hci_clock_offset_evt(hdev, skb);
3351 break;
3352
Marcel Holtmanna8746412008-07-14 20:13:46 +02003353 case HCI_EV_PKT_TYPE_CHANGE:
3354 hci_pkt_type_change_evt(hdev, skb);
3355 break;
3356
Marcel Holtmann85a1e932005-08-09 20:28:02 -07003357 case HCI_EV_PSCAN_REP_MODE:
3358 hci_pscan_rep_mode_evt(hdev, skb);
3359 break;
3360
Marcel Holtmanna9de9242007-10-20 13:33:56 +02003361 case HCI_EV_INQUIRY_RESULT_WITH_RSSI:
3362 hci_inquiry_result_with_rssi_evt(hdev, skb);
3363 break;
3364
3365 case HCI_EV_REMOTE_EXT_FEATURES:
3366 hci_remote_ext_features_evt(hdev, skb);
3367 break;
3368
3369 case HCI_EV_SYNC_CONN_COMPLETE:
3370 hci_sync_conn_complete_evt(hdev, skb);
3371 break;
3372
3373 case HCI_EV_SYNC_CONN_CHANGED:
3374 hci_sync_conn_changed_evt(hdev, skb);
3375 break;
3376
Marcel Holtmann04837f62006-07-03 10:02:33 +02003377 case HCI_EV_SNIFF_SUBRATE:
3378 hci_sniff_subrate_evt(hdev, skb);
3379 break;
3380
Marcel Holtmanna9de9242007-10-20 13:33:56 +02003381 case HCI_EV_EXTENDED_INQUIRY_RESULT:
3382 hci_extended_inquiry_result_evt(hdev, skb);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003383 break;
3384
Marcel Holtmann04936842008-07-14 20:13:48 +02003385 case HCI_EV_IO_CAPA_REQUEST:
3386 hci_io_capa_request_evt(hdev, skb);
3387 break;
3388
Johan Hedberg03b555e2011-01-04 15:40:05 +02003389 case HCI_EV_IO_CAPA_REPLY:
3390 hci_io_capa_reply_evt(hdev, skb);
3391 break;
3392
Brian Gixa68668b2011-08-11 15:49:36 -07003393 case HCI_EV_USER_PASSKEY_REQUEST:
3394 case HCI_EV_USER_PASSKEY_NOTIFICATION:
Johan Hedberga5c29682011-02-19 12:05:57 -03003395 case HCI_EV_USER_CONFIRM_REQUEST:
Brian Gixa68668b2011-08-11 15:49:36 -07003396 hci_user_ssp_confirmation_evt(hdev, event, skb);
Johan Hedberga5c29682011-02-19 12:05:57 -03003397 break;
3398
Marcel Holtmann04936842008-07-14 20:13:48 +02003399 case HCI_EV_SIMPLE_PAIR_COMPLETE:
3400 hci_simple_pair_complete_evt(hdev, skb);
3401 break;
3402
Marcel Holtmann41a96212008-07-14 20:13:48 +02003403 case HCI_EV_REMOTE_HOST_FEATURES:
3404 hci_remote_host_features_evt(hdev, skb);
3405 break;
3406
Ville Tervofcd89c02011-02-10 22:38:47 -03003407 case HCI_EV_LE_META:
3408 hci_le_meta_evt(hdev, skb);
3409 break;
3410
Szymon Janc2763eda2011-03-22 13:12:22 +01003411 case HCI_EV_REMOTE_OOB_DATA_REQUEST:
3412 hci_remote_oob_data_request_evt(hdev, skb);
3413 break;
3414
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003415 case HCI_EV_PHYS_LINK_COMPLETE:
3416 hci_phy_link_complete(hdev, skb);
3417 hci_amp_event_packet(hdev, event, skb);
3418 break;
3419
3420 case HCI_EV_LOG_LINK_COMPLETE:
3421 hci_log_link_complete(hdev, skb);
3422 break;
3423
3424 case HCI_EV_FLOW_SPEC_MODIFY_COMPLETE:
3425 hci_flow_spec_modify_complete(hdev, skb);
3426 break;
3427
3428 case HCI_EV_DISCONN_LOG_LINK_COMPLETE:
3429 hci_disconn_log_link_complete_evt(hdev, skb);
3430 break;
3431
3432 case HCI_EV_DISCONN_PHYS_LINK_COMPLETE:
3433 hci_disconn_phy_link_complete_evt(hdev, skb);
3434 hci_amp_event_packet(hdev, event, skb);
3435 break;
3436
3437 case HCI_EV_NUM_COMP_BLOCKS:
3438 hci_num_comp_blocks_evt(hdev, skb);
3439 break;
3440
3441 case HCI_EV_CHANNEL_SELECTED:
3442 hci_amp_event_packet(hdev, event, skb);
3443 break;
3444
3445 case HCI_EV_AMP_STATUS_CHANGE:
3446 hci_amp_event_packet(hdev, event, skb);
3447 break;
3448
Marcel Holtmanna9de9242007-10-20 13:33:56 +02003449 default:
3450 BT_DBG("%s event 0x%x", hdev->name, event);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003451 break;
3452 }
3453
3454 kfree_skb(skb);
3455 hdev->stat.evt_rx++;
3456}
3457
3458/* Generate internal stack event */
3459void hci_si_event(struct hci_dev *hdev, int type, int dlen, void *data)
3460{
3461 struct hci_event_hdr *hdr;
3462 struct hci_ev_stack_internal *ev;
3463 struct sk_buff *skb;
3464
3465 skb = bt_skb_alloc(HCI_EVENT_HDR_SIZE + sizeof(*ev) + dlen, GFP_ATOMIC);
3466 if (!skb)
3467 return;
3468
3469 hdr = (void *) skb_put(skb, HCI_EVENT_HDR_SIZE);
3470 hdr->evt = HCI_EV_STACK_INTERNAL;
3471 hdr->plen = sizeof(*ev) + dlen;
3472
3473 ev = (void *) skb_put(skb, sizeof(*ev) + dlen);
3474 ev->type = type;
3475 memcpy(ev->data, data, dlen);
3476
Marcel Holtmann576c7d82005-08-06 12:36:54 +02003477 bt_cb(skb)->incoming = 1;
Patrick McHardya61bbcf2005-08-14 17:24:31 -07003478 __net_timestamp(skb);
Marcel Holtmann576c7d82005-08-06 12:36:54 +02003479
Marcel Holtmann0d48d932005-08-09 20:30:28 -07003480 bt_cb(skb)->pkt_type = HCI_EVENT_PKT;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003481 skb->dev = (void *) hdev;
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02003482 hci_send_to_sock(hdev, skb, NULL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003483 kfree_skb(skb);
3484}