blob: 0a936291f0e7879c2190e9108061421781a5c08d [file] [log] [blame]
YOSHIFUJI Hideaki8e87d142007-02-09 23:24:33 +09001/*
Linus Torvalds1da177e2005-04-16 15:20:36 -07002 BlueZ - Bluetooth protocol stack for Linux
Ron Shaffer2d0a0342010-05-28 11:53:46 -04003 Copyright (c) 2000-2001, 2010, Code Aurora Forum. All rights reserved.
Linus Torvalds1da177e2005-04-16 15:20:36 -07004
5 Written 2000,2001 by Maxim Krasnyansky <maxk@qualcomm.com>
6
7 This program is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License version 2 as
9 published by the Free Software Foundation;
10
11 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
12 OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
13 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF THIRD PARTY RIGHTS.
14 IN NO EVENT SHALL THE COPYRIGHT HOLDER(S) AND AUTHOR(S) BE LIABLE FOR ANY
YOSHIFUJI Hideaki8e87d142007-02-09 23:24:33 +090015 CLAIM, OR ANY SPECIAL INDIRECT OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES
16 WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
17 ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
Linus Torvalds1da177e2005-04-16 15:20:36 -070018 OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
19
YOSHIFUJI Hideaki8e87d142007-02-09 23:24:33 +090020 ALL LIABILITY, INCLUDING LIABILITY FOR INFRINGEMENT OF ANY PATENTS,
21 COPYRIGHTS, TRADEMARKS OR OTHER RIGHTS, RELATING TO USE OF THIS
Linus Torvalds1da177e2005-04-16 15:20:36 -070022 SOFTWARE IS DISCLAIMED.
23*/
24
25/* Bluetooth HCI event handling. */
26
Linus Torvalds1da177e2005-04-16 15:20:36 -070027#include <linux/module.h>
28
29#include <linux/types.h>
30#include <linux/errno.h>
31#include <linux/kernel.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070032#include <linux/slab.h>
33#include <linux/poll.h>
34#include <linux/fcntl.h>
35#include <linux/init.h>
36#include <linux/skbuff.h>
37#include <linux/interrupt.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070038#include <net/sock.h>
39
Andrei Emeltchenko70f230202010-12-01 16:58:25 +020040#include <linux/uaccess.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070041#include <asm/unaligned.h>
42
43#include <net/bluetooth/bluetooth.h>
44#include <net/bluetooth/hci_core.h>
45
Linus Torvalds1da177e2005-04-16 15:20:36 -070046/* Handle HCI Event packets */
47
Marcel Holtmanna9de9242007-10-20 13:33:56 +020048static void hci_cc_inquiry_cancel(struct hci_dev *hdev, struct sk_buff *skb)
Linus Torvalds1da177e2005-04-16 15:20:36 -070049{
Marcel Holtmanna9de9242007-10-20 13:33:56 +020050 __u8 status = *((__u8 *) skb->data);
Linus Torvalds1da177e2005-04-16 15:20:36 -070051
Marcel Holtmanna9de9242007-10-20 13:33:56 +020052 BT_DBG("%s status 0x%x", hdev->name, status);
Linus Torvalds1da177e2005-04-16 15:20:36 -070053
Andre Guedese6d465c2011-11-09 17:14:26 -030054 if (status) {
55 hci_dev_lock(hdev);
56 mgmt_stop_discovery_failed(hdev, status);
57 hci_dev_unlock(hdev);
Marcel Holtmanna9de9242007-10-20 13:33:56 +020058 return;
Andre Guedese6d465c2011-11-09 17:14:26 -030059 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070060
Andre Guedes89352e72011-11-04 14:16:53 -030061 clear_bit(HCI_INQUIRY, &hdev->flags);
62
Johan Hedberg56e5cb82011-11-08 20:40:16 +020063 hci_dev_lock(hdev);
Johan Hedbergff9ef572012-01-04 14:23:45 +020064 hci_discovery_set_state(hdev, DISCOVERY_STOPPED);
Johan Hedberg56e5cb82011-11-08 20:40:16 +020065 hci_dev_unlock(hdev);
Marcel Holtmann6bd57412006-11-18 22:14:22 +010066
Johan Hedberg23bb5762010-12-21 23:01:27 +020067 hci_req_complete(hdev, HCI_OP_INQUIRY_CANCEL, status);
Marcel Holtmann6bd57412006-11-18 22:14:22 +010068
Marcel Holtmanna9de9242007-10-20 13:33:56 +020069 hci_conn_check_pending(hdev);
Linus Torvalds1da177e2005-04-16 15:20:36 -070070}
71
Marcel Holtmanna9de9242007-10-20 13:33:56 +020072static void hci_cc_exit_periodic_inq(struct hci_dev *hdev, struct sk_buff *skb)
Linus Torvalds1da177e2005-04-16 15:20:36 -070073{
Marcel Holtmanna9de9242007-10-20 13:33:56 +020074 __u8 status = *((__u8 *) skb->data);
75
76 BT_DBG("%s status 0x%x", hdev->name, status);
77
78 if (status)
79 return;
80
Marcel Holtmanna9de9242007-10-20 13:33:56 +020081 hci_conn_check_pending(hdev);
82}
83
84static void hci_cc_remote_name_req_cancel(struct hci_dev *hdev, struct sk_buff *skb)
85{
86 BT_DBG("%s", hdev->name);
87}
88
89static void hci_cc_role_discovery(struct hci_dev *hdev, struct sk_buff *skb)
90{
91 struct hci_rp_role_discovery *rp = (void *) skb->data;
Linus Torvalds1da177e2005-04-16 15:20:36 -070092 struct hci_conn *conn;
Linus Torvalds1da177e2005-04-16 15:20:36 -070093
Marcel Holtmanna9de9242007-10-20 13:33:56 +020094 BT_DBG("%s status 0x%x", hdev->name, rp->status);
Linus Torvalds1da177e2005-04-16 15:20:36 -070095
Marcel Holtmanna9de9242007-10-20 13:33:56 +020096 if (rp->status)
97 return;
Linus Torvalds1da177e2005-04-16 15:20:36 -070098
Marcel Holtmanna9de9242007-10-20 13:33:56 +020099 hci_dev_lock(hdev);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700100
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200101 conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(rp->handle));
102 if (conn) {
103 if (rp->role)
104 conn->link_mode &= ~HCI_LM_MASTER;
105 else
106 conn->link_mode |= HCI_LM_MASTER;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700107 }
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200108
109 hci_dev_unlock(hdev);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700110}
111
Marcel Holtmanne4e8e372008-07-14 20:13:47 +0200112static void hci_cc_read_link_policy(struct hci_dev *hdev, struct sk_buff *skb)
113{
114 struct hci_rp_read_link_policy *rp = (void *) skb->data;
115 struct hci_conn *conn;
116
117 BT_DBG("%s status 0x%x", hdev->name, rp->status);
118
119 if (rp->status)
120 return;
121
122 hci_dev_lock(hdev);
123
124 conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(rp->handle));
125 if (conn)
126 conn->link_policy = __le16_to_cpu(rp->policy);
127
128 hci_dev_unlock(hdev);
129}
130
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200131static void hci_cc_write_link_policy(struct hci_dev *hdev, struct sk_buff *skb)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700132{
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200133 struct hci_rp_write_link_policy *rp = (void *) skb->data;
134 struct hci_conn *conn;
135 void *sent;
136
137 BT_DBG("%s status 0x%x", hdev->name, rp->status);
138
139 if (rp->status)
140 return;
141
142 sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_LINK_POLICY);
143 if (!sent)
144 return;
145
146 hci_dev_lock(hdev);
147
148 conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(rp->handle));
Marcel Holtmanne4e8e372008-07-14 20:13:47 +0200149 if (conn)
Harvey Harrison83985312008-05-02 16:25:46 -0700150 conn->link_policy = get_unaligned_le16(sent + 2);
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200151
152 hci_dev_unlock(hdev);
153}
154
Marcel Holtmanne4e8e372008-07-14 20:13:47 +0200155static void hci_cc_read_def_link_policy(struct hci_dev *hdev, struct sk_buff *skb)
156{
157 struct hci_rp_read_def_link_policy *rp = (void *) skb->data;
158
159 BT_DBG("%s status 0x%x", hdev->name, rp->status);
160
161 if (rp->status)
162 return;
163
164 hdev->link_policy = __le16_to_cpu(rp->policy);
165}
166
167static void hci_cc_write_def_link_policy(struct hci_dev *hdev, struct sk_buff *skb)
168{
169 __u8 status = *((__u8 *) skb->data);
170 void *sent;
171
172 BT_DBG("%s status 0x%x", hdev->name, status);
173
174 sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_DEF_LINK_POLICY);
175 if (!sent)
176 return;
177
178 if (!status)
179 hdev->link_policy = get_unaligned_le16(sent);
180
Johan Hedberg23bb5762010-12-21 23:01:27 +0200181 hci_req_complete(hdev, HCI_OP_WRITE_DEF_LINK_POLICY, status);
Marcel Holtmanne4e8e372008-07-14 20:13:47 +0200182}
183
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200184static void hci_cc_reset(struct hci_dev *hdev, struct sk_buff *skb)
185{
186 __u8 status = *((__u8 *) skb->data);
187
188 BT_DBG("%s status 0x%x", hdev->name, status);
189
Gustavo F. Padovan10572132011-03-16 15:36:29 -0300190 clear_bit(HCI_RESET, &hdev->flags);
191
Johan Hedberg23bb5762010-12-21 23:01:27 +0200192 hci_req_complete(hdev, HCI_OP_RESET, status);
Andre Guedesd23264a2011-11-25 20:53:38 -0300193
Johan Hedberga297e972012-02-21 17:55:47 +0200194 /* Reset all non-persistent flags */
Johan Hedberg9f8ce962012-03-02 03:06:04 +0200195 hdev->dev_flags &= ~(BIT(HCI_LE_SCAN) | BIT(HCI_PENDING_CLASS));
Andre Guedes69775ff2012-02-23 16:50:05 +0200196
197 hdev->discovery.state = DISCOVERY_STOPPED;
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200198}
199
200static void hci_cc_write_local_name(struct hci_dev *hdev, struct sk_buff *skb)
201{
202 __u8 status = *((__u8 *) skb->data);
203 void *sent;
204
205 BT_DBG("%s status 0x%x", hdev->name, status);
206
207 sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_LOCAL_NAME);
208 if (!sent)
209 return;
210
Johan Hedberg56e5cb82011-11-08 20:40:16 +0200211 hci_dev_lock(hdev);
212
Johan Hedbergf51d5b22012-02-22 18:17:32 +0200213 if (test_bit(HCI_MGMT, &hdev->dev_flags))
214 mgmt_set_local_name_complete(hdev, sent, status);
Johan Hedberg28cc7bd2012-02-22 21:06:55 +0200215 else if (!status)
216 memcpy(hdev->dev_name, sent, HCI_MAX_NAME_LENGTH);
Johan Hedbergf51d5b22012-02-22 18:17:32 +0200217
Johan Hedberg56e5cb82011-11-08 20:40:16 +0200218 hci_dev_unlock(hdev);
Johan Hedberg3159d382012-02-24 13:47:56 +0200219
220 hci_req_complete(hdev, HCI_OP_WRITE_LOCAL_NAME, status);
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200221}
222
223static void hci_cc_read_local_name(struct hci_dev *hdev, struct sk_buff *skb)
224{
225 struct hci_rp_read_local_name *rp = (void *) skb->data;
226
227 BT_DBG("%s status 0x%x", hdev->name, rp->status);
228
229 if (rp->status)
230 return;
231
Johan Hedbergdb99b5f2012-02-22 20:14:22 +0200232 if (test_bit(HCI_SETUP, &hdev->dev_flags))
233 memcpy(hdev->dev_name, rp->name, HCI_MAX_NAME_LENGTH);
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200234}
235
236static void hci_cc_write_auth_enable(struct hci_dev *hdev, struct sk_buff *skb)
237{
238 __u8 status = *((__u8 *) skb->data);
239 void *sent;
240
241 BT_DBG("%s status 0x%x", hdev->name, status);
242
243 sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_AUTH_ENABLE);
244 if (!sent)
245 return;
246
247 if (!status) {
248 __u8 param = *((__u8 *) sent);
249
250 if (param == AUTH_ENABLED)
251 set_bit(HCI_AUTH, &hdev->flags);
252 else
253 clear_bit(HCI_AUTH, &hdev->flags);
254 }
255
Johan Hedberg33ef95e2012-02-16 23:56:27 +0200256 if (test_bit(HCI_MGMT, &hdev->dev_flags))
257 mgmt_auth_enable_complete(hdev, status);
258
Johan Hedberg23bb5762010-12-21 23:01:27 +0200259 hci_req_complete(hdev, HCI_OP_WRITE_AUTH_ENABLE, status);
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200260}
261
262static void hci_cc_write_encrypt_mode(struct hci_dev *hdev, struct sk_buff *skb)
263{
264 __u8 status = *((__u8 *) skb->data);
265 void *sent;
266
267 BT_DBG("%s status 0x%x", hdev->name, status);
268
269 sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_ENCRYPT_MODE);
270 if (!sent)
271 return;
272
273 if (!status) {
274 __u8 param = *((__u8 *) sent);
275
276 if (param)
277 set_bit(HCI_ENCRYPT, &hdev->flags);
278 else
279 clear_bit(HCI_ENCRYPT, &hdev->flags);
280 }
281
Johan Hedberg23bb5762010-12-21 23:01:27 +0200282 hci_req_complete(hdev, HCI_OP_WRITE_ENCRYPT_MODE, status);
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200283}
284
285static void hci_cc_write_scan_enable(struct hci_dev *hdev, struct sk_buff *skb)
286{
Johan Hedberg36f7fc72011-11-04 00:17:45 +0200287 __u8 param, status = *((__u8 *) skb->data);
288 int old_pscan, old_iscan;
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200289 void *sent;
290
291 BT_DBG("%s status 0x%x", hdev->name, status);
292
293 sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_SCAN_ENABLE);
294 if (!sent)
295 return;
296
Johan Hedberg36f7fc72011-11-04 00:17:45 +0200297 param = *((__u8 *) sent);
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200298
Johan Hedberg56e5cb82011-11-08 20:40:16 +0200299 hci_dev_lock(hdev);
300
Johan Hedberg2d7cee52011-11-07 22:16:03 +0200301 if (status != 0) {
Johan Hedberg744cf192011-11-08 20:40:14 +0200302 mgmt_write_scan_failed(hdev, param, status);
Johan Hedberg2d7cee52011-11-07 22:16:03 +0200303 hdev->discov_timeout = 0;
304 goto done;
305 }
306
Johan Hedberg36f7fc72011-11-04 00:17:45 +0200307 old_pscan = test_and_clear_bit(HCI_PSCAN, &hdev->flags);
308 old_iscan = test_and_clear_bit(HCI_ISCAN, &hdev->flags);
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200309
Johan Hedberg36f7fc72011-11-04 00:17:45 +0200310 if (param & SCAN_INQUIRY) {
311 set_bit(HCI_ISCAN, &hdev->flags);
312 if (!old_iscan)
Johan Hedberg744cf192011-11-08 20:40:14 +0200313 mgmt_discoverable(hdev, 1);
Johan Hedberg16ab91a2011-11-07 22:16:02 +0200314 if (hdev->discov_timeout > 0) {
315 int to = msecs_to_jiffies(hdev->discov_timeout * 1000);
316 queue_delayed_work(hdev->workqueue, &hdev->discov_off,
317 to);
318 }
Johan Hedberg36f7fc72011-11-04 00:17:45 +0200319 } else if (old_iscan)
Johan Hedberg744cf192011-11-08 20:40:14 +0200320 mgmt_discoverable(hdev, 0);
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200321
Johan Hedberg36f7fc72011-11-04 00:17:45 +0200322 if (param & SCAN_PAGE) {
323 set_bit(HCI_PSCAN, &hdev->flags);
324 if (!old_pscan)
Johan Hedberg744cf192011-11-08 20:40:14 +0200325 mgmt_connectable(hdev, 1);
Johan Hedberg36f7fc72011-11-04 00:17:45 +0200326 } else if (old_pscan)
Johan Hedberg744cf192011-11-08 20:40:14 +0200327 mgmt_connectable(hdev, 0);
Johan Hedberg36f7fc72011-11-04 00:17:45 +0200328
329done:
Johan Hedberg56e5cb82011-11-08 20:40:16 +0200330 hci_dev_unlock(hdev);
Johan Hedberg23bb5762010-12-21 23:01:27 +0200331 hci_req_complete(hdev, HCI_OP_WRITE_SCAN_ENABLE, status);
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200332}
333
334static void hci_cc_read_class_of_dev(struct hci_dev *hdev, struct sk_buff *skb)
335{
336 struct hci_rp_read_class_of_dev *rp = (void *) skb->data;
337
338 BT_DBG("%s status 0x%x", hdev->name, rp->status);
339
340 if (rp->status)
341 return;
342
343 memcpy(hdev->dev_class, rp->dev_class, 3);
344
345 BT_DBG("%s class 0x%.2x%.2x%.2x", hdev->name,
346 hdev->dev_class[2], hdev->dev_class[1], hdev->dev_class[0]);
347}
348
349static void hci_cc_write_class_of_dev(struct hci_dev *hdev, struct sk_buff *skb)
350{
351 __u8 status = *((__u8 *) skb->data);
352 void *sent;
353
354 BT_DBG("%s status 0x%x", hdev->name, status);
355
356 sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_CLASS_OF_DEV);
357 if (!sent)
358 return;
359
Marcel Holtmann7f9a9032012-02-22 18:38:01 +0100360 hci_dev_lock(hdev);
361
362 if (status == 0)
363 memcpy(hdev->dev_class, sent, 3);
364
365 if (test_bit(HCI_MGMT, &hdev->dev_flags))
366 mgmt_set_class_of_dev_complete(hdev, sent, status);
367
368 hci_dev_unlock(hdev);
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200369}
370
371static void hci_cc_read_voice_setting(struct hci_dev *hdev, struct sk_buff *skb)
372{
373 struct hci_rp_read_voice_setting *rp = (void *) skb->data;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700374 __u16 setting;
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200375
376 BT_DBG("%s status 0x%x", hdev->name, rp->status);
377
378 if (rp->status)
379 return;
380
381 setting = __le16_to_cpu(rp->voice_setting);
382
Marcel Holtmannf383f272008-07-14 20:13:47 +0200383 if (hdev->voice_setting == setting)
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200384 return;
385
386 hdev->voice_setting = setting;
387
388 BT_DBG("%s voice setting 0x%04x", hdev->name, setting);
389
Gustavo F. Padovan3c547112011-12-14 22:58:44 -0200390 if (hdev->notify)
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200391 hdev->notify(hdev, HCI_NOTIFY_VOICE_SETTING);
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200392}
393
394static void hci_cc_write_voice_setting(struct hci_dev *hdev, struct sk_buff *skb)
395{
396 __u8 status = *((__u8 *) skb->data);
Marcel Holtmannf383f272008-07-14 20:13:47 +0200397 __u16 setting;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700398 void *sent;
399
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200400 BT_DBG("%s status 0x%x", hdev->name, status);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700401
Marcel Holtmannf383f272008-07-14 20:13:47 +0200402 if (status)
403 return;
404
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200405 sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_VOICE_SETTING);
406 if (!sent)
407 return;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700408
Marcel Holtmannf383f272008-07-14 20:13:47 +0200409 setting = get_unaligned_le16(sent);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700410
Marcel Holtmannf383f272008-07-14 20:13:47 +0200411 if (hdev->voice_setting == setting)
412 return;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700413
Marcel Holtmannf383f272008-07-14 20:13:47 +0200414 hdev->voice_setting = setting;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700415
Marcel Holtmannf383f272008-07-14 20:13:47 +0200416 BT_DBG("%s voice setting 0x%04x", hdev->name, setting);
417
Gustavo F. Padovan3c547112011-12-14 22:58:44 -0200418 if (hdev->notify)
Marcel Holtmannf383f272008-07-14 20:13:47 +0200419 hdev->notify(hdev, HCI_NOTIFY_VOICE_SETTING);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700420}
421
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200422static void hci_cc_host_buffer_size(struct hci_dev *hdev, struct sk_buff *skb)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700423{
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200424 __u8 status = *((__u8 *) skb->data);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700425
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200426 BT_DBG("%s status 0x%x", hdev->name, status);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700427
Johan Hedberg23bb5762010-12-21 23:01:27 +0200428 hci_req_complete(hdev, HCI_OP_HOST_BUFFER_SIZE, status);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700429}
430
Marcel Holtmann333140b2008-07-14 20:13:48 +0200431static void hci_cc_write_ssp_mode(struct hci_dev *hdev, struct sk_buff *skb)
432{
433 __u8 status = *((__u8 *) skb->data);
434 void *sent;
435
436 BT_DBG("%s status 0x%x", hdev->name, status);
437
Marcel Holtmann333140b2008-07-14 20:13:48 +0200438 sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_SSP_MODE);
439 if (!sent)
440 return;
441
Johan Hedberged2c4ee2012-02-17 00:56:28 +0200442 if (test_bit(HCI_MGMT, &hdev->dev_flags))
Johan Hedbergc0ecddc2012-02-22 12:38:31 +0200443 mgmt_ssp_enable_complete(hdev, *((u8 *) sent), status);
444 else if (!status) {
445 if (*((u8 *) sent))
446 set_bit(HCI_SSP_ENABLED, &hdev->dev_flags);
447 else
448 clear_bit(HCI_SSP_ENABLED, &hdev->dev_flags);
449 }
Marcel Holtmann333140b2008-07-14 20:13:48 +0200450}
451
Johan Hedbergd5859e22011-01-25 01:19:58 +0200452static u8 hci_get_inquiry_mode(struct hci_dev *hdev)
453{
454 if (hdev->features[6] & LMP_EXT_INQ)
455 return 2;
456
457 if (hdev->features[3] & LMP_RSSI_INQ)
458 return 1;
459
460 if (hdev->manufacturer == 11 && hdev->hci_rev == 0x00 &&
461 hdev->lmp_subver == 0x0757)
462 return 1;
463
464 if (hdev->manufacturer == 15) {
465 if (hdev->hci_rev == 0x03 && hdev->lmp_subver == 0x6963)
466 return 1;
467 if (hdev->hci_rev == 0x09 && hdev->lmp_subver == 0x6963)
468 return 1;
469 if (hdev->hci_rev == 0x00 && hdev->lmp_subver == 0x6965)
470 return 1;
471 }
472
473 if (hdev->manufacturer == 31 && hdev->hci_rev == 0x2005 &&
474 hdev->lmp_subver == 0x1805)
475 return 1;
476
477 return 0;
478}
479
480static void hci_setup_inquiry_mode(struct hci_dev *hdev)
481{
482 u8 mode;
483
484 mode = hci_get_inquiry_mode(hdev);
485
486 hci_send_cmd(hdev, HCI_OP_WRITE_INQUIRY_MODE, 1, &mode);
487}
488
489static void hci_setup_event_mask(struct hci_dev *hdev)
490{
491 /* The second byte is 0xff instead of 0x9f (two reserved bits
492 * disabled) since a Broadcom 1.2 dongle doesn't respond to the
493 * command otherwise */
494 u8 events[8] = { 0xff, 0xff, 0xfb, 0xff, 0x00, 0x00, 0x00, 0x00 };
495
Ville Tervo6de6c182011-05-27 11:16:21 +0300496 /* CSR 1.1 dongles does not accept any bitfield so don't try to set
497 * any event mask for pre 1.2 devices */
Andrei Emeltchenko5a13b092011-12-01 14:33:28 +0200498 if (hdev->hci_ver < BLUETOOTH_VER_1_2)
Ville Tervo6de6c182011-05-27 11:16:21 +0300499 return;
500
501 events[4] |= 0x01; /* Flow Specification Complete */
502 events[4] |= 0x02; /* Inquiry Result with RSSI */
503 events[4] |= 0x04; /* Read Remote Extended Features Complete */
504 events[5] |= 0x08; /* Synchronous Connection Complete */
505 events[5] |= 0x10; /* Synchronous Connection Changed */
Johan Hedbergd5859e22011-01-25 01:19:58 +0200506
507 if (hdev->features[3] & LMP_RSSI_INQ)
508 events[4] |= 0x04; /* Inquiry Result with RSSI */
509
510 if (hdev->features[5] & LMP_SNIFF_SUBR)
511 events[5] |= 0x20; /* Sniff Subrating */
512
513 if (hdev->features[5] & LMP_PAUSE_ENC)
514 events[5] |= 0x80; /* Encryption Key Refresh Complete */
515
516 if (hdev->features[6] & LMP_EXT_INQ)
517 events[5] |= 0x40; /* Extended Inquiry Result */
518
519 if (hdev->features[6] & LMP_NO_FLUSH)
520 events[7] |= 0x01; /* Enhanced Flush Complete */
521
522 if (hdev->features[7] & LMP_LSTO)
523 events[6] |= 0x80; /* Link Supervision Timeout Changed */
524
525 if (hdev->features[6] & LMP_SIMPLE_PAIR) {
526 events[6] |= 0x01; /* IO Capability Request */
527 events[6] |= 0x02; /* IO Capability Response */
528 events[6] |= 0x04; /* User Confirmation Request */
529 events[6] |= 0x08; /* User Passkey Request */
530 events[6] |= 0x10; /* Remote OOB Data Request */
531 events[6] |= 0x20; /* Simple Pairing Complete */
532 events[7] |= 0x04; /* User Passkey Notification */
533 events[7] |= 0x08; /* Keypress Notification */
534 events[7] |= 0x10; /* Remote Host Supported
535 * Features Notification */
536 }
537
538 if (hdev->features[4] & LMP_LE)
539 events[7] |= 0x20; /* LE Meta-Event */
540
541 hci_send_cmd(hdev, HCI_OP_SET_EVENT_MASK, sizeof(events), events);
542}
543
544static void hci_setup(struct hci_dev *hdev)
545{
Andrei Emeltchenkoe61ef4992011-12-19 16:31:27 +0200546 if (hdev->dev_type != HCI_BREDR)
547 return;
548
Johan Hedbergd5859e22011-01-25 01:19:58 +0200549 hci_setup_event_mask(hdev);
550
Andrei Emeltchenkod095c1e2011-12-01 14:33:27 +0200551 if (hdev->hci_ver > BLUETOOTH_VER_1_1)
Johan Hedbergd5859e22011-01-25 01:19:58 +0200552 hci_send_cmd(hdev, HCI_OP_READ_LOCAL_COMMANDS, 0, NULL);
553
Johan Hedberg54d04db2012-02-22 15:47:48 +0200554 if (hdev->features[6] & LMP_SIMPLE_PAIR) {
555 if (test_bit(HCI_SSP_ENABLED, &hdev->dev_flags)) {
556 u8 mode = 0x01;
557 hci_send_cmd(hdev, HCI_OP_WRITE_SSP_MODE,
Gustavo F. Padovan04124682012-03-08 01:25:00 -0300558 sizeof(mode), &mode);
Johan Hedberg54d04db2012-02-22 15:47:48 +0200559 } else {
560 struct hci_cp_write_eir cp;
561
562 memset(hdev->eir, 0, sizeof(hdev->eir));
563 memset(&cp, 0, sizeof(cp));
564
565 hci_send_cmd(hdev, HCI_OP_WRITE_EIR, sizeof(cp), &cp);
566 }
Johan Hedbergd5859e22011-01-25 01:19:58 +0200567 }
568
569 if (hdev->features[3] & LMP_RSSI_INQ)
570 hci_setup_inquiry_mode(hdev);
571
572 if (hdev->features[7] & LMP_INQ_TX_PWR)
573 hci_send_cmd(hdev, HCI_OP_READ_INQ_RSP_TX_POWER, 0, NULL);
Andre Guedes971e3a42011-06-30 19:20:52 -0300574
575 if (hdev->features[7] & LMP_EXTFEATURES) {
576 struct hci_cp_read_local_ext_features cp;
577
578 cp.page = 0x01;
Gustavo F. Padovan04124682012-03-08 01:25:00 -0300579 hci_send_cmd(hdev, HCI_OP_READ_LOCAL_EXT_FEATURES, sizeof(cp),
580 &cp);
Andre Guedes971e3a42011-06-30 19:20:52 -0300581 }
Andre Guedese6100a22011-06-30 19:20:54 -0300582
Johan Hedberg47990ea2012-02-22 11:58:37 +0200583 if (test_bit(HCI_LINK_SECURITY, &hdev->dev_flags)) {
584 u8 enable = 1;
Gustavo F. Padovan04124682012-03-08 01:25:00 -0300585 hci_send_cmd(hdev, HCI_OP_WRITE_AUTH_ENABLE, sizeof(enable),
586 &enable);
Johan Hedberg47990ea2012-02-22 11:58:37 +0200587 }
Johan Hedbergd5859e22011-01-25 01:19:58 +0200588}
589
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200590static void hci_cc_read_local_version(struct hci_dev *hdev, struct sk_buff *skb)
591{
592 struct hci_rp_read_local_version *rp = (void *) skb->data;
593
594 BT_DBG("%s status 0x%x", hdev->name, rp->status);
595
596 if (rp->status)
Andrei Emeltchenko28b8df72012-02-24 12:45:44 +0200597 goto done;
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200598
599 hdev->hci_ver = rp->hci_ver;
Marcel Holtmanne4e8e372008-07-14 20:13:47 +0200600 hdev->hci_rev = __le16_to_cpu(rp->hci_rev);
Johan Hedbergd5859e22011-01-25 01:19:58 +0200601 hdev->lmp_ver = rp->lmp_ver;
Marcel Holtmanne4e8e372008-07-14 20:13:47 +0200602 hdev->manufacturer = __le16_to_cpu(rp->manufacturer);
Johan Hedbergd5859e22011-01-25 01:19:58 +0200603 hdev->lmp_subver = __le16_to_cpu(rp->lmp_subver);
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200604
605 BT_DBG("%s manufacturer %d hci ver %d:%d", hdev->name,
606 hdev->manufacturer,
607 hdev->hci_ver, hdev->hci_rev);
Johan Hedbergd5859e22011-01-25 01:19:58 +0200608
609 if (test_bit(HCI_INIT, &hdev->flags))
610 hci_setup(hdev);
Andrei Emeltchenko28b8df72012-02-24 12:45:44 +0200611
612done:
613 hci_req_complete(hdev, HCI_OP_READ_LOCAL_VERSION, rp->status);
Johan Hedbergd5859e22011-01-25 01:19:58 +0200614}
615
616static void hci_setup_link_policy(struct hci_dev *hdev)
617{
Andrei Emeltchenko035100c2012-03-12 15:59:32 +0200618 struct hci_cp_write_def_link_policy cp;
Johan Hedbergd5859e22011-01-25 01:19:58 +0200619 u16 link_policy = 0;
620
621 if (hdev->features[0] & LMP_RSWITCH)
622 link_policy |= HCI_LP_RSWITCH;
623 if (hdev->features[0] & LMP_HOLD)
624 link_policy |= HCI_LP_HOLD;
625 if (hdev->features[0] & LMP_SNIFF)
626 link_policy |= HCI_LP_SNIFF;
627 if (hdev->features[1] & LMP_PARK)
628 link_policy |= HCI_LP_PARK;
629
Andrei Emeltchenko035100c2012-03-12 15:59:32 +0200630 cp.policy = cpu_to_le16(link_policy);
631 hci_send_cmd(hdev, HCI_OP_WRITE_DEF_LINK_POLICY, sizeof(cp), &cp);
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200632}
633
634static void hci_cc_read_local_commands(struct hci_dev *hdev, struct sk_buff *skb)
635{
636 struct hci_rp_read_local_commands *rp = (void *) skb->data;
637
638 BT_DBG("%s status 0x%x", hdev->name, rp->status);
639
640 if (rp->status)
Johan Hedbergd5859e22011-01-25 01:19:58 +0200641 goto done;
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200642
643 memcpy(hdev->commands, rp->commands, sizeof(hdev->commands));
Johan Hedbergd5859e22011-01-25 01:19:58 +0200644
645 if (test_bit(HCI_INIT, &hdev->flags) && (hdev->commands[5] & 0x10))
646 hci_setup_link_policy(hdev);
647
648done:
649 hci_req_complete(hdev, HCI_OP_READ_LOCAL_COMMANDS, rp->status);
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200650}
651
652static void hci_cc_read_local_features(struct hci_dev *hdev, struct sk_buff *skb)
653{
654 struct hci_rp_read_local_features *rp = (void *) skb->data;
655
656 BT_DBG("%s status 0x%x", hdev->name, rp->status);
657
658 if (rp->status)
659 return;
660
661 memcpy(hdev->features, rp->features, 8);
662
663 /* Adjust default settings according to features
664 * supported by device. */
665
666 if (hdev->features[0] & LMP_3SLOT)
667 hdev->pkt_type |= (HCI_DM3 | HCI_DH3);
668
669 if (hdev->features[0] & LMP_5SLOT)
670 hdev->pkt_type |= (HCI_DM5 | HCI_DH5);
671
672 if (hdev->features[1] & LMP_HV2) {
673 hdev->pkt_type |= (HCI_HV2);
674 hdev->esco_type |= (ESCO_HV2);
675 }
676
677 if (hdev->features[1] & LMP_HV3) {
678 hdev->pkt_type |= (HCI_HV3);
679 hdev->esco_type |= (ESCO_HV3);
680 }
681
682 if (hdev->features[3] & LMP_ESCO)
683 hdev->esco_type |= (ESCO_EV3);
684
685 if (hdev->features[4] & LMP_EV4)
686 hdev->esco_type |= (ESCO_EV4);
687
688 if (hdev->features[4] & LMP_EV5)
689 hdev->esco_type |= (ESCO_EV5);
690
Marcel Holtmannefc76882009-02-06 09:13:37 +0100691 if (hdev->features[5] & LMP_EDR_ESCO_2M)
692 hdev->esco_type |= (ESCO_2EV3);
693
694 if (hdev->features[5] & LMP_EDR_ESCO_3M)
695 hdev->esco_type |= (ESCO_3EV3);
696
697 if (hdev->features[5] & LMP_EDR_3S_ESCO)
698 hdev->esco_type |= (ESCO_2EV5 | ESCO_3EV5);
699
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200700 BT_DBG("%s features 0x%.2x%.2x%.2x%.2x%.2x%.2x%.2x%.2x", hdev->name,
701 hdev->features[0], hdev->features[1],
702 hdev->features[2], hdev->features[3],
703 hdev->features[4], hdev->features[5],
704 hdev->features[6], hdev->features[7]);
705}
706
Johan Hedberg8f984df2012-02-28 01:07:22 +0200707static void hci_set_le_support(struct hci_dev *hdev)
708{
709 struct hci_cp_write_le_host_supported cp;
710
711 memset(&cp, 0, sizeof(cp));
712
713 if (enable_le && test_bit(HCI_LE_ENABLED, &hdev->dev_flags)) {
714 cp.le = 1;
715 cp.simul = !!(hdev->features[6] & LMP_SIMUL_LE_BR);
716 }
717
718 if (cp.le != !!(hdev->host_features[0] & LMP_HOST_LE))
Gustavo F. Padovan04124682012-03-08 01:25:00 -0300719 hci_send_cmd(hdev, HCI_OP_WRITE_LE_HOST_SUPPORTED, sizeof(cp),
720 &cp);
Johan Hedberg8f984df2012-02-28 01:07:22 +0200721}
722
Andre Guedes971e3a42011-06-30 19:20:52 -0300723static void hci_cc_read_local_ext_features(struct hci_dev *hdev,
724 struct sk_buff *skb)
725{
726 struct hci_rp_read_local_ext_features *rp = (void *) skb->data;
727
728 BT_DBG("%s status 0x%x", hdev->name, rp->status);
729
730 if (rp->status)
Johan Hedberg8f984df2012-02-28 01:07:22 +0200731 goto done;
Andre Guedes971e3a42011-06-30 19:20:52 -0300732
Andre Guedesb5b32b62011-12-30 10:34:04 -0300733 switch (rp->page) {
734 case 0:
735 memcpy(hdev->features, rp->features, 8);
736 break;
737 case 1:
738 memcpy(hdev->host_features, rp->features, 8);
739 break;
740 }
Andre Guedes971e3a42011-06-30 19:20:52 -0300741
Johan Hedberg8f984df2012-02-28 01:07:22 +0200742 if (test_bit(HCI_INIT, &hdev->flags) && hdev->features[4] & LMP_LE)
743 hci_set_le_support(hdev);
744
745done:
Andre Guedes971e3a42011-06-30 19:20:52 -0300746 hci_req_complete(hdev, HCI_OP_READ_LOCAL_EXT_FEATURES, rp->status);
747}
748
Andrei Emeltchenko1e89cff2011-11-24 14:52:02 +0200749static void hci_cc_read_flow_control_mode(struct hci_dev *hdev,
750 struct sk_buff *skb)
751{
752 struct hci_rp_read_flow_control_mode *rp = (void *) skb->data;
753
754 BT_DBG("%s status 0x%x", hdev->name, rp->status);
755
756 if (rp->status)
757 return;
758
759 hdev->flow_ctl_mode = rp->mode;
760
761 hci_req_complete(hdev, HCI_OP_READ_FLOW_CONTROL_MODE, rp->status);
762}
763
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200764static void hci_cc_read_buffer_size(struct hci_dev *hdev, struct sk_buff *skb)
765{
766 struct hci_rp_read_buffer_size *rp = (void *) skb->data;
767
768 BT_DBG("%s status 0x%x", hdev->name, rp->status);
769
770 if (rp->status)
771 return;
772
773 hdev->acl_mtu = __le16_to_cpu(rp->acl_mtu);
774 hdev->sco_mtu = rp->sco_mtu;
775 hdev->acl_pkts = __le16_to_cpu(rp->acl_max_pkt);
776 hdev->sco_pkts = __le16_to_cpu(rp->sco_max_pkt);
777
778 if (test_bit(HCI_QUIRK_FIXUP_BUFFER_SIZE, &hdev->quirks)) {
779 hdev->sco_mtu = 64;
780 hdev->sco_pkts = 8;
781 }
782
783 hdev->acl_cnt = hdev->acl_pkts;
784 hdev->sco_cnt = hdev->sco_pkts;
785
786 BT_DBG("%s acl mtu %d:%d sco mtu %d:%d", hdev->name,
787 hdev->acl_mtu, hdev->acl_pkts,
788 hdev->sco_mtu, hdev->sco_pkts);
789}
790
791static void hci_cc_read_bd_addr(struct hci_dev *hdev, struct sk_buff *skb)
792{
793 struct hci_rp_read_bd_addr *rp = (void *) skb->data;
794
795 BT_DBG("%s status 0x%x", hdev->name, rp->status);
796
797 if (!rp->status)
798 bacpy(&hdev->bdaddr, &rp->bdaddr);
799
Johan Hedberg23bb5762010-12-21 23:01:27 +0200800 hci_req_complete(hdev, HCI_OP_READ_BD_ADDR, rp->status);
801}
802
Andrei Emeltchenko350ee4c2011-12-07 15:56:51 +0200803static void hci_cc_read_data_block_size(struct hci_dev *hdev,
804 struct sk_buff *skb)
805{
806 struct hci_rp_read_data_block_size *rp = (void *) skb->data;
807
808 BT_DBG("%s status 0x%x", hdev->name, rp->status);
809
810 if (rp->status)
811 return;
812
813 hdev->block_mtu = __le16_to_cpu(rp->max_acl_len);
814 hdev->block_len = __le16_to_cpu(rp->block_len);
815 hdev->num_blocks = __le16_to_cpu(rp->num_blocks);
816
817 hdev->block_cnt = hdev->num_blocks;
818
819 BT_DBG("%s blk mtu %d cnt %d len %d", hdev->name, hdev->block_mtu,
820 hdev->block_cnt, hdev->block_len);
821
822 hci_req_complete(hdev, HCI_OP_READ_DATA_BLOCK_SIZE, rp->status);
823}
824
Johan Hedberg23bb5762010-12-21 23:01:27 +0200825static void hci_cc_write_ca_timeout(struct hci_dev *hdev, struct sk_buff *skb)
826{
827 __u8 status = *((__u8 *) skb->data);
828
829 BT_DBG("%s status 0x%x", hdev->name, status);
830
831 hci_req_complete(hdev, HCI_OP_WRITE_CA_TIMEOUT, status);
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200832}
833
Andrei Emeltchenko928abaa2011-10-12 10:53:57 +0300834static void hci_cc_read_local_amp_info(struct hci_dev *hdev,
835 struct sk_buff *skb)
836{
837 struct hci_rp_read_local_amp_info *rp = (void *) skb->data;
838
839 BT_DBG("%s status 0x%x", hdev->name, rp->status);
840
841 if (rp->status)
842 return;
843
844 hdev->amp_status = rp->amp_status;
845 hdev->amp_total_bw = __le32_to_cpu(rp->total_bw);
846 hdev->amp_max_bw = __le32_to_cpu(rp->max_bw);
847 hdev->amp_min_latency = __le32_to_cpu(rp->min_latency);
848 hdev->amp_max_pdu = __le32_to_cpu(rp->max_pdu);
849 hdev->amp_type = rp->amp_type;
850 hdev->amp_pal_cap = __le16_to_cpu(rp->pal_cap);
851 hdev->amp_assoc_size = __le16_to_cpu(rp->max_assoc_size);
852 hdev->amp_be_flush_to = __le32_to_cpu(rp->be_flush_to);
853 hdev->amp_max_flush_to = __le32_to_cpu(rp->max_flush_to);
854
855 hci_req_complete(hdev, HCI_OP_READ_LOCAL_AMP_INFO, rp->status);
856}
857
Johan Hedbergb0916ea2011-01-10 13:44:55 +0200858static void hci_cc_delete_stored_link_key(struct hci_dev *hdev,
859 struct sk_buff *skb)
860{
861 __u8 status = *((__u8 *) skb->data);
862
863 BT_DBG("%s status 0x%x", hdev->name, status);
864
865 hci_req_complete(hdev, HCI_OP_DELETE_STORED_LINK_KEY, status);
866}
867
Johan Hedbergd5859e22011-01-25 01:19:58 +0200868static void hci_cc_set_event_mask(struct hci_dev *hdev, struct sk_buff *skb)
869{
870 __u8 status = *((__u8 *) skb->data);
871
872 BT_DBG("%s status 0x%x", hdev->name, status);
873
874 hci_req_complete(hdev, HCI_OP_SET_EVENT_MASK, status);
875}
876
877static void hci_cc_write_inquiry_mode(struct hci_dev *hdev,
878 struct sk_buff *skb)
879{
880 __u8 status = *((__u8 *) skb->data);
881
882 BT_DBG("%s status 0x%x", hdev->name, status);
883
884 hci_req_complete(hdev, HCI_OP_WRITE_INQUIRY_MODE, status);
885}
886
887static void hci_cc_read_inq_rsp_tx_power(struct hci_dev *hdev,
888 struct sk_buff *skb)
889{
Marcel Holtmann91c4e9b2012-03-11 19:27:21 -0700890 struct hci_rp_read_inq_rsp_tx_power *rp = (void *) skb->data;
Johan Hedbergd5859e22011-01-25 01:19:58 +0200891
Marcel Holtmann91c4e9b2012-03-11 19:27:21 -0700892 BT_DBG("%s status 0x%x", hdev->name, rp->status);
Johan Hedbergd5859e22011-01-25 01:19:58 +0200893
Marcel Holtmann91c4e9b2012-03-11 19:27:21 -0700894 if (!rp->status)
895 hdev->inq_tx_power = rp->tx_power;
896
897 hci_req_complete(hdev, HCI_OP_READ_INQ_RSP_TX_POWER, rp->status);
Johan Hedbergd5859e22011-01-25 01:19:58 +0200898}
899
900static void hci_cc_set_event_flt(struct hci_dev *hdev, struct sk_buff *skb)
901{
902 __u8 status = *((__u8 *) skb->data);
903
904 BT_DBG("%s status 0x%x", hdev->name, status);
905
906 hci_req_complete(hdev, HCI_OP_SET_EVENT_FLT, status);
907}
908
Johan Hedberg980e1a52011-01-22 06:10:07 +0200909static void hci_cc_pin_code_reply(struct hci_dev *hdev, struct sk_buff *skb)
910{
911 struct hci_rp_pin_code_reply *rp = (void *) skb->data;
912 struct hci_cp_pin_code_reply *cp;
913 struct hci_conn *conn;
914
915 BT_DBG("%s status 0x%x", hdev->name, rp->status);
916
Johan Hedberg56e5cb82011-11-08 20:40:16 +0200917 hci_dev_lock(hdev);
918
Johan Hedberga8b2d5c2012-01-08 23:11:15 +0200919 if (test_bit(HCI_MGMT, &hdev->dev_flags))
Johan Hedberg744cf192011-11-08 20:40:14 +0200920 mgmt_pin_code_reply_complete(hdev, &rp->bdaddr, rp->status);
Johan Hedberg980e1a52011-01-22 06:10:07 +0200921
922 if (rp->status != 0)
Johan Hedberg56e5cb82011-11-08 20:40:16 +0200923 goto unlock;
Johan Hedberg980e1a52011-01-22 06:10:07 +0200924
925 cp = hci_sent_cmd_data(hdev, HCI_OP_PIN_CODE_REPLY);
926 if (!cp)
Johan Hedberg56e5cb82011-11-08 20:40:16 +0200927 goto unlock;
Johan Hedberg980e1a52011-01-22 06:10:07 +0200928
929 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &cp->bdaddr);
930 if (conn)
931 conn->pin_length = cp->pin_len;
Johan Hedberg56e5cb82011-11-08 20:40:16 +0200932
933unlock:
934 hci_dev_unlock(hdev);
Johan Hedberg980e1a52011-01-22 06:10:07 +0200935}
936
937static void hci_cc_pin_code_neg_reply(struct hci_dev *hdev, struct sk_buff *skb)
938{
939 struct hci_rp_pin_code_neg_reply *rp = (void *) skb->data;
940
941 BT_DBG("%s status 0x%x", hdev->name, rp->status);
942
Johan Hedberg56e5cb82011-11-08 20:40:16 +0200943 hci_dev_lock(hdev);
944
Johan Hedberga8b2d5c2012-01-08 23:11:15 +0200945 if (test_bit(HCI_MGMT, &hdev->dev_flags))
Johan Hedberg744cf192011-11-08 20:40:14 +0200946 mgmt_pin_code_neg_reply_complete(hdev, &rp->bdaddr,
Johan Hedberg980e1a52011-01-22 06:10:07 +0200947 rp->status);
Johan Hedberg56e5cb82011-11-08 20:40:16 +0200948
949 hci_dev_unlock(hdev);
Johan Hedberg980e1a52011-01-22 06:10:07 +0200950}
Johan Hedberg56e5cb82011-11-08 20:40:16 +0200951
Ville Tervo6ed58ec2011-02-10 22:38:48 -0300952static void hci_cc_le_read_buffer_size(struct hci_dev *hdev,
953 struct sk_buff *skb)
954{
955 struct hci_rp_le_read_buffer_size *rp = (void *) skb->data;
956
957 BT_DBG("%s status 0x%x", hdev->name, rp->status);
958
959 if (rp->status)
960 return;
961
962 hdev->le_mtu = __le16_to_cpu(rp->le_mtu);
963 hdev->le_pkts = rp->le_max_pkt;
964
965 hdev->le_cnt = hdev->le_pkts;
966
967 BT_DBG("%s le mtu %d:%d", hdev->name, hdev->le_mtu, hdev->le_pkts);
968
969 hci_req_complete(hdev, HCI_OP_LE_READ_BUFFER_SIZE, rp->status);
970}
Johan Hedberg980e1a52011-01-22 06:10:07 +0200971
Johan Hedberga5c29682011-02-19 12:05:57 -0300972static void hci_cc_user_confirm_reply(struct hci_dev *hdev, struct sk_buff *skb)
973{
974 struct hci_rp_user_confirm_reply *rp = (void *) skb->data;
975
976 BT_DBG("%s status 0x%x", hdev->name, rp->status);
977
Johan Hedberg56e5cb82011-11-08 20:40:16 +0200978 hci_dev_lock(hdev);
979
Johan Hedberga8b2d5c2012-01-08 23:11:15 +0200980 if (test_bit(HCI_MGMT, &hdev->dev_flags))
Gustavo F. Padovan04124682012-03-08 01:25:00 -0300981 mgmt_user_confirm_reply_complete(hdev, &rp->bdaddr, ACL_LINK, 0,
982 rp->status);
Johan Hedberg56e5cb82011-11-08 20:40:16 +0200983
984 hci_dev_unlock(hdev);
Johan Hedberga5c29682011-02-19 12:05:57 -0300985}
986
987static void hci_cc_user_confirm_neg_reply(struct hci_dev *hdev,
988 struct sk_buff *skb)
989{
990 struct hci_rp_user_confirm_reply *rp = (void *) skb->data;
991
992 BT_DBG("%s status 0x%x", hdev->name, rp->status);
993
Johan Hedberg56e5cb82011-11-08 20:40:16 +0200994 hci_dev_lock(hdev);
995
Johan Hedberga8b2d5c2012-01-08 23:11:15 +0200996 if (test_bit(HCI_MGMT, &hdev->dev_flags))
Johan Hedberg744cf192011-11-08 20:40:14 +0200997 mgmt_user_confirm_neg_reply_complete(hdev, &rp->bdaddr,
Gustavo F. Padovan04124682012-03-08 01:25:00 -0300998 ACL_LINK, 0, rp->status);
Johan Hedberg56e5cb82011-11-08 20:40:16 +0200999
1000 hci_dev_unlock(hdev);
Johan Hedberga5c29682011-02-19 12:05:57 -03001001}
1002
Brian Gix1143d452011-11-23 08:28:34 -08001003static void hci_cc_user_passkey_reply(struct hci_dev *hdev, struct sk_buff *skb)
1004{
1005 struct hci_rp_user_confirm_reply *rp = (void *) skb->data;
1006
1007 BT_DBG("%s status 0x%x", hdev->name, rp->status);
1008
1009 hci_dev_lock(hdev);
1010
Johan Hedberga8b2d5c2012-01-08 23:11:15 +02001011 if (test_bit(HCI_MGMT, &hdev->dev_flags))
Johan Hedberg272d90d2012-02-09 15:26:12 +02001012 mgmt_user_passkey_reply_complete(hdev, &rp->bdaddr, ACL_LINK,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001013 0, rp->status);
Brian Gix1143d452011-11-23 08:28:34 -08001014
1015 hci_dev_unlock(hdev);
1016}
1017
1018static void hci_cc_user_passkey_neg_reply(struct hci_dev *hdev,
1019 struct sk_buff *skb)
1020{
1021 struct hci_rp_user_confirm_reply *rp = (void *) skb->data;
1022
1023 BT_DBG("%s status 0x%x", hdev->name, rp->status);
1024
1025 hci_dev_lock(hdev);
1026
Johan Hedberga8b2d5c2012-01-08 23:11:15 +02001027 if (test_bit(HCI_MGMT, &hdev->dev_flags))
Brian Gix1143d452011-11-23 08:28:34 -08001028 mgmt_user_passkey_neg_reply_complete(hdev, &rp->bdaddr,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001029 ACL_LINK, 0, rp->status);
Brian Gix1143d452011-11-23 08:28:34 -08001030
1031 hci_dev_unlock(hdev);
1032}
1033
Szymon Jancc35938b2011-03-22 13:12:21 +01001034static void hci_cc_read_local_oob_data_reply(struct hci_dev *hdev,
1035 struct sk_buff *skb)
1036{
1037 struct hci_rp_read_local_oob_data *rp = (void *) skb->data;
1038
1039 BT_DBG("%s status 0x%x", hdev->name, rp->status);
1040
Johan Hedberg56e5cb82011-11-08 20:40:16 +02001041 hci_dev_lock(hdev);
Johan Hedberg744cf192011-11-08 20:40:14 +02001042 mgmt_read_local_oob_data_reply_complete(hdev, rp->hash,
Szymon Jancc35938b2011-03-22 13:12:21 +01001043 rp->randomizer, rp->status);
Johan Hedberg56e5cb82011-11-08 20:40:16 +02001044 hci_dev_unlock(hdev);
Szymon Jancc35938b2011-03-22 13:12:21 +01001045}
1046
Andre Guedes07f7fa52011-12-02 21:13:31 +09001047static void hci_cc_le_set_scan_param(struct hci_dev *hdev, struct sk_buff *skb)
1048{
1049 __u8 status = *((__u8 *) skb->data);
1050
1051 BT_DBG("%s status 0x%x", hdev->name, status);
Andre Guedes7ba8b4b2012-02-03 17:47:59 -03001052
1053 hci_req_complete(hdev, HCI_OP_LE_SET_SCAN_PARAM, status);
Andre Guedes3fd24152012-02-03 17:48:01 -03001054
1055 if (status) {
1056 hci_dev_lock(hdev);
1057 mgmt_start_discovery_failed(hdev, status);
1058 hci_dev_unlock(hdev);
1059 return;
1060 }
Andre Guedes07f7fa52011-12-02 21:13:31 +09001061}
1062
Andre Guedeseb9d91f2011-05-26 16:23:52 -03001063static void hci_cc_le_set_scan_enable(struct hci_dev *hdev,
1064 struct sk_buff *skb)
1065{
1066 struct hci_cp_le_set_scan_enable *cp;
1067 __u8 status = *((__u8 *) skb->data);
1068
1069 BT_DBG("%s status 0x%x", hdev->name, status);
1070
Andre Guedeseb9d91f2011-05-26 16:23:52 -03001071 cp = hci_sent_cmd_data(hdev, HCI_OP_LE_SET_SCAN_ENABLE);
1072 if (!cp)
1073 return;
1074
Andrei Emeltchenko68a8aea2011-12-19 16:14:18 +02001075 switch (cp->enable) {
1076 case LE_SCANNING_ENABLED:
Andre Guedes7ba8b4b2012-02-03 17:47:59 -03001077 hci_req_complete(hdev, HCI_OP_LE_SET_SCAN_ENABLE, status);
1078
Andre Guedes3fd24152012-02-03 17:48:01 -03001079 if (status) {
1080 hci_dev_lock(hdev);
1081 mgmt_start_discovery_failed(hdev, status);
1082 hci_dev_unlock(hdev);
Andre Guedes7ba8b4b2012-02-03 17:47:59 -03001083 return;
Andre Guedes3fd24152012-02-03 17:48:01 -03001084 }
Andre Guedes7ba8b4b2012-02-03 17:47:59 -03001085
Andre Guedesd23264a2011-11-25 20:53:38 -03001086 set_bit(HCI_LE_SCAN, &hdev->dev_flags);
1087
Gustavo F. Padovandb323f22011-06-20 16:39:29 -03001088 cancel_delayed_work_sync(&hdev->adv_work);
Andre Guedesa8f13c82011-09-09 18:56:24 -03001089
1090 hci_dev_lock(hdev);
Andre Guedeseb9d91f2011-05-26 16:23:52 -03001091 hci_adv_entries_clear(hdev);
Andre Guedes343f9352012-02-17 20:39:37 -03001092 hci_discovery_set_state(hdev, DISCOVERY_FINDING);
Andre Guedesa8f13c82011-09-09 18:56:24 -03001093 hci_dev_unlock(hdev);
Andrei Emeltchenko68a8aea2011-12-19 16:14:18 +02001094 break;
1095
1096 case LE_SCANNING_DISABLED:
Andre Guedesc9ecc482012-03-15 16:52:08 -03001097 if (status) {
1098 hci_dev_lock(hdev);
1099 mgmt_stop_discovery_failed(hdev, status);
1100 hci_dev_unlock(hdev);
Andre Guedes7ba8b4b2012-02-03 17:47:59 -03001101 return;
Andre Guedesc9ecc482012-03-15 16:52:08 -03001102 }
Andre Guedes7ba8b4b2012-02-03 17:47:59 -03001103
Andre Guedesd23264a2011-11-25 20:53:38 -03001104 clear_bit(HCI_LE_SCAN, &hdev->dev_flags);
1105
Andre Guedesd0843292012-01-02 19:18:11 -03001106 schedule_delayed_work(&hdev->adv_work, ADV_CLEAR_TIMEOUT);
Andre Guedes5e0452c2012-02-17 20:39:38 -03001107
Andre Guedesbc3dd332012-03-06 19:37:06 -03001108 if (hdev->discovery.type == DISCOV_TYPE_INTERLEAVED &&
1109 hdev->discovery.state == DISCOVERY_FINDING) {
Andre Guedes5e0452c2012-02-17 20:39:38 -03001110 mgmt_interleaved_discovery(hdev);
1111 } else {
1112 hci_dev_lock(hdev);
1113 hci_discovery_set_state(hdev, DISCOVERY_STOPPED);
1114 hci_dev_unlock(hdev);
1115 }
1116
Andrei Emeltchenko68a8aea2011-12-19 16:14:18 +02001117 break;
1118
1119 default:
1120 BT_ERR("Used reserved LE_Scan_Enable param %d", cp->enable);
1121 break;
Andre Guedes35815082011-05-26 16:23:53 -03001122 }
Andre Guedeseb9d91f2011-05-26 16:23:52 -03001123}
1124
Vinicius Costa Gomesa7a595f2011-06-09 18:50:47 -03001125static void hci_cc_le_ltk_reply(struct hci_dev *hdev, struct sk_buff *skb)
1126{
1127 struct hci_rp_le_ltk_reply *rp = (void *) skb->data;
1128
1129 BT_DBG("%s status 0x%x", hdev->name, rp->status);
1130
1131 if (rp->status)
1132 return;
1133
1134 hci_req_complete(hdev, HCI_OP_LE_LTK_REPLY, rp->status);
1135}
1136
1137static void hci_cc_le_ltk_neg_reply(struct hci_dev *hdev, struct sk_buff *skb)
1138{
1139 struct hci_rp_le_ltk_neg_reply *rp = (void *) skb->data;
1140
1141 BT_DBG("%s status 0x%x", hdev->name, rp->status);
1142
1143 if (rp->status)
1144 return;
1145
1146 hci_req_complete(hdev, HCI_OP_LE_LTK_NEG_REPLY, rp->status);
1147}
1148
Andre Guedesf9b49302011-06-30 19:20:53 -03001149static inline void hci_cc_write_le_host_supported(struct hci_dev *hdev,
1150 struct sk_buff *skb)
1151{
Johan Hedberg06199cf2012-02-22 16:37:11 +02001152 struct hci_cp_write_le_host_supported *sent;
Andre Guedesf9b49302011-06-30 19:20:53 -03001153 __u8 status = *((__u8 *) skb->data);
1154
1155 BT_DBG("%s status 0x%x", hdev->name, status);
1156
Johan Hedberg06199cf2012-02-22 16:37:11 +02001157 sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_LE_HOST_SUPPORTED);
Johan Hedberg8f984df2012-02-28 01:07:22 +02001158 if (!sent)
Andre Guedesf9b49302011-06-30 19:20:53 -03001159 return;
1160
Johan Hedberg8f984df2012-02-28 01:07:22 +02001161 if (!status) {
1162 if (sent->le)
1163 hdev->host_features[0] |= LMP_HOST_LE;
1164 else
1165 hdev->host_features[0] &= ~LMP_HOST_LE;
1166 }
1167
1168 if (test_bit(HCI_MGMT, &hdev->dev_flags) &&
1169 !test_bit(HCI_INIT, &hdev->flags))
1170 mgmt_le_enable_complete(hdev, sent->le, status);
1171
1172 hci_req_complete(hdev, HCI_OP_WRITE_LE_HOST_SUPPORTED, status);
Andre Guedesf9b49302011-06-30 19:20:53 -03001173}
1174
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001175static inline void hci_cs_inquiry(struct hci_dev *hdev, __u8 status)
1176{
1177 BT_DBG("%s status 0x%x", hdev->name, status);
1178
1179 if (status) {
Johan Hedberg23bb5762010-12-21 23:01:27 +02001180 hci_req_complete(hdev, HCI_OP_INQUIRY, status);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001181 hci_conn_check_pending(hdev);
Johan Hedberg56e5cb82011-11-08 20:40:16 +02001182 hci_dev_lock(hdev);
Johan Hedberga8b2d5c2012-01-08 23:11:15 +02001183 if (test_bit(HCI_MGMT, &hdev->dev_flags))
Andre Guedes7a135102011-11-09 17:14:25 -03001184 mgmt_start_discovery_failed(hdev, status);
Johan Hedberg56e5cb82011-11-08 20:40:16 +02001185 hci_dev_unlock(hdev);
Johan Hedberg314b2382011-04-27 10:29:57 -04001186 return;
1187 }
1188
Andre Guedes89352e72011-11-04 14:16:53 -03001189 set_bit(HCI_INQUIRY, &hdev->flags);
1190
Johan Hedberg56e5cb82011-11-08 20:40:16 +02001191 hci_dev_lock(hdev);
Andre Guedes343f9352012-02-17 20:39:37 -03001192 hci_discovery_set_state(hdev, DISCOVERY_FINDING);
Johan Hedberg56e5cb82011-11-08 20:40:16 +02001193 hci_dev_unlock(hdev);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001194}
1195
Linus Torvalds1da177e2005-04-16 15:20:36 -07001196static inline void hci_cs_create_conn(struct hci_dev *hdev, __u8 status)
1197{
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001198 struct hci_cp_create_conn *cp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001199 struct hci_conn *conn;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001200
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001201 BT_DBG("%s status 0x%x", hdev->name, status);
1202
1203 cp = hci_sent_cmd_data(hdev, HCI_OP_CREATE_CONN);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001204 if (!cp)
1205 return;
1206
1207 hci_dev_lock(hdev);
1208
1209 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &cp->bdaddr);
1210
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001211 BT_DBG("%s bdaddr %s conn %p", hdev->name, batostr(&cp->bdaddr), conn);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001212
1213 if (status) {
1214 if (conn && conn->state == BT_CONNECT) {
Marcel Holtmann4c67bc72006-10-15 17:30:56 +02001215 if (status != 0x0c || conn->attempt > 2) {
1216 conn->state = BT_CLOSED;
1217 hci_proto_connect_cfm(conn, status);
1218 hci_conn_del(conn);
1219 } else
1220 conn->state = BT_CONNECT2;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001221 }
1222 } else {
1223 if (!conn) {
1224 conn = hci_conn_add(hdev, ACL_LINK, &cp->bdaddr);
1225 if (conn) {
Johan Hedberga0c808b2012-01-16 09:49:58 +02001226 conn->out = true;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001227 conn->link_mode |= HCI_LM_MASTER;
1228 } else
Gustavo F. Padovan893ef972010-07-18 15:13:37 -03001229 BT_ERR("No memory for new connection");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001230 }
1231 }
1232
1233 hci_dev_unlock(hdev);
1234}
1235
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001236static void hci_cs_add_sco(struct hci_dev *hdev, __u8 status)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001237{
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001238 struct hci_cp_add_sco *cp;
1239 struct hci_conn *acl, *sco;
1240 __u16 handle;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001241
Marcel Holtmannb6a0dc82007-10-20 14:55:10 +02001242 BT_DBG("%s status 0x%x", hdev->name, status);
1243
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001244 if (!status)
1245 return;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001246
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001247 cp = hci_sent_cmd_data(hdev, HCI_OP_ADD_SCO);
1248 if (!cp)
1249 return;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001250
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001251 handle = __le16_to_cpu(cp->handle);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001252
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001253 BT_DBG("%s handle %d", hdev->name, handle);
Marcel Holtmann6bd57412006-11-18 22:14:22 +01001254
1255 hci_dev_lock(hdev);
1256
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001257 acl = hci_conn_hash_lookup_handle(hdev, handle);
Andrei Emeltchenko5a08ecc2011-01-11 17:20:20 +02001258 if (acl) {
1259 sco = acl->link;
1260 if (sco) {
1261 sco->state = BT_CLOSED;
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001262
Andrei Emeltchenko5a08ecc2011-01-11 17:20:20 +02001263 hci_proto_connect_cfm(sco, status);
1264 hci_conn_del(sco);
1265 }
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001266 }
Marcel Holtmann6bd57412006-11-18 22:14:22 +01001267
1268 hci_dev_unlock(hdev);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001269}
1270
Marcel Holtmannf8558552008-07-14 20:13:49 +02001271static void hci_cs_auth_requested(struct hci_dev *hdev, __u8 status)
1272{
1273 struct hci_cp_auth_requested *cp;
1274 struct hci_conn *conn;
1275
1276 BT_DBG("%s status 0x%x", hdev->name, status);
1277
1278 if (!status)
1279 return;
1280
1281 cp = hci_sent_cmd_data(hdev, HCI_OP_AUTH_REQUESTED);
1282 if (!cp)
1283 return;
1284
1285 hci_dev_lock(hdev);
1286
1287 conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(cp->handle));
1288 if (conn) {
1289 if (conn->state == BT_CONFIG) {
1290 hci_proto_connect_cfm(conn, status);
1291 hci_conn_put(conn);
1292 }
1293 }
1294
1295 hci_dev_unlock(hdev);
1296}
1297
1298static void hci_cs_set_conn_encrypt(struct hci_dev *hdev, __u8 status)
1299{
1300 struct hci_cp_set_conn_encrypt *cp;
1301 struct hci_conn *conn;
1302
1303 BT_DBG("%s status 0x%x", hdev->name, status);
1304
1305 if (!status)
1306 return;
1307
1308 cp = hci_sent_cmd_data(hdev, HCI_OP_SET_CONN_ENCRYPT);
1309 if (!cp)
1310 return;
1311
1312 hci_dev_lock(hdev);
1313
1314 conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(cp->handle));
1315 if (conn) {
1316 if (conn->state == BT_CONFIG) {
1317 hci_proto_connect_cfm(conn, status);
1318 hci_conn_put(conn);
1319 }
1320 }
1321
1322 hci_dev_unlock(hdev);
1323}
1324
Johan Hedberg127178d2010-11-18 22:22:29 +02001325static int hci_outgoing_auth_needed(struct hci_dev *hdev,
Szymon Janc138d22e2011-02-17 16:44:23 +01001326 struct hci_conn *conn)
Johan Hedberg392599b2010-11-18 22:22:28 +02001327{
Johan Hedberg392599b2010-11-18 22:22:28 +02001328 if (conn->state != BT_CONFIG || !conn->out)
1329 return 0;
1330
Johan Hedberg765c2a92011-01-19 12:06:52 +05301331 if (conn->pending_sec_level == BT_SECURITY_SDP)
Johan Hedberg392599b2010-11-18 22:22:28 +02001332 return 0;
1333
1334 /* Only request authentication for SSP connections or non-SSP
Vinicius Costa Gomese9bf2bf2011-09-02 14:51:20 -03001335 * devices with sec_level HIGH or if MITM protection is requested */
Johan Hedbergaa64a8b2012-01-18 21:33:12 +02001336 if (!hci_conn_ssp_enabled(conn) &&
Vinicius Costa Gomese9bf2bf2011-09-02 14:51:20 -03001337 conn->pending_sec_level != BT_SECURITY_HIGH &&
1338 !(conn->auth_type & 0x01))
Johan Hedberg392599b2010-11-18 22:22:28 +02001339 return 0;
1340
Johan Hedberg392599b2010-11-18 22:22:28 +02001341 return 1;
1342}
1343
Gustavo F. Padovan00abfe42012-03-01 00:37:10 -03001344static inline int hci_resolve_name(struct hci_dev *hdev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001345 struct inquiry_entry *e)
Johan Hedberg30dc78e2012-01-04 15:44:20 +02001346{
1347 struct hci_cp_remote_name_req cp;
1348
1349 memset(&cp, 0, sizeof(cp));
1350
1351 bacpy(&cp.bdaddr, &e->data.bdaddr);
1352 cp.pscan_rep_mode = e->data.pscan_rep_mode;
1353 cp.pscan_mode = e->data.pscan_mode;
1354 cp.clock_offset = e->data.clock_offset;
1355
1356 return hci_send_cmd(hdev, HCI_OP_REMOTE_NAME_REQ, sizeof(cp), &cp);
1357}
1358
Johan Hedbergb644ba32012-01-17 21:48:47 +02001359static bool hci_resolve_next_name(struct hci_dev *hdev)
Johan Hedberg30dc78e2012-01-04 15:44:20 +02001360{
1361 struct discovery_state *discov = &hdev->discovery;
1362 struct inquiry_entry *e;
1363
Johan Hedbergb644ba32012-01-17 21:48:47 +02001364 if (list_empty(&discov->resolve))
1365 return false;
1366
1367 e = hci_inquiry_cache_lookup_resolve(hdev, BDADDR_ANY, NAME_NEEDED);
1368 if (hci_resolve_name(hdev, e) == 0) {
1369 e->name_state = NAME_PENDING;
1370 return true;
1371 }
1372
1373 return false;
1374}
1375
1376static void hci_check_pending_name(struct hci_dev *hdev, struct hci_conn *conn,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001377 bdaddr_t *bdaddr, u8 *name, u8 name_len)
Johan Hedbergb644ba32012-01-17 21:48:47 +02001378{
1379 struct discovery_state *discov = &hdev->discovery;
1380 struct inquiry_entry *e;
1381
1382 if (conn && !test_and_set_bit(HCI_CONN_MGMT_CONNECTED, &conn->flags))
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001383 mgmt_device_connected(hdev, bdaddr, ACL_LINK, 0x00, 0, name,
1384 name_len, conn->dev_class);
Johan Hedbergb644ba32012-01-17 21:48:47 +02001385
1386 if (discov->state == DISCOVERY_STOPPED)
1387 return;
1388
Johan Hedberg30dc78e2012-01-04 15:44:20 +02001389 if (discov->state == DISCOVERY_STOPPING)
1390 goto discov_complete;
1391
1392 if (discov->state != DISCOVERY_RESOLVING)
1393 return;
1394
1395 e = hci_inquiry_cache_lookup_resolve(hdev, bdaddr, NAME_PENDING);
1396 if (e) {
1397 e->name_state = NAME_KNOWN;
1398 list_del(&e->list);
Johan Hedbergb644ba32012-01-17 21:48:47 +02001399 if (name)
1400 mgmt_remote_name(hdev, bdaddr, ACL_LINK, 0x00,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001401 e->data.rssi, name, name_len);
Johan Hedberg30dc78e2012-01-04 15:44:20 +02001402 }
1403
Johan Hedbergb644ba32012-01-17 21:48:47 +02001404 if (hci_resolve_next_name(hdev))
Johan Hedberg30dc78e2012-01-04 15:44:20 +02001405 return;
Johan Hedberg30dc78e2012-01-04 15:44:20 +02001406
1407discov_complete:
1408 hci_discovery_set_state(hdev, DISCOVERY_STOPPED);
1409}
1410
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001411static void hci_cs_remote_name_req(struct hci_dev *hdev, __u8 status)
1412{
Johan Hedberg127178d2010-11-18 22:22:29 +02001413 struct hci_cp_remote_name_req *cp;
1414 struct hci_conn *conn;
1415
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001416 BT_DBG("%s status 0x%x", hdev->name, status);
Johan Hedberg127178d2010-11-18 22:22:29 +02001417
1418 /* If successful wait for the name req complete event before
1419 * checking for the need to do authentication */
1420 if (!status)
1421 return;
1422
1423 cp = hci_sent_cmd_data(hdev, HCI_OP_REMOTE_NAME_REQ);
1424 if (!cp)
1425 return;
1426
1427 hci_dev_lock(hdev);
1428
1429 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &cp->bdaddr);
Johan Hedbergb644ba32012-01-17 21:48:47 +02001430
1431 if (test_bit(HCI_MGMT, &hdev->dev_flags))
1432 hci_check_pending_name(hdev, conn, &cp->bdaddr, NULL, 0);
1433
Johan Hedberg79c6c702011-04-28 11:28:55 -07001434 if (!conn)
1435 goto unlock;
1436
1437 if (!hci_outgoing_auth_needed(hdev, conn))
1438 goto unlock;
1439
Johan Hedberg51a8efd2012-01-16 06:10:31 +02001440 if (!test_and_set_bit(HCI_CONN_AUTH_PEND, &conn->flags)) {
Johan Hedberg127178d2010-11-18 22:22:29 +02001441 struct hci_cp_auth_requested cp;
1442 cp.handle = __cpu_to_le16(conn->handle);
1443 hci_send_cmd(hdev, HCI_OP_AUTH_REQUESTED, sizeof(cp), &cp);
1444 }
1445
Johan Hedberg79c6c702011-04-28 11:28:55 -07001446unlock:
Johan Hedberg127178d2010-11-18 22:22:29 +02001447 hci_dev_unlock(hdev);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001448}
1449
Marcel Holtmann769be972008-07-14 20:13:49 +02001450static void hci_cs_read_remote_features(struct hci_dev *hdev, __u8 status)
1451{
1452 struct hci_cp_read_remote_features *cp;
1453 struct hci_conn *conn;
1454
1455 BT_DBG("%s status 0x%x", hdev->name, status);
1456
1457 if (!status)
1458 return;
1459
1460 cp = hci_sent_cmd_data(hdev, HCI_OP_READ_REMOTE_FEATURES);
1461 if (!cp)
1462 return;
1463
1464 hci_dev_lock(hdev);
1465
1466 conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(cp->handle));
1467 if (conn) {
1468 if (conn->state == BT_CONFIG) {
Marcel Holtmann769be972008-07-14 20:13:49 +02001469 hci_proto_connect_cfm(conn, status);
1470 hci_conn_put(conn);
1471 }
1472 }
1473
1474 hci_dev_unlock(hdev);
1475}
1476
1477static void hci_cs_read_remote_ext_features(struct hci_dev *hdev, __u8 status)
1478{
1479 struct hci_cp_read_remote_ext_features *cp;
1480 struct hci_conn *conn;
1481
1482 BT_DBG("%s status 0x%x", hdev->name, status);
1483
1484 if (!status)
1485 return;
1486
1487 cp = hci_sent_cmd_data(hdev, HCI_OP_READ_REMOTE_EXT_FEATURES);
1488 if (!cp)
1489 return;
1490
1491 hci_dev_lock(hdev);
1492
1493 conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(cp->handle));
1494 if (conn) {
1495 if (conn->state == BT_CONFIG) {
Marcel Holtmann769be972008-07-14 20:13:49 +02001496 hci_proto_connect_cfm(conn, status);
1497 hci_conn_put(conn);
1498 }
1499 }
1500
1501 hci_dev_unlock(hdev);
1502}
1503
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001504static void hci_cs_setup_sync_conn(struct hci_dev *hdev, __u8 status)
1505{
Marcel Holtmannb6a0dc82007-10-20 14:55:10 +02001506 struct hci_cp_setup_sync_conn *cp;
1507 struct hci_conn *acl, *sco;
1508 __u16 handle;
1509
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001510 BT_DBG("%s status 0x%x", hdev->name, status);
Marcel Holtmannb6a0dc82007-10-20 14:55:10 +02001511
1512 if (!status)
1513 return;
1514
1515 cp = hci_sent_cmd_data(hdev, HCI_OP_SETUP_SYNC_CONN);
1516 if (!cp)
1517 return;
1518
1519 handle = __le16_to_cpu(cp->handle);
1520
1521 BT_DBG("%s handle %d", hdev->name, handle);
1522
1523 hci_dev_lock(hdev);
1524
1525 acl = hci_conn_hash_lookup_handle(hdev, handle);
Andrei Emeltchenko5a08ecc2011-01-11 17:20:20 +02001526 if (acl) {
1527 sco = acl->link;
1528 if (sco) {
1529 sco->state = BT_CLOSED;
Marcel Holtmannb6a0dc82007-10-20 14:55:10 +02001530
Andrei Emeltchenko5a08ecc2011-01-11 17:20:20 +02001531 hci_proto_connect_cfm(sco, status);
1532 hci_conn_del(sco);
1533 }
Marcel Holtmannb6a0dc82007-10-20 14:55:10 +02001534 }
1535
1536 hci_dev_unlock(hdev);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001537}
1538
1539static void hci_cs_sniff_mode(struct hci_dev *hdev, __u8 status)
1540{
1541 struct hci_cp_sniff_mode *cp;
1542 struct hci_conn *conn;
1543
1544 BT_DBG("%s status 0x%x", hdev->name, status);
1545
1546 if (!status)
1547 return;
1548
1549 cp = hci_sent_cmd_data(hdev, HCI_OP_SNIFF_MODE);
1550 if (!cp)
1551 return;
1552
1553 hci_dev_lock(hdev);
1554
1555 conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(cp->handle));
Marcel Holtmanne73439d2010-07-26 10:06:00 -04001556 if (conn) {
Johan Hedberg51a8efd2012-01-16 06:10:31 +02001557 clear_bit(HCI_CONN_MODE_CHANGE_PEND, &conn->flags);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001558
Johan Hedberg51a8efd2012-01-16 06:10:31 +02001559 if (test_and_clear_bit(HCI_CONN_SCO_SETUP_PEND, &conn->flags))
Marcel Holtmanne73439d2010-07-26 10:06:00 -04001560 hci_sco_setup(conn, status);
1561 }
1562
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001563 hci_dev_unlock(hdev);
1564}
1565
1566static void hci_cs_exit_sniff_mode(struct hci_dev *hdev, __u8 status)
1567{
1568 struct hci_cp_exit_sniff_mode *cp;
1569 struct hci_conn *conn;
1570
1571 BT_DBG("%s status 0x%x", hdev->name, status);
1572
1573 if (!status)
1574 return;
1575
1576 cp = hci_sent_cmd_data(hdev, HCI_OP_EXIT_SNIFF_MODE);
1577 if (!cp)
1578 return;
1579
1580 hci_dev_lock(hdev);
1581
1582 conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(cp->handle));
Marcel Holtmanne73439d2010-07-26 10:06:00 -04001583 if (conn) {
Johan Hedberg51a8efd2012-01-16 06:10:31 +02001584 clear_bit(HCI_CONN_MODE_CHANGE_PEND, &conn->flags);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001585
Johan Hedberg51a8efd2012-01-16 06:10:31 +02001586 if (test_and_clear_bit(HCI_CONN_SCO_SETUP_PEND, &conn->flags))
Marcel Holtmanne73439d2010-07-26 10:06:00 -04001587 hci_sco_setup(conn, status);
1588 }
1589
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001590 hci_dev_unlock(hdev);
1591}
1592
Johan Hedberg88c3df12012-02-09 14:27:38 +02001593static void hci_cs_disconnect(struct hci_dev *hdev, u8 status)
1594{
1595 struct hci_cp_disconnect *cp;
1596 struct hci_conn *conn;
1597
1598 if (!status)
1599 return;
1600
1601 cp = hci_sent_cmd_data(hdev, HCI_OP_DISCONNECT);
1602 if (!cp)
1603 return;
1604
1605 hci_dev_lock(hdev);
1606
1607 conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(cp->handle));
1608 if (conn)
1609 mgmt_disconnect_failed(hdev, &conn->dst, conn->type,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001610 conn->dst_type, status);
Johan Hedberg88c3df12012-02-09 14:27:38 +02001611
1612 hci_dev_unlock(hdev);
1613}
1614
Ville Tervofcd89c02011-02-10 22:38:47 -03001615static void hci_cs_le_create_conn(struct hci_dev *hdev, __u8 status)
1616{
1617 struct hci_cp_le_create_conn *cp;
1618 struct hci_conn *conn;
1619
1620 BT_DBG("%s status 0x%x", hdev->name, status);
1621
1622 cp = hci_sent_cmd_data(hdev, HCI_OP_LE_CREATE_CONN);
1623 if (!cp)
1624 return;
1625
1626 hci_dev_lock(hdev);
1627
1628 conn = hci_conn_hash_lookup_ba(hdev, LE_LINK, &cp->peer_addr);
1629
1630 BT_DBG("%s bdaddr %s conn %p", hdev->name, batostr(&cp->peer_addr),
1631 conn);
1632
1633 if (status) {
1634 if (conn && conn->state == BT_CONNECT) {
1635 conn->state = BT_CLOSED;
1636 hci_proto_connect_cfm(conn, status);
1637 hci_conn_del(conn);
1638 }
1639 } else {
1640 if (!conn) {
1641 conn = hci_conn_add(hdev, LE_LINK, &cp->peer_addr);
Andre Guedes29b79882011-05-31 14:20:54 -03001642 if (conn) {
1643 conn->dst_type = cp->peer_addr_type;
Johan Hedberga0c808b2012-01-16 09:49:58 +02001644 conn->out = true;
Andre Guedes29b79882011-05-31 14:20:54 -03001645 } else {
Ville Tervofcd89c02011-02-10 22:38:47 -03001646 BT_ERR("No memory for new connection");
Andre Guedes29b79882011-05-31 14:20:54 -03001647 }
Ville Tervofcd89c02011-02-10 22:38:47 -03001648 }
1649 }
1650
1651 hci_dev_unlock(hdev);
1652}
1653
Vinicius Costa Gomesa7a595f2011-06-09 18:50:47 -03001654static void hci_cs_le_start_enc(struct hci_dev *hdev, u8 status)
1655{
1656 BT_DBG("%s status 0x%x", hdev->name, status);
1657}
1658
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001659static inline void hci_inquiry_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
1660{
1661 __u8 status = *((__u8 *) skb->data);
Johan Hedberg30dc78e2012-01-04 15:44:20 +02001662 struct discovery_state *discov = &hdev->discovery;
1663 struct inquiry_entry *e;
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001664
1665 BT_DBG("%s status %d", hdev->name, status);
1666
Johan Hedberg23bb5762010-12-21 23:01:27 +02001667 hci_req_complete(hdev, HCI_OP_INQUIRY, status);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001668
1669 hci_conn_check_pending(hdev);
Andre Guedes89352e72011-11-04 14:16:53 -03001670
1671 if (!test_and_clear_bit(HCI_INQUIRY, &hdev->flags))
1672 return;
1673
Johan Hedberga8b2d5c2012-01-08 23:11:15 +02001674 if (!test_bit(HCI_MGMT, &hdev->dev_flags))
Johan Hedberg30dc78e2012-01-04 15:44:20 +02001675 return;
1676
Johan Hedberg56e5cb82011-11-08 20:40:16 +02001677 hci_dev_lock(hdev);
Johan Hedberg30dc78e2012-01-04 15:44:20 +02001678
Andre Guedes343f9352012-02-17 20:39:37 -03001679 if (discov->state != DISCOVERY_FINDING)
Johan Hedberg30dc78e2012-01-04 15:44:20 +02001680 goto unlock;
1681
1682 if (list_empty(&discov->resolve)) {
1683 hci_discovery_set_state(hdev, DISCOVERY_STOPPED);
1684 goto unlock;
1685 }
1686
1687 e = hci_inquiry_cache_lookup_resolve(hdev, BDADDR_ANY, NAME_NEEDED);
1688 if (e && hci_resolve_name(hdev, e) == 0) {
1689 e->name_state = NAME_PENDING;
1690 hci_discovery_set_state(hdev, DISCOVERY_RESOLVING);
1691 } else {
1692 hci_discovery_set_state(hdev, DISCOVERY_STOPPED);
1693 }
1694
1695unlock:
Johan Hedberg56e5cb82011-11-08 20:40:16 +02001696 hci_dev_unlock(hdev);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001697}
1698
Linus Torvalds1da177e2005-04-16 15:20:36 -07001699static inline void hci_inquiry_result_evt(struct hci_dev *hdev, struct sk_buff *skb)
1700{
Marcel Holtmann45bb4bf2005-08-09 20:27:49 -07001701 struct inquiry_data data;
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001702 struct inquiry_info *info = (void *) (skb->data + 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001703 int num_rsp = *((__u8 *) skb->data);
1704
1705 BT_DBG("%s num_rsp %d", hdev->name, num_rsp);
1706
Marcel Holtmann45bb4bf2005-08-09 20:27:49 -07001707 if (!num_rsp)
1708 return;
1709
Linus Torvalds1da177e2005-04-16 15:20:36 -07001710 hci_dev_lock(hdev);
Marcel Holtmann45bb4bf2005-08-09 20:27:49 -07001711
Johan Hedberge17acd42011-03-30 23:57:16 +03001712 for (; num_rsp; num_rsp--, info++) {
Johan Hedberg388fc8f2012-02-23 00:38:59 +02001713 bool name_known, ssp;
Johan Hedberg31754052012-01-04 13:39:52 +02001714
Linus Torvalds1da177e2005-04-16 15:20:36 -07001715 bacpy(&data.bdaddr, &info->bdaddr);
1716 data.pscan_rep_mode = info->pscan_rep_mode;
1717 data.pscan_period_mode = info->pscan_period_mode;
1718 data.pscan_mode = info->pscan_mode;
1719 memcpy(data.dev_class, info->dev_class, 3);
1720 data.clock_offset = info->clock_offset;
1721 data.rssi = 0x00;
Marcel Holtmann41a96212008-07-14 20:13:48 +02001722 data.ssp_mode = 0x00;
Johan Hedberg31754052012-01-04 13:39:52 +02001723
Johan Hedberg388fc8f2012-02-23 00:38:59 +02001724 name_known = hci_inquiry_cache_update(hdev, &data, false, &ssp);
Johan Hedberg48264f02011-11-09 13:58:58 +02001725 mgmt_device_found(hdev, &info->bdaddr, ACL_LINK, 0x00,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001726 info->dev_class, 0, !name_known, ssp, NULL,
1727 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001728 }
Marcel Holtmann45bb4bf2005-08-09 20:27:49 -07001729
Linus Torvalds1da177e2005-04-16 15:20:36 -07001730 hci_dev_unlock(hdev);
1731}
1732
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001733static inline void hci_conn_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001734{
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001735 struct hci_ev_conn_complete *ev = (void *) skb->data;
1736 struct hci_conn *conn;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001737
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001738 BT_DBG("%s", hdev->name);
Marcel Holtmann45bb4bf2005-08-09 20:27:49 -07001739
Linus Torvalds1da177e2005-04-16 15:20:36 -07001740 hci_dev_lock(hdev);
Marcel Holtmann45bb4bf2005-08-09 20:27:49 -07001741
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001742 conn = hci_conn_hash_lookup_ba(hdev, ev->link_type, &ev->bdaddr);
Marcel Holtmann94992372009-04-19 19:30:03 +02001743 if (!conn) {
1744 if (ev->link_type != SCO_LINK)
1745 goto unlock;
1746
1747 conn = hci_conn_hash_lookup_ba(hdev, ESCO_LINK, &ev->bdaddr);
1748 if (!conn)
1749 goto unlock;
1750
1751 conn->type = SCO_LINK;
1752 }
Marcel Holtmann45bb4bf2005-08-09 20:27:49 -07001753
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001754 if (!ev->status) {
1755 conn->handle = __le16_to_cpu(ev->handle);
Marcel Holtmann769be972008-07-14 20:13:49 +02001756
1757 if (conn->type == ACL_LINK) {
1758 conn->state = BT_CONFIG;
1759 hci_conn_hold(conn);
Marcel Holtmann052b30b2009-04-26 20:01:22 +02001760 conn->disc_timeout = HCI_DISCONN_TIMEOUT;
Marcel Holtmann769be972008-07-14 20:13:49 +02001761 } else
1762 conn->state = BT_CONNECTED;
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001763
Marcel Holtmann9eba32b2009-08-22 14:19:26 -07001764 hci_conn_hold_device(conn);
Marcel Holtmann7d0db0a2008-07-14 20:13:51 +02001765 hci_conn_add_sysfs(conn);
1766
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001767 if (test_bit(HCI_AUTH, &hdev->flags))
1768 conn->link_mode |= HCI_LM_AUTH;
1769
1770 if (test_bit(HCI_ENCRYPT, &hdev->flags))
1771 conn->link_mode |= HCI_LM_ENCRYPT;
1772
1773 /* Get remote features */
1774 if (conn->type == ACL_LINK) {
1775 struct hci_cp_read_remote_features cp;
1776 cp.handle = ev->handle;
Marcel Holtmann769be972008-07-14 20:13:49 +02001777 hci_send_cmd(hdev, HCI_OP_READ_REMOTE_FEATURES,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001778 sizeof(cp), &cp);
Marcel Holtmann45bb4bf2005-08-09 20:27:49 -07001779 }
Marcel Holtmann45bb4bf2005-08-09 20:27:49 -07001780
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001781 /* Set packet type for incoming connection */
Andrei Emeltchenkod095c1e2011-12-01 14:33:27 +02001782 if (!conn->out && hdev->hci_ver < BLUETOOTH_VER_2_0) {
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001783 struct hci_cp_change_conn_ptype cp;
1784 cp.handle = ev->handle;
Marcel Holtmanna8746412008-07-14 20:13:46 +02001785 cp.pkt_type = cpu_to_le16(conn->pkt_type);
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001786 hci_send_cmd(hdev, HCI_OP_CHANGE_CONN_PTYPE, sizeof(cp),
1787 &cp);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001788 }
Johan Hedberg17d5c042011-01-22 06:09:08 +02001789 } else {
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001790 conn->state = BT_CLOSED;
Johan Hedberg17d5c042011-01-22 06:09:08 +02001791 if (conn->type == ACL_LINK)
Johan Hedberg744cf192011-11-08 20:40:14 +02001792 mgmt_connect_failed(hdev, &ev->bdaddr, conn->type,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001793 conn->dst_type, ev->status);
Johan Hedberg17d5c042011-01-22 06:09:08 +02001794 }
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001795
Marcel Holtmanne73439d2010-07-26 10:06:00 -04001796 if (conn->type == ACL_LINK)
1797 hci_sco_setup(conn, ev->status);
Marcel Holtmann45bb4bf2005-08-09 20:27:49 -07001798
Marcel Holtmann769be972008-07-14 20:13:49 +02001799 if (ev->status) {
1800 hci_proto_connect_cfm(conn, ev->status);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001801 hci_conn_del(conn);
Marcel Holtmannc89b6e62009-01-15 21:57:03 +01001802 } else if (ev->link_type != ACL_LINK)
1803 hci_proto_connect_cfm(conn, ev->status);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001804
1805unlock:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001806 hci_dev_unlock(hdev);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001807
1808 hci_conn_check_pending(hdev);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001809}
1810
Linus Torvalds1da177e2005-04-16 15:20:36 -07001811static inline void hci_conn_request_evt(struct hci_dev *hdev, struct sk_buff *skb)
1812{
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001813 struct hci_ev_conn_request *ev = (void *) skb->data;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001814 int mask = hdev->link_mode;
1815
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001816 BT_DBG("%s bdaddr %s type 0x%x", hdev->name,
1817 batostr(&ev->bdaddr), ev->link_type);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001818
1819 mask |= hci_proto_connect_ind(hdev, &ev->bdaddr, ev->link_type);
1820
Szymon Janc138d22e2011-02-17 16:44:23 +01001821 if ((mask & HCI_LM_ACCEPT) &&
1822 !hci_blacklist_lookup(hdev, &ev->bdaddr)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001823 /* Connection accepted */
Marcel Holtmannc7bdd502008-07-14 20:13:47 +02001824 struct inquiry_entry *ie;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001825 struct hci_conn *conn;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001826
1827 hci_dev_lock(hdev);
Marcel Holtmannb6a0dc82007-10-20 14:55:10 +02001828
Andrei Emeltchenkocc11b9c2010-11-22 13:21:37 +02001829 ie = hci_inquiry_cache_lookup(hdev, &ev->bdaddr);
1830 if (ie)
Marcel Holtmannc7bdd502008-07-14 20:13:47 +02001831 memcpy(ie->data.dev_class, ev->dev_class, 3);
1832
Linus Torvalds1da177e2005-04-16 15:20:36 -07001833 conn = hci_conn_hash_lookup_ba(hdev, ev->link_type, &ev->bdaddr);
1834 if (!conn) {
Andrei Emeltchenkocc11b9c2010-11-22 13:21:37 +02001835 conn = hci_conn_add(hdev, ev->link_type, &ev->bdaddr);
1836 if (!conn) {
Gustavo F. Padovan893ef972010-07-18 15:13:37 -03001837 BT_ERR("No memory for new connection");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001838 hci_dev_unlock(hdev);
1839 return;
1840 }
1841 }
Marcel Holtmannb6a0dc82007-10-20 14:55:10 +02001842
Linus Torvalds1da177e2005-04-16 15:20:36 -07001843 memcpy(conn->dev_class, ev->dev_class, 3);
1844 conn->state = BT_CONNECT;
Marcel Holtmannb6a0dc82007-10-20 14:55:10 +02001845
Linus Torvalds1da177e2005-04-16 15:20:36 -07001846 hci_dev_unlock(hdev);
1847
Marcel Holtmannb6a0dc82007-10-20 14:55:10 +02001848 if (ev->link_type == ACL_LINK || !lmp_esco_capable(hdev)) {
1849 struct hci_cp_accept_conn_req cp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001850
Marcel Holtmannb6a0dc82007-10-20 14:55:10 +02001851 bacpy(&cp.bdaddr, &ev->bdaddr);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001852
Marcel Holtmannb6a0dc82007-10-20 14:55:10 +02001853 if (lmp_rswitch_capable(hdev) && (mask & HCI_LM_MASTER))
1854 cp.role = 0x00; /* Become master */
1855 else
1856 cp.role = 0x01; /* Remain slave */
1857
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001858 hci_send_cmd(hdev, HCI_OP_ACCEPT_CONN_REQ, sizeof(cp),
1859 &cp);
Marcel Holtmannb6a0dc82007-10-20 14:55:10 +02001860 } else {
1861 struct hci_cp_accept_sync_conn_req cp;
1862
1863 bacpy(&cp.bdaddr, &ev->bdaddr);
Marcel Holtmanna8746412008-07-14 20:13:46 +02001864 cp.pkt_type = cpu_to_le16(conn->pkt_type);
Marcel Holtmannb6a0dc82007-10-20 14:55:10 +02001865
1866 cp.tx_bandwidth = cpu_to_le32(0x00001f40);
1867 cp.rx_bandwidth = cpu_to_le32(0x00001f40);
1868 cp.max_latency = cpu_to_le16(0xffff);
1869 cp.content_format = cpu_to_le16(hdev->voice_setting);
1870 cp.retrans_effort = 0xff;
1871
1872 hci_send_cmd(hdev, HCI_OP_ACCEPT_SYNC_CONN_REQ,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001873 sizeof(cp), &cp);
Marcel Holtmannb6a0dc82007-10-20 14:55:10 +02001874 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001875 } else {
1876 /* Connection rejected */
1877 struct hci_cp_reject_conn_req cp;
1878
1879 bacpy(&cp.bdaddr, &ev->bdaddr);
Andrei Emeltchenko9f5a0d72011-11-07 14:20:25 +02001880 cp.reason = HCI_ERROR_REJ_BAD_ADDR;
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001881 hci_send_cmd(hdev, HCI_OP_REJECT_CONN_REQ, sizeof(cp), &cp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001882 }
1883}
1884
Linus Torvalds1da177e2005-04-16 15:20:36 -07001885static inline void hci_disconn_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
1886{
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001887 struct hci_ev_disconn_complete *ev = (void *) skb->data;
Marcel Holtmann04837f62006-07-03 10:02:33 +02001888 struct hci_conn *conn;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001889
1890 BT_DBG("%s status %d", hdev->name, ev->status);
1891
Linus Torvalds1da177e2005-04-16 15:20:36 -07001892 hci_dev_lock(hdev);
1893
Marcel Holtmann04837f62006-07-03 10:02:33 +02001894 conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
Johan Hedbergf7520542011-01-20 12:34:39 +02001895 if (!conn)
1896 goto unlock;
Marcel Holtmann7d0db0a2008-07-14 20:13:51 +02001897
Johan Hedberg37d9ef72011-11-10 15:54:39 +02001898 if (ev->status == 0)
1899 conn->state = BT_CLOSED;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001900
Johan Hedbergb644ba32012-01-17 21:48:47 +02001901 if (test_and_clear_bit(HCI_CONN_MGMT_CONNECTED, &conn->flags) &&
1902 (conn->type == ACL_LINK || conn->type == LE_LINK)) {
Johan Hedberg37d9ef72011-11-10 15:54:39 +02001903 if (ev->status != 0)
Johan Hedberg88c3df12012-02-09 14:27:38 +02001904 mgmt_disconnect_failed(hdev, &conn->dst, conn->type,
1905 conn->dst_type, ev->status);
Johan Hedberg37d9ef72011-11-10 15:54:39 +02001906 else
Johan Hedbergafc747a2012-01-15 18:11:07 +02001907 mgmt_device_disconnected(hdev, &conn->dst, conn->type,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001908 conn->dst_type);
Johan Hedberg37d9ef72011-11-10 15:54:39 +02001909 }
Johan Hedbergf7520542011-01-20 12:34:39 +02001910
Johan Hedberg37d9ef72011-11-10 15:54:39 +02001911 if (ev->status == 0) {
Vishal Agarwal6ec5bca2012-04-16 14:44:44 +05301912 if (conn->type == ACL_LINK && conn->flush_key)
1913 hci_remove_link_key(hdev, &conn->dst);
Johan Hedberg37d9ef72011-11-10 15:54:39 +02001914 hci_proto_disconn_cfm(conn, ev->reason);
1915 hci_conn_del(conn);
1916 }
Johan Hedbergf7520542011-01-20 12:34:39 +02001917
1918unlock:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001919 hci_dev_unlock(hdev);
1920}
1921
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001922static inline void hci_auth_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
1923{
1924 struct hci_ev_auth_complete *ev = (void *) skb->data;
1925 struct hci_conn *conn;
1926
1927 BT_DBG("%s status %d", hdev->name, ev->status);
1928
1929 hci_dev_lock(hdev);
1930
1931 conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
Waldemar Rymarkiewiczd7556e22011-05-31 15:49:26 +02001932 if (!conn)
1933 goto unlock;
1934
1935 if (!ev->status) {
Johan Hedbergaa64a8b2012-01-18 21:33:12 +02001936 if (!hci_conn_ssp_enabled(conn) &&
1937 test_bit(HCI_CONN_REAUTH_PEND, &conn->flags)) {
Waldemar Rymarkiewiczd7556e22011-05-31 15:49:26 +02001938 BT_INFO("re-auth of legacy device is not possible.");
Johan Hedberg2a611692011-02-19 12:06:00 -03001939 } else {
Waldemar Rymarkiewiczd7556e22011-05-31 15:49:26 +02001940 conn->link_mode |= HCI_LM_AUTH;
1941 conn->sec_level = conn->pending_sec_level;
Johan Hedberg2a611692011-02-19 12:06:00 -03001942 }
Waldemar Rymarkiewiczd7556e22011-05-31 15:49:26 +02001943 } else {
Johan Hedbergbab73cb2012-02-09 16:07:29 +02001944 mgmt_auth_failed(hdev, &conn->dst, conn->type, conn->dst_type,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001945 ev->status);
Waldemar Rymarkiewiczd7556e22011-05-31 15:49:26 +02001946 }
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001947
Johan Hedberg51a8efd2012-01-16 06:10:31 +02001948 clear_bit(HCI_CONN_AUTH_PEND, &conn->flags);
1949 clear_bit(HCI_CONN_REAUTH_PEND, &conn->flags);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001950
Waldemar Rymarkiewiczd7556e22011-05-31 15:49:26 +02001951 if (conn->state == BT_CONFIG) {
Johan Hedbergaa64a8b2012-01-18 21:33:12 +02001952 if (!ev->status && hci_conn_ssp_enabled(conn)) {
Waldemar Rymarkiewiczd7556e22011-05-31 15:49:26 +02001953 struct hci_cp_set_conn_encrypt cp;
1954 cp.handle = ev->handle;
1955 cp.encrypt = 0x01;
1956 hci_send_cmd(hdev, HCI_OP_SET_CONN_ENCRYPT, sizeof(cp),
1957 &cp);
Marcel Holtmann052b30b2009-04-26 20:01:22 +02001958 } else {
Waldemar Rymarkiewiczd7556e22011-05-31 15:49:26 +02001959 conn->state = BT_CONNECTED;
1960 hci_proto_connect_cfm(conn, ev->status);
Marcel Holtmann052b30b2009-04-26 20:01:22 +02001961 hci_conn_put(conn);
1962 }
Waldemar Rymarkiewiczd7556e22011-05-31 15:49:26 +02001963 } else {
1964 hci_auth_cfm(conn, ev->status);
Marcel Holtmann052b30b2009-04-26 20:01:22 +02001965
Waldemar Rymarkiewiczd7556e22011-05-31 15:49:26 +02001966 hci_conn_hold(conn);
1967 conn->disc_timeout = HCI_DISCONN_TIMEOUT;
1968 hci_conn_put(conn);
1969 }
1970
Johan Hedberg51a8efd2012-01-16 06:10:31 +02001971 if (test_bit(HCI_CONN_ENCRYPT_PEND, &conn->flags)) {
Waldemar Rymarkiewiczd7556e22011-05-31 15:49:26 +02001972 if (!ev->status) {
1973 struct hci_cp_set_conn_encrypt cp;
1974 cp.handle = ev->handle;
1975 cp.encrypt = 0x01;
1976 hci_send_cmd(hdev, HCI_OP_SET_CONN_ENCRYPT, sizeof(cp),
1977 &cp);
1978 } else {
Johan Hedberg51a8efd2012-01-16 06:10:31 +02001979 clear_bit(HCI_CONN_ENCRYPT_PEND, &conn->flags);
Waldemar Rymarkiewiczd7556e22011-05-31 15:49:26 +02001980 hci_encrypt_cfm(conn, ev->status, 0x00);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001981 }
1982 }
1983
Waldemar Rymarkiewiczd7556e22011-05-31 15:49:26 +02001984unlock:
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001985 hci_dev_unlock(hdev);
1986}
1987
1988static inline void hci_remote_name_evt(struct hci_dev *hdev, struct sk_buff *skb)
1989{
Johan Hedberg127178d2010-11-18 22:22:29 +02001990 struct hci_ev_remote_name *ev = (void *) skb->data;
1991 struct hci_conn *conn;
1992
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001993 BT_DBG("%s", hdev->name);
1994
1995 hci_conn_check_pending(hdev);
Johan Hedberg127178d2010-11-18 22:22:29 +02001996
1997 hci_dev_lock(hdev);
1998
1999 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
Johan Hedbergb644ba32012-01-17 21:48:47 +02002000
2001 if (!test_bit(HCI_MGMT, &hdev->dev_flags))
2002 goto check_auth;
2003
2004 if (ev->status == 0)
2005 hci_check_pending_name(hdev, conn, &ev->bdaddr, ev->name,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002006 strnlen(ev->name, HCI_MAX_NAME_LENGTH));
Johan Hedbergb644ba32012-01-17 21:48:47 +02002007 else
2008 hci_check_pending_name(hdev, conn, &ev->bdaddr, NULL, 0);
2009
2010check_auth:
Johan Hedberg79c6c702011-04-28 11:28:55 -07002011 if (!conn)
2012 goto unlock;
2013
2014 if (!hci_outgoing_auth_needed(hdev, conn))
2015 goto unlock;
2016
Johan Hedberg51a8efd2012-01-16 06:10:31 +02002017 if (!test_and_set_bit(HCI_CONN_AUTH_PEND, &conn->flags)) {
Johan Hedberg127178d2010-11-18 22:22:29 +02002018 struct hci_cp_auth_requested cp;
2019 cp.handle = __cpu_to_le16(conn->handle);
2020 hci_send_cmd(hdev, HCI_OP_AUTH_REQUESTED, sizeof(cp), &cp);
2021 }
2022
Johan Hedberg79c6c702011-04-28 11:28:55 -07002023unlock:
Johan Hedberg127178d2010-11-18 22:22:29 +02002024 hci_dev_unlock(hdev);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002025}
2026
2027static inline void hci_encrypt_change_evt(struct hci_dev *hdev, struct sk_buff *skb)
2028{
2029 struct hci_ev_encrypt_change *ev = (void *) skb->data;
2030 struct hci_conn *conn;
2031
2032 BT_DBG("%s status %d", hdev->name, ev->status);
2033
2034 hci_dev_lock(hdev);
2035
2036 conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
2037 if (conn) {
2038 if (!ev->status) {
Marcel Holtmannae293192008-07-14 20:13:45 +02002039 if (ev->encrypt) {
2040 /* Encryption implies authentication */
2041 conn->link_mode |= HCI_LM_AUTH;
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002042 conn->link_mode |= HCI_LM_ENCRYPT;
Vinicius Costa Gomesda85e5e2011-06-09 18:50:53 -03002043 conn->sec_level = conn->pending_sec_level;
Marcel Holtmannae293192008-07-14 20:13:45 +02002044 } else
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002045 conn->link_mode &= ~HCI_LM_ENCRYPT;
2046 }
2047
Johan Hedberg51a8efd2012-01-16 06:10:31 +02002048 clear_bit(HCI_CONN_ENCRYPT_PEND, &conn->flags);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002049
Marcel Holtmannf8558552008-07-14 20:13:49 +02002050 if (conn->state == BT_CONFIG) {
2051 if (!ev->status)
2052 conn->state = BT_CONNECTED;
2053
2054 hci_proto_connect_cfm(conn, ev->status);
2055 hci_conn_put(conn);
2056 } else
2057 hci_encrypt_cfm(conn, ev->status, ev->encrypt);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002058 }
2059
2060 hci_dev_unlock(hdev);
2061}
2062
2063static inline void hci_change_link_key_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
2064{
2065 struct hci_ev_change_link_key_complete *ev = (void *) skb->data;
2066 struct hci_conn *conn;
2067
2068 BT_DBG("%s status %d", hdev->name, ev->status);
2069
2070 hci_dev_lock(hdev);
2071
2072 conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
2073 if (conn) {
2074 if (!ev->status)
2075 conn->link_mode |= HCI_LM_SECURE;
2076
Johan Hedberg51a8efd2012-01-16 06:10:31 +02002077 clear_bit(HCI_CONN_AUTH_PEND, &conn->flags);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002078
2079 hci_key_change_cfm(conn, ev->status);
2080 }
2081
2082 hci_dev_unlock(hdev);
2083}
2084
2085static inline void hci_remote_features_evt(struct hci_dev *hdev, struct sk_buff *skb)
2086{
2087 struct hci_ev_remote_features *ev = (void *) skb->data;
2088 struct hci_conn *conn;
2089
2090 BT_DBG("%s status %d", hdev->name, ev->status);
2091
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002092 hci_dev_lock(hdev);
2093
2094 conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
Johan Hedbergccd556f2010-11-10 17:11:51 +02002095 if (!conn)
2096 goto unlock;
Marcel Holtmann769be972008-07-14 20:13:49 +02002097
Johan Hedbergccd556f2010-11-10 17:11:51 +02002098 if (!ev->status)
2099 memcpy(conn->features, ev->features, 8);
2100
2101 if (conn->state != BT_CONFIG)
2102 goto unlock;
2103
2104 if (!ev->status && lmp_ssp_capable(hdev) && lmp_ssp_capable(conn)) {
2105 struct hci_cp_read_remote_ext_features cp;
2106 cp.handle = ev->handle;
2107 cp.page = 0x01;
2108 hci_send_cmd(hdev, HCI_OP_READ_REMOTE_EXT_FEATURES,
Marcel Holtmann769be972008-07-14 20:13:49 +02002109 sizeof(cp), &cp);
Johan Hedberg392599b2010-11-18 22:22:28 +02002110 goto unlock;
2111 }
2112
Johan Hedberg127178d2010-11-18 22:22:29 +02002113 if (!ev->status) {
2114 struct hci_cp_remote_name_req cp;
2115 memset(&cp, 0, sizeof(cp));
2116 bacpy(&cp.bdaddr, &conn->dst);
2117 cp.pscan_rep_mode = 0x02;
2118 hci_send_cmd(hdev, HCI_OP_REMOTE_NAME_REQ, sizeof(cp), &cp);
Johan Hedbergb644ba32012-01-17 21:48:47 +02002119 } else if (!test_and_set_bit(HCI_CONN_MGMT_CONNECTED, &conn->flags))
2120 mgmt_device_connected(hdev, &conn->dst, conn->type,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002121 conn->dst_type, 0, NULL, 0,
2122 conn->dev_class);
Johan Hedberg392599b2010-11-18 22:22:28 +02002123
Johan Hedberg127178d2010-11-18 22:22:29 +02002124 if (!hci_outgoing_auth_needed(hdev, conn)) {
Johan Hedbergccd556f2010-11-10 17:11:51 +02002125 conn->state = BT_CONNECTED;
2126 hci_proto_connect_cfm(conn, ev->status);
2127 hci_conn_put(conn);
Marcel Holtmann769be972008-07-14 20:13:49 +02002128 }
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002129
Johan Hedbergccd556f2010-11-10 17:11:51 +02002130unlock:
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002131 hci_dev_unlock(hdev);
2132}
2133
2134static inline void hci_remote_version_evt(struct hci_dev *hdev, struct sk_buff *skb)
2135{
2136 BT_DBG("%s", hdev->name);
2137}
2138
2139static inline void hci_qos_setup_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
2140{
2141 BT_DBG("%s", hdev->name);
2142}
2143
2144static inline void hci_cmd_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
2145{
2146 struct hci_ev_cmd_complete *ev = (void *) skb->data;
2147 __u16 opcode;
2148
2149 skb_pull(skb, sizeof(*ev));
2150
2151 opcode = __le16_to_cpu(ev->opcode);
2152
2153 switch (opcode) {
2154 case HCI_OP_INQUIRY_CANCEL:
2155 hci_cc_inquiry_cancel(hdev, skb);
2156 break;
2157
2158 case HCI_OP_EXIT_PERIODIC_INQ:
2159 hci_cc_exit_periodic_inq(hdev, skb);
2160 break;
2161
2162 case HCI_OP_REMOTE_NAME_REQ_CANCEL:
2163 hci_cc_remote_name_req_cancel(hdev, skb);
2164 break;
2165
2166 case HCI_OP_ROLE_DISCOVERY:
2167 hci_cc_role_discovery(hdev, skb);
2168 break;
2169
Marcel Holtmanne4e8e372008-07-14 20:13:47 +02002170 case HCI_OP_READ_LINK_POLICY:
2171 hci_cc_read_link_policy(hdev, skb);
2172 break;
2173
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002174 case HCI_OP_WRITE_LINK_POLICY:
2175 hci_cc_write_link_policy(hdev, skb);
2176 break;
2177
Marcel Holtmanne4e8e372008-07-14 20:13:47 +02002178 case HCI_OP_READ_DEF_LINK_POLICY:
2179 hci_cc_read_def_link_policy(hdev, skb);
2180 break;
2181
2182 case HCI_OP_WRITE_DEF_LINK_POLICY:
2183 hci_cc_write_def_link_policy(hdev, skb);
2184 break;
2185
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002186 case HCI_OP_RESET:
2187 hci_cc_reset(hdev, skb);
2188 break;
2189
2190 case HCI_OP_WRITE_LOCAL_NAME:
2191 hci_cc_write_local_name(hdev, skb);
2192 break;
2193
2194 case HCI_OP_READ_LOCAL_NAME:
2195 hci_cc_read_local_name(hdev, skb);
2196 break;
2197
2198 case HCI_OP_WRITE_AUTH_ENABLE:
2199 hci_cc_write_auth_enable(hdev, skb);
2200 break;
2201
2202 case HCI_OP_WRITE_ENCRYPT_MODE:
2203 hci_cc_write_encrypt_mode(hdev, skb);
2204 break;
2205
2206 case HCI_OP_WRITE_SCAN_ENABLE:
2207 hci_cc_write_scan_enable(hdev, skb);
2208 break;
2209
2210 case HCI_OP_READ_CLASS_OF_DEV:
2211 hci_cc_read_class_of_dev(hdev, skb);
2212 break;
2213
2214 case HCI_OP_WRITE_CLASS_OF_DEV:
2215 hci_cc_write_class_of_dev(hdev, skb);
2216 break;
2217
2218 case HCI_OP_READ_VOICE_SETTING:
2219 hci_cc_read_voice_setting(hdev, skb);
2220 break;
2221
2222 case HCI_OP_WRITE_VOICE_SETTING:
2223 hci_cc_write_voice_setting(hdev, skb);
2224 break;
2225
2226 case HCI_OP_HOST_BUFFER_SIZE:
2227 hci_cc_host_buffer_size(hdev, skb);
2228 break;
2229
Marcel Holtmann333140b2008-07-14 20:13:48 +02002230 case HCI_OP_WRITE_SSP_MODE:
2231 hci_cc_write_ssp_mode(hdev, skb);
2232 break;
2233
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002234 case HCI_OP_READ_LOCAL_VERSION:
2235 hci_cc_read_local_version(hdev, skb);
2236 break;
2237
2238 case HCI_OP_READ_LOCAL_COMMANDS:
2239 hci_cc_read_local_commands(hdev, skb);
2240 break;
2241
2242 case HCI_OP_READ_LOCAL_FEATURES:
2243 hci_cc_read_local_features(hdev, skb);
2244 break;
2245
Andre Guedes971e3a42011-06-30 19:20:52 -03002246 case HCI_OP_READ_LOCAL_EXT_FEATURES:
2247 hci_cc_read_local_ext_features(hdev, skb);
2248 break;
2249
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002250 case HCI_OP_READ_BUFFER_SIZE:
2251 hci_cc_read_buffer_size(hdev, skb);
2252 break;
2253
2254 case HCI_OP_READ_BD_ADDR:
2255 hci_cc_read_bd_addr(hdev, skb);
2256 break;
2257
Andrei Emeltchenko350ee4c2011-12-07 15:56:51 +02002258 case HCI_OP_READ_DATA_BLOCK_SIZE:
2259 hci_cc_read_data_block_size(hdev, skb);
2260 break;
2261
Johan Hedberg23bb5762010-12-21 23:01:27 +02002262 case HCI_OP_WRITE_CA_TIMEOUT:
2263 hci_cc_write_ca_timeout(hdev, skb);
2264 break;
2265
Andrei Emeltchenko1e89cff2011-11-24 14:52:02 +02002266 case HCI_OP_READ_FLOW_CONTROL_MODE:
2267 hci_cc_read_flow_control_mode(hdev, skb);
2268 break;
2269
Andrei Emeltchenko928abaa2011-10-12 10:53:57 +03002270 case HCI_OP_READ_LOCAL_AMP_INFO:
2271 hci_cc_read_local_amp_info(hdev, skb);
2272 break;
2273
Johan Hedbergb0916ea2011-01-10 13:44:55 +02002274 case HCI_OP_DELETE_STORED_LINK_KEY:
2275 hci_cc_delete_stored_link_key(hdev, skb);
2276 break;
2277
Johan Hedbergd5859e22011-01-25 01:19:58 +02002278 case HCI_OP_SET_EVENT_MASK:
2279 hci_cc_set_event_mask(hdev, skb);
2280 break;
2281
2282 case HCI_OP_WRITE_INQUIRY_MODE:
2283 hci_cc_write_inquiry_mode(hdev, skb);
2284 break;
2285
2286 case HCI_OP_READ_INQ_RSP_TX_POWER:
2287 hci_cc_read_inq_rsp_tx_power(hdev, skb);
2288 break;
2289
2290 case HCI_OP_SET_EVENT_FLT:
2291 hci_cc_set_event_flt(hdev, skb);
2292 break;
2293
Johan Hedberg980e1a52011-01-22 06:10:07 +02002294 case HCI_OP_PIN_CODE_REPLY:
2295 hci_cc_pin_code_reply(hdev, skb);
2296 break;
2297
2298 case HCI_OP_PIN_CODE_NEG_REPLY:
2299 hci_cc_pin_code_neg_reply(hdev, skb);
2300 break;
2301
Szymon Jancc35938b2011-03-22 13:12:21 +01002302 case HCI_OP_READ_LOCAL_OOB_DATA:
2303 hci_cc_read_local_oob_data_reply(hdev, skb);
2304 break;
2305
Ville Tervo6ed58ec2011-02-10 22:38:48 -03002306 case HCI_OP_LE_READ_BUFFER_SIZE:
2307 hci_cc_le_read_buffer_size(hdev, skb);
2308 break;
2309
Johan Hedberga5c29682011-02-19 12:05:57 -03002310 case HCI_OP_USER_CONFIRM_REPLY:
2311 hci_cc_user_confirm_reply(hdev, skb);
2312 break;
2313
2314 case HCI_OP_USER_CONFIRM_NEG_REPLY:
2315 hci_cc_user_confirm_neg_reply(hdev, skb);
2316 break;
2317
Brian Gix1143d452011-11-23 08:28:34 -08002318 case HCI_OP_USER_PASSKEY_REPLY:
2319 hci_cc_user_passkey_reply(hdev, skb);
2320 break;
2321
2322 case HCI_OP_USER_PASSKEY_NEG_REPLY:
2323 hci_cc_user_passkey_neg_reply(hdev, skb);
Szymon Janc16cde992012-04-13 12:32:42 +02002324 break;
Andre Guedes07f7fa52011-12-02 21:13:31 +09002325
2326 case HCI_OP_LE_SET_SCAN_PARAM:
2327 hci_cc_le_set_scan_param(hdev, skb);
Brian Gix1143d452011-11-23 08:28:34 -08002328 break;
2329
Andre Guedeseb9d91f2011-05-26 16:23:52 -03002330 case HCI_OP_LE_SET_SCAN_ENABLE:
2331 hci_cc_le_set_scan_enable(hdev, skb);
2332 break;
2333
Vinicius Costa Gomesa7a595f2011-06-09 18:50:47 -03002334 case HCI_OP_LE_LTK_REPLY:
2335 hci_cc_le_ltk_reply(hdev, skb);
2336 break;
2337
2338 case HCI_OP_LE_LTK_NEG_REPLY:
2339 hci_cc_le_ltk_neg_reply(hdev, skb);
2340 break;
2341
Andre Guedesf9b49302011-06-30 19:20:53 -03002342 case HCI_OP_WRITE_LE_HOST_SUPPORTED:
2343 hci_cc_write_le_host_supported(hdev, skb);
2344 break;
2345
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002346 default:
2347 BT_DBG("%s opcode 0x%x", hdev->name, opcode);
2348 break;
2349 }
2350
Ville Tervo6bd32322011-02-16 16:32:41 +02002351 if (ev->opcode != HCI_OP_NOP)
2352 del_timer(&hdev->cmd_timer);
2353
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002354 if (ev->ncmd) {
2355 atomic_set(&hdev->cmd_cnt, 1);
2356 if (!skb_queue_empty(&hdev->cmd_q))
Gustavo F. Padovanc347b762011-12-14 23:53:47 -02002357 queue_work(hdev->workqueue, &hdev->cmd_work);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002358 }
2359}
2360
2361static inline void hci_cmd_status_evt(struct hci_dev *hdev, struct sk_buff *skb)
2362{
2363 struct hci_ev_cmd_status *ev = (void *) skb->data;
2364 __u16 opcode;
2365
2366 skb_pull(skb, sizeof(*ev));
2367
2368 opcode = __le16_to_cpu(ev->opcode);
2369
2370 switch (opcode) {
2371 case HCI_OP_INQUIRY:
2372 hci_cs_inquiry(hdev, ev->status);
2373 break;
2374
2375 case HCI_OP_CREATE_CONN:
2376 hci_cs_create_conn(hdev, ev->status);
2377 break;
2378
2379 case HCI_OP_ADD_SCO:
2380 hci_cs_add_sco(hdev, ev->status);
2381 break;
2382
Marcel Holtmannf8558552008-07-14 20:13:49 +02002383 case HCI_OP_AUTH_REQUESTED:
2384 hci_cs_auth_requested(hdev, ev->status);
2385 break;
2386
2387 case HCI_OP_SET_CONN_ENCRYPT:
2388 hci_cs_set_conn_encrypt(hdev, ev->status);
2389 break;
2390
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002391 case HCI_OP_REMOTE_NAME_REQ:
2392 hci_cs_remote_name_req(hdev, ev->status);
2393 break;
2394
Marcel Holtmann769be972008-07-14 20:13:49 +02002395 case HCI_OP_READ_REMOTE_FEATURES:
2396 hci_cs_read_remote_features(hdev, ev->status);
2397 break;
2398
2399 case HCI_OP_READ_REMOTE_EXT_FEATURES:
2400 hci_cs_read_remote_ext_features(hdev, ev->status);
2401 break;
2402
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002403 case HCI_OP_SETUP_SYNC_CONN:
2404 hci_cs_setup_sync_conn(hdev, ev->status);
2405 break;
2406
2407 case HCI_OP_SNIFF_MODE:
2408 hci_cs_sniff_mode(hdev, ev->status);
2409 break;
2410
2411 case HCI_OP_EXIT_SNIFF_MODE:
2412 hci_cs_exit_sniff_mode(hdev, ev->status);
2413 break;
2414
Johan Hedberg8962ee72011-01-20 12:40:27 +02002415 case HCI_OP_DISCONNECT:
Johan Hedberg88c3df12012-02-09 14:27:38 +02002416 hci_cs_disconnect(hdev, ev->status);
Johan Hedberg8962ee72011-01-20 12:40:27 +02002417 break;
2418
Ville Tervofcd89c02011-02-10 22:38:47 -03002419 case HCI_OP_LE_CREATE_CONN:
2420 hci_cs_le_create_conn(hdev, ev->status);
2421 break;
2422
Vinicius Costa Gomesa7a595f2011-06-09 18:50:47 -03002423 case HCI_OP_LE_START_ENC:
2424 hci_cs_le_start_enc(hdev, ev->status);
2425 break;
2426
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002427 default:
2428 BT_DBG("%s opcode 0x%x", hdev->name, opcode);
2429 break;
2430 }
2431
Ville Tervo6bd32322011-02-16 16:32:41 +02002432 if (ev->opcode != HCI_OP_NOP)
2433 del_timer(&hdev->cmd_timer);
2434
Gustavo F. Padovan10572132011-03-16 15:36:29 -03002435 if (ev->ncmd && !test_bit(HCI_RESET, &hdev->flags)) {
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002436 atomic_set(&hdev->cmd_cnt, 1);
2437 if (!skb_queue_empty(&hdev->cmd_q))
Gustavo F. Padovanc347b762011-12-14 23:53:47 -02002438 queue_work(hdev->workqueue, &hdev->cmd_work);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002439 }
2440}
2441
2442static inline void hci_role_change_evt(struct hci_dev *hdev, struct sk_buff *skb)
2443{
2444 struct hci_ev_role_change *ev = (void *) skb->data;
2445 struct hci_conn *conn;
2446
2447 BT_DBG("%s status %d", hdev->name, ev->status);
2448
2449 hci_dev_lock(hdev);
2450
2451 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
2452 if (conn) {
2453 if (!ev->status) {
2454 if (ev->role)
2455 conn->link_mode &= ~HCI_LM_MASTER;
2456 else
2457 conn->link_mode |= HCI_LM_MASTER;
2458 }
2459
Johan Hedberg51a8efd2012-01-16 06:10:31 +02002460 clear_bit(HCI_CONN_RSWITCH_PEND, &conn->flags);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002461
2462 hci_role_switch_cfm(conn, ev->status, ev->role);
2463 }
2464
2465 hci_dev_unlock(hdev);
2466}
2467
Linus Torvalds1da177e2005-04-16 15:20:36 -07002468static inline void hci_num_comp_pkts_evt(struct hci_dev *hdev, struct sk_buff *skb)
2469{
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002470 struct hci_ev_num_comp_pkts *ev = (void *) skb->data;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002471 int i;
2472
Andrei Emeltchenko32ac5b92011-12-19 16:31:29 +02002473 if (hdev->flow_ctl_mode != HCI_FLOW_CTL_MODE_PACKET_BASED) {
2474 BT_ERR("Wrong event for mode %d", hdev->flow_ctl_mode);
2475 return;
2476 }
2477
Andrei Emeltchenkoc5993de2011-12-30 12:07:47 +02002478 if (skb->len < sizeof(*ev) || skb->len < sizeof(*ev) +
2479 ev->num_hndl * sizeof(struct hci_comp_pkts_info)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002480 BT_DBG("%s bad parameters", hdev->name);
2481 return;
2482 }
2483
Andrei Emeltchenkoc5993de2011-12-30 12:07:47 +02002484 BT_DBG("%s num_hndl %d", hdev->name, ev->num_hndl);
2485
Andrei Emeltchenko613a1c02011-12-19 16:31:30 +02002486 for (i = 0; i < ev->num_hndl; i++) {
2487 struct hci_comp_pkts_info *info = &ev->handles[i];
Linus Torvalds1da177e2005-04-16 15:20:36 -07002488 struct hci_conn *conn;
2489 __u16 handle, count;
2490
Andrei Emeltchenko613a1c02011-12-19 16:31:30 +02002491 handle = __le16_to_cpu(info->handle);
2492 count = __le16_to_cpu(info->count);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002493
2494 conn = hci_conn_hash_lookup_handle(hdev, handle);
Andrei Emeltchenkof4280912011-12-07 15:56:52 +02002495 if (!conn)
2496 continue;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002497
Andrei Emeltchenkof4280912011-12-07 15:56:52 +02002498 conn->sent -= count;
2499
2500 switch (conn->type) {
2501 case ACL_LINK:
2502 hdev->acl_cnt += count;
2503 if (hdev->acl_cnt > hdev->acl_pkts)
2504 hdev->acl_cnt = hdev->acl_pkts;
2505 break;
2506
2507 case LE_LINK:
2508 if (hdev->le_pkts) {
2509 hdev->le_cnt += count;
2510 if (hdev->le_cnt > hdev->le_pkts)
2511 hdev->le_cnt = hdev->le_pkts;
2512 } else {
Andrei Emeltchenko70f230202010-12-01 16:58:25 +02002513 hdev->acl_cnt += count;
2514 if (hdev->acl_cnt > hdev->acl_pkts)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002515 hdev->acl_cnt = hdev->acl_pkts;
2516 }
Andrei Emeltchenkof4280912011-12-07 15:56:52 +02002517 break;
2518
2519 case SCO_LINK:
2520 hdev->sco_cnt += count;
2521 if (hdev->sco_cnt > hdev->sco_pkts)
2522 hdev->sco_cnt = hdev->sco_pkts;
2523 break;
2524
2525 default:
2526 BT_ERR("Unknown type %d conn %p", conn->type, conn);
2527 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002528 }
2529 }
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002530
Gustavo F. Padovan3eff45e2011-12-15 00:50:02 -02002531 queue_work(hdev->workqueue, &hdev->tx_work);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002532}
2533
Andrei Emeltchenko25e89e92012-01-04 12:41:58 +02002534static inline void hci_num_comp_blocks_evt(struct hci_dev *hdev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002535 struct sk_buff *skb)
Andrei Emeltchenko25e89e92012-01-04 12:41:58 +02002536{
2537 struct hci_ev_num_comp_blocks *ev = (void *) skb->data;
2538 int i;
2539
2540 if (hdev->flow_ctl_mode != HCI_FLOW_CTL_MODE_BLOCK_BASED) {
2541 BT_ERR("Wrong event for mode %d", hdev->flow_ctl_mode);
2542 return;
2543 }
2544
2545 if (skb->len < sizeof(*ev) || skb->len < sizeof(*ev) +
2546 ev->num_hndl * sizeof(struct hci_comp_blocks_info)) {
2547 BT_DBG("%s bad parameters", hdev->name);
2548 return;
2549 }
2550
2551 BT_DBG("%s num_blocks %d num_hndl %d", hdev->name, ev->num_blocks,
2552 ev->num_hndl);
2553
2554 for (i = 0; i < ev->num_hndl; i++) {
2555 struct hci_comp_blocks_info *info = &ev->handles[i];
2556 struct hci_conn *conn;
2557 __u16 handle, block_count;
2558
2559 handle = __le16_to_cpu(info->handle);
2560 block_count = __le16_to_cpu(info->blocks);
2561
2562 conn = hci_conn_hash_lookup_handle(hdev, handle);
2563 if (!conn)
2564 continue;
2565
2566 conn->sent -= block_count;
2567
2568 switch (conn->type) {
2569 case ACL_LINK:
2570 hdev->block_cnt += block_count;
2571 if (hdev->block_cnt > hdev->num_blocks)
2572 hdev->block_cnt = hdev->num_blocks;
2573 break;
2574
2575 default:
2576 BT_ERR("Unknown type %d conn %p", conn->type, conn);
2577 break;
2578 }
2579 }
2580
2581 queue_work(hdev->workqueue, &hdev->tx_work);
2582}
2583
Marcel Holtmann04837f62006-07-03 10:02:33 +02002584static inline void hci_mode_change_evt(struct hci_dev *hdev, struct sk_buff *skb)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002585{
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002586 struct hci_ev_mode_change *ev = (void *) skb->data;
Marcel Holtmann04837f62006-07-03 10:02:33 +02002587 struct hci_conn *conn;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002588
2589 BT_DBG("%s status %d", hdev->name, ev->status);
2590
2591 hci_dev_lock(hdev);
2592
Marcel Holtmann04837f62006-07-03 10:02:33 +02002593 conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
2594 if (conn) {
2595 conn->mode = ev->mode;
2596 conn->interval = __le16_to_cpu(ev->interval);
2597
Johan Hedberg51a8efd2012-01-16 06:10:31 +02002598 if (!test_and_clear_bit(HCI_CONN_MODE_CHANGE_PEND, &conn->flags)) {
Marcel Holtmann04837f62006-07-03 10:02:33 +02002599 if (conn->mode == HCI_CM_ACTIVE)
Johan Hedberg58a681e2012-01-16 06:47:28 +02002600 set_bit(HCI_CONN_POWER_SAVE, &conn->flags);
Marcel Holtmann04837f62006-07-03 10:02:33 +02002601 else
Johan Hedberg58a681e2012-01-16 06:47:28 +02002602 clear_bit(HCI_CONN_POWER_SAVE, &conn->flags);
Marcel Holtmann04837f62006-07-03 10:02:33 +02002603 }
Marcel Holtmanne73439d2010-07-26 10:06:00 -04002604
Johan Hedberg51a8efd2012-01-16 06:10:31 +02002605 if (test_and_clear_bit(HCI_CONN_SCO_SETUP_PEND, &conn->flags))
Marcel Holtmanne73439d2010-07-26 10:06:00 -04002606 hci_sco_setup(conn, ev->status);
Marcel Holtmann04837f62006-07-03 10:02:33 +02002607 }
2608
2609 hci_dev_unlock(hdev);
2610}
2611
Linus Torvalds1da177e2005-04-16 15:20:36 -07002612static inline void hci_pin_code_request_evt(struct hci_dev *hdev, struct sk_buff *skb)
2613{
Marcel Holtmann052b30b2009-04-26 20:01:22 +02002614 struct hci_ev_pin_code_req *ev = (void *) skb->data;
2615 struct hci_conn *conn;
2616
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002617 BT_DBG("%s", hdev->name);
Marcel Holtmann052b30b2009-04-26 20:01:22 +02002618
2619 hci_dev_lock(hdev);
2620
2621 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
Waldemar Rymarkiewiczb6f98042011-09-23 10:01:30 +02002622 if (!conn)
2623 goto unlock;
2624
2625 if (conn->state == BT_CONNECTED) {
Marcel Holtmann052b30b2009-04-26 20:01:22 +02002626 hci_conn_hold(conn);
2627 conn->disc_timeout = HCI_PAIRING_TIMEOUT;
2628 hci_conn_put(conn);
2629 }
2630
Johan Hedberga8b2d5c2012-01-08 23:11:15 +02002631 if (!test_bit(HCI_PAIRABLE, &hdev->dev_flags))
Johan Hedberg03b555e2011-01-04 15:40:05 +02002632 hci_send_cmd(hdev, HCI_OP_PIN_CODE_NEG_REPLY,
2633 sizeof(ev->bdaddr), &ev->bdaddr);
Johan Hedberga8b2d5c2012-01-08 23:11:15 +02002634 else if (test_bit(HCI_MGMT, &hdev->dev_flags)) {
Waldemar Rymarkiewicza770bb52011-04-28 12:07:59 +02002635 u8 secure;
2636
2637 if (conn->pending_sec_level == BT_SECURITY_HIGH)
2638 secure = 1;
2639 else
2640 secure = 0;
2641
Johan Hedberg744cf192011-11-08 20:40:14 +02002642 mgmt_pin_code_request(hdev, &ev->bdaddr, secure);
Waldemar Rymarkiewicza770bb52011-04-28 12:07:59 +02002643 }
Johan Hedberg980e1a52011-01-22 06:10:07 +02002644
Waldemar Rymarkiewiczb6f98042011-09-23 10:01:30 +02002645unlock:
Marcel Holtmann052b30b2009-04-26 20:01:22 +02002646 hci_dev_unlock(hdev);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002647}
2648
Linus Torvalds1da177e2005-04-16 15:20:36 -07002649static inline void hci_link_key_request_evt(struct hci_dev *hdev, struct sk_buff *skb)
2650{
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002651 struct hci_ev_link_key_req *ev = (void *) skb->data;
2652 struct hci_cp_link_key_reply cp;
2653 struct hci_conn *conn;
2654 struct link_key *key;
2655
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002656 BT_DBG("%s", hdev->name);
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002657
Johan Hedberga8b2d5c2012-01-08 23:11:15 +02002658 if (!test_bit(HCI_LINK_KEYS, &hdev->dev_flags))
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002659 return;
2660
2661 hci_dev_lock(hdev);
2662
2663 key = hci_find_link_key(hdev, &ev->bdaddr);
2664 if (!key) {
2665 BT_DBG("%s link key not found for %s", hdev->name,
2666 batostr(&ev->bdaddr));
2667 goto not_found;
2668 }
2669
2670 BT_DBG("%s found key type %u for %s", hdev->name, key->type,
2671 batostr(&ev->bdaddr));
2672
Johan Hedberga8b2d5c2012-01-08 23:11:15 +02002673 if (!test_bit(HCI_DEBUG_KEYS, &hdev->dev_flags) &&
Waldemar Rymarkiewiczb6020ba2011-04-28 12:07:53 +02002674 key->type == HCI_LK_DEBUG_COMBINATION) {
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002675 BT_DBG("%s ignoring debug key", hdev->name);
2676 goto not_found;
2677 }
2678
2679 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
Waldemar Rymarkiewicz60b83f52011-04-28 12:07:56 +02002680 if (conn) {
2681 if (key->type == HCI_LK_UNAUTH_COMBINATION &&
2682 conn->auth_type != 0xff &&
2683 (conn->auth_type & 0x01)) {
2684 BT_DBG("%s ignoring unauthenticated key", hdev->name);
2685 goto not_found;
2686 }
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002687
Waldemar Rymarkiewicz60b83f52011-04-28 12:07:56 +02002688 if (key->type == HCI_LK_COMBINATION && key->pin_len < 16 &&
2689 conn->pending_sec_level == BT_SECURITY_HIGH) {
2690 BT_DBG("%s ignoring key unauthenticated for high \
2691 security", hdev->name);
2692 goto not_found;
2693 }
2694
2695 conn->key_type = key->type;
2696 conn->pin_length = key->pin_len;
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002697 }
2698
2699 bacpy(&cp.bdaddr, &ev->bdaddr);
2700 memcpy(cp.link_key, key->val, 16);
2701
2702 hci_send_cmd(hdev, HCI_OP_LINK_KEY_REPLY, sizeof(cp), &cp);
2703
2704 hci_dev_unlock(hdev);
2705
2706 return;
2707
2708not_found:
2709 hci_send_cmd(hdev, HCI_OP_LINK_KEY_NEG_REPLY, 6, &ev->bdaddr);
2710 hci_dev_unlock(hdev);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002711}
2712
Linus Torvalds1da177e2005-04-16 15:20:36 -07002713static inline void hci_link_key_notify_evt(struct hci_dev *hdev, struct sk_buff *skb)
2714{
Marcel Holtmann052b30b2009-04-26 20:01:22 +02002715 struct hci_ev_link_key_notify *ev = (void *) skb->data;
2716 struct hci_conn *conn;
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002717 u8 pin_len = 0;
Marcel Holtmann052b30b2009-04-26 20:01:22 +02002718
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002719 BT_DBG("%s", hdev->name);
Marcel Holtmann052b30b2009-04-26 20:01:22 +02002720
2721 hci_dev_lock(hdev);
2722
2723 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
2724 if (conn) {
2725 hci_conn_hold(conn);
2726 conn->disc_timeout = HCI_DISCONN_TIMEOUT;
Johan Hedberg980e1a52011-01-22 06:10:07 +02002727 pin_len = conn->pin_length;
Waldemar Rymarkiewicz13d39312011-04-28 12:07:55 +02002728
2729 if (ev->key_type != HCI_LK_CHANGED_COMBINATION)
2730 conn->key_type = ev->key_type;
2731
Marcel Holtmann052b30b2009-04-26 20:01:22 +02002732 hci_conn_put(conn);
2733 }
2734
Johan Hedberga8b2d5c2012-01-08 23:11:15 +02002735 if (test_bit(HCI_LINK_KEYS, &hdev->dev_flags))
Johan Hedbergd25e28a2011-04-28 11:28:59 -07002736 hci_add_link_key(hdev, conn, 1, &ev->bdaddr, ev->link_key,
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002737 ev->key_type, pin_len);
2738
Marcel Holtmann052b30b2009-04-26 20:01:22 +02002739 hci_dev_unlock(hdev);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002740}
2741
Marcel Holtmann04837f62006-07-03 10:02:33 +02002742static inline void hci_clock_offset_evt(struct hci_dev *hdev, struct sk_buff *skb)
2743{
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002744 struct hci_ev_clock_offset *ev = (void *) skb->data;
Marcel Holtmann04837f62006-07-03 10:02:33 +02002745 struct hci_conn *conn;
2746
2747 BT_DBG("%s status %d", hdev->name, ev->status);
2748
2749 hci_dev_lock(hdev);
2750
2751 conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
Linus Torvalds1da177e2005-04-16 15:20:36 -07002752 if (conn && !ev->status) {
2753 struct inquiry_entry *ie;
2754
Andrei Emeltchenkocc11b9c2010-11-22 13:21:37 +02002755 ie = hci_inquiry_cache_lookup(hdev, &conn->dst);
2756 if (ie) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002757 ie->data.clock_offset = ev->clock_offset;
2758 ie->timestamp = jiffies;
2759 }
2760 }
2761
2762 hci_dev_unlock(hdev);
2763}
2764
Marcel Holtmanna8746412008-07-14 20:13:46 +02002765static inline void hci_pkt_type_change_evt(struct hci_dev *hdev, struct sk_buff *skb)
2766{
2767 struct hci_ev_pkt_type_change *ev = (void *) skb->data;
2768 struct hci_conn *conn;
2769
2770 BT_DBG("%s status %d", hdev->name, ev->status);
2771
2772 hci_dev_lock(hdev);
2773
2774 conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
2775 if (conn && !ev->status)
2776 conn->pkt_type = __le16_to_cpu(ev->pkt_type);
2777
2778 hci_dev_unlock(hdev);
2779}
2780
Marcel Holtmann85a1e932005-08-09 20:28:02 -07002781static inline void hci_pscan_rep_mode_evt(struct hci_dev *hdev, struct sk_buff *skb)
2782{
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002783 struct hci_ev_pscan_rep_mode *ev = (void *) skb->data;
Marcel Holtmann85a1e932005-08-09 20:28:02 -07002784 struct inquiry_entry *ie;
2785
2786 BT_DBG("%s", hdev->name);
2787
2788 hci_dev_lock(hdev);
2789
Andrei Emeltchenkocc11b9c2010-11-22 13:21:37 +02002790 ie = hci_inquiry_cache_lookup(hdev, &ev->bdaddr);
2791 if (ie) {
Marcel Holtmann85a1e932005-08-09 20:28:02 -07002792 ie->data.pscan_rep_mode = ev->pscan_rep_mode;
2793 ie->timestamp = jiffies;
2794 }
2795
2796 hci_dev_unlock(hdev);
2797}
2798
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002799static inline void hci_inquiry_result_with_rssi_evt(struct hci_dev *hdev, struct sk_buff *skb)
2800{
2801 struct inquiry_data data;
2802 int num_rsp = *((__u8 *) skb->data);
Johan Hedberg388fc8f2012-02-23 00:38:59 +02002803 bool name_known, ssp;
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002804
2805 BT_DBG("%s num_rsp %d", hdev->name, num_rsp);
2806
2807 if (!num_rsp)
2808 return;
2809
2810 hci_dev_lock(hdev);
2811
2812 if ((skb->len - 1) / num_rsp != sizeof(struct inquiry_info_with_rssi)) {
Szymon Janc138d22e2011-02-17 16:44:23 +01002813 struct inquiry_info_with_rssi_and_pscan_mode *info;
2814 info = (void *) (skb->data + 1);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002815
Johan Hedberge17acd42011-03-30 23:57:16 +03002816 for (; num_rsp; num_rsp--, info++) {
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002817 bacpy(&data.bdaddr, &info->bdaddr);
2818 data.pscan_rep_mode = info->pscan_rep_mode;
2819 data.pscan_period_mode = info->pscan_period_mode;
2820 data.pscan_mode = info->pscan_mode;
2821 memcpy(data.dev_class, info->dev_class, 3);
2822 data.clock_offset = info->clock_offset;
2823 data.rssi = info->rssi;
Marcel Holtmann41a96212008-07-14 20:13:48 +02002824 data.ssp_mode = 0x00;
Johan Hedberg31754052012-01-04 13:39:52 +02002825
2826 name_known = hci_inquiry_cache_update(hdev, &data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002827 false, &ssp);
Johan Hedberg48264f02011-11-09 13:58:58 +02002828 mgmt_device_found(hdev, &info->bdaddr, ACL_LINK, 0x00,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002829 info->dev_class, info->rssi,
2830 !name_known, ssp, NULL, 0);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002831 }
2832 } else {
2833 struct inquiry_info_with_rssi *info = (void *) (skb->data + 1);
2834
Johan Hedberge17acd42011-03-30 23:57:16 +03002835 for (; num_rsp; num_rsp--, info++) {
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002836 bacpy(&data.bdaddr, &info->bdaddr);
2837 data.pscan_rep_mode = info->pscan_rep_mode;
2838 data.pscan_period_mode = info->pscan_period_mode;
2839 data.pscan_mode = 0x00;
2840 memcpy(data.dev_class, info->dev_class, 3);
2841 data.clock_offset = info->clock_offset;
2842 data.rssi = info->rssi;
Marcel Holtmann41a96212008-07-14 20:13:48 +02002843 data.ssp_mode = 0x00;
Johan Hedberg31754052012-01-04 13:39:52 +02002844 name_known = hci_inquiry_cache_update(hdev, &data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002845 false, &ssp);
Johan Hedberg48264f02011-11-09 13:58:58 +02002846 mgmt_device_found(hdev, &info->bdaddr, ACL_LINK, 0x00,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002847 info->dev_class, info->rssi,
2848 !name_known, ssp, NULL, 0);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002849 }
2850 }
2851
2852 hci_dev_unlock(hdev);
2853}
2854
2855static inline void hci_remote_ext_features_evt(struct hci_dev *hdev, struct sk_buff *skb)
2856{
Marcel Holtmann41a96212008-07-14 20:13:48 +02002857 struct hci_ev_remote_ext_features *ev = (void *) skb->data;
2858 struct hci_conn *conn;
2859
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002860 BT_DBG("%s", hdev->name);
Marcel Holtmann41a96212008-07-14 20:13:48 +02002861
Marcel Holtmann41a96212008-07-14 20:13:48 +02002862 hci_dev_lock(hdev);
2863
2864 conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
Johan Hedbergccd556f2010-11-10 17:11:51 +02002865 if (!conn)
2866 goto unlock;
Marcel Holtmann41a96212008-07-14 20:13:48 +02002867
Johan Hedbergccd556f2010-11-10 17:11:51 +02002868 if (!ev->status && ev->page == 0x01) {
2869 struct inquiry_entry *ie;
Marcel Holtmann41a96212008-07-14 20:13:48 +02002870
Andrei Emeltchenkocc11b9c2010-11-22 13:21:37 +02002871 ie = hci_inquiry_cache_lookup(hdev, &conn->dst);
2872 if (ie)
Johan Hedberg02b7cc62012-02-28 02:28:43 +02002873 ie->data.ssp_mode = (ev->features[0] & LMP_HOST_SSP);
Marcel Holtmann769be972008-07-14 20:13:49 +02002874
Johan Hedberg02b7cc62012-02-28 02:28:43 +02002875 if (ev->features[0] & LMP_HOST_SSP)
Johan Hedberg58a681e2012-01-16 06:47:28 +02002876 set_bit(HCI_CONN_SSP_ENABLED, &conn->flags);
Marcel Holtmann41a96212008-07-14 20:13:48 +02002877 }
2878
Johan Hedbergccd556f2010-11-10 17:11:51 +02002879 if (conn->state != BT_CONFIG)
2880 goto unlock;
2881
Johan Hedberg127178d2010-11-18 22:22:29 +02002882 if (!ev->status) {
2883 struct hci_cp_remote_name_req cp;
2884 memset(&cp, 0, sizeof(cp));
2885 bacpy(&cp.bdaddr, &conn->dst);
2886 cp.pscan_rep_mode = 0x02;
2887 hci_send_cmd(hdev, HCI_OP_REMOTE_NAME_REQ, sizeof(cp), &cp);
Johan Hedbergb644ba32012-01-17 21:48:47 +02002888 } else if (!test_and_set_bit(HCI_CONN_MGMT_CONNECTED, &conn->flags))
2889 mgmt_device_connected(hdev, &conn->dst, conn->type,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002890 conn->dst_type, 0, NULL, 0,
2891 conn->dev_class);
Johan Hedberg392599b2010-11-18 22:22:28 +02002892
Johan Hedberg127178d2010-11-18 22:22:29 +02002893 if (!hci_outgoing_auth_needed(hdev, conn)) {
Johan Hedbergccd556f2010-11-10 17:11:51 +02002894 conn->state = BT_CONNECTED;
2895 hci_proto_connect_cfm(conn, ev->status);
2896 hci_conn_put(conn);
2897 }
2898
2899unlock:
Marcel Holtmann41a96212008-07-14 20:13:48 +02002900 hci_dev_unlock(hdev);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002901}
2902
2903static inline void hci_sync_conn_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
2904{
Marcel Holtmannb6a0dc82007-10-20 14:55:10 +02002905 struct hci_ev_sync_conn_complete *ev = (void *) skb->data;
2906 struct hci_conn *conn;
2907
2908 BT_DBG("%s status %d", hdev->name, ev->status);
2909
2910 hci_dev_lock(hdev);
2911
2912 conn = hci_conn_hash_lookup_ba(hdev, ev->link_type, &ev->bdaddr);
Marcel Holtmann9dc0a3a2008-07-14 20:13:46 +02002913 if (!conn) {
2914 if (ev->link_type == ESCO_LINK)
2915 goto unlock;
2916
2917 conn = hci_conn_hash_lookup_ba(hdev, ESCO_LINK, &ev->bdaddr);
2918 if (!conn)
2919 goto unlock;
2920
2921 conn->type = SCO_LINK;
2922 }
Marcel Holtmannb6a0dc82007-10-20 14:55:10 +02002923
Marcel Holtmann732547f2009-04-19 19:14:14 +02002924 switch (ev->status) {
2925 case 0x00:
Marcel Holtmannb6a0dc82007-10-20 14:55:10 +02002926 conn->handle = __le16_to_cpu(ev->handle);
2927 conn->state = BT_CONNECTED;
Marcel Holtmann7d0db0a2008-07-14 20:13:51 +02002928
Marcel Holtmann9eba32b2009-08-22 14:19:26 -07002929 hci_conn_hold_device(conn);
Marcel Holtmann7d0db0a2008-07-14 20:13:51 +02002930 hci_conn_add_sysfs(conn);
Marcel Holtmann732547f2009-04-19 19:14:14 +02002931 break;
2932
Stephen Coe705e5712010-02-16 11:29:44 -05002933 case 0x11: /* Unsupported Feature or Parameter Value */
Marcel Holtmann732547f2009-04-19 19:14:14 +02002934 case 0x1c: /* SCO interval rejected */
Nick Pelly1038a002010-02-03 11:42:26 -08002935 case 0x1a: /* Unsupported Remote Feature */
Marcel Holtmann732547f2009-04-19 19:14:14 +02002936 case 0x1f: /* Unspecified error */
2937 if (conn->out && conn->attempt < 2) {
2938 conn->pkt_type = (hdev->esco_type & SCO_ESCO_MASK) |
2939 (hdev->esco_type & EDR_ESCO_MASK);
2940 hci_setup_sync(conn, conn->link->handle);
2941 goto unlock;
2942 }
2943 /* fall through */
2944
2945 default:
Marcel Holtmannb6a0dc82007-10-20 14:55:10 +02002946 conn->state = BT_CLOSED;
Marcel Holtmann732547f2009-04-19 19:14:14 +02002947 break;
2948 }
Marcel Holtmannb6a0dc82007-10-20 14:55:10 +02002949
2950 hci_proto_connect_cfm(conn, ev->status);
2951 if (ev->status)
2952 hci_conn_del(conn);
2953
2954unlock:
2955 hci_dev_unlock(hdev);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002956}
2957
2958static inline void hci_sync_conn_changed_evt(struct hci_dev *hdev, struct sk_buff *skb)
2959{
2960 BT_DBG("%s", hdev->name);
2961}
2962
Marcel Holtmann04837f62006-07-03 10:02:33 +02002963static inline void hci_sniff_subrate_evt(struct hci_dev *hdev, struct sk_buff *skb)
2964{
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002965 struct hci_ev_sniff_subrate *ev = (void *) skb->data;
Marcel Holtmann04837f62006-07-03 10:02:33 +02002966
2967 BT_DBG("%s status %d", hdev->name, ev->status);
Marcel Holtmann04837f62006-07-03 10:02:33 +02002968}
2969
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002970static inline void hci_extended_inquiry_result_evt(struct hci_dev *hdev, struct sk_buff *skb)
2971{
2972 struct inquiry_data data;
2973 struct extended_inquiry_info *info = (void *) (skb->data + 1);
2974 int num_rsp = *((__u8 *) skb->data);
2975
2976 BT_DBG("%s num_rsp %d", hdev->name, num_rsp);
2977
2978 if (!num_rsp)
2979 return;
2980
2981 hci_dev_lock(hdev);
2982
Johan Hedberge17acd42011-03-30 23:57:16 +03002983 for (; num_rsp; num_rsp--, info++) {
Johan Hedberg388fc8f2012-02-23 00:38:59 +02002984 bool name_known, ssp;
Johan Hedberg561aafb2012-01-04 13:31:59 +02002985
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002986 bacpy(&data.bdaddr, &info->bdaddr);
Szymon Janc138d22e2011-02-17 16:44:23 +01002987 data.pscan_rep_mode = info->pscan_rep_mode;
2988 data.pscan_period_mode = info->pscan_period_mode;
2989 data.pscan_mode = 0x00;
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002990 memcpy(data.dev_class, info->dev_class, 3);
Szymon Janc138d22e2011-02-17 16:44:23 +01002991 data.clock_offset = info->clock_offset;
2992 data.rssi = info->rssi;
Marcel Holtmann41a96212008-07-14 20:13:48 +02002993 data.ssp_mode = 0x01;
Johan Hedberg561aafb2012-01-04 13:31:59 +02002994
Johan Hedberga8b2d5c2012-01-08 23:11:15 +02002995 if (test_bit(HCI_MGMT, &hdev->dev_flags))
Johan Hedberg4ddb1932012-01-15 20:04:43 +02002996 name_known = eir_has_data_type(info->data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002997 sizeof(info->data),
2998 EIR_NAME_COMPLETE);
Johan Hedberg561aafb2012-01-04 13:31:59 +02002999 else
3000 name_known = true;
3001
Johan Hedberg388fc8f2012-02-23 00:38:59 +02003002 name_known = hci_inquiry_cache_update(hdev, &data, name_known,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003003 &ssp);
Johan Hedberg48264f02011-11-09 13:58:58 +02003004 mgmt_device_found(hdev, &info->bdaddr, ACL_LINK, 0x00,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003005 info->dev_class, info->rssi, !name_known,
3006 ssp, info->data, sizeof(info->data));
Marcel Holtmanna9de9242007-10-20 13:33:56 +02003007 }
3008
3009 hci_dev_unlock(hdev);
3010}
3011
Johan Hedberg17fa4b92011-01-25 13:28:33 +02003012static inline u8 hci_get_auth_req(struct hci_conn *conn)
3013{
3014 /* If remote requests dedicated bonding follow that lead */
3015 if (conn->remote_auth == 0x02 || conn->remote_auth == 0x03) {
3016 /* If both remote and local IO capabilities allow MITM
3017 * protection then require it, otherwise don't */
3018 if (conn->remote_cap == 0x03 || conn->io_capability == 0x03)
3019 return 0x02;
3020 else
3021 return 0x03;
3022 }
3023
3024 /* If remote requests no-bonding follow that lead */
3025 if (conn->remote_auth == 0x00 || conn->remote_auth == 0x01)
Waldemar Rymarkiewicz58797bf2011-04-28 12:07:58 +02003026 return conn->remote_auth | (conn->auth_type & 0x01);
Johan Hedberg17fa4b92011-01-25 13:28:33 +02003027
3028 return conn->auth_type;
3029}
3030
Marcel Holtmann04936842008-07-14 20:13:48 +02003031static inline void hci_io_capa_request_evt(struct hci_dev *hdev, struct sk_buff *skb)
3032{
3033 struct hci_ev_io_capa_request *ev = (void *) skb->data;
3034 struct hci_conn *conn;
3035
3036 BT_DBG("%s", hdev->name);
3037
3038 hci_dev_lock(hdev);
3039
3040 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
Johan Hedberg03b555e2011-01-04 15:40:05 +02003041 if (!conn)
3042 goto unlock;
Marcel Holtmann04936842008-07-14 20:13:48 +02003043
Johan Hedberg03b555e2011-01-04 15:40:05 +02003044 hci_conn_hold(conn);
3045
Johan Hedberga8b2d5c2012-01-08 23:11:15 +02003046 if (!test_bit(HCI_MGMT, &hdev->dev_flags))
Johan Hedberg03b555e2011-01-04 15:40:05 +02003047 goto unlock;
3048
Johan Hedberga8b2d5c2012-01-08 23:11:15 +02003049 if (test_bit(HCI_PAIRABLE, &hdev->dev_flags) ||
Johan Hedberg03b555e2011-01-04 15:40:05 +02003050 (conn->remote_auth & ~0x01) == HCI_AT_NO_BONDING) {
Johan Hedberg17fa4b92011-01-25 13:28:33 +02003051 struct hci_cp_io_capability_reply cp;
3052
3053 bacpy(&cp.bdaddr, &ev->bdaddr);
Hemant Gupta7a7f1e72012-01-16 13:34:29 +05303054 /* Change the IO capability from KeyboardDisplay
3055 * to DisplayYesNo as it is not supported by BT spec. */
3056 cp.capability = (conn->io_capability == 0x04) ?
3057 0x01 : conn->io_capability;
Johan Hedberg7cbc9bd2011-04-28 11:29:04 -07003058 conn->auth_type = hci_get_auth_req(conn);
3059 cp.authentication = conn->auth_type;
Johan Hedberg17fa4b92011-01-25 13:28:33 +02003060
Johan Hedberg58a681e2012-01-16 06:47:28 +02003061 if ((conn->out || test_bit(HCI_CONN_REMOTE_OOB, &conn->flags)) &&
Szymon Jancce85ee12011-03-22 13:12:23 +01003062 hci_find_remote_oob_data(hdev, &conn->dst))
3063 cp.oob_data = 0x01;
3064 else
3065 cp.oob_data = 0x00;
3066
Johan Hedberg17fa4b92011-01-25 13:28:33 +02003067 hci_send_cmd(hdev, HCI_OP_IO_CAPABILITY_REPLY,
3068 sizeof(cp), &cp);
Johan Hedberg03b555e2011-01-04 15:40:05 +02003069 } else {
3070 struct hci_cp_io_capability_neg_reply cp;
3071
3072 bacpy(&cp.bdaddr, &ev->bdaddr);
Andrei Emeltchenko9f5a0d72011-11-07 14:20:25 +02003073 cp.reason = HCI_ERROR_PAIRING_NOT_ALLOWED;
Johan Hedberg03b555e2011-01-04 15:40:05 +02003074
3075 hci_send_cmd(hdev, HCI_OP_IO_CAPABILITY_NEG_REPLY,
3076 sizeof(cp), &cp);
3077 }
3078
3079unlock:
3080 hci_dev_unlock(hdev);
3081}
3082
3083static inline void hci_io_capa_reply_evt(struct hci_dev *hdev, struct sk_buff *skb)
3084{
3085 struct hci_ev_io_capa_reply *ev = (void *) skb->data;
3086 struct hci_conn *conn;
3087
3088 BT_DBG("%s", hdev->name);
3089
3090 hci_dev_lock(hdev);
3091
3092 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
3093 if (!conn)
3094 goto unlock;
3095
Johan Hedberg03b555e2011-01-04 15:40:05 +02003096 conn->remote_cap = ev->capability;
Johan Hedberg03b555e2011-01-04 15:40:05 +02003097 conn->remote_auth = ev->authentication;
Johan Hedberg58a681e2012-01-16 06:47:28 +02003098 if (ev->oob_data)
3099 set_bit(HCI_CONN_REMOTE_OOB, &conn->flags);
Johan Hedberg03b555e2011-01-04 15:40:05 +02003100
3101unlock:
Marcel Holtmann04936842008-07-14 20:13:48 +02003102 hci_dev_unlock(hdev);
3103}
3104
Johan Hedberga5c29682011-02-19 12:05:57 -03003105static inline void hci_user_confirm_request_evt(struct hci_dev *hdev,
3106 struct sk_buff *skb)
3107{
3108 struct hci_ev_user_confirm_req *ev = (void *) skb->data;
Johan Hedberg55bc1a32011-04-28 11:28:56 -07003109 int loc_mitm, rem_mitm, confirm_hint = 0;
Johan Hedberg7a828902011-04-28 11:28:53 -07003110 struct hci_conn *conn;
Johan Hedberga5c29682011-02-19 12:05:57 -03003111
3112 BT_DBG("%s", hdev->name);
3113
3114 hci_dev_lock(hdev);
3115
Johan Hedberga8b2d5c2012-01-08 23:11:15 +02003116 if (!test_bit(HCI_MGMT, &hdev->dev_flags))
Johan Hedberg7a828902011-04-28 11:28:53 -07003117 goto unlock;
Johan Hedberga5c29682011-02-19 12:05:57 -03003118
Johan Hedberg7a828902011-04-28 11:28:53 -07003119 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
3120 if (!conn)
3121 goto unlock;
3122
3123 loc_mitm = (conn->auth_type & 0x01);
3124 rem_mitm = (conn->remote_auth & 0x01);
3125
3126 /* If we require MITM but the remote device can't provide that
3127 * (it has NoInputNoOutput) then reject the confirmation
3128 * request. The only exception is when we're dedicated bonding
3129 * initiators (connect_cfm_cb set) since then we always have the MITM
3130 * bit set. */
3131 if (!conn->connect_cfm_cb && loc_mitm && conn->remote_cap == 0x03) {
3132 BT_DBG("Rejecting request: remote device can't provide MITM");
3133 hci_send_cmd(hdev, HCI_OP_USER_CONFIRM_NEG_REPLY,
3134 sizeof(ev->bdaddr), &ev->bdaddr);
3135 goto unlock;
3136 }
3137
3138 /* If no side requires MITM protection; auto-accept */
3139 if ((!loc_mitm || conn->remote_cap == 0x03) &&
3140 (!rem_mitm || conn->io_capability == 0x03)) {
Johan Hedberg55bc1a32011-04-28 11:28:56 -07003141
3142 /* If we're not the initiators request authorization to
3143 * proceed from user space (mgmt_user_confirm with
3144 * confirm_hint set to 1). */
Johan Hedberg51a8efd2012-01-16 06:10:31 +02003145 if (!test_bit(HCI_CONN_AUTH_PEND, &conn->flags)) {
Johan Hedberg55bc1a32011-04-28 11:28:56 -07003146 BT_DBG("Confirming auto-accept as acceptor");
3147 confirm_hint = 1;
3148 goto confirm;
3149 }
3150
Johan Hedberg9f616562011-04-28 11:28:54 -07003151 BT_DBG("Auto-accept of user confirmation with %ums delay",
3152 hdev->auto_accept_delay);
3153
3154 if (hdev->auto_accept_delay > 0) {
3155 int delay = msecs_to_jiffies(hdev->auto_accept_delay);
3156 mod_timer(&conn->auto_accept_timer, jiffies + delay);
3157 goto unlock;
3158 }
3159
Johan Hedberg7a828902011-04-28 11:28:53 -07003160 hci_send_cmd(hdev, HCI_OP_USER_CONFIRM_REPLY,
3161 sizeof(ev->bdaddr), &ev->bdaddr);
3162 goto unlock;
3163 }
3164
Johan Hedberg55bc1a32011-04-28 11:28:56 -07003165confirm:
Johan Hedberg272d90d2012-02-09 15:26:12 +02003166 mgmt_user_confirm_request(hdev, &ev->bdaddr, ACL_LINK, 0, ev->passkey,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003167 confirm_hint);
Johan Hedberg7a828902011-04-28 11:28:53 -07003168
3169unlock:
Johan Hedberga5c29682011-02-19 12:05:57 -03003170 hci_dev_unlock(hdev);
3171}
3172
Brian Gix1143d452011-11-23 08:28:34 -08003173static inline void hci_user_passkey_request_evt(struct hci_dev *hdev,
3174 struct sk_buff *skb)
3175{
3176 struct hci_ev_user_passkey_req *ev = (void *) skb->data;
3177
3178 BT_DBG("%s", hdev->name);
3179
3180 hci_dev_lock(hdev);
3181
Johan Hedberga8b2d5c2012-01-08 23:11:15 +02003182 if (test_bit(HCI_MGMT, &hdev->dev_flags))
Johan Hedberg272d90d2012-02-09 15:26:12 +02003183 mgmt_user_passkey_request(hdev, &ev->bdaddr, ACL_LINK, 0);
Brian Gix1143d452011-11-23 08:28:34 -08003184
3185 hci_dev_unlock(hdev);
3186}
3187
Marcel Holtmann04936842008-07-14 20:13:48 +02003188static inline void hci_simple_pair_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
3189{
3190 struct hci_ev_simple_pair_complete *ev = (void *) skb->data;
3191 struct hci_conn *conn;
3192
3193 BT_DBG("%s", hdev->name);
3194
3195 hci_dev_lock(hdev);
3196
3197 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
Johan Hedberg2a611692011-02-19 12:06:00 -03003198 if (!conn)
3199 goto unlock;
Marcel Holtmann04936842008-07-14 20:13:48 +02003200
Johan Hedberg2a611692011-02-19 12:06:00 -03003201 /* To avoid duplicate auth_failed events to user space we check
3202 * the HCI_CONN_AUTH_PEND flag which will be set if we
3203 * initiated the authentication. A traditional auth_complete
3204 * event gets always produced as initiator and is also mapped to
3205 * the mgmt_auth_failed event */
Johan Hedberg51a8efd2012-01-16 06:10:31 +02003206 if (!test_bit(HCI_CONN_AUTH_PEND, &conn->flags) && ev->status != 0)
Johan Hedbergbab73cb2012-02-09 16:07:29 +02003207 mgmt_auth_failed(hdev, &conn->dst, conn->type, conn->dst_type,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003208 ev->status);
Johan Hedberg2a611692011-02-19 12:06:00 -03003209
3210 hci_conn_put(conn);
3211
3212unlock:
Marcel Holtmann04936842008-07-14 20:13:48 +02003213 hci_dev_unlock(hdev);
3214}
3215
Marcel Holtmann41a96212008-07-14 20:13:48 +02003216static inline void hci_remote_host_features_evt(struct hci_dev *hdev, struct sk_buff *skb)
3217{
3218 struct hci_ev_remote_host_features *ev = (void *) skb->data;
3219 struct inquiry_entry *ie;
3220
3221 BT_DBG("%s", hdev->name);
3222
3223 hci_dev_lock(hdev);
3224
Andrei Emeltchenkocc11b9c2010-11-22 13:21:37 +02003225 ie = hci_inquiry_cache_lookup(hdev, &ev->bdaddr);
3226 if (ie)
Johan Hedberg02b7cc62012-02-28 02:28:43 +02003227 ie->data.ssp_mode = (ev->features[0] & LMP_HOST_SSP);
Marcel Holtmann41a96212008-07-14 20:13:48 +02003228
3229 hci_dev_unlock(hdev);
3230}
3231
Szymon Janc2763eda2011-03-22 13:12:22 +01003232static inline void hci_remote_oob_data_request_evt(struct hci_dev *hdev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003233 struct sk_buff *skb)
Szymon Janc2763eda2011-03-22 13:12:22 +01003234{
3235 struct hci_ev_remote_oob_data_request *ev = (void *) skb->data;
3236 struct oob_data *data;
3237
3238 BT_DBG("%s", hdev->name);
3239
3240 hci_dev_lock(hdev);
3241
Johan Hedberga8b2d5c2012-01-08 23:11:15 +02003242 if (!test_bit(HCI_MGMT, &hdev->dev_flags))
Szymon Jance1ba1f12011-04-06 13:01:59 +02003243 goto unlock;
3244
Szymon Janc2763eda2011-03-22 13:12:22 +01003245 data = hci_find_remote_oob_data(hdev, &ev->bdaddr);
3246 if (data) {
3247 struct hci_cp_remote_oob_data_reply cp;
3248
3249 bacpy(&cp.bdaddr, &ev->bdaddr);
3250 memcpy(cp.hash, data->hash, sizeof(cp.hash));
3251 memcpy(cp.randomizer, data->randomizer, sizeof(cp.randomizer));
3252
3253 hci_send_cmd(hdev, HCI_OP_REMOTE_OOB_DATA_REPLY, sizeof(cp),
3254 &cp);
3255 } else {
3256 struct hci_cp_remote_oob_data_neg_reply cp;
3257
3258 bacpy(&cp.bdaddr, &ev->bdaddr);
3259 hci_send_cmd(hdev, HCI_OP_REMOTE_OOB_DATA_NEG_REPLY, sizeof(cp),
3260 &cp);
3261 }
3262
Szymon Jance1ba1f12011-04-06 13:01:59 +02003263unlock:
Szymon Janc2763eda2011-03-22 13:12:22 +01003264 hci_dev_unlock(hdev);
3265}
3266
Ville Tervofcd89c02011-02-10 22:38:47 -03003267static inline void hci_le_conn_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
3268{
3269 struct hci_ev_le_conn_complete *ev = (void *) skb->data;
3270 struct hci_conn *conn;
3271
3272 BT_DBG("%s status %d", hdev->name, ev->status);
3273
3274 hci_dev_lock(hdev);
3275
3276 conn = hci_conn_hash_lookup_ba(hdev, LE_LINK, &ev->bdaddr);
Ville Tervob62f3282011-02-10 22:38:50 -03003277 if (!conn) {
3278 conn = hci_conn_add(hdev, LE_LINK, &ev->bdaddr);
3279 if (!conn) {
3280 BT_ERR("No memory for new connection");
3281 hci_dev_unlock(hdev);
3282 return;
3283 }
Andre Guedes29b79882011-05-31 14:20:54 -03003284
3285 conn->dst_type = ev->bdaddr_type;
Ville Tervob62f3282011-02-10 22:38:50 -03003286 }
Ville Tervofcd89c02011-02-10 22:38:47 -03003287
3288 if (ev->status) {
Johan Hedberg48264f02011-11-09 13:58:58 +02003289 mgmt_connect_failed(hdev, &ev->bdaddr, conn->type,
3290 conn->dst_type, ev->status);
Ville Tervofcd89c02011-02-10 22:38:47 -03003291 hci_proto_connect_cfm(conn, ev->status);
3292 conn->state = BT_CLOSED;
3293 hci_conn_del(conn);
3294 goto unlock;
3295 }
3296
Johan Hedbergb644ba32012-01-17 21:48:47 +02003297 if (!test_and_set_bit(HCI_CONN_MGMT_CONNECTED, &conn->flags))
3298 mgmt_device_connected(hdev, &ev->bdaddr, conn->type,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003299 conn->dst_type, 0, NULL, 0, NULL);
Vinicius Costa Gomes83bc71b2011-05-06 18:41:43 -03003300
Vinicius Costa Gomes7b5c0d52011-06-09 18:50:50 -03003301 conn->sec_level = BT_SECURITY_LOW;
Ville Tervofcd89c02011-02-10 22:38:47 -03003302 conn->handle = __le16_to_cpu(ev->handle);
3303 conn->state = BT_CONNECTED;
3304
3305 hci_conn_hold_device(conn);
3306 hci_conn_add_sysfs(conn);
3307
3308 hci_proto_connect_cfm(conn, ev->status);
3309
3310unlock:
3311 hci_dev_unlock(hdev);
3312}
3313
Andre Guedes9aa04c92011-05-26 16:23:51 -03003314static inline void hci_le_adv_report_evt(struct hci_dev *hdev,
3315 struct sk_buff *skb)
3316{
Andre Guedese95beb42011-09-26 20:48:35 -03003317 u8 num_reports = skb->data[0];
3318 void *ptr = &skb->data[1];
Andre Guedes3c9e9192012-01-10 18:20:50 -03003319 s8 rssi;
Andre Guedes9aa04c92011-05-26 16:23:51 -03003320
3321 hci_dev_lock(hdev);
3322
Andre Guedese95beb42011-09-26 20:48:35 -03003323 while (num_reports--) {
3324 struct hci_ev_le_advertising_info *ev = ptr;
Andre Guedes9aa04c92011-05-26 16:23:51 -03003325
Andre Guedes9aa04c92011-05-26 16:23:51 -03003326 hci_add_adv_entry(hdev, ev);
Andre Guedese95beb42011-09-26 20:48:35 -03003327
Andre Guedes3c9e9192012-01-10 18:20:50 -03003328 rssi = ev->data[ev->length];
3329 mgmt_device_found(hdev, &ev->bdaddr, LE_LINK, ev->bdaddr_type,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003330 NULL, rssi, 0, 1, ev->data, ev->length);
Andre Guedes3c9e9192012-01-10 18:20:50 -03003331
Andre Guedese95beb42011-09-26 20:48:35 -03003332 ptr += sizeof(*ev) + ev->length + 1;
Andre Guedes9aa04c92011-05-26 16:23:51 -03003333 }
3334
3335 hci_dev_unlock(hdev);
3336}
3337
Vinicius Costa Gomesa7a595f2011-06-09 18:50:47 -03003338static inline void hci_le_ltk_request_evt(struct hci_dev *hdev,
3339 struct sk_buff *skb)
3340{
3341 struct hci_ev_le_ltk_req *ev = (void *) skb->data;
3342 struct hci_cp_le_ltk_reply cp;
Vinicius Costa Gomesbea710f2011-07-07 18:59:37 -03003343 struct hci_cp_le_ltk_neg_reply neg;
Vinicius Costa Gomesa7a595f2011-06-09 18:50:47 -03003344 struct hci_conn *conn;
Vinicius Costa Gomesc9839a12012-02-02 21:08:01 -03003345 struct smp_ltk *ltk;
Vinicius Costa Gomesa7a595f2011-06-09 18:50:47 -03003346
Andrei Emeltchenkoe4666882012-03-09 11:59:15 +02003347 BT_DBG("%s handle %d", hdev->name, __le16_to_cpu(ev->handle));
Vinicius Costa Gomesa7a595f2011-06-09 18:50:47 -03003348
3349 hci_dev_lock(hdev);
3350
3351 conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
Vinicius Costa Gomesbea710f2011-07-07 18:59:37 -03003352 if (conn == NULL)
3353 goto not_found;
Vinicius Costa Gomesa7a595f2011-06-09 18:50:47 -03003354
Vinicius Costa Gomesbea710f2011-07-07 18:59:37 -03003355 ltk = hci_find_ltk(hdev, ev->ediv, ev->random);
3356 if (ltk == NULL)
3357 goto not_found;
3358
3359 memcpy(cp.ltk, ltk->val, sizeof(ltk->val));
Vinicius Costa Gomesa7a595f2011-06-09 18:50:47 -03003360 cp.handle = cpu_to_le16(conn->handle);
Vinicius Costa Gomesc9839a12012-02-02 21:08:01 -03003361
3362 if (ltk->authenticated)
3363 conn->sec_level = BT_SECURITY_HIGH;
Vinicius Costa Gomesa7a595f2011-06-09 18:50:47 -03003364
3365 hci_send_cmd(hdev, HCI_OP_LE_LTK_REPLY, sizeof(cp), &cp);
3366
Vinicius Costa Gomesc9839a12012-02-02 21:08:01 -03003367 if (ltk->type & HCI_SMP_STK) {
3368 list_del(&ltk->list);
3369 kfree(ltk);
3370 }
3371
Vinicius Costa Gomesa7a595f2011-06-09 18:50:47 -03003372 hci_dev_unlock(hdev);
Vinicius Costa Gomesbea710f2011-07-07 18:59:37 -03003373
3374 return;
3375
3376not_found:
3377 neg.handle = ev->handle;
3378 hci_send_cmd(hdev, HCI_OP_LE_LTK_NEG_REPLY, sizeof(neg), &neg);
3379 hci_dev_unlock(hdev);
Vinicius Costa Gomesa7a595f2011-06-09 18:50:47 -03003380}
3381
Ville Tervofcd89c02011-02-10 22:38:47 -03003382static inline void hci_le_meta_evt(struct hci_dev *hdev, struct sk_buff *skb)
3383{
3384 struct hci_ev_le_meta *le_ev = (void *) skb->data;
3385
3386 skb_pull(skb, sizeof(*le_ev));
3387
3388 switch (le_ev->subevent) {
3389 case HCI_EV_LE_CONN_COMPLETE:
3390 hci_le_conn_complete_evt(hdev, skb);
3391 break;
3392
Andre Guedes9aa04c92011-05-26 16:23:51 -03003393 case HCI_EV_LE_ADVERTISING_REPORT:
3394 hci_le_adv_report_evt(hdev, skb);
3395 break;
3396
Vinicius Costa Gomesa7a595f2011-06-09 18:50:47 -03003397 case HCI_EV_LE_LTK_REQ:
3398 hci_le_ltk_request_evt(hdev, skb);
3399 break;
3400
Ville Tervofcd89c02011-02-10 22:38:47 -03003401 default:
3402 break;
3403 }
3404}
3405
Linus Torvalds1da177e2005-04-16 15:20:36 -07003406void hci_event_packet(struct hci_dev *hdev, struct sk_buff *skb)
3407{
Marcel Holtmanna9de9242007-10-20 13:33:56 +02003408 struct hci_event_hdr *hdr = (void *) skb->data;
3409 __u8 event = hdr->evt;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003410
3411 skb_pull(skb, HCI_EVENT_HDR_SIZE);
3412
Marcel Holtmanna9de9242007-10-20 13:33:56 +02003413 switch (event) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003414 case HCI_EV_INQUIRY_COMPLETE:
3415 hci_inquiry_complete_evt(hdev, skb);
3416 break;
3417
3418 case HCI_EV_INQUIRY_RESULT:
3419 hci_inquiry_result_evt(hdev, skb);
3420 break;
3421
Marcel Holtmanna9de9242007-10-20 13:33:56 +02003422 case HCI_EV_CONN_COMPLETE:
3423 hci_conn_complete_evt(hdev, skb);
Marcel Holtmann21d9e302005-09-13 01:32:25 +02003424 break;
3425
Linus Torvalds1da177e2005-04-16 15:20:36 -07003426 case HCI_EV_CONN_REQUEST:
3427 hci_conn_request_evt(hdev, skb);
3428 break;
3429
Linus Torvalds1da177e2005-04-16 15:20:36 -07003430 case HCI_EV_DISCONN_COMPLETE:
3431 hci_disconn_complete_evt(hdev, skb);
3432 break;
3433
Linus Torvalds1da177e2005-04-16 15:20:36 -07003434 case HCI_EV_AUTH_COMPLETE:
3435 hci_auth_complete_evt(hdev, skb);
3436 break;
3437
Marcel Holtmanna9de9242007-10-20 13:33:56 +02003438 case HCI_EV_REMOTE_NAME:
3439 hci_remote_name_evt(hdev, skb);
3440 break;
3441
Linus Torvalds1da177e2005-04-16 15:20:36 -07003442 case HCI_EV_ENCRYPT_CHANGE:
3443 hci_encrypt_change_evt(hdev, skb);
3444 break;
3445
Marcel Holtmanna9de9242007-10-20 13:33:56 +02003446 case HCI_EV_CHANGE_LINK_KEY_COMPLETE:
3447 hci_change_link_key_complete_evt(hdev, skb);
3448 break;
3449
3450 case HCI_EV_REMOTE_FEATURES:
3451 hci_remote_features_evt(hdev, skb);
3452 break;
3453
3454 case HCI_EV_REMOTE_VERSION:
3455 hci_remote_version_evt(hdev, skb);
3456 break;
3457
3458 case HCI_EV_QOS_SETUP_COMPLETE:
3459 hci_qos_setup_complete_evt(hdev, skb);
3460 break;
3461
3462 case HCI_EV_CMD_COMPLETE:
3463 hci_cmd_complete_evt(hdev, skb);
3464 break;
3465
3466 case HCI_EV_CMD_STATUS:
3467 hci_cmd_status_evt(hdev, skb);
3468 break;
3469
3470 case HCI_EV_ROLE_CHANGE:
3471 hci_role_change_evt(hdev, skb);
3472 break;
3473
3474 case HCI_EV_NUM_COMP_PKTS:
3475 hci_num_comp_pkts_evt(hdev, skb);
3476 break;
3477
3478 case HCI_EV_MODE_CHANGE:
3479 hci_mode_change_evt(hdev, skb);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003480 break;
3481
3482 case HCI_EV_PIN_CODE_REQ:
3483 hci_pin_code_request_evt(hdev, skb);
3484 break;
3485
3486 case HCI_EV_LINK_KEY_REQ:
3487 hci_link_key_request_evt(hdev, skb);
3488 break;
3489
3490 case HCI_EV_LINK_KEY_NOTIFY:
3491 hci_link_key_notify_evt(hdev, skb);
3492 break;
3493
3494 case HCI_EV_CLOCK_OFFSET:
3495 hci_clock_offset_evt(hdev, skb);
3496 break;
3497
Marcel Holtmanna8746412008-07-14 20:13:46 +02003498 case HCI_EV_PKT_TYPE_CHANGE:
3499 hci_pkt_type_change_evt(hdev, skb);
3500 break;
3501
Marcel Holtmann85a1e932005-08-09 20:28:02 -07003502 case HCI_EV_PSCAN_REP_MODE:
3503 hci_pscan_rep_mode_evt(hdev, skb);
3504 break;
3505
Marcel Holtmanna9de9242007-10-20 13:33:56 +02003506 case HCI_EV_INQUIRY_RESULT_WITH_RSSI:
3507 hci_inquiry_result_with_rssi_evt(hdev, skb);
3508 break;
3509
3510 case HCI_EV_REMOTE_EXT_FEATURES:
3511 hci_remote_ext_features_evt(hdev, skb);
3512 break;
3513
3514 case HCI_EV_SYNC_CONN_COMPLETE:
3515 hci_sync_conn_complete_evt(hdev, skb);
3516 break;
3517
3518 case HCI_EV_SYNC_CONN_CHANGED:
3519 hci_sync_conn_changed_evt(hdev, skb);
3520 break;
3521
Marcel Holtmann04837f62006-07-03 10:02:33 +02003522 case HCI_EV_SNIFF_SUBRATE:
3523 hci_sniff_subrate_evt(hdev, skb);
3524 break;
3525
Marcel Holtmanna9de9242007-10-20 13:33:56 +02003526 case HCI_EV_EXTENDED_INQUIRY_RESULT:
3527 hci_extended_inquiry_result_evt(hdev, skb);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003528 break;
3529
Marcel Holtmann04936842008-07-14 20:13:48 +02003530 case HCI_EV_IO_CAPA_REQUEST:
3531 hci_io_capa_request_evt(hdev, skb);
3532 break;
3533
Johan Hedberg03b555e2011-01-04 15:40:05 +02003534 case HCI_EV_IO_CAPA_REPLY:
3535 hci_io_capa_reply_evt(hdev, skb);
3536 break;
3537
Johan Hedberga5c29682011-02-19 12:05:57 -03003538 case HCI_EV_USER_CONFIRM_REQUEST:
3539 hci_user_confirm_request_evt(hdev, skb);
3540 break;
3541
Brian Gix1143d452011-11-23 08:28:34 -08003542 case HCI_EV_USER_PASSKEY_REQUEST:
3543 hci_user_passkey_request_evt(hdev, skb);
3544 break;
3545
Marcel Holtmann04936842008-07-14 20:13:48 +02003546 case HCI_EV_SIMPLE_PAIR_COMPLETE:
3547 hci_simple_pair_complete_evt(hdev, skb);
3548 break;
3549
Marcel Holtmann41a96212008-07-14 20:13:48 +02003550 case HCI_EV_REMOTE_HOST_FEATURES:
3551 hci_remote_host_features_evt(hdev, skb);
3552 break;
3553
Ville Tervofcd89c02011-02-10 22:38:47 -03003554 case HCI_EV_LE_META:
3555 hci_le_meta_evt(hdev, skb);
3556 break;
3557
Szymon Janc2763eda2011-03-22 13:12:22 +01003558 case HCI_EV_REMOTE_OOB_DATA_REQUEST:
3559 hci_remote_oob_data_request_evt(hdev, skb);
3560 break;
3561
Andrei Emeltchenko25e89e92012-01-04 12:41:58 +02003562 case HCI_EV_NUM_COMP_BLOCKS:
3563 hci_num_comp_blocks_evt(hdev, skb);
3564 break;
3565
Marcel Holtmanna9de9242007-10-20 13:33:56 +02003566 default:
3567 BT_DBG("%s event 0x%x", hdev->name, event);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003568 break;
3569 }
3570
3571 kfree_skb(skb);
3572 hdev->stat.evt_rx++;
3573}