blob: b9d77be92d3b1dc548d00009c1262cc7dde6ea53 [file] [log] [blame]
YOSHIFUJI Hideaki8e87d142007-02-09 23:24:33 +09001/*
Linus Torvalds1da177e2005-04-16 15:20:36 -07002 BlueZ - Bluetooth protocol stack for Linux
Ron Shaffer2d0a0342010-05-28 11:53:46 -04003 Copyright (c) 2000-2001, 2010, Code Aurora Forum. All rights reserved.
Linus Torvalds1da177e2005-04-16 15:20:36 -07004
5 Written 2000,2001 by Maxim Krasnyansky <maxk@qualcomm.com>
6
7 This program is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License version 2 as
9 published by the Free Software Foundation;
10
11 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
12 OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
13 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF THIRD PARTY RIGHTS.
14 IN NO EVENT SHALL THE COPYRIGHT HOLDER(S) AND AUTHOR(S) BE LIABLE FOR ANY
YOSHIFUJI Hideaki8e87d142007-02-09 23:24:33 +090015 CLAIM, OR ANY SPECIAL INDIRECT OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES
16 WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
17 ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
Linus Torvalds1da177e2005-04-16 15:20:36 -070018 OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
19
YOSHIFUJI Hideaki8e87d142007-02-09 23:24:33 +090020 ALL LIABILITY, INCLUDING LIABILITY FOR INFRINGEMENT OF ANY PATENTS,
21 COPYRIGHTS, TRADEMARKS OR OTHER RIGHTS, RELATING TO USE OF THIS
Linus Torvalds1da177e2005-04-16 15:20:36 -070022 SOFTWARE IS DISCLAIMED.
23*/
24
25/* Bluetooth HCI event handling. */
26
Linus Torvalds1da177e2005-04-16 15:20:36 -070027#include <linux/module.h>
28
29#include <linux/types.h>
30#include <linux/errno.h>
31#include <linux/kernel.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070032#include <linux/slab.h>
33#include <linux/poll.h>
34#include <linux/fcntl.h>
35#include <linux/init.h>
36#include <linux/skbuff.h>
37#include <linux/interrupt.h>
38#include <linux/notifier.h>
39#include <net/sock.h>
40
41#include <asm/system.h>
Andrei Emeltchenko70f230202010-12-01 16:58:25 +020042#include <linux/uaccess.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070043#include <asm/unaligned.h>
44
45#include <net/bluetooth/bluetooth.h>
46#include <net/bluetooth/hci_core.h>
47
Andre Guedese6100a22011-06-30 19:20:54 -030048static int enable_le;
49
Linus Torvalds1da177e2005-04-16 15:20:36 -070050/* Handle HCI Event packets */
51
Marcel Holtmanna9de9242007-10-20 13:33:56 +020052static void hci_cc_inquiry_cancel(struct hci_dev *hdev, struct sk_buff *skb)
Linus Torvalds1da177e2005-04-16 15:20:36 -070053{
Marcel Holtmanna9de9242007-10-20 13:33:56 +020054 __u8 status = *((__u8 *) skb->data);
Linus Torvalds1da177e2005-04-16 15:20:36 -070055
Marcel Holtmanna9de9242007-10-20 13:33:56 +020056 BT_DBG("%s status 0x%x", hdev->name, status);
Linus Torvalds1da177e2005-04-16 15:20:36 -070057
Andre Guedese6d465c2011-11-09 17:14:26 -030058 if (status) {
59 hci_dev_lock(hdev);
60 mgmt_stop_discovery_failed(hdev, status);
61 hci_dev_unlock(hdev);
Marcel Holtmanna9de9242007-10-20 13:33:56 +020062 return;
Andre Guedese6d465c2011-11-09 17:14:26 -030063 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070064
Andre Guedes89352e72011-11-04 14:16:53 -030065 clear_bit(HCI_INQUIRY, &hdev->flags);
66
Johan Hedberg56e5cb82011-11-08 20:40:16 +020067 hci_dev_lock(hdev);
Johan Hedberg744cf192011-11-08 20:40:14 +020068 mgmt_discovering(hdev, 0);
Johan Hedberg56e5cb82011-11-08 20:40:16 +020069 hci_dev_unlock(hdev);
Marcel Holtmann6bd57412006-11-18 22:14:22 +010070
Johan Hedberg23bb5762010-12-21 23:01:27 +020071 hci_req_complete(hdev, HCI_OP_INQUIRY_CANCEL, status);
Marcel Holtmann6bd57412006-11-18 22:14:22 +010072
Marcel Holtmanna9de9242007-10-20 13:33:56 +020073 hci_conn_check_pending(hdev);
Linus Torvalds1da177e2005-04-16 15:20:36 -070074}
75
Marcel Holtmanna9de9242007-10-20 13:33:56 +020076static void hci_cc_exit_periodic_inq(struct hci_dev *hdev, struct sk_buff *skb)
Linus Torvalds1da177e2005-04-16 15:20:36 -070077{
Marcel Holtmanna9de9242007-10-20 13:33:56 +020078 __u8 status = *((__u8 *) skb->data);
79
80 BT_DBG("%s status 0x%x", hdev->name, status);
81
82 if (status)
83 return;
84
Marcel Holtmanna9de9242007-10-20 13:33:56 +020085 hci_conn_check_pending(hdev);
86}
87
88static void hci_cc_remote_name_req_cancel(struct hci_dev *hdev, struct sk_buff *skb)
89{
90 BT_DBG("%s", hdev->name);
91}
92
93static void hci_cc_role_discovery(struct hci_dev *hdev, struct sk_buff *skb)
94{
95 struct hci_rp_role_discovery *rp = (void *) skb->data;
Linus Torvalds1da177e2005-04-16 15:20:36 -070096 struct hci_conn *conn;
Linus Torvalds1da177e2005-04-16 15:20:36 -070097
Marcel Holtmanna9de9242007-10-20 13:33:56 +020098 BT_DBG("%s status 0x%x", hdev->name, rp->status);
Linus Torvalds1da177e2005-04-16 15:20:36 -070099
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200100 if (rp->status)
101 return;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700102
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200103 hci_dev_lock(hdev);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700104
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200105 conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(rp->handle));
106 if (conn) {
107 if (rp->role)
108 conn->link_mode &= ~HCI_LM_MASTER;
109 else
110 conn->link_mode |= HCI_LM_MASTER;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700111 }
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200112
113 hci_dev_unlock(hdev);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700114}
115
Marcel Holtmanne4e8e372008-07-14 20:13:47 +0200116static void hci_cc_read_link_policy(struct hci_dev *hdev, struct sk_buff *skb)
117{
118 struct hci_rp_read_link_policy *rp = (void *) skb->data;
119 struct hci_conn *conn;
120
121 BT_DBG("%s status 0x%x", hdev->name, rp->status);
122
123 if (rp->status)
124 return;
125
126 hci_dev_lock(hdev);
127
128 conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(rp->handle));
129 if (conn)
130 conn->link_policy = __le16_to_cpu(rp->policy);
131
132 hci_dev_unlock(hdev);
133}
134
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200135static void hci_cc_write_link_policy(struct hci_dev *hdev, struct sk_buff *skb)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700136{
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200137 struct hci_rp_write_link_policy *rp = (void *) skb->data;
138 struct hci_conn *conn;
139 void *sent;
140
141 BT_DBG("%s status 0x%x", hdev->name, rp->status);
142
143 if (rp->status)
144 return;
145
146 sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_LINK_POLICY);
147 if (!sent)
148 return;
149
150 hci_dev_lock(hdev);
151
152 conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(rp->handle));
Marcel Holtmanne4e8e372008-07-14 20:13:47 +0200153 if (conn)
Harvey Harrison83985312008-05-02 16:25:46 -0700154 conn->link_policy = get_unaligned_le16(sent + 2);
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200155
156 hci_dev_unlock(hdev);
157}
158
Marcel Holtmanne4e8e372008-07-14 20:13:47 +0200159static void hci_cc_read_def_link_policy(struct hci_dev *hdev, struct sk_buff *skb)
160{
161 struct hci_rp_read_def_link_policy *rp = (void *) skb->data;
162
163 BT_DBG("%s status 0x%x", hdev->name, rp->status);
164
165 if (rp->status)
166 return;
167
168 hdev->link_policy = __le16_to_cpu(rp->policy);
169}
170
171static void hci_cc_write_def_link_policy(struct hci_dev *hdev, struct sk_buff *skb)
172{
173 __u8 status = *((__u8 *) skb->data);
174 void *sent;
175
176 BT_DBG("%s status 0x%x", hdev->name, status);
177
178 sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_DEF_LINK_POLICY);
179 if (!sent)
180 return;
181
182 if (!status)
183 hdev->link_policy = get_unaligned_le16(sent);
184
Johan Hedberg23bb5762010-12-21 23:01:27 +0200185 hci_req_complete(hdev, HCI_OP_WRITE_DEF_LINK_POLICY, status);
Marcel Holtmanne4e8e372008-07-14 20:13:47 +0200186}
187
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200188static void hci_cc_reset(struct hci_dev *hdev, struct sk_buff *skb)
189{
190 __u8 status = *((__u8 *) skb->data);
191
192 BT_DBG("%s status 0x%x", hdev->name, status);
193
Gustavo F. Padovan10572132011-03-16 15:36:29 -0300194 clear_bit(HCI_RESET, &hdev->flags);
195
Johan Hedberg23bb5762010-12-21 23:01:27 +0200196 hci_req_complete(hdev, HCI_OP_RESET, status);
Andre Guedesd23264a2011-11-25 20:53:38 -0300197
198 hdev->dev_flags = 0;
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200199}
200
201static void hci_cc_write_local_name(struct hci_dev *hdev, struct sk_buff *skb)
202{
203 __u8 status = *((__u8 *) skb->data);
204 void *sent;
205
206 BT_DBG("%s status 0x%x", hdev->name, status);
207
208 sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_LOCAL_NAME);
209 if (!sent)
210 return;
211
Johan Hedberg56e5cb82011-11-08 20:40:16 +0200212 hci_dev_lock(hdev);
213
Johan Hedbergb312b1612011-03-16 14:29:37 +0200214 if (test_bit(HCI_MGMT, &hdev->flags))
Johan Hedberg744cf192011-11-08 20:40:14 +0200215 mgmt_set_local_name_complete(hdev, sent, status);
Johan Hedbergb312b1612011-03-16 14:29:37 +0200216
Johan Hedberg56e5cb82011-11-08 20:40:16 +0200217 if (status == 0)
218 memcpy(hdev->dev_name, sent, HCI_MAX_NAME_LENGTH);
Johan Hedbergb312b1612011-03-16 14:29:37 +0200219
Johan Hedberg56e5cb82011-11-08 20:40:16 +0200220 hci_dev_unlock(hdev);
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 Hedberg1f6c6372011-03-16 14:29:35 +0200232 memcpy(hdev->dev_name, rp->name, HCI_MAX_NAME_LENGTH);
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200233}
234
235static void hci_cc_write_auth_enable(struct hci_dev *hdev, struct sk_buff *skb)
236{
237 __u8 status = *((__u8 *) skb->data);
238 void *sent;
239
240 BT_DBG("%s status 0x%x", hdev->name, status);
241
242 sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_AUTH_ENABLE);
243 if (!sent)
244 return;
245
246 if (!status) {
247 __u8 param = *((__u8 *) sent);
248
249 if (param == AUTH_ENABLED)
250 set_bit(HCI_AUTH, &hdev->flags);
251 else
252 clear_bit(HCI_AUTH, &hdev->flags);
253 }
254
Johan Hedberg23bb5762010-12-21 23:01:27 +0200255 hci_req_complete(hdev, HCI_OP_WRITE_AUTH_ENABLE, status);
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200256}
257
258static void hci_cc_write_encrypt_mode(struct hci_dev *hdev, struct sk_buff *skb)
259{
260 __u8 status = *((__u8 *) skb->data);
261 void *sent;
262
263 BT_DBG("%s status 0x%x", hdev->name, status);
264
265 sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_ENCRYPT_MODE);
266 if (!sent)
267 return;
268
269 if (!status) {
270 __u8 param = *((__u8 *) sent);
271
272 if (param)
273 set_bit(HCI_ENCRYPT, &hdev->flags);
274 else
275 clear_bit(HCI_ENCRYPT, &hdev->flags);
276 }
277
Johan Hedberg23bb5762010-12-21 23:01:27 +0200278 hci_req_complete(hdev, HCI_OP_WRITE_ENCRYPT_MODE, status);
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200279}
280
281static void hci_cc_write_scan_enable(struct hci_dev *hdev, struct sk_buff *skb)
282{
Johan Hedberg36f7fc72011-11-04 00:17:45 +0200283 __u8 param, status = *((__u8 *) skb->data);
284 int old_pscan, old_iscan;
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200285 void *sent;
286
287 BT_DBG("%s status 0x%x", hdev->name, status);
288
289 sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_SCAN_ENABLE);
290 if (!sent)
291 return;
292
Johan Hedberg36f7fc72011-11-04 00:17:45 +0200293 param = *((__u8 *) sent);
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200294
Johan Hedberg56e5cb82011-11-08 20:40:16 +0200295 hci_dev_lock(hdev);
296
Johan Hedberg2d7cee52011-11-07 22:16:03 +0200297 if (status != 0) {
Johan Hedberg744cf192011-11-08 20:40:14 +0200298 mgmt_write_scan_failed(hdev, param, status);
Johan Hedberg2d7cee52011-11-07 22:16:03 +0200299 hdev->discov_timeout = 0;
300 goto done;
301 }
302
Johan Hedberg36f7fc72011-11-04 00:17:45 +0200303 old_pscan = test_and_clear_bit(HCI_PSCAN, &hdev->flags);
304 old_iscan = test_and_clear_bit(HCI_ISCAN, &hdev->flags);
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200305
Johan Hedberg36f7fc72011-11-04 00:17:45 +0200306 if (param & SCAN_INQUIRY) {
307 set_bit(HCI_ISCAN, &hdev->flags);
308 if (!old_iscan)
Johan Hedberg744cf192011-11-08 20:40:14 +0200309 mgmt_discoverable(hdev, 1);
Johan Hedberg16ab91a2011-11-07 22:16:02 +0200310 if (hdev->discov_timeout > 0) {
311 int to = msecs_to_jiffies(hdev->discov_timeout * 1000);
312 queue_delayed_work(hdev->workqueue, &hdev->discov_off,
313 to);
314 }
Johan Hedberg36f7fc72011-11-04 00:17:45 +0200315 } else if (old_iscan)
Johan Hedberg744cf192011-11-08 20:40:14 +0200316 mgmt_discoverable(hdev, 0);
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200317
Johan Hedberg36f7fc72011-11-04 00:17:45 +0200318 if (param & SCAN_PAGE) {
319 set_bit(HCI_PSCAN, &hdev->flags);
320 if (!old_pscan)
Johan Hedberg744cf192011-11-08 20:40:14 +0200321 mgmt_connectable(hdev, 1);
Johan Hedberg36f7fc72011-11-04 00:17:45 +0200322 } else if (old_pscan)
Johan Hedberg744cf192011-11-08 20:40:14 +0200323 mgmt_connectable(hdev, 0);
Johan Hedberg36f7fc72011-11-04 00:17:45 +0200324
325done:
Johan Hedberg56e5cb82011-11-08 20:40:16 +0200326 hci_dev_unlock(hdev);
Johan Hedberg23bb5762010-12-21 23:01:27 +0200327 hci_req_complete(hdev, HCI_OP_WRITE_SCAN_ENABLE, status);
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200328}
329
330static void hci_cc_read_class_of_dev(struct hci_dev *hdev, struct sk_buff *skb)
331{
332 struct hci_rp_read_class_of_dev *rp = (void *) skb->data;
333
334 BT_DBG("%s status 0x%x", hdev->name, rp->status);
335
336 if (rp->status)
337 return;
338
339 memcpy(hdev->dev_class, rp->dev_class, 3);
340
341 BT_DBG("%s class 0x%.2x%.2x%.2x", hdev->name,
342 hdev->dev_class[2], hdev->dev_class[1], hdev->dev_class[0]);
343}
344
345static void hci_cc_write_class_of_dev(struct hci_dev *hdev, struct sk_buff *skb)
346{
347 __u8 status = *((__u8 *) skb->data);
348 void *sent;
349
350 BT_DBG("%s status 0x%x", hdev->name, status);
351
Marcel Holtmannf383f272008-07-14 20:13:47 +0200352 if (status)
353 return;
354
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200355 sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_CLASS_OF_DEV);
356 if (!sent)
357 return;
358
Marcel Holtmannf383f272008-07-14 20:13:47 +0200359 memcpy(hdev->dev_class, sent, 3);
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200360}
361
362static void hci_cc_read_voice_setting(struct hci_dev *hdev, struct sk_buff *skb)
363{
364 struct hci_rp_read_voice_setting *rp = (void *) skb->data;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700365 __u16 setting;
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200366
367 BT_DBG("%s status 0x%x", hdev->name, rp->status);
368
369 if (rp->status)
370 return;
371
372 setting = __le16_to_cpu(rp->voice_setting);
373
Marcel Holtmannf383f272008-07-14 20:13:47 +0200374 if (hdev->voice_setting == setting)
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200375 return;
376
377 hdev->voice_setting = setting;
378
379 BT_DBG("%s voice setting 0x%04x", hdev->name, setting);
380
Gustavo F. Padovan3c547112011-12-14 22:58:44 -0200381 if (hdev->notify)
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200382 hdev->notify(hdev, HCI_NOTIFY_VOICE_SETTING);
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200383}
384
385static void hci_cc_write_voice_setting(struct hci_dev *hdev, struct sk_buff *skb)
386{
387 __u8 status = *((__u8 *) skb->data);
Marcel Holtmannf383f272008-07-14 20:13:47 +0200388 __u16 setting;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700389 void *sent;
390
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200391 BT_DBG("%s status 0x%x", hdev->name, status);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700392
Marcel Holtmannf383f272008-07-14 20:13:47 +0200393 if (status)
394 return;
395
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200396 sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_VOICE_SETTING);
397 if (!sent)
398 return;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700399
Marcel Holtmannf383f272008-07-14 20:13:47 +0200400 setting = get_unaligned_le16(sent);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700401
Marcel Holtmannf383f272008-07-14 20:13:47 +0200402 if (hdev->voice_setting == setting)
403 return;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700404
Marcel Holtmannf383f272008-07-14 20:13:47 +0200405 hdev->voice_setting = setting;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700406
Marcel Holtmannf383f272008-07-14 20:13:47 +0200407 BT_DBG("%s voice setting 0x%04x", hdev->name, setting);
408
Gustavo F. Padovan3c547112011-12-14 22:58:44 -0200409 if (hdev->notify)
Marcel Holtmannf383f272008-07-14 20:13:47 +0200410 hdev->notify(hdev, HCI_NOTIFY_VOICE_SETTING);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700411}
412
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200413static void hci_cc_host_buffer_size(struct hci_dev *hdev, struct sk_buff *skb)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700414{
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200415 __u8 status = *((__u8 *) skb->data);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700416
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200417 BT_DBG("%s status 0x%x", hdev->name, status);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700418
Johan Hedberg23bb5762010-12-21 23:01:27 +0200419 hci_req_complete(hdev, HCI_OP_HOST_BUFFER_SIZE, status);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700420}
421
Marcel Holtmann333140b2008-07-14 20:13:48 +0200422static void hci_cc_read_ssp_mode(struct hci_dev *hdev, struct sk_buff *skb)
423{
424 struct hci_rp_read_ssp_mode *rp = (void *) skb->data;
425
426 BT_DBG("%s status 0x%x", hdev->name, rp->status);
427
428 if (rp->status)
429 return;
430
431 hdev->ssp_mode = rp->mode;
432}
433
434static void hci_cc_write_ssp_mode(struct hci_dev *hdev, struct sk_buff *skb)
435{
436 __u8 status = *((__u8 *) skb->data);
437 void *sent;
438
439 BT_DBG("%s status 0x%x", hdev->name, status);
440
441 if (status)
442 return;
443
444 sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_SSP_MODE);
445 if (!sent)
446 return;
447
448 hdev->ssp_mode = *((__u8 *) sent);
449}
450
Johan Hedbergd5859e22011-01-25 01:19:58 +0200451static u8 hci_get_inquiry_mode(struct hci_dev *hdev)
452{
453 if (hdev->features[6] & LMP_EXT_INQ)
454 return 2;
455
456 if (hdev->features[3] & LMP_RSSI_INQ)
457 return 1;
458
459 if (hdev->manufacturer == 11 && hdev->hci_rev == 0x00 &&
460 hdev->lmp_subver == 0x0757)
461 return 1;
462
463 if (hdev->manufacturer == 15) {
464 if (hdev->hci_rev == 0x03 && hdev->lmp_subver == 0x6963)
465 return 1;
466 if (hdev->hci_rev == 0x09 && hdev->lmp_subver == 0x6963)
467 return 1;
468 if (hdev->hci_rev == 0x00 && hdev->lmp_subver == 0x6965)
469 return 1;
470 }
471
472 if (hdev->manufacturer == 31 && hdev->hci_rev == 0x2005 &&
473 hdev->lmp_subver == 0x1805)
474 return 1;
475
476 return 0;
477}
478
479static void hci_setup_inquiry_mode(struct hci_dev *hdev)
480{
481 u8 mode;
482
483 mode = hci_get_inquiry_mode(hdev);
484
485 hci_send_cmd(hdev, HCI_OP_WRITE_INQUIRY_MODE, 1, &mode);
486}
487
488static void hci_setup_event_mask(struct hci_dev *hdev)
489{
490 /* The second byte is 0xff instead of 0x9f (two reserved bits
491 * disabled) since a Broadcom 1.2 dongle doesn't respond to the
492 * command otherwise */
493 u8 events[8] = { 0xff, 0xff, 0xfb, 0xff, 0x00, 0x00, 0x00, 0x00 };
494
Ville Tervo6de6c182011-05-27 11:16:21 +0300495 /* CSR 1.1 dongles does not accept any bitfield so don't try to set
496 * any event mask for pre 1.2 devices */
Andrei Emeltchenko5a13b092011-12-01 14:33:28 +0200497 if (hdev->hci_ver < BLUETOOTH_VER_1_2)
Ville Tervo6de6c182011-05-27 11:16:21 +0300498 return;
499
500 events[4] |= 0x01; /* Flow Specification Complete */
501 events[4] |= 0x02; /* Inquiry Result with RSSI */
502 events[4] |= 0x04; /* Read Remote Extended Features Complete */
503 events[5] |= 0x08; /* Synchronous Connection Complete */
504 events[5] |= 0x10; /* Synchronous Connection Changed */
Johan Hedbergd5859e22011-01-25 01:19:58 +0200505
506 if (hdev->features[3] & LMP_RSSI_INQ)
507 events[4] |= 0x04; /* Inquiry Result with RSSI */
508
509 if (hdev->features[5] & LMP_SNIFF_SUBR)
510 events[5] |= 0x20; /* Sniff Subrating */
511
512 if (hdev->features[5] & LMP_PAUSE_ENC)
513 events[5] |= 0x80; /* Encryption Key Refresh Complete */
514
515 if (hdev->features[6] & LMP_EXT_INQ)
516 events[5] |= 0x40; /* Extended Inquiry Result */
517
518 if (hdev->features[6] & LMP_NO_FLUSH)
519 events[7] |= 0x01; /* Enhanced Flush Complete */
520
521 if (hdev->features[7] & LMP_LSTO)
522 events[6] |= 0x80; /* Link Supervision Timeout Changed */
523
524 if (hdev->features[6] & LMP_SIMPLE_PAIR) {
525 events[6] |= 0x01; /* IO Capability Request */
526 events[6] |= 0x02; /* IO Capability Response */
527 events[6] |= 0x04; /* User Confirmation Request */
528 events[6] |= 0x08; /* User Passkey Request */
529 events[6] |= 0x10; /* Remote OOB Data Request */
530 events[6] |= 0x20; /* Simple Pairing Complete */
531 events[7] |= 0x04; /* User Passkey Notification */
532 events[7] |= 0x08; /* Keypress Notification */
533 events[7] |= 0x10; /* Remote Host Supported
534 * Features Notification */
535 }
536
537 if (hdev->features[4] & LMP_LE)
538 events[7] |= 0x20; /* LE Meta-Event */
539
540 hci_send_cmd(hdev, HCI_OP_SET_EVENT_MASK, sizeof(events), events);
541}
542
Andre Guedese6100a22011-06-30 19:20:54 -0300543static void hci_set_le_support(struct hci_dev *hdev)
544{
545 struct hci_cp_write_le_host_supported cp;
546
547 memset(&cp, 0, sizeof(cp));
548
549 if (enable_le) {
550 cp.le = 1;
551 cp.simul = !!(hdev->features[6] & LMP_SIMUL_LE_BR);
552 }
553
554 hci_send_cmd(hdev, HCI_OP_WRITE_LE_HOST_SUPPORTED, sizeof(cp), &cp);
555}
556
Johan Hedbergd5859e22011-01-25 01:19:58 +0200557static void hci_setup(struct hci_dev *hdev)
558{
Andrei Emeltchenkoe61ef492011-12-19 16:31:27 +0200559 if (hdev->dev_type != HCI_BREDR)
560 return;
561
Johan Hedbergd5859e22011-01-25 01:19:58 +0200562 hci_setup_event_mask(hdev);
563
Andrei Emeltchenkod095c1e2011-12-01 14:33:27 +0200564 if (hdev->hci_ver > BLUETOOTH_VER_1_1)
Johan Hedbergd5859e22011-01-25 01:19:58 +0200565 hci_send_cmd(hdev, HCI_OP_READ_LOCAL_COMMANDS, 0, NULL);
566
567 if (hdev->features[6] & LMP_SIMPLE_PAIR) {
568 u8 mode = 0x01;
569 hci_send_cmd(hdev, HCI_OP_WRITE_SSP_MODE, sizeof(mode), &mode);
570 }
571
572 if (hdev->features[3] & LMP_RSSI_INQ)
573 hci_setup_inquiry_mode(hdev);
574
575 if (hdev->features[7] & LMP_INQ_TX_PWR)
576 hci_send_cmd(hdev, HCI_OP_READ_INQ_RSP_TX_POWER, 0, NULL);
Andre Guedes971e3a42011-06-30 19:20:52 -0300577
578 if (hdev->features[7] & LMP_EXTFEATURES) {
579 struct hci_cp_read_local_ext_features cp;
580
581 cp.page = 0x01;
582 hci_send_cmd(hdev, HCI_OP_READ_LOCAL_EXT_FEATURES,
583 sizeof(cp), &cp);
584 }
Andre Guedese6100a22011-06-30 19:20:54 -0300585
586 if (hdev->features[4] & LMP_LE)
587 hci_set_le_support(hdev);
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)
597 return;
598
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);
611}
612
613static void hci_setup_link_policy(struct hci_dev *hdev)
614{
615 u16 link_policy = 0;
616
617 if (hdev->features[0] & LMP_RSWITCH)
618 link_policy |= HCI_LP_RSWITCH;
619 if (hdev->features[0] & LMP_HOLD)
620 link_policy |= HCI_LP_HOLD;
621 if (hdev->features[0] & LMP_SNIFF)
622 link_policy |= HCI_LP_SNIFF;
623 if (hdev->features[1] & LMP_PARK)
624 link_policy |= HCI_LP_PARK;
625
626 link_policy = cpu_to_le16(link_policy);
627 hci_send_cmd(hdev, HCI_OP_WRITE_DEF_LINK_POLICY,
628 sizeof(link_policy), &link_policy);
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200629}
630
631static void hci_cc_read_local_commands(struct hci_dev *hdev, struct sk_buff *skb)
632{
633 struct hci_rp_read_local_commands *rp = (void *) skb->data;
634
635 BT_DBG("%s status 0x%x", hdev->name, rp->status);
636
637 if (rp->status)
Johan Hedbergd5859e22011-01-25 01:19:58 +0200638 goto done;
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200639
640 memcpy(hdev->commands, rp->commands, sizeof(hdev->commands));
Johan Hedbergd5859e22011-01-25 01:19:58 +0200641
642 if (test_bit(HCI_INIT, &hdev->flags) && (hdev->commands[5] & 0x10))
643 hci_setup_link_policy(hdev);
644
645done:
646 hci_req_complete(hdev, HCI_OP_READ_LOCAL_COMMANDS, rp->status);
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200647}
648
649static void hci_cc_read_local_features(struct hci_dev *hdev, struct sk_buff *skb)
650{
651 struct hci_rp_read_local_features *rp = (void *) skb->data;
652
653 BT_DBG("%s status 0x%x", hdev->name, rp->status);
654
655 if (rp->status)
656 return;
657
658 memcpy(hdev->features, rp->features, 8);
659
660 /* Adjust default settings according to features
661 * supported by device. */
662
663 if (hdev->features[0] & LMP_3SLOT)
664 hdev->pkt_type |= (HCI_DM3 | HCI_DH3);
665
666 if (hdev->features[0] & LMP_5SLOT)
667 hdev->pkt_type |= (HCI_DM5 | HCI_DH5);
668
669 if (hdev->features[1] & LMP_HV2) {
670 hdev->pkt_type |= (HCI_HV2);
671 hdev->esco_type |= (ESCO_HV2);
672 }
673
674 if (hdev->features[1] & LMP_HV3) {
675 hdev->pkt_type |= (HCI_HV3);
676 hdev->esco_type |= (ESCO_HV3);
677 }
678
679 if (hdev->features[3] & LMP_ESCO)
680 hdev->esco_type |= (ESCO_EV3);
681
682 if (hdev->features[4] & LMP_EV4)
683 hdev->esco_type |= (ESCO_EV4);
684
685 if (hdev->features[4] & LMP_EV5)
686 hdev->esco_type |= (ESCO_EV5);
687
Marcel Holtmannefc76882009-02-06 09:13:37 +0100688 if (hdev->features[5] & LMP_EDR_ESCO_2M)
689 hdev->esco_type |= (ESCO_2EV3);
690
691 if (hdev->features[5] & LMP_EDR_ESCO_3M)
692 hdev->esco_type |= (ESCO_3EV3);
693
694 if (hdev->features[5] & LMP_EDR_3S_ESCO)
695 hdev->esco_type |= (ESCO_2EV5 | ESCO_3EV5);
696
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200697 BT_DBG("%s features 0x%.2x%.2x%.2x%.2x%.2x%.2x%.2x%.2x", hdev->name,
698 hdev->features[0], hdev->features[1],
699 hdev->features[2], hdev->features[3],
700 hdev->features[4], hdev->features[5],
701 hdev->features[6], hdev->features[7]);
702}
703
Andre Guedes971e3a42011-06-30 19:20:52 -0300704static void hci_cc_read_local_ext_features(struct hci_dev *hdev,
705 struct sk_buff *skb)
706{
707 struct hci_rp_read_local_ext_features *rp = (void *) skb->data;
708
709 BT_DBG("%s status 0x%x", hdev->name, rp->status);
710
711 if (rp->status)
712 return;
713
714 memcpy(hdev->extfeatures, rp->features, 8);
715
716 hci_req_complete(hdev, HCI_OP_READ_LOCAL_EXT_FEATURES, rp->status);
717}
718
Andrei Emeltchenko1e89cff2011-11-24 14:52:02 +0200719static void hci_cc_read_flow_control_mode(struct hci_dev *hdev,
720 struct sk_buff *skb)
721{
722 struct hci_rp_read_flow_control_mode *rp = (void *) skb->data;
723
724 BT_DBG("%s status 0x%x", hdev->name, rp->status);
725
726 if (rp->status)
727 return;
728
729 hdev->flow_ctl_mode = rp->mode;
730
731 hci_req_complete(hdev, HCI_OP_READ_FLOW_CONTROL_MODE, rp->status);
732}
733
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200734static void hci_cc_read_buffer_size(struct hci_dev *hdev, struct sk_buff *skb)
735{
736 struct hci_rp_read_buffer_size *rp = (void *) skb->data;
737
738 BT_DBG("%s status 0x%x", hdev->name, rp->status);
739
740 if (rp->status)
741 return;
742
743 hdev->acl_mtu = __le16_to_cpu(rp->acl_mtu);
744 hdev->sco_mtu = rp->sco_mtu;
745 hdev->acl_pkts = __le16_to_cpu(rp->acl_max_pkt);
746 hdev->sco_pkts = __le16_to_cpu(rp->sco_max_pkt);
747
748 if (test_bit(HCI_QUIRK_FIXUP_BUFFER_SIZE, &hdev->quirks)) {
749 hdev->sco_mtu = 64;
750 hdev->sco_pkts = 8;
751 }
752
753 hdev->acl_cnt = hdev->acl_pkts;
754 hdev->sco_cnt = hdev->sco_pkts;
755
756 BT_DBG("%s acl mtu %d:%d sco mtu %d:%d", hdev->name,
757 hdev->acl_mtu, hdev->acl_pkts,
758 hdev->sco_mtu, hdev->sco_pkts);
759}
760
761static void hci_cc_read_bd_addr(struct hci_dev *hdev, struct sk_buff *skb)
762{
763 struct hci_rp_read_bd_addr *rp = (void *) skb->data;
764
765 BT_DBG("%s status 0x%x", hdev->name, rp->status);
766
767 if (!rp->status)
768 bacpy(&hdev->bdaddr, &rp->bdaddr);
769
Johan Hedberg23bb5762010-12-21 23:01:27 +0200770 hci_req_complete(hdev, HCI_OP_READ_BD_ADDR, rp->status);
771}
772
Andrei Emeltchenko350ee4c2011-12-07 15:56:51 +0200773static void hci_cc_read_data_block_size(struct hci_dev *hdev,
774 struct sk_buff *skb)
775{
776 struct hci_rp_read_data_block_size *rp = (void *) skb->data;
777
778 BT_DBG("%s status 0x%x", hdev->name, rp->status);
779
780 if (rp->status)
781 return;
782
783 hdev->block_mtu = __le16_to_cpu(rp->max_acl_len);
784 hdev->block_len = __le16_to_cpu(rp->block_len);
785 hdev->num_blocks = __le16_to_cpu(rp->num_blocks);
786
787 hdev->block_cnt = hdev->num_blocks;
788
789 BT_DBG("%s blk mtu %d cnt %d len %d", hdev->name, hdev->block_mtu,
790 hdev->block_cnt, hdev->block_len);
791
792 hci_req_complete(hdev, HCI_OP_READ_DATA_BLOCK_SIZE, rp->status);
793}
794
Johan Hedberg23bb5762010-12-21 23:01:27 +0200795static void hci_cc_write_ca_timeout(struct hci_dev *hdev, struct sk_buff *skb)
796{
797 __u8 status = *((__u8 *) skb->data);
798
799 BT_DBG("%s status 0x%x", hdev->name, status);
800
801 hci_req_complete(hdev, HCI_OP_WRITE_CA_TIMEOUT, status);
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200802}
803
Andrei Emeltchenko928abaa2011-10-12 10:53:57 +0300804static void hci_cc_read_local_amp_info(struct hci_dev *hdev,
805 struct sk_buff *skb)
806{
807 struct hci_rp_read_local_amp_info *rp = (void *) skb->data;
808
809 BT_DBG("%s status 0x%x", hdev->name, rp->status);
810
811 if (rp->status)
812 return;
813
814 hdev->amp_status = rp->amp_status;
815 hdev->amp_total_bw = __le32_to_cpu(rp->total_bw);
816 hdev->amp_max_bw = __le32_to_cpu(rp->max_bw);
817 hdev->amp_min_latency = __le32_to_cpu(rp->min_latency);
818 hdev->amp_max_pdu = __le32_to_cpu(rp->max_pdu);
819 hdev->amp_type = rp->amp_type;
820 hdev->amp_pal_cap = __le16_to_cpu(rp->pal_cap);
821 hdev->amp_assoc_size = __le16_to_cpu(rp->max_assoc_size);
822 hdev->amp_be_flush_to = __le32_to_cpu(rp->be_flush_to);
823 hdev->amp_max_flush_to = __le32_to_cpu(rp->max_flush_to);
824
825 hci_req_complete(hdev, HCI_OP_READ_LOCAL_AMP_INFO, rp->status);
826}
827
Johan Hedbergb0916ea2011-01-10 13:44:55 +0200828static void hci_cc_delete_stored_link_key(struct hci_dev *hdev,
829 struct sk_buff *skb)
830{
831 __u8 status = *((__u8 *) skb->data);
832
833 BT_DBG("%s status 0x%x", hdev->name, status);
834
835 hci_req_complete(hdev, HCI_OP_DELETE_STORED_LINK_KEY, status);
836}
837
Johan Hedbergd5859e22011-01-25 01:19:58 +0200838static void hci_cc_set_event_mask(struct hci_dev *hdev, struct sk_buff *skb)
839{
840 __u8 status = *((__u8 *) skb->data);
841
842 BT_DBG("%s status 0x%x", hdev->name, status);
843
844 hci_req_complete(hdev, HCI_OP_SET_EVENT_MASK, status);
845}
846
847static void hci_cc_write_inquiry_mode(struct hci_dev *hdev,
848 struct sk_buff *skb)
849{
850 __u8 status = *((__u8 *) skb->data);
851
852 BT_DBG("%s status 0x%x", hdev->name, status);
853
854 hci_req_complete(hdev, HCI_OP_WRITE_INQUIRY_MODE, status);
855}
856
857static void hci_cc_read_inq_rsp_tx_power(struct hci_dev *hdev,
858 struct sk_buff *skb)
859{
860 __u8 status = *((__u8 *) skb->data);
861
862 BT_DBG("%s status 0x%x", hdev->name, status);
863
864 hci_req_complete(hdev, HCI_OP_READ_INQ_RSP_TX_POWER, status);
865}
866
867static void hci_cc_set_event_flt(struct hci_dev *hdev, struct sk_buff *skb)
868{
869 __u8 status = *((__u8 *) skb->data);
870
871 BT_DBG("%s status 0x%x", hdev->name, status);
872
873 hci_req_complete(hdev, HCI_OP_SET_EVENT_FLT, status);
874}
875
Johan Hedberg980e1a52011-01-22 06:10:07 +0200876static void hci_cc_pin_code_reply(struct hci_dev *hdev, struct sk_buff *skb)
877{
878 struct hci_rp_pin_code_reply *rp = (void *) skb->data;
879 struct hci_cp_pin_code_reply *cp;
880 struct hci_conn *conn;
881
882 BT_DBG("%s status 0x%x", hdev->name, rp->status);
883
Johan Hedberg56e5cb82011-11-08 20:40:16 +0200884 hci_dev_lock(hdev);
885
Johan Hedberg980e1a52011-01-22 06:10:07 +0200886 if (test_bit(HCI_MGMT, &hdev->flags))
Johan Hedberg744cf192011-11-08 20:40:14 +0200887 mgmt_pin_code_reply_complete(hdev, &rp->bdaddr, rp->status);
Johan Hedberg980e1a52011-01-22 06:10:07 +0200888
889 if (rp->status != 0)
Johan Hedberg56e5cb82011-11-08 20:40:16 +0200890 goto unlock;
Johan Hedberg980e1a52011-01-22 06:10:07 +0200891
892 cp = hci_sent_cmd_data(hdev, HCI_OP_PIN_CODE_REPLY);
893 if (!cp)
Johan Hedberg56e5cb82011-11-08 20:40:16 +0200894 goto unlock;
Johan Hedberg980e1a52011-01-22 06:10:07 +0200895
896 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &cp->bdaddr);
897 if (conn)
898 conn->pin_length = cp->pin_len;
Johan Hedberg56e5cb82011-11-08 20:40:16 +0200899
900unlock:
901 hci_dev_unlock(hdev);
Johan Hedberg980e1a52011-01-22 06:10:07 +0200902}
903
904static void hci_cc_pin_code_neg_reply(struct hci_dev *hdev, struct sk_buff *skb)
905{
906 struct hci_rp_pin_code_neg_reply *rp = (void *) skb->data;
907
908 BT_DBG("%s status 0x%x", hdev->name, rp->status);
909
Johan Hedberg56e5cb82011-11-08 20:40:16 +0200910 hci_dev_lock(hdev);
911
Johan Hedberg980e1a52011-01-22 06:10:07 +0200912 if (test_bit(HCI_MGMT, &hdev->flags))
Johan Hedberg744cf192011-11-08 20:40:14 +0200913 mgmt_pin_code_neg_reply_complete(hdev, &rp->bdaddr,
Johan Hedberg980e1a52011-01-22 06:10:07 +0200914 rp->status);
Johan Hedberg56e5cb82011-11-08 20:40:16 +0200915
916 hci_dev_unlock(hdev);
Johan Hedberg980e1a52011-01-22 06:10:07 +0200917}
Johan Hedberg56e5cb82011-11-08 20:40:16 +0200918
Ville Tervo6ed58ec2011-02-10 22:38:48 -0300919static void hci_cc_le_read_buffer_size(struct hci_dev *hdev,
920 struct sk_buff *skb)
921{
922 struct hci_rp_le_read_buffer_size *rp = (void *) skb->data;
923
924 BT_DBG("%s status 0x%x", hdev->name, rp->status);
925
926 if (rp->status)
927 return;
928
929 hdev->le_mtu = __le16_to_cpu(rp->le_mtu);
930 hdev->le_pkts = rp->le_max_pkt;
931
932 hdev->le_cnt = hdev->le_pkts;
933
934 BT_DBG("%s le mtu %d:%d", hdev->name, hdev->le_mtu, hdev->le_pkts);
935
936 hci_req_complete(hdev, HCI_OP_LE_READ_BUFFER_SIZE, rp->status);
937}
Johan Hedberg980e1a52011-01-22 06:10:07 +0200938
Johan Hedberga5c29682011-02-19 12:05:57 -0300939static void hci_cc_user_confirm_reply(struct hci_dev *hdev, struct sk_buff *skb)
940{
941 struct hci_rp_user_confirm_reply *rp = (void *) skb->data;
942
943 BT_DBG("%s status 0x%x", hdev->name, rp->status);
944
Johan Hedberg56e5cb82011-11-08 20:40:16 +0200945 hci_dev_lock(hdev);
946
Johan Hedberga5c29682011-02-19 12:05:57 -0300947 if (test_bit(HCI_MGMT, &hdev->flags))
Johan Hedberg744cf192011-11-08 20:40:14 +0200948 mgmt_user_confirm_reply_complete(hdev, &rp->bdaddr,
Johan Hedberga5c29682011-02-19 12:05:57 -0300949 rp->status);
Johan Hedberg56e5cb82011-11-08 20:40:16 +0200950
951 hci_dev_unlock(hdev);
Johan Hedberga5c29682011-02-19 12:05:57 -0300952}
953
954static void hci_cc_user_confirm_neg_reply(struct hci_dev *hdev,
955 struct sk_buff *skb)
956{
957 struct hci_rp_user_confirm_reply *rp = (void *) skb->data;
958
959 BT_DBG("%s status 0x%x", hdev->name, rp->status);
960
Johan Hedberg56e5cb82011-11-08 20:40:16 +0200961 hci_dev_lock(hdev);
962
Johan Hedberga5c29682011-02-19 12:05:57 -0300963 if (test_bit(HCI_MGMT, &hdev->flags))
Johan Hedberg744cf192011-11-08 20:40:14 +0200964 mgmt_user_confirm_neg_reply_complete(hdev, &rp->bdaddr,
Johan Hedberga5c29682011-02-19 12:05:57 -0300965 rp->status);
Johan Hedberg56e5cb82011-11-08 20:40:16 +0200966
967 hci_dev_unlock(hdev);
Johan Hedberga5c29682011-02-19 12:05:57 -0300968}
969
Brian Gix1143d452011-11-23 08:28:34 -0800970static void hci_cc_user_passkey_reply(struct hci_dev *hdev, struct sk_buff *skb)
971{
972 struct hci_rp_user_confirm_reply *rp = (void *) skb->data;
973
974 BT_DBG("%s status 0x%x", hdev->name, rp->status);
975
976 hci_dev_lock(hdev);
977
978 if (test_bit(HCI_MGMT, &hdev->flags))
979 mgmt_user_passkey_reply_complete(hdev, &rp->bdaddr,
980 rp->status);
981
982 hci_dev_unlock(hdev);
983}
984
985static void hci_cc_user_passkey_neg_reply(struct hci_dev *hdev,
986 struct sk_buff *skb)
987{
988 struct hci_rp_user_confirm_reply *rp = (void *) skb->data;
989
990 BT_DBG("%s status 0x%x", hdev->name, rp->status);
991
992 hci_dev_lock(hdev);
993
994 if (test_bit(HCI_MGMT, &hdev->flags))
995 mgmt_user_passkey_neg_reply_complete(hdev, &rp->bdaddr,
996 rp->status);
997
998 hci_dev_unlock(hdev);
999}
1000
Szymon Jancc35938b2011-03-22 13:12:21 +01001001static void hci_cc_read_local_oob_data_reply(struct hci_dev *hdev,
1002 struct sk_buff *skb)
1003{
1004 struct hci_rp_read_local_oob_data *rp = (void *) skb->data;
1005
1006 BT_DBG("%s status 0x%x", hdev->name, rp->status);
1007
Johan Hedberg56e5cb82011-11-08 20:40:16 +02001008 hci_dev_lock(hdev);
Johan Hedberg744cf192011-11-08 20:40:14 +02001009 mgmt_read_local_oob_data_reply_complete(hdev, rp->hash,
Szymon Jancc35938b2011-03-22 13:12:21 +01001010 rp->randomizer, rp->status);
Johan Hedberg56e5cb82011-11-08 20:40:16 +02001011 hci_dev_unlock(hdev);
Szymon Jancc35938b2011-03-22 13:12:21 +01001012}
1013
Andre Guedes07f7fa52011-12-02 21:13:31 +09001014static void hci_cc_le_set_scan_param(struct hci_dev *hdev, struct sk_buff *skb)
1015{
1016 __u8 status = *((__u8 *) skb->data);
1017
1018 BT_DBG("%s status 0x%x", hdev->name, status);
1019}
1020
Andre Guedeseb9d91f2011-05-26 16:23:52 -03001021static void hci_cc_le_set_scan_enable(struct hci_dev *hdev,
1022 struct sk_buff *skb)
1023{
1024 struct hci_cp_le_set_scan_enable *cp;
1025 __u8 status = *((__u8 *) skb->data);
1026
1027 BT_DBG("%s status 0x%x", hdev->name, status);
1028
1029 if (status)
1030 return;
1031
1032 cp = hci_sent_cmd_data(hdev, HCI_OP_LE_SET_SCAN_ENABLE);
1033 if (!cp)
1034 return;
1035
Andre Guedes35815082011-05-26 16:23:53 -03001036 if (cp->enable == 0x01) {
Andre Guedesd23264a2011-11-25 20:53:38 -03001037 set_bit(HCI_LE_SCAN, &hdev->dev_flags);
1038
Gustavo F. Padovandb323f22011-06-20 16:39:29 -03001039 cancel_delayed_work_sync(&hdev->adv_work);
Andre Guedesa8f13c82011-09-09 18:56:24 -03001040
1041 hci_dev_lock(hdev);
Andre Guedeseb9d91f2011-05-26 16:23:52 -03001042 hci_adv_entries_clear(hdev);
Andre Guedesa8f13c82011-09-09 18:56:24 -03001043 hci_dev_unlock(hdev);
Andre Guedes35815082011-05-26 16:23:53 -03001044 } else if (cp->enable == 0x00) {
Andre Guedesd23264a2011-11-25 20:53:38 -03001045 clear_bit(HCI_LE_SCAN, &hdev->dev_flags);
1046
Gustavo F. Padovandb323f22011-06-20 16:39:29 -03001047 cancel_delayed_work_sync(&hdev->adv_work);
1048 queue_delayed_work(hdev->workqueue, &hdev->adv_work,
1049 jiffies + ADV_CLEAR_TIMEOUT);
Andre Guedes35815082011-05-26 16:23:53 -03001050 }
Andre Guedeseb9d91f2011-05-26 16:23:52 -03001051}
1052
Vinicius Costa Gomesa7a595f2011-06-09 18:50:47 -03001053static void hci_cc_le_ltk_reply(struct hci_dev *hdev, struct sk_buff *skb)
1054{
1055 struct hci_rp_le_ltk_reply *rp = (void *) skb->data;
1056
1057 BT_DBG("%s status 0x%x", hdev->name, rp->status);
1058
1059 if (rp->status)
1060 return;
1061
1062 hci_req_complete(hdev, HCI_OP_LE_LTK_REPLY, rp->status);
1063}
1064
1065static void hci_cc_le_ltk_neg_reply(struct hci_dev *hdev, struct sk_buff *skb)
1066{
1067 struct hci_rp_le_ltk_neg_reply *rp = (void *) skb->data;
1068
1069 BT_DBG("%s status 0x%x", hdev->name, rp->status);
1070
1071 if (rp->status)
1072 return;
1073
1074 hci_req_complete(hdev, HCI_OP_LE_LTK_NEG_REPLY, rp->status);
1075}
1076
Andre Guedesf9b49302011-06-30 19:20:53 -03001077static inline void hci_cc_write_le_host_supported(struct hci_dev *hdev,
1078 struct sk_buff *skb)
1079{
1080 struct hci_cp_read_local_ext_features cp;
1081 __u8 status = *((__u8 *) skb->data);
1082
1083 BT_DBG("%s status 0x%x", hdev->name, status);
1084
1085 if (status)
1086 return;
1087
1088 cp.page = 0x01;
1089 hci_send_cmd(hdev, HCI_OP_READ_LOCAL_EXT_FEATURES, sizeof(cp), &cp);
1090}
1091
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001092static inline void hci_cs_inquiry(struct hci_dev *hdev, __u8 status)
1093{
1094 BT_DBG("%s status 0x%x", hdev->name, status);
1095
1096 if (status) {
Johan Hedberg23bb5762010-12-21 23:01:27 +02001097 hci_req_complete(hdev, HCI_OP_INQUIRY, status);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001098 hci_conn_check_pending(hdev);
Johan Hedberg56e5cb82011-11-08 20:40:16 +02001099 hci_dev_lock(hdev);
Johan Hedberg164a6e72011-11-01 17:06:44 +02001100 if (test_bit(HCI_MGMT, &hdev->flags))
Andre Guedes7a135102011-11-09 17:14:25 -03001101 mgmt_start_discovery_failed(hdev, status);
Johan Hedberg56e5cb82011-11-08 20:40:16 +02001102 hci_dev_unlock(hdev);
Johan Hedberg314b2382011-04-27 10:29:57 -04001103 return;
1104 }
1105
Andre Guedes89352e72011-11-04 14:16:53 -03001106 set_bit(HCI_INQUIRY, &hdev->flags);
1107
Johan Hedberg56e5cb82011-11-08 20:40:16 +02001108 hci_dev_lock(hdev);
Johan Hedberg744cf192011-11-08 20:40:14 +02001109 mgmt_discovering(hdev, 1);
Johan Hedberg56e5cb82011-11-08 20:40:16 +02001110 hci_dev_unlock(hdev);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001111}
1112
Linus Torvalds1da177e2005-04-16 15:20:36 -07001113static inline void hci_cs_create_conn(struct hci_dev *hdev, __u8 status)
1114{
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001115 struct hci_cp_create_conn *cp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001116 struct hci_conn *conn;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001117
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001118 BT_DBG("%s status 0x%x", hdev->name, status);
1119
1120 cp = hci_sent_cmd_data(hdev, HCI_OP_CREATE_CONN);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001121 if (!cp)
1122 return;
1123
1124 hci_dev_lock(hdev);
1125
1126 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &cp->bdaddr);
1127
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001128 BT_DBG("%s bdaddr %s conn %p", hdev->name, batostr(&cp->bdaddr), conn);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001129
1130 if (status) {
1131 if (conn && conn->state == BT_CONNECT) {
Marcel Holtmann4c67bc72006-10-15 17:30:56 +02001132 if (status != 0x0c || conn->attempt > 2) {
1133 conn->state = BT_CLOSED;
1134 hci_proto_connect_cfm(conn, status);
1135 hci_conn_del(conn);
1136 } else
1137 conn->state = BT_CONNECT2;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001138 }
1139 } else {
1140 if (!conn) {
1141 conn = hci_conn_add(hdev, ACL_LINK, &cp->bdaddr);
1142 if (conn) {
1143 conn->out = 1;
1144 conn->link_mode |= HCI_LM_MASTER;
1145 } else
Gustavo F. Padovan893ef972010-07-18 15:13:37 -03001146 BT_ERR("No memory for new connection");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001147 }
1148 }
1149
1150 hci_dev_unlock(hdev);
1151}
1152
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001153static void hci_cs_add_sco(struct hci_dev *hdev, __u8 status)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001154{
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001155 struct hci_cp_add_sco *cp;
1156 struct hci_conn *acl, *sco;
1157 __u16 handle;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001158
Marcel Holtmannb6a0dc82007-10-20 14:55:10 +02001159 BT_DBG("%s status 0x%x", hdev->name, status);
1160
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001161 if (!status)
1162 return;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001163
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001164 cp = hci_sent_cmd_data(hdev, HCI_OP_ADD_SCO);
1165 if (!cp)
1166 return;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001167
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001168 handle = __le16_to_cpu(cp->handle);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001169
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001170 BT_DBG("%s handle %d", hdev->name, handle);
Marcel Holtmann6bd57412006-11-18 22:14:22 +01001171
1172 hci_dev_lock(hdev);
1173
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001174 acl = hci_conn_hash_lookup_handle(hdev, handle);
Andrei Emeltchenko5a08ecc2011-01-11 17:20:20 +02001175 if (acl) {
1176 sco = acl->link;
1177 if (sco) {
1178 sco->state = BT_CLOSED;
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001179
Andrei Emeltchenko5a08ecc2011-01-11 17:20:20 +02001180 hci_proto_connect_cfm(sco, status);
1181 hci_conn_del(sco);
1182 }
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001183 }
Marcel Holtmann6bd57412006-11-18 22:14:22 +01001184
1185 hci_dev_unlock(hdev);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001186}
1187
Marcel Holtmannf8558552008-07-14 20:13:49 +02001188static void hci_cs_auth_requested(struct hci_dev *hdev, __u8 status)
1189{
1190 struct hci_cp_auth_requested *cp;
1191 struct hci_conn *conn;
1192
1193 BT_DBG("%s status 0x%x", hdev->name, status);
1194
1195 if (!status)
1196 return;
1197
1198 cp = hci_sent_cmd_data(hdev, HCI_OP_AUTH_REQUESTED);
1199 if (!cp)
1200 return;
1201
1202 hci_dev_lock(hdev);
1203
1204 conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(cp->handle));
1205 if (conn) {
1206 if (conn->state == BT_CONFIG) {
1207 hci_proto_connect_cfm(conn, status);
1208 hci_conn_put(conn);
1209 }
1210 }
1211
1212 hci_dev_unlock(hdev);
1213}
1214
1215static void hci_cs_set_conn_encrypt(struct hci_dev *hdev, __u8 status)
1216{
1217 struct hci_cp_set_conn_encrypt *cp;
1218 struct hci_conn *conn;
1219
1220 BT_DBG("%s status 0x%x", hdev->name, status);
1221
1222 if (!status)
1223 return;
1224
1225 cp = hci_sent_cmd_data(hdev, HCI_OP_SET_CONN_ENCRYPT);
1226 if (!cp)
1227 return;
1228
1229 hci_dev_lock(hdev);
1230
1231 conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(cp->handle));
1232 if (conn) {
1233 if (conn->state == BT_CONFIG) {
1234 hci_proto_connect_cfm(conn, status);
1235 hci_conn_put(conn);
1236 }
1237 }
1238
1239 hci_dev_unlock(hdev);
1240}
1241
Johan Hedberg127178d2010-11-18 22:22:29 +02001242static int hci_outgoing_auth_needed(struct hci_dev *hdev,
Szymon Janc138d22e2011-02-17 16:44:23 +01001243 struct hci_conn *conn)
Johan Hedberg392599b2010-11-18 22:22:28 +02001244{
Johan Hedberg392599b2010-11-18 22:22:28 +02001245 if (conn->state != BT_CONFIG || !conn->out)
1246 return 0;
1247
Johan Hedberg765c2a92011-01-19 12:06:52 +05301248 if (conn->pending_sec_level == BT_SECURITY_SDP)
Johan Hedberg392599b2010-11-18 22:22:28 +02001249 return 0;
1250
1251 /* Only request authentication for SSP connections or non-SSP
Vinicius Costa Gomese9bf2bf2011-09-02 14:51:20 -03001252 * devices with sec_level HIGH or if MITM protection is requested */
Johan Hedberg392599b2010-11-18 22:22:28 +02001253 if (!(hdev->ssp_mode > 0 && conn->ssp_mode > 0) &&
Vinicius Costa Gomese9bf2bf2011-09-02 14:51:20 -03001254 conn->pending_sec_level != BT_SECURITY_HIGH &&
1255 !(conn->auth_type & 0x01))
Johan Hedberg392599b2010-11-18 22:22:28 +02001256 return 0;
1257
Johan Hedberg392599b2010-11-18 22:22:28 +02001258 return 1;
1259}
1260
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001261static void hci_cs_remote_name_req(struct hci_dev *hdev, __u8 status)
1262{
Johan Hedberg127178d2010-11-18 22:22:29 +02001263 struct hci_cp_remote_name_req *cp;
1264 struct hci_conn *conn;
1265
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001266 BT_DBG("%s status 0x%x", hdev->name, status);
Johan Hedberg127178d2010-11-18 22:22:29 +02001267
1268 /* If successful wait for the name req complete event before
1269 * checking for the need to do authentication */
1270 if (!status)
1271 return;
1272
1273 cp = hci_sent_cmd_data(hdev, HCI_OP_REMOTE_NAME_REQ);
1274 if (!cp)
1275 return;
1276
1277 hci_dev_lock(hdev);
1278
1279 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &cp->bdaddr);
Johan Hedberg79c6c702011-04-28 11:28:55 -07001280 if (!conn)
1281 goto unlock;
1282
1283 if (!hci_outgoing_auth_needed(hdev, conn))
1284 goto unlock;
1285
1286 if (!test_and_set_bit(HCI_CONN_AUTH_PEND, &conn->pend)) {
Johan Hedberg127178d2010-11-18 22:22:29 +02001287 struct hci_cp_auth_requested cp;
1288 cp.handle = __cpu_to_le16(conn->handle);
1289 hci_send_cmd(hdev, HCI_OP_AUTH_REQUESTED, sizeof(cp), &cp);
1290 }
1291
Johan Hedberg79c6c702011-04-28 11:28:55 -07001292unlock:
Johan Hedberg127178d2010-11-18 22:22:29 +02001293 hci_dev_unlock(hdev);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001294}
1295
Marcel Holtmann769be972008-07-14 20:13:49 +02001296static void hci_cs_read_remote_features(struct hci_dev *hdev, __u8 status)
1297{
1298 struct hci_cp_read_remote_features *cp;
1299 struct hci_conn *conn;
1300
1301 BT_DBG("%s status 0x%x", hdev->name, status);
1302
1303 if (!status)
1304 return;
1305
1306 cp = hci_sent_cmd_data(hdev, HCI_OP_READ_REMOTE_FEATURES);
1307 if (!cp)
1308 return;
1309
1310 hci_dev_lock(hdev);
1311
1312 conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(cp->handle));
1313 if (conn) {
1314 if (conn->state == BT_CONFIG) {
Marcel Holtmann769be972008-07-14 20:13:49 +02001315 hci_proto_connect_cfm(conn, status);
1316 hci_conn_put(conn);
1317 }
1318 }
1319
1320 hci_dev_unlock(hdev);
1321}
1322
1323static void hci_cs_read_remote_ext_features(struct hci_dev *hdev, __u8 status)
1324{
1325 struct hci_cp_read_remote_ext_features *cp;
1326 struct hci_conn *conn;
1327
1328 BT_DBG("%s status 0x%x", hdev->name, status);
1329
1330 if (!status)
1331 return;
1332
1333 cp = hci_sent_cmd_data(hdev, HCI_OP_READ_REMOTE_EXT_FEATURES);
1334 if (!cp)
1335 return;
1336
1337 hci_dev_lock(hdev);
1338
1339 conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(cp->handle));
1340 if (conn) {
1341 if (conn->state == BT_CONFIG) {
Marcel Holtmann769be972008-07-14 20:13:49 +02001342 hci_proto_connect_cfm(conn, status);
1343 hci_conn_put(conn);
1344 }
1345 }
1346
1347 hci_dev_unlock(hdev);
1348}
1349
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001350static void hci_cs_setup_sync_conn(struct hci_dev *hdev, __u8 status)
1351{
Marcel Holtmannb6a0dc82007-10-20 14:55:10 +02001352 struct hci_cp_setup_sync_conn *cp;
1353 struct hci_conn *acl, *sco;
1354 __u16 handle;
1355
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001356 BT_DBG("%s status 0x%x", hdev->name, status);
Marcel Holtmannb6a0dc82007-10-20 14:55:10 +02001357
1358 if (!status)
1359 return;
1360
1361 cp = hci_sent_cmd_data(hdev, HCI_OP_SETUP_SYNC_CONN);
1362 if (!cp)
1363 return;
1364
1365 handle = __le16_to_cpu(cp->handle);
1366
1367 BT_DBG("%s handle %d", hdev->name, handle);
1368
1369 hci_dev_lock(hdev);
1370
1371 acl = hci_conn_hash_lookup_handle(hdev, handle);
Andrei Emeltchenko5a08ecc2011-01-11 17:20:20 +02001372 if (acl) {
1373 sco = acl->link;
1374 if (sco) {
1375 sco->state = BT_CLOSED;
Marcel Holtmannb6a0dc82007-10-20 14:55:10 +02001376
Andrei Emeltchenko5a08ecc2011-01-11 17:20:20 +02001377 hci_proto_connect_cfm(sco, status);
1378 hci_conn_del(sco);
1379 }
Marcel Holtmannb6a0dc82007-10-20 14:55:10 +02001380 }
1381
1382 hci_dev_unlock(hdev);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001383}
1384
1385static void hci_cs_sniff_mode(struct hci_dev *hdev, __u8 status)
1386{
1387 struct hci_cp_sniff_mode *cp;
1388 struct hci_conn *conn;
1389
1390 BT_DBG("%s status 0x%x", hdev->name, status);
1391
1392 if (!status)
1393 return;
1394
1395 cp = hci_sent_cmd_data(hdev, HCI_OP_SNIFF_MODE);
1396 if (!cp)
1397 return;
1398
1399 hci_dev_lock(hdev);
1400
1401 conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(cp->handle));
Marcel Holtmanne73439d2010-07-26 10:06:00 -04001402 if (conn) {
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001403 clear_bit(HCI_CONN_MODE_CHANGE_PEND, &conn->pend);
1404
Marcel Holtmanne73439d2010-07-26 10:06:00 -04001405 if (test_and_clear_bit(HCI_CONN_SCO_SETUP_PEND, &conn->pend))
1406 hci_sco_setup(conn, status);
1407 }
1408
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001409 hci_dev_unlock(hdev);
1410}
1411
1412static void hci_cs_exit_sniff_mode(struct hci_dev *hdev, __u8 status)
1413{
1414 struct hci_cp_exit_sniff_mode *cp;
1415 struct hci_conn *conn;
1416
1417 BT_DBG("%s status 0x%x", hdev->name, status);
1418
1419 if (!status)
1420 return;
1421
1422 cp = hci_sent_cmd_data(hdev, HCI_OP_EXIT_SNIFF_MODE);
1423 if (!cp)
1424 return;
1425
1426 hci_dev_lock(hdev);
1427
1428 conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(cp->handle));
Marcel Holtmanne73439d2010-07-26 10:06:00 -04001429 if (conn) {
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001430 clear_bit(HCI_CONN_MODE_CHANGE_PEND, &conn->pend);
1431
Marcel Holtmanne73439d2010-07-26 10:06:00 -04001432 if (test_and_clear_bit(HCI_CONN_SCO_SETUP_PEND, &conn->pend))
1433 hci_sco_setup(conn, status);
1434 }
1435
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001436 hci_dev_unlock(hdev);
1437}
1438
Ville Tervofcd89c02011-02-10 22:38:47 -03001439static void hci_cs_le_create_conn(struct hci_dev *hdev, __u8 status)
1440{
1441 struct hci_cp_le_create_conn *cp;
1442 struct hci_conn *conn;
1443
1444 BT_DBG("%s status 0x%x", hdev->name, status);
1445
1446 cp = hci_sent_cmd_data(hdev, HCI_OP_LE_CREATE_CONN);
1447 if (!cp)
1448 return;
1449
1450 hci_dev_lock(hdev);
1451
1452 conn = hci_conn_hash_lookup_ba(hdev, LE_LINK, &cp->peer_addr);
1453
1454 BT_DBG("%s bdaddr %s conn %p", hdev->name, batostr(&cp->peer_addr),
1455 conn);
1456
1457 if (status) {
1458 if (conn && conn->state == BT_CONNECT) {
1459 conn->state = BT_CLOSED;
1460 hci_proto_connect_cfm(conn, status);
1461 hci_conn_del(conn);
1462 }
1463 } else {
1464 if (!conn) {
1465 conn = hci_conn_add(hdev, LE_LINK, &cp->peer_addr);
Andre Guedes29b79882011-05-31 14:20:54 -03001466 if (conn) {
1467 conn->dst_type = cp->peer_addr_type;
Ville Tervofcd89c02011-02-10 22:38:47 -03001468 conn->out = 1;
Andre Guedes29b79882011-05-31 14:20:54 -03001469 } else {
Ville Tervofcd89c02011-02-10 22:38:47 -03001470 BT_ERR("No memory for new connection");
Andre Guedes29b79882011-05-31 14:20:54 -03001471 }
Ville Tervofcd89c02011-02-10 22:38:47 -03001472 }
1473 }
1474
1475 hci_dev_unlock(hdev);
1476}
1477
Vinicius Costa Gomesa7a595f2011-06-09 18:50:47 -03001478static void hci_cs_le_start_enc(struct hci_dev *hdev, u8 status)
1479{
1480 BT_DBG("%s status 0x%x", hdev->name, status);
1481}
1482
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001483static inline void hci_inquiry_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
1484{
1485 __u8 status = *((__u8 *) skb->data);
1486
1487 BT_DBG("%s status %d", hdev->name, status);
1488
Johan Hedberg23bb5762010-12-21 23:01:27 +02001489 hci_req_complete(hdev, HCI_OP_INQUIRY, status);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001490
1491 hci_conn_check_pending(hdev);
Andre Guedes89352e72011-11-04 14:16:53 -03001492
1493 if (!test_and_clear_bit(HCI_INQUIRY, &hdev->flags))
1494 return;
1495
Johan Hedberg56e5cb82011-11-08 20:40:16 +02001496 hci_dev_lock(hdev);
Johan Hedberg744cf192011-11-08 20:40:14 +02001497 mgmt_discovering(hdev, 0);
Johan Hedberg56e5cb82011-11-08 20:40:16 +02001498 hci_dev_unlock(hdev);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001499}
1500
Linus Torvalds1da177e2005-04-16 15:20:36 -07001501static inline void hci_inquiry_result_evt(struct hci_dev *hdev, struct sk_buff *skb)
1502{
Marcel Holtmann45bb4bf2005-08-09 20:27:49 -07001503 struct inquiry_data data;
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001504 struct inquiry_info *info = (void *) (skb->data + 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001505 int num_rsp = *((__u8 *) skb->data);
1506
1507 BT_DBG("%s num_rsp %d", hdev->name, num_rsp);
1508
Marcel Holtmann45bb4bf2005-08-09 20:27:49 -07001509 if (!num_rsp)
1510 return;
1511
Linus Torvalds1da177e2005-04-16 15:20:36 -07001512 hci_dev_lock(hdev);
Marcel Holtmann45bb4bf2005-08-09 20:27:49 -07001513
Johan Hedberge17acd42011-03-30 23:57:16 +03001514 for (; num_rsp; num_rsp--, info++) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001515 bacpy(&data.bdaddr, &info->bdaddr);
1516 data.pscan_rep_mode = info->pscan_rep_mode;
1517 data.pscan_period_mode = info->pscan_period_mode;
1518 data.pscan_mode = info->pscan_mode;
1519 memcpy(data.dev_class, info->dev_class, 3);
1520 data.clock_offset = info->clock_offset;
1521 data.rssi = 0x00;
Marcel Holtmann41a96212008-07-14 20:13:48 +02001522 data.ssp_mode = 0x00;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001523 hci_inquiry_cache_update(hdev, &data);
Johan Hedberg48264f02011-11-09 13:58:58 +02001524 mgmt_device_found(hdev, &info->bdaddr, ACL_LINK, 0x00,
Johan Hedberg4c659c32011-11-07 23:13:39 +02001525 info->dev_class, 0, NULL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001526 }
Marcel Holtmann45bb4bf2005-08-09 20:27:49 -07001527
Linus Torvalds1da177e2005-04-16 15:20:36 -07001528 hci_dev_unlock(hdev);
1529}
1530
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001531static inline void hci_conn_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001532{
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001533 struct hci_ev_conn_complete *ev = (void *) skb->data;
1534 struct hci_conn *conn;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001535
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001536 BT_DBG("%s", hdev->name);
Marcel Holtmann45bb4bf2005-08-09 20:27:49 -07001537
Linus Torvalds1da177e2005-04-16 15:20:36 -07001538 hci_dev_lock(hdev);
Marcel Holtmann45bb4bf2005-08-09 20:27:49 -07001539
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001540 conn = hci_conn_hash_lookup_ba(hdev, ev->link_type, &ev->bdaddr);
Marcel Holtmann94992372009-04-19 19:30:03 +02001541 if (!conn) {
1542 if (ev->link_type != SCO_LINK)
1543 goto unlock;
1544
1545 conn = hci_conn_hash_lookup_ba(hdev, ESCO_LINK, &ev->bdaddr);
1546 if (!conn)
1547 goto unlock;
1548
1549 conn->type = SCO_LINK;
1550 }
Marcel Holtmann45bb4bf2005-08-09 20:27:49 -07001551
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001552 if (!ev->status) {
1553 conn->handle = __le16_to_cpu(ev->handle);
Marcel Holtmann769be972008-07-14 20:13:49 +02001554
1555 if (conn->type == ACL_LINK) {
1556 conn->state = BT_CONFIG;
1557 hci_conn_hold(conn);
Marcel Holtmann052b30b2009-04-26 20:01:22 +02001558 conn->disc_timeout = HCI_DISCONN_TIMEOUT;
Johan Hedberg48264f02011-11-09 13:58:58 +02001559 mgmt_connected(hdev, &ev->bdaddr, conn->type,
1560 conn->dst_type);
Marcel Holtmann769be972008-07-14 20:13:49 +02001561 } else
1562 conn->state = BT_CONNECTED;
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001563
Marcel Holtmann9eba32b2009-08-22 14:19:26 -07001564 hci_conn_hold_device(conn);
Marcel Holtmann7d0db0a2008-07-14 20:13:51 +02001565 hci_conn_add_sysfs(conn);
1566
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001567 if (test_bit(HCI_AUTH, &hdev->flags))
1568 conn->link_mode |= HCI_LM_AUTH;
1569
1570 if (test_bit(HCI_ENCRYPT, &hdev->flags))
1571 conn->link_mode |= HCI_LM_ENCRYPT;
1572
1573 /* Get remote features */
1574 if (conn->type == ACL_LINK) {
1575 struct hci_cp_read_remote_features cp;
1576 cp.handle = ev->handle;
Marcel Holtmann769be972008-07-14 20:13:49 +02001577 hci_send_cmd(hdev, HCI_OP_READ_REMOTE_FEATURES,
1578 sizeof(cp), &cp);
Marcel Holtmann45bb4bf2005-08-09 20:27:49 -07001579 }
Marcel Holtmann45bb4bf2005-08-09 20:27:49 -07001580
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001581 /* Set packet type for incoming connection */
Andrei Emeltchenkod095c1e2011-12-01 14:33:27 +02001582 if (!conn->out && hdev->hci_ver < BLUETOOTH_VER_2_0) {
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001583 struct hci_cp_change_conn_ptype cp;
1584 cp.handle = ev->handle;
Marcel Holtmanna8746412008-07-14 20:13:46 +02001585 cp.pkt_type = cpu_to_le16(conn->pkt_type);
1586 hci_send_cmd(hdev, HCI_OP_CHANGE_CONN_PTYPE,
1587 sizeof(cp), &cp);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001588 }
Johan Hedberg17d5c042011-01-22 06:09:08 +02001589 } else {
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001590 conn->state = BT_CLOSED;
Johan Hedberg17d5c042011-01-22 06:09:08 +02001591 if (conn->type == ACL_LINK)
Johan Hedberg744cf192011-11-08 20:40:14 +02001592 mgmt_connect_failed(hdev, &ev->bdaddr, conn->type,
Johan Hedberg48264f02011-11-09 13:58:58 +02001593 conn->dst_type, ev->status);
Johan Hedberg17d5c042011-01-22 06:09:08 +02001594 }
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001595
Marcel Holtmanne73439d2010-07-26 10:06:00 -04001596 if (conn->type == ACL_LINK)
1597 hci_sco_setup(conn, ev->status);
Marcel Holtmann45bb4bf2005-08-09 20:27:49 -07001598
Marcel Holtmann769be972008-07-14 20:13:49 +02001599 if (ev->status) {
1600 hci_proto_connect_cfm(conn, ev->status);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001601 hci_conn_del(conn);
Marcel Holtmannc89b6e62009-01-15 21:57:03 +01001602 } else if (ev->link_type != ACL_LINK)
1603 hci_proto_connect_cfm(conn, ev->status);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001604
1605unlock:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001606 hci_dev_unlock(hdev);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001607
1608 hci_conn_check_pending(hdev);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001609}
1610
Linus Torvalds1da177e2005-04-16 15:20:36 -07001611static inline void hci_conn_request_evt(struct hci_dev *hdev, struct sk_buff *skb)
1612{
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001613 struct hci_ev_conn_request *ev = (void *) skb->data;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001614 int mask = hdev->link_mode;
1615
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001616 BT_DBG("%s bdaddr %s type 0x%x", hdev->name,
1617 batostr(&ev->bdaddr), ev->link_type);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001618
1619 mask |= hci_proto_connect_ind(hdev, &ev->bdaddr, ev->link_type);
1620
Szymon Janc138d22e2011-02-17 16:44:23 +01001621 if ((mask & HCI_LM_ACCEPT) &&
1622 !hci_blacklist_lookup(hdev, &ev->bdaddr)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001623 /* Connection accepted */
Marcel Holtmannc7bdd502008-07-14 20:13:47 +02001624 struct inquiry_entry *ie;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001625 struct hci_conn *conn;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001626
1627 hci_dev_lock(hdev);
Marcel Holtmannb6a0dc82007-10-20 14:55:10 +02001628
Andrei Emeltchenkocc11b9c2010-11-22 13:21:37 +02001629 ie = hci_inquiry_cache_lookup(hdev, &ev->bdaddr);
1630 if (ie)
Marcel Holtmannc7bdd502008-07-14 20:13:47 +02001631 memcpy(ie->data.dev_class, ev->dev_class, 3);
1632
Linus Torvalds1da177e2005-04-16 15:20:36 -07001633 conn = hci_conn_hash_lookup_ba(hdev, ev->link_type, &ev->bdaddr);
1634 if (!conn) {
Andrei Emeltchenkocc11b9c2010-11-22 13:21:37 +02001635 conn = hci_conn_add(hdev, ev->link_type, &ev->bdaddr);
1636 if (!conn) {
Gustavo F. Padovan893ef972010-07-18 15:13:37 -03001637 BT_ERR("No memory for new connection");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001638 hci_dev_unlock(hdev);
1639 return;
1640 }
1641 }
Marcel Holtmannb6a0dc82007-10-20 14:55:10 +02001642
Linus Torvalds1da177e2005-04-16 15:20:36 -07001643 memcpy(conn->dev_class, ev->dev_class, 3);
1644 conn->state = BT_CONNECT;
Marcel Holtmannb6a0dc82007-10-20 14:55:10 +02001645
Linus Torvalds1da177e2005-04-16 15:20:36 -07001646 hci_dev_unlock(hdev);
1647
Marcel Holtmannb6a0dc82007-10-20 14:55:10 +02001648 if (ev->link_type == ACL_LINK || !lmp_esco_capable(hdev)) {
1649 struct hci_cp_accept_conn_req cp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001650
Marcel Holtmannb6a0dc82007-10-20 14:55:10 +02001651 bacpy(&cp.bdaddr, &ev->bdaddr);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001652
Marcel Holtmannb6a0dc82007-10-20 14:55:10 +02001653 if (lmp_rswitch_capable(hdev) && (mask & HCI_LM_MASTER))
1654 cp.role = 0x00; /* Become master */
1655 else
1656 cp.role = 0x01; /* Remain slave */
1657
1658 hci_send_cmd(hdev, HCI_OP_ACCEPT_CONN_REQ,
1659 sizeof(cp), &cp);
1660 } else {
1661 struct hci_cp_accept_sync_conn_req cp;
1662
1663 bacpy(&cp.bdaddr, &ev->bdaddr);
Marcel Holtmanna8746412008-07-14 20:13:46 +02001664 cp.pkt_type = cpu_to_le16(conn->pkt_type);
Marcel Holtmannb6a0dc82007-10-20 14:55:10 +02001665
1666 cp.tx_bandwidth = cpu_to_le32(0x00001f40);
1667 cp.rx_bandwidth = cpu_to_le32(0x00001f40);
1668 cp.max_latency = cpu_to_le16(0xffff);
1669 cp.content_format = cpu_to_le16(hdev->voice_setting);
1670 cp.retrans_effort = 0xff;
1671
1672 hci_send_cmd(hdev, HCI_OP_ACCEPT_SYNC_CONN_REQ,
1673 sizeof(cp), &cp);
1674 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001675 } else {
1676 /* Connection rejected */
1677 struct hci_cp_reject_conn_req cp;
1678
1679 bacpy(&cp.bdaddr, &ev->bdaddr);
Andrei Emeltchenko9f5a0d72011-11-07 14:20:25 +02001680 cp.reason = HCI_ERROR_REJ_BAD_ADDR;
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001681 hci_send_cmd(hdev, HCI_OP_REJECT_CONN_REQ, sizeof(cp), &cp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001682 }
1683}
1684
Linus Torvalds1da177e2005-04-16 15:20:36 -07001685static inline void hci_disconn_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
1686{
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001687 struct hci_ev_disconn_complete *ev = (void *) skb->data;
Marcel Holtmann04837f62006-07-03 10:02:33 +02001688 struct hci_conn *conn;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001689
1690 BT_DBG("%s status %d", hdev->name, ev->status);
1691
Linus Torvalds1da177e2005-04-16 15:20:36 -07001692 hci_dev_lock(hdev);
1693
Marcel Holtmann04837f62006-07-03 10:02:33 +02001694 conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
Johan Hedbergf7520542011-01-20 12:34:39 +02001695 if (!conn)
1696 goto unlock;
Marcel Holtmann7d0db0a2008-07-14 20:13:51 +02001697
Johan Hedberg37d9ef72011-11-10 15:54:39 +02001698 if (ev->status == 0)
1699 conn->state = BT_CLOSED;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001700
Johan Hedberg37d9ef72011-11-10 15:54:39 +02001701 if (conn->type == ACL_LINK || conn->type == LE_LINK) {
1702 if (ev->status != 0)
1703 mgmt_disconnect_failed(hdev, &conn->dst, ev->status);
1704 else
1705 mgmt_disconnected(hdev, &conn->dst, conn->type,
Johan Hedberg48264f02011-11-09 13:58:58 +02001706 conn->dst_type);
Johan Hedberg37d9ef72011-11-10 15:54:39 +02001707 }
Johan Hedbergf7520542011-01-20 12:34:39 +02001708
Johan Hedberg37d9ef72011-11-10 15:54:39 +02001709 if (ev->status == 0) {
1710 hci_proto_disconn_cfm(conn, ev->reason);
1711 hci_conn_del(conn);
1712 }
Johan Hedbergf7520542011-01-20 12:34:39 +02001713
1714unlock:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001715 hci_dev_unlock(hdev);
1716}
1717
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001718static inline void hci_auth_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
1719{
1720 struct hci_ev_auth_complete *ev = (void *) skb->data;
1721 struct hci_conn *conn;
1722
1723 BT_DBG("%s status %d", hdev->name, ev->status);
1724
1725 hci_dev_lock(hdev);
1726
1727 conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
Waldemar Rymarkiewiczd7556e22011-05-31 15:49:26 +02001728 if (!conn)
1729 goto unlock;
1730
1731 if (!ev->status) {
1732 if (!(conn->ssp_mode > 0 && hdev->ssp_mode > 0) &&
1733 test_bit(HCI_CONN_REAUTH_PEND, &conn->pend)) {
1734 BT_INFO("re-auth of legacy device is not possible.");
Johan Hedberg2a611692011-02-19 12:06:00 -03001735 } else {
Waldemar Rymarkiewiczd7556e22011-05-31 15:49:26 +02001736 conn->link_mode |= HCI_LM_AUTH;
1737 conn->sec_level = conn->pending_sec_level;
Johan Hedberg2a611692011-02-19 12:06:00 -03001738 }
Waldemar Rymarkiewiczd7556e22011-05-31 15:49:26 +02001739 } else {
Johan Hedberg744cf192011-11-08 20:40:14 +02001740 mgmt_auth_failed(hdev, &conn->dst, ev->status);
Waldemar Rymarkiewiczd7556e22011-05-31 15:49:26 +02001741 }
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001742
Waldemar Rymarkiewiczd7556e22011-05-31 15:49:26 +02001743 clear_bit(HCI_CONN_AUTH_PEND, &conn->pend);
1744 clear_bit(HCI_CONN_REAUTH_PEND, &conn->pend);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001745
Waldemar Rymarkiewiczd7556e22011-05-31 15:49:26 +02001746 if (conn->state == BT_CONFIG) {
1747 if (!ev->status && hdev->ssp_mode > 0 && conn->ssp_mode > 0) {
1748 struct hci_cp_set_conn_encrypt cp;
1749 cp.handle = ev->handle;
1750 cp.encrypt = 0x01;
1751 hci_send_cmd(hdev, HCI_OP_SET_CONN_ENCRYPT, sizeof(cp),
1752 &cp);
Marcel Holtmann052b30b2009-04-26 20:01:22 +02001753 } else {
Waldemar Rymarkiewiczd7556e22011-05-31 15:49:26 +02001754 conn->state = BT_CONNECTED;
1755 hci_proto_connect_cfm(conn, ev->status);
Marcel Holtmann052b30b2009-04-26 20:01:22 +02001756 hci_conn_put(conn);
1757 }
Waldemar Rymarkiewiczd7556e22011-05-31 15:49:26 +02001758 } else {
1759 hci_auth_cfm(conn, ev->status);
Marcel Holtmann052b30b2009-04-26 20:01:22 +02001760
Waldemar Rymarkiewiczd7556e22011-05-31 15:49:26 +02001761 hci_conn_hold(conn);
1762 conn->disc_timeout = HCI_DISCONN_TIMEOUT;
1763 hci_conn_put(conn);
1764 }
1765
1766 if (test_bit(HCI_CONN_ENCRYPT_PEND, &conn->pend)) {
1767 if (!ev->status) {
1768 struct hci_cp_set_conn_encrypt cp;
1769 cp.handle = ev->handle;
1770 cp.encrypt = 0x01;
1771 hci_send_cmd(hdev, HCI_OP_SET_CONN_ENCRYPT, sizeof(cp),
1772 &cp);
1773 } else {
1774 clear_bit(HCI_CONN_ENCRYPT_PEND, &conn->pend);
1775 hci_encrypt_cfm(conn, ev->status, 0x00);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001776 }
1777 }
1778
Waldemar Rymarkiewiczd7556e22011-05-31 15:49:26 +02001779unlock:
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001780 hci_dev_unlock(hdev);
1781}
1782
1783static inline void hci_remote_name_evt(struct hci_dev *hdev, struct sk_buff *skb)
1784{
Johan Hedberg127178d2010-11-18 22:22:29 +02001785 struct hci_ev_remote_name *ev = (void *) skb->data;
1786 struct hci_conn *conn;
1787
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001788 BT_DBG("%s", hdev->name);
1789
1790 hci_conn_check_pending(hdev);
Johan Hedberg127178d2010-11-18 22:22:29 +02001791
1792 hci_dev_lock(hdev);
1793
Johan Hedberga88a9652011-03-30 13:18:12 +03001794 if (ev->status == 0 && test_bit(HCI_MGMT, &hdev->flags))
Johan Hedberg744cf192011-11-08 20:40:14 +02001795 mgmt_remote_name(hdev, &ev->bdaddr, ev->name);
Johan Hedberga88a9652011-03-30 13:18:12 +03001796
Johan Hedberg127178d2010-11-18 22:22:29 +02001797 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
Johan Hedberg79c6c702011-04-28 11:28:55 -07001798 if (!conn)
1799 goto unlock;
1800
1801 if (!hci_outgoing_auth_needed(hdev, conn))
1802 goto unlock;
1803
1804 if (!test_and_set_bit(HCI_CONN_AUTH_PEND, &conn->pend)) {
Johan Hedberg127178d2010-11-18 22:22:29 +02001805 struct hci_cp_auth_requested cp;
1806 cp.handle = __cpu_to_le16(conn->handle);
1807 hci_send_cmd(hdev, HCI_OP_AUTH_REQUESTED, sizeof(cp), &cp);
1808 }
1809
Johan Hedberg79c6c702011-04-28 11:28:55 -07001810unlock:
Johan Hedberg127178d2010-11-18 22:22:29 +02001811 hci_dev_unlock(hdev);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001812}
1813
1814static inline void hci_encrypt_change_evt(struct hci_dev *hdev, struct sk_buff *skb)
1815{
1816 struct hci_ev_encrypt_change *ev = (void *) skb->data;
1817 struct hci_conn *conn;
1818
1819 BT_DBG("%s status %d", hdev->name, ev->status);
1820
1821 hci_dev_lock(hdev);
1822
1823 conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
1824 if (conn) {
1825 if (!ev->status) {
Marcel Holtmannae293192008-07-14 20:13:45 +02001826 if (ev->encrypt) {
1827 /* Encryption implies authentication */
1828 conn->link_mode |= HCI_LM_AUTH;
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001829 conn->link_mode |= HCI_LM_ENCRYPT;
Vinicius Costa Gomesda85e5e2011-06-09 18:50:53 -03001830 conn->sec_level = conn->pending_sec_level;
Marcel Holtmannae293192008-07-14 20:13:45 +02001831 } else
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001832 conn->link_mode &= ~HCI_LM_ENCRYPT;
1833 }
1834
1835 clear_bit(HCI_CONN_ENCRYPT_PEND, &conn->pend);
1836
Marcel Holtmannf8558552008-07-14 20:13:49 +02001837 if (conn->state == BT_CONFIG) {
1838 if (!ev->status)
1839 conn->state = BT_CONNECTED;
1840
1841 hci_proto_connect_cfm(conn, ev->status);
1842 hci_conn_put(conn);
1843 } else
1844 hci_encrypt_cfm(conn, ev->status, ev->encrypt);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001845 }
1846
1847 hci_dev_unlock(hdev);
1848}
1849
1850static inline void hci_change_link_key_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
1851{
1852 struct hci_ev_change_link_key_complete *ev = (void *) skb->data;
1853 struct hci_conn *conn;
1854
1855 BT_DBG("%s status %d", hdev->name, ev->status);
1856
1857 hci_dev_lock(hdev);
1858
1859 conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
1860 if (conn) {
1861 if (!ev->status)
1862 conn->link_mode |= HCI_LM_SECURE;
1863
1864 clear_bit(HCI_CONN_AUTH_PEND, &conn->pend);
1865
1866 hci_key_change_cfm(conn, ev->status);
1867 }
1868
1869 hci_dev_unlock(hdev);
1870}
1871
1872static inline void hci_remote_features_evt(struct hci_dev *hdev, struct sk_buff *skb)
1873{
1874 struct hci_ev_remote_features *ev = (void *) skb->data;
1875 struct hci_conn *conn;
1876
1877 BT_DBG("%s status %d", hdev->name, ev->status);
1878
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001879 hci_dev_lock(hdev);
1880
1881 conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
Johan Hedbergccd556f2010-11-10 17:11:51 +02001882 if (!conn)
1883 goto unlock;
Marcel Holtmann769be972008-07-14 20:13:49 +02001884
Johan Hedbergccd556f2010-11-10 17:11:51 +02001885 if (!ev->status)
1886 memcpy(conn->features, ev->features, 8);
1887
1888 if (conn->state != BT_CONFIG)
1889 goto unlock;
1890
1891 if (!ev->status && lmp_ssp_capable(hdev) && lmp_ssp_capable(conn)) {
1892 struct hci_cp_read_remote_ext_features cp;
1893 cp.handle = ev->handle;
1894 cp.page = 0x01;
1895 hci_send_cmd(hdev, HCI_OP_READ_REMOTE_EXT_FEATURES,
Marcel Holtmann769be972008-07-14 20:13:49 +02001896 sizeof(cp), &cp);
Johan Hedberg392599b2010-11-18 22:22:28 +02001897 goto unlock;
1898 }
1899
Johan Hedberg127178d2010-11-18 22:22:29 +02001900 if (!ev->status) {
1901 struct hci_cp_remote_name_req cp;
1902 memset(&cp, 0, sizeof(cp));
1903 bacpy(&cp.bdaddr, &conn->dst);
1904 cp.pscan_rep_mode = 0x02;
1905 hci_send_cmd(hdev, HCI_OP_REMOTE_NAME_REQ, sizeof(cp), &cp);
1906 }
Johan Hedberg392599b2010-11-18 22:22:28 +02001907
Johan Hedberg127178d2010-11-18 22:22:29 +02001908 if (!hci_outgoing_auth_needed(hdev, conn)) {
Johan Hedbergccd556f2010-11-10 17:11:51 +02001909 conn->state = BT_CONNECTED;
1910 hci_proto_connect_cfm(conn, ev->status);
1911 hci_conn_put(conn);
Marcel Holtmann769be972008-07-14 20:13:49 +02001912 }
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001913
Johan Hedbergccd556f2010-11-10 17:11:51 +02001914unlock:
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001915 hci_dev_unlock(hdev);
1916}
1917
1918static inline void hci_remote_version_evt(struct hci_dev *hdev, struct sk_buff *skb)
1919{
1920 BT_DBG("%s", hdev->name);
1921}
1922
1923static inline void hci_qos_setup_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
1924{
1925 BT_DBG("%s", hdev->name);
1926}
1927
1928static inline void hci_cmd_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
1929{
1930 struct hci_ev_cmd_complete *ev = (void *) skb->data;
1931 __u16 opcode;
1932
1933 skb_pull(skb, sizeof(*ev));
1934
1935 opcode = __le16_to_cpu(ev->opcode);
1936
1937 switch (opcode) {
1938 case HCI_OP_INQUIRY_CANCEL:
1939 hci_cc_inquiry_cancel(hdev, skb);
1940 break;
1941
1942 case HCI_OP_EXIT_PERIODIC_INQ:
1943 hci_cc_exit_periodic_inq(hdev, skb);
1944 break;
1945
1946 case HCI_OP_REMOTE_NAME_REQ_CANCEL:
1947 hci_cc_remote_name_req_cancel(hdev, skb);
1948 break;
1949
1950 case HCI_OP_ROLE_DISCOVERY:
1951 hci_cc_role_discovery(hdev, skb);
1952 break;
1953
Marcel Holtmanne4e8e372008-07-14 20:13:47 +02001954 case HCI_OP_READ_LINK_POLICY:
1955 hci_cc_read_link_policy(hdev, skb);
1956 break;
1957
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001958 case HCI_OP_WRITE_LINK_POLICY:
1959 hci_cc_write_link_policy(hdev, skb);
1960 break;
1961
Marcel Holtmanne4e8e372008-07-14 20:13:47 +02001962 case HCI_OP_READ_DEF_LINK_POLICY:
1963 hci_cc_read_def_link_policy(hdev, skb);
1964 break;
1965
1966 case HCI_OP_WRITE_DEF_LINK_POLICY:
1967 hci_cc_write_def_link_policy(hdev, skb);
1968 break;
1969
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001970 case HCI_OP_RESET:
1971 hci_cc_reset(hdev, skb);
1972 break;
1973
1974 case HCI_OP_WRITE_LOCAL_NAME:
1975 hci_cc_write_local_name(hdev, skb);
1976 break;
1977
1978 case HCI_OP_READ_LOCAL_NAME:
1979 hci_cc_read_local_name(hdev, skb);
1980 break;
1981
1982 case HCI_OP_WRITE_AUTH_ENABLE:
1983 hci_cc_write_auth_enable(hdev, skb);
1984 break;
1985
1986 case HCI_OP_WRITE_ENCRYPT_MODE:
1987 hci_cc_write_encrypt_mode(hdev, skb);
1988 break;
1989
1990 case HCI_OP_WRITE_SCAN_ENABLE:
1991 hci_cc_write_scan_enable(hdev, skb);
1992 break;
1993
1994 case HCI_OP_READ_CLASS_OF_DEV:
1995 hci_cc_read_class_of_dev(hdev, skb);
1996 break;
1997
1998 case HCI_OP_WRITE_CLASS_OF_DEV:
1999 hci_cc_write_class_of_dev(hdev, skb);
2000 break;
2001
2002 case HCI_OP_READ_VOICE_SETTING:
2003 hci_cc_read_voice_setting(hdev, skb);
2004 break;
2005
2006 case HCI_OP_WRITE_VOICE_SETTING:
2007 hci_cc_write_voice_setting(hdev, skb);
2008 break;
2009
2010 case HCI_OP_HOST_BUFFER_SIZE:
2011 hci_cc_host_buffer_size(hdev, skb);
2012 break;
2013
Marcel Holtmann333140b2008-07-14 20:13:48 +02002014 case HCI_OP_READ_SSP_MODE:
2015 hci_cc_read_ssp_mode(hdev, skb);
2016 break;
2017
2018 case HCI_OP_WRITE_SSP_MODE:
2019 hci_cc_write_ssp_mode(hdev, skb);
2020 break;
2021
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002022 case HCI_OP_READ_LOCAL_VERSION:
2023 hci_cc_read_local_version(hdev, skb);
2024 break;
2025
2026 case HCI_OP_READ_LOCAL_COMMANDS:
2027 hci_cc_read_local_commands(hdev, skb);
2028 break;
2029
2030 case HCI_OP_READ_LOCAL_FEATURES:
2031 hci_cc_read_local_features(hdev, skb);
2032 break;
2033
Andre Guedes971e3a42011-06-30 19:20:52 -03002034 case HCI_OP_READ_LOCAL_EXT_FEATURES:
2035 hci_cc_read_local_ext_features(hdev, skb);
2036 break;
2037
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002038 case HCI_OP_READ_BUFFER_SIZE:
2039 hci_cc_read_buffer_size(hdev, skb);
2040 break;
2041
2042 case HCI_OP_READ_BD_ADDR:
2043 hci_cc_read_bd_addr(hdev, skb);
2044 break;
2045
Andrei Emeltchenko350ee4c2011-12-07 15:56:51 +02002046 case HCI_OP_READ_DATA_BLOCK_SIZE:
2047 hci_cc_read_data_block_size(hdev, skb);
2048 break;
2049
Johan Hedberg23bb5762010-12-21 23:01:27 +02002050 case HCI_OP_WRITE_CA_TIMEOUT:
2051 hci_cc_write_ca_timeout(hdev, skb);
2052 break;
2053
Andrei Emeltchenko1e89cff2011-11-24 14:52:02 +02002054 case HCI_OP_READ_FLOW_CONTROL_MODE:
2055 hci_cc_read_flow_control_mode(hdev, skb);
2056 break;
2057
Andrei Emeltchenko928abaa2011-10-12 10:53:57 +03002058 case HCI_OP_READ_LOCAL_AMP_INFO:
2059 hci_cc_read_local_amp_info(hdev, skb);
2060 break;
2061
Johan Hedbergb0916ea2011-01-10 13:44:55 +02002062 case HCI_OP_DELETE_STORED_LINK_KEY:
2063 hci_cc_delete_stored_link_key(hdev, skb);
2064 break;
2065
Johan Hedbergd5859e22011-01-25 01:19:58 +02002066 case HCI_OP_SET_EVENT_MASK:
2067 hci_cc_set_event_mask(hdev, skb);
2068 break;
2069
2070 case HCI_OP_WRITE_INQUIRY_MODE:
2071 hci_cc_write_inquiry_mode(hdev, skb);
2072 break;
2073
2074 case HCI_OP_READ_INQ_RSP_TX_POWER:
2075 hci_cc_read_inq_rsp_tx_power(hdev, skb);
2076 break;
2077
2078 case HCI_OP_SET_EVENT_FLT:
2079 hci_cc_set_event_flt(hdev, skb);
2080 break;
2081
Johan Hedberg980e1a52011-01-22 06:10:07 +02002082 case HCI_OP_PIN_CODE_REPLY:
2083 hci_cc_pin_code_reply(hdev, skb);
2084 break;
2085
2086 case HCI_OP_PIN_CODE_NEG_REPLY:
2087 hci_cc_pin_code_neg_reply(hdev, skb);
2088 break;
2089
Szymon Jancc35938b2011-03-22 13:12:21 +01002090 case HCI_OP_READ_LOCAL_OOB_DATA:
2091 hci_cc_read_local_oob_data_reply(hdev, skb);
2092 break;
2093
Ville Tervo6ed58ec2011-02-10 22:38:48 -03002094 case HCI_OP_LE_READ_BUFFER_SIZE:
2095 hci_cc_le_read_buffer_size(hdev, skb);
2096 break;
2097
Johan Hedberga5c29682011-02-19 12:05:57 -03002098 case HCI_OP_USER_CONFIRM_REPLY:
2099 hci_cc_user_confirm_reply(hdev, skb);
2100 break;
2101
2102 case HCI_OP_USER_CONFIRM_NEG_REPLY:
2103 hci_cc_user_confirm_neg_reply(hdev, skb);
2104 break;
2105
Brian Gix1143d452011-11-23 08:28:34 -08002106 case HCI_OP_USER_PASSKEY_REPLY:
2107 hci_cc_user_passkey_reply(hdev, skb);
2108 break;
2109
2110 case HCI_OP_USER_PASSKEY_NEG_REPLY:
2111 hci_cc_user_passkey_neg_reply(hdev, skb);
Andre Guedes07f7fa52011-12-02 21:13:31 +09002112
2113 case HCI_OP_LE_SET_SCAN_PARAM:
2114 hci_cc_le_set_scan_param(hdev, skb);
Brian Gix1143d452011-11-23 08:28:34 -08002115 break;
2116
Andre Guedeseb9d91f2011-05-26 16:23:52 -03002117 case HCI_OP_LE_SET_SCAN_ENABLE:
2118 hci_cc_le_set_scan_enable(hdev, skb);
2119 break;
2120
Vinicius Costa Gomesa7a595f2011-06-09 18:50:47 -03002121 case HCI_OP_LE_LTK_REPLY:
2122 hci_cc_le_ltk_reply(hdev, skb);
2123 break;
2124
2125 case HCI_OP_LE_LTK_NEG_REPLY:
2126 hci_cc_le_ltk_neg_reply(hdev, skb);
2127 break;
2128
Andre Guedesf9b49302011-06-30 19:20:53 -03002129 case HCI_OP_WRITE_LE_HOST_SUPPORTED:
2130 hci_cc_write_le_host_supported(hdev, skb);
2131 break;
2132
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002133 default:
2134 BT_DBG("%s opcode 0x%x", hdev->name, opcode);
2135 break;
2136 }
2137
Ville Tervo6bd32322011-02-16 16:32:41 +02002138 if (ev->opcode != HCI_OP_NOP)
2139 del_timer(&hdev->cmd_timer);
2140
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002141 if (ev->ncmd) {
2142 atomic_set(&hdev->cmd_cnt, 1);
2143 if (!skb_queue_empty(&hdev->cmd_q))
Gustavo F. Padovanc347b762011-12-14 23:53:47 -02002144 queue_work(hdev->workqueue, &hdev->cmd_work);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002145 }
2146}
2147
2148static inline void hci_cmd_status_evt(struct hci_dev *hdev, struct sk_buff *skb)
2149{
2150 struct hci_ev_cmd_status *ev = (void *) skb->data;
2151 __u16 opcode;
2152
2153 skb_pull(skb, sizeof(*ev));
2154
2155 opcode = __le16_to_cpu(ev->opcode);
2156
2157 switch (opcode) {
2158 case HCI_OP_INQUIRY:
2159 hci_cs_inquiry(hdev, ev->status);
2160 break;
2161
2162 case HCI_OP_CREATE_CONN:
2163 hci_cs_create_conn(hdev, ev->status);
2164 break;
2165
2166 case HCI_OP_ADD_SCO:
2167 hci_cs_add_sco(hdev, ev->status);
2168 break;
2169
Marcel Holtmannf8558552008-07-14 20:13:49 +02002170 case HCI_OP_AUTH_REQUESTED:
2171 hci_cs_auth_requested(hdev, ev->status);
2172 break;
2173
2174 case HCI_OP_SET_CONN_ENCRYPT:
2175 hci_cs_set_conn_encrypt(hdev, ev->status);
2176 break;
2177
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002178 case HCI_OP_REMOTE_NAME_REQ:
2179 hci_cs_remote_name_req(hdev, ev->status);
2180 break;
2181
Marcel Holtmann769be972008-07-14 20:13:49 +02002182 case HCI_OP_READ_REMOTE_FEATURES:
2183 hci_cs_read_remote_features(hdev, ev->status);
2184 break;
2185
2186 case HCI_OP_READ_REMOTE_EXT_FEATURES:
2187 hci_cs_read_remote_ext_features(hdev, ev->status);
2188 break;
2189
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002190 case HCI_OP_SETUP_SYNC_CONN:
2191 hci_cs_setup_sync_conn(hdev, ev->status);
2192 break;
2193
2194 case HCI_OP_SNIFF_MODE:
2195 hci_cs_sniff_mode(hdev, ev->status);
2196 break;
2197
2198 case HCI_OP_EXIT_SNIFF_MODE:
2199 hci_cs_exit_sniff_mode(hdev, ev->status);
2200 break;
2201
Johan Hedberg8962ee72011-01-20 12:40:27 +02002202 case HCI_OP_DISCONNECT:
2203 if (ev->status != 0)
Johan Hedberg37d9ef72011-11-10 15:54:39 +02002204 mgmt_disconnect_failed(hdev, NULL, ev->status);
Johan Hedberg8962ee72011-01-20 12:40:27 +02002205 break;
2206
Ville Tervofcd89c02011-02-10 22:38:47 -03002207 case HCI_OP_LE_CREATE_CONN:
2208 hci_cs_le_create_conn(hdev, ev->status);
2209 break;
2210
Vinicius Costa Gomesa7a595f2011-06-09 18:50:47 -03002211 case HCI_OP_LE_START_ENC:
2212 hci_cs_le_start_enc(hdev, ev->status);
2213 break;
2214
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002215 default:
2216 BT_DBG("%s opcode 0x%x", hdev->name, opcode);
2217 break;
2218 }
2219
Ville Tervo6bd32322011-02-16 16:32:41 +02002220 if (ev->opcode != HCI_OP_NOP)
2221 del_timer(&hdev->cmd_timer);
2222
Gustavo F. Padovan10572132011-03-16 15:36:29 -03002223 if (ev->ncmd && !test_bit(HCI_RESET, &hdev->flags)) {
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002224 atomic_set(&hdev->cmd_cnt, 1);
2225 if (!skb_queue_empty(&hdev->cmd_q))
Gustavo F. Padovanc347b762011-12-14 23:53:47 -02002226 queue_work(hdev->workqueue, &hdev->cmd_work);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002227 }
2228}
2229
2230static inline void hci_role_change_evt(struct hci_dev *hdev, struct sk_buff *skb)
2231{
2232 struct hci_ev_role_change *ev = (void *) skb->data;
2233 struct hci_conn *conn;
2234
2235 BT_DBG("%s status %d", hdev->name, ev->status);
2236
2237 hci_dev_lock(hdev);
2238
2239 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
2240 if (conn) {
2241 if (!ev->status) {
2242 if (ev->role)
2243 conn->link_mode &= ~HCI_LM_MASTER;
2244 else
2245 conn->link_mode |= HCI_LM_MASTER;
2246 }
2247
2248 clear_bit(HCI_CONN_RSWITCH_PEND, &conn->pend);
2249
2250 hci_role_switch_cfm(conn, ev->status, ev->role);
2251 }
2252
2253 hci_dev_unlock(hdev);
2254}
2255
Linus Torvalds1da177e2005-04-16 15:20:36 -07002256static inline void hci_num_comp_pkts_evt(struct hci_dev *hdev, struct sk_buff *skb)
2257{
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002258 struct hci_ev_num_comp_pkts *ev = (void *) skb->data;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002259 int i;
2260
2261 skb_pull(skb, sizeof(*ev));
2262
2263 BT_DBG("%s num_hndl %d", hdev->name, ev->num_hndl);
2264
Andrei Emeltchenko32ac5b92011-12-19 16:31:29 +02002265 if (hdev->flow_ctl_mode != HCI_FLOW_CTL_MODE_PACKET_BASED) {
2266 BT_ERR("Wrong event for mode %d", hdev->flow_ctl_mode);
2267 return;
2268 }
2269
Linus Torvalds1da177e2005-04-16 15:20:36 -07002270 if (skb->len < ev->num_hndl * 4) {
2271 BT_DBG("%s bad parameters", hdev->name);
2272 return;
2273 }
2274
Andrei Emeltchenko613a1c02011-12-19 16:31:30 +02002275 for (i = 0; i < ev->num_hndl; i++) {
2276 struct hci_comp_pkts_info *info = &ev->handles[i];
Linus Torvalds1da177e2005-04-16 15:20:36 -07002277 struct hci_conn *conn;
2278 __u16 handle, count;
2279
Andrei Emeltchenko613a1c02011-12-19 16:31:30 +02002280 handle = __le16_to_cpu(info->handle);
2281 count = __le16_to_cpu(info->count);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002282
2283 conn = hci_conn_hash_lookup_handle(hdev, handle);
Andrei Emeltchenkof4280912011-12-07 15:56:52 +02002284 if (!conn)
2285 continue;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002286
Andrei Emeltchenkof4280912011-12-07 15:56:52 +02002287 conn->sent -= count;
2288
2289 switch (conn->type) {
2290 case ACL_LINK:
2291 hdev->acl_cnt += count;
2292 if (hdev->acl_cnt > hdev->acl_pkts)
2293 hdev->acl_cnt = hdev->acl_pkts;
2294 break;
2295
2296 case LE_LINK:
2297 if (hdev->le_pkts) {
2298 hdev->le_cnt += count;
2299 if (hdev->le_cnt > hdev->le_pkts)
2300 hdev->le_cnt = hdev->le_pkts;
2301 } else {
Andrei Emeltchenko70f230202010-12-01 16:58:25 +02002302 hdev->acl_cnt += count;
2303 if (hdev->acl_cnt > hdev->acl_pkts)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002304 hdev->acl_cnt = hdev->acl_pkts;
2305 }
Andrei Emeltchenkof4280912011-12-07 15:56:52 +02002306 break;
2307
2308 case SCO_LINK:
2309 hdev->sco_cnt += count;
2310 if (hdev->sco_cnt > hdev->sco_pkts)
2311 hdev->sco_cnt = hdev->sco_pkts;
2312 break;
2313
2314 default:
2315 BT_ERR("Unknown type %d conn %p", conn->type, conn);
2316 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002317 }
2318 }
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002319
Gustavo F. Padovan3eff45e2011-12-15 00:50:02 -02002320 queue_work(hdev->workqueue, &hdev->tx_work);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002321}
2322
Marcel Holtmann04837f62006-07-03 10:02:33 +02002323static inline void hci_mode_change_evt(struct hci_dev *hdev, struct sk_buff *skb)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002324{
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002325 struct hci_ev_mode_change *ev = (void *) skb->data;
Marcel Holtmann04837f62006-07-03 10:02:33 +02002326 struct hci_conn *conn;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002327
2328 BT_DBG("%s status %d", hdev->name, ev->status);
2329
2330 hci_dev_lock(hdev);
2331
Marcel Holtmann04837f62006-07-03 10:02:33 +02002332 conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
2333 if (conn) {
2334 conn->mode = ev->mode;
2335 conn->interval = __le16_to_cpu(ev->interval);
2336
2337 if (!test_and_clear_bit(HCI_CONN_MODE_CHANGE_PEND, &conn->pend)) {
2338 if (conn->mode == HCI_CM_ACTIVE)
2339 conn->power_save = 1;
2340 else
2341 conn->power_save = 0;
2342 }
Marcel Holtmanne73439d2010-07-26 10:06:00 -04002343
2344 if (test_and_clear_bit(HCI_CONN_SCO_SETUP_PEND, &conn->pend))
2345 hci_sco_setup(conn, ev->status);
Marcel Holtmann04837f62006-07-03 10:02:33 +02002346 }
2347
2348 hci_dev_unlock(hdev);
2349}
2350
Linus Torvalds1da177e2005-04-16 15:20:36 -07002351static inline void hci_pin_code_request_evt(struct hci_dev *hdev, struct sk_buff *skb)
2352{
Marcel Holtmann052b30b2009-04-26 20:01:22 +02002353 struct hci_ev_pin_code_req *ev = (void *) skb->data;
2354 struct hci_conn *conn;
2355
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002356 BT_DBG("%s", hdev->name);
Marcel Holtmann052b30b2009-04-26 20:01:22 +02002357
2358 hci_dev_lock(hdev);
2359
2360 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
Waldemar Rymarkiewiczb6f98042011-09-23 10:01:30 +02002361 if (!conn)
2362 goto unlock;
2363
2364 if (conn->state == BT_CONNECTED) {
Marcel Holtmann052b30b2009-04-26 20:01:22 +02002365 hci_conn_hold(conn);
2366 conn->disc_timeout = HCI_PAIRING_TIMEOUT;
2367 hci_conn_put(conn);
2368 }
2369
Johan Hedberg03b555e2011-01-04 15:40:05 +02002370 if (!test_bit(HCI_PAIRABLE, &hdev->flags))
2371 hci_send_cmd(hdev, HCI_OP_PIN_CODE_NEG_REPLY,
2372 sizeof(ev->bdaddr), &ev->bdaddr);
Johan Hedberg582fbe92011-04-28 11:28:58 -07002373 else if (test_bit(HCI_MGMT, &hdev->flags)) {
Waldemar Rymarkiewicza770bb52011-04-28 12:07:59 +02002374 u8 secure;
2375
2376 if (conn->pending_sec_level == BT_SECURITY_HIGH)
2377 secure = 1;
2378 else
2379 secure = 0;
2380
Johan Hedberg744cf192011-11-08 20:40:14 +02002381 mgmt_pin_code_request(hdev, &ev->bdaddr, secure);
Waldemar Rymarkiewicza770bb52011-04-28 12:07:59 +02002382 }
Johan Hedberg980e1a52011-01-22 06:10:07 +02002383
Waldemar Rymarkiewiczb6f98042011-09-23 10:01:30 +02002384unlock:
Marcel Holtmann052b30b2009-04-26 20:01:22 +02002385 hci_dev_unlock(hdev);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002386}
2387
Linus Torvalds1da177e2005-04-16 15:20:36 -07002388static inline void hci_link_key_request_evt(struct hci_dev *hdev, struct sk_buff *skb)
2389{
Johan Hedberg55ed8ca2011-01-17 14:41:05 +02002390 struct hci_ev_link_key_req *ev = (void *) skb->data;
2391 struct hci_cp_link_key_reply cp;
2392 struct hci_conn *conn;
2393 struct link_key *key;
2394
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002395 BT_DBG("%s", hdev->name);
Johan Hedberg55ed8ca2011-01-17 14:41:05 +02002396
2397 if (!test_bit(HCI_LINK_KEYS, &hdev->flags))
2398 return;
2399
2400 hci_dev_lock(hdev);
2401
2402 key = hci_find_link_key(hdev, &ev->bdaddr);
2403 if (!key) {
2404 BT_DBG("%s link key not found for %s", hdev->name,
2405 batostr(&ev->bdaddr));
2406 goto not_found;
2407 }
2408
2409 BT_DBG("%s found key type %u for %s", hdev->name, key->type,
2410 batostr(&ev->bdaddr));
2411
Waldemar Rymarkiewiczb6020ba2011-04-28 12:07:53 +02002412 if (!test_bit(HCI_DEBUG_KEYS, &hdev->flags) &&
2413 key->type == HCI_LK_DEBUG_COMBINATION) {
Johan Hedberg55ed8ca2011-01-17 14:41:05 +02002414 BT_DBG("%s ignoring debug key", hdev->name);
2415 goto not_found;
2416 }
2417
2418 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
Waldemar Rymarkiewicz60b83f52011-04-28 12:07:56 +02002419 if (conn) {
2420 if (key->type == HCI_LK_UNAUTH_COMBINATION &&
2421 conn->auth_type != 0xff &&
2422 (conn->auth_type & 0x01)) {
2423 BT_DBG("%s ignoring unauthenticated key", hdev->name);
2424 goto not_found;
2425 }
Johan Hedberg55ed8ca2011-01-17 14:41:05 +02002426
Waldemar Rymarkiewicz60b83f52011-04-28 12:07:56 +02002427 if (key->type == HCI_LK_COMBINATION && key->pin_len < 16 &&
2428 conn->pending_sec_level == BT_SECURITY_HIGH) {
2429 BT_DBG("%s ignoring key unauthenticated for high \
2430 security", hdev->name);
2431 goto not_found;
2432 }
2433
2434 conn->key_type = key->type;
2435 conn->pin_length = key->pin_len;
Johan Hedberg55ed8ca2011-01-17 14:41:05 +02002436 }
2437
2438 bacpy(&cp.bdaddr, &ev->bdaddr);
2439 memcpy(cp.link_key, key->val, 16);
2440
2441 hci_send_cmd(hdev, HCI_OP_LINK_KEY_REPLY, sizeof(cp), &cp);
2442
2443 hci_dev_unlock(hdev);
2444
2445 return;
2446
2447not_found:
2448 hci_send_cmd(hdev, HCI_OP_LINK_KEY_NEG_REPLY, 6, &ev->bdaddr);
2449 hci_dev_unlock(hdev);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002450}
2451
Linus Torvalds1da177e2005-04-16 15:20:36 -07002452static inline void hci_link_key_notify_evt(struct hci_dev *hdev, struct sk_buff *skb)
2453{
Marcel Holtmann052b30b2009-04-26 20:01:22 +02002454 struct hci_ev_link_key_notify *ev = (void *) skb->data;
2455 struct hci_conn *conn;
Johan Hedberg55ed8ca2011-01-17 14:41:05 +02002456 u8 pin_len = 0;
Marcel Holtmann052b30b2009-04-26 20:01:22 +02002457
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002458 BT_DBG("%s", hdev->name);
Marcel Holtmann052b30b2009-04-26 20:01:22 +02002459
2460 hci_dev_lock(hdev);
2461
2462 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
2463 if (conn) {
2464 hci_conn_hold(conn);
2465 conn->disc_timeout = HCI_DISCONN_TIMEOUT;
Johan Hedberg980e1a52011-01-22 06:10:07 +02002466 pin_len = conn->pin_length;
Waldemar Rymarkiewicz13d39312011-04-28 12:07:55 +02002467
2468 if (ev->key_type != HCI_LK_CHANGED_COMBINATION)
2469 conn->key_type = ev->key_type;
2470
Marcel Holtmann052b30b2009-04-26 20:01:22 +02002471 hci_conn_put(conn);
2472 }
2473
Johan Hedberg55ed8ca2011-01-17 14:41:05 +02002474 if (test_bit(HCI_LINK_KEYS, &hdev->flags))
Johan Hedbergd25e28a2011-04-28 11:28:59 -07002475 hci_add_link_key(hdev, conn, 1, &ev->bdaddr, ev->link_key,
Johan Hedberg55ed8ca2011-01-17 14:41:05 +02002476 ev->key_type, pin_len);
2477
Marcel Holtmann052b30b2009-04-26 20:01:22 +02002478 hci_dev_unlock(hdev);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002479}
2480
Marcel Holtmann04837f62006-07-03 10:02:33 +02002481static inline void hci_clock_offset_evt(struct hci_dev *hdev, struct sk_buff *skb)
2482{
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002483 struct hci_ev_clock_offset *ev = (void *) skb->data;
Marcel Holtmann04837f62006-07-03 10:02:33 +02002484 struct hci_conn *conn;
2485
2486 BT_DBG("%s status %d", hdev->name, ev->status);
2487
2488 hci_dev_lock(hdev);
2489
2490 conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
Linus Torvalds1da177e2005-04-16 15:20:36 -07002491 if (conn && !ev->status) {
2492 struct inquiry_entry *ie;
2493
Andrei Emeltchenkocc11b9c2010-11-22 13:21:37 +02002494 ie = hci_inquiry_cache_lookup(hdev, &conn->dst);
2495 if (ie) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002496 ie->data.clock_offset = ev->clock_offset;
2497 ie->timestamp = jiffies;
2498 }
2499 }
2500
2501 hci_dev_unlock(hdev);
2502}
2503
Marcel Holtmanna8746412008-07-14 20:13:46 +02002504static inline void hci_pkt_type_change_evt(struct hci_dev *hdev, struct sk_buff *skb)
2505{
2506 struct hci_ev_pkt_type_change *ev = (void *) skb->data;
2507 struct hci_conn *conn;
2508
2509 BT_DBG("%s status %d", hdev->name, ev->status);
2510
2511 hci_dev_lock(hdev);
2512
2513 conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
2514 if (conn && !ev->status)
2515 conn->pkt_type = __le16_to_cpu(ev->pkt_type);
2516
2517 hci_dev_unlock(hdev);
2518}
2519
Marcel Holtmann85a1e932005-08-09 20:28:02 -07002520static inline void hci_pscan_rep_mode_evt(struct hci_dev *hdev, struct sk_buff *skb)
2521{
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002522 struct hci_ev_pscan_rep_mode *ev = (void *) skb->data;
Marcel Holtmann85a1e932005-08-09 20:28:02 -07002523 struct inquiry_entry *ie;
2524
2525 BT_DBG("%s", hdev->name);
2526
2527 hci_dev_lock(hdev);
2528
Andrei Emeltchenkocc11b9c2010-11-22 13:21:37 +02002529 ie = hci_inquiry_cache_lookup(hdev, &ev->bdaddr);
2530 if (ie) {
Marcel Holtmann85a1e932005-08-09 20:28:02 -07002531 ie->data.pscan_rep_mode = ev->pscan_rep_mode;
2532 ie->timestamp = jiffies;
2533 }
2534
2535 hci_dev_unlock(hdev);
2536}
2537
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002538static inline void hci_inquiry_result_with_rssi_evt(struct hci_dev *hdev, struct sk_buff *skb)
2539{
2540 struct inquiry_data data;
2541 int num_rsp = *((__u8 *) skb->data);
2542
2543 BT_DBG("%s num_rsp %d", hdev->name, num_rsp);
2544
2545 if (!num_rsp)
2546 return;
2547
2548 hci_dev_lock(hdev);
2549
2550 if ((skb->len - 1) / num_rsp != sizeof(struct inquiry_info_with_rssi)) {
Szymon Janc138d22e2011-02-17 16:44:23 +01002551 struct inquiry_info_with_rssi_and_pscan_mode *info;
2552 info = (void *) (skb->data + 1);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002553
Johan Hedberge17acd42011-03-30 23:57:16 +03002554 for (; num_rsp; num_rsp--, info++) {
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002555 bacpy(&data.bdaddr, &info->bdaddr);
2556 data.pscan_rep_mode = info->pscan_rep_mode;
2557 data.pscan_period_mode = info->pscan_period_mode;
2558 data.pscan_mode = info->pscan_mode;
2559 memcpy(data.dev_class, info->dev_class, 3);
2560 data.clock_offset = info->clock_offset;
2561 data.rssi = info->rssi;
Marcel Holtmann41a96212008-07-14 20:13:48 +02002562 data.ssp_mode = 0x00;
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002563 hci_inquiry_cache_update(hdev, &data);
Johan Hedberg48264f02011-11-09 13:58:58 +02002564 mgmt_device_found(hdev, &info->bdaddr, ACL_LINK, 0x00,
Johan Hedberge17acd42011-03-30 23:57:16 +03002565 info->dev_class, info->rssi,
2566 NULL);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002567 }
2568 } else {
2569 struct inquiry_info_with_rssi *info = (void *) (skb->data + 1);
2570
Johan Hedberge17acd42011-03-30 23:57:16 +03002571 for (; num_rsp; num_rsp--, info++) {
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002572 bacpy(&data.bdaddr, &info->bdaddr);
2573 data.pscan_rep_mode = info->pscan_rep_mode;
2574 data.pscan_period_mode = info->pscan_period_mode;
2575 data.pscan_mode = 0x00;
2576 memcpy(data.dev_class, info->dev_class, 3);
2577 data.clock_offset = info->clock_offset;
2578 data.rssi = info->rssi;
Marcel Holtmann41a96212008-07-14 20:13:48 +02002579 data.ssp_mode = 0x00;
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002580 hci_inquiry_cache_update(hdev, &data);
Johan Hedberg48264f02011-11-09 13:58:58 +02002581 mgmt_device_found(hdev, &info->bdaddr, ACL_LINK, 0x00,
Johan Hedberge17acd42011-03-30 23:57:16 +03002582 info->dev_class, info->rssi,
2583 NULL);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002584 }
2585 }
2586
2587 hci_dev_unlock(hdev);
2588}
2589
2590static inline void hci_remote_ext_features_evt(struct hci_dev *hdev, struct sk_buff *skb)
2591{
Marcel Holtmann41a96212008-07-14 20:13:48 +02002592 struct hci_ev_remote_ext_features *ev = (void *) skb->data;
2593 struct hci_conn *conn;
2594
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002595 BT_DBG("%s", hdev->name);
Marcel Holtmann41a96212008-07-14 20:13:48 +02002596
Marcel Holtmann41a96212008-07-14 20:13:48 +02002597 hci_dev_lock(hdev);
2598
2599 conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
Johan Hedbergccd556f2010-11-10 17:11:51 +02002600 if (!conn)
2601 goto unlock;
Marcel Holtmann41a96212008-07-14 20:13:48 +02002602
Johan Hedbergccd556f2010-11-10 17:11:51 +02002603 if (!ev->status && ev->page == 0x01) {
2604 struct inquiry_entry *ie;
Marcel Holtmann41a96212008-07-14 20:13:48 +02002605
Andrei Emeltchenkocc11b9c2010-11-22 13:21:37 +02002606 ie = hci_inquiry_cache_lookup(hdev, &conn->dst);
2607 if (ie)
Johan Hedbergccd556f2010-11-10 17:11:51 +02002608 ie->data.ssp_mode = (ev->features[0] & 0x01);
Marcel Holtmann769be972008-07-14 20:13:49 +02002609
Johan Hedbergccd556f2010-11-10 17:11:51 +02002610 conn->ssp_mode = (ev->features[0] & 0x01);
Marcel Holtmann41a96212008-07-14 20:13:48 +02002611 }
2612
Johan Hedbergccd556f2010-11-10 17:11:51 +02002613 if (conn->state != BT_CONFIG)
2614 goto unlock;
2615
Johan Hedberg127178d2010-11-18 22:22:29 +02002616 if (!ev->status) {
2617 struct hci_cp_remote_name_req cp;
2618 memset(&cp, 0, sizeof(cp));
2619 bacpy(&cp.bdaddr, &conn->dst);
2620 cp.pscan_rep_mode = 0x02;
2621 hci_send_cmd(hdev, HCI_OP_REMOTE_NAME_REQ, sizeof(cp), &cp);
2622 }
Johan Hedberg392599b2010-11-18 22:22:28 +02002623
Johan Hedberg127178d2010-11-18 22:22:29 +02002624 if (!hci_outgoing_auth_needed(hdev, conn)) {
Johan Hedbergccd556f2010-11-10 17:11:51 +02002625 conn->state = BT_CONNECTED;
2626 hci_proto_connect_cfm(conn, ev->status);
2627 hci_conn_put(conn);
2628 }
2629
2630unlock:
Marcel Holtmann41a96212008-07-14 20:13:48 +02002631 hci_dev_unlock(hdev);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002632}
2633
2634static inline void hci_sync_conn_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
2635{
Marcel Holtmannb6a0dc82007-10-20 14:55:10 +02002636 struct hci_ev_sync_conn_complete *ev = (void *) skb->data;
2637 struct hci_conn *conn;
2638
2639 BT_DBG("%s status %d", hdev->name, ev->status);
2640
2641 hci_dev_lock(hdev);
2642
2643 conn = hci_conn_hash_lookup_ba(hdev, ev->link_type, &ev->bdaddr);
Marcel Holtmann9dc0a3a2008-07-14 20:13:46 +02002644 if (!conn) {
2645 if (ev->link_type == ESCO_LINK)
2646 goto unlock;
2647
2648 conn = hci_conn_hash_lookup_ba(hdev, ESCO_LINK, &ev->bdaddr);
2649 if (!conn)
2650 goto unlock;
2651
2652 conn->type = SCO_LINK;
2653 }
Marcel Holtmannb6a0dc82007-10-20 14:55:10 +02002654
Marcel Holtmann732547f2009-04-19 19:14:14 +02002655 switch (ev->status) {
2656 case 0x00:
Marcel Holtmannb6a0dc82007-10-20 14:55:10 +02002657 conn->handle = __le16_to_cpu(ev->handle);
2658 conn->state = BT_CONNECTED;
Marcel Holtmann7d0db0a2008-07-14 20:13:51 +02002659
Marcel Holtmann9eba32b2009-08-22 14:19:26 -07002660 hci_conn_hold_device(conn);
Marcel Holtmann7d0db0a2008-07-14 20:13:51 +02002661 hci_conn_add_sysfs(conn);
Marcel Holtmann732547f2009-04-19 19:14:14 +02002662 break;
2663
Stephen Coe705e5712010-02-16 11:29:44 -05002664 case 0x11: /* Unsupported Feature or Parameter Value */
Marcel Holtmann732547f2009-04-19 19:14:14 +02002665 case 0x1c: /* SCO interval rejected */
Nick Pelly1038a002010-02-03 11:42:26 -08002666 case 0x1a: /* Unsupported Remote Feature */
Marcel Holtmann732547f2009-04-19 19:14:14 +02002667 case 0x1f: /* Unspecified error */
2668 if (conn->out && conn->attempt < 2) {
2669 conn->pkt_type = (hdev->esco_type & SCO_ESCO_MASK) |
2670 (hdev->esco_type & EDR_ESCO_MASK);
2671 hci_setup_sync(conn, conn->link->handle);
2672 goto unlock;
2673 }
2674 /* fall through */
2675
2676 default:
Marcel Holtmannb6a0dc82007-10-20 14:55:10 +02002677 conn->state = BT_CLOSED;
Marcel Holtmann732547f2009-04-19 19:14:14 +02002678 break;
2679 }
Marcel Holtmannb6a0dc82007-10-20 14:55:10 +02002680
2681 hci_proto_connect_cfm(conn, ev->status);
2682 if (ev->status)
2683 hci_conn_del(conn);
2684
2685unlock:
2686 hci_dev_unlock(hdev);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002687}
2688
2689static inline void hci_sync_conn_changed_evt(struct hci_dev *hdev, struct sk_buff *skb)
2690{
2691 BT_DBG("%s", hdev->name);
2692}
2693
Marcel Holtmann04837f62006-07-03 10:02:33 +02002694static inline void hci_sniff_subrate_evt(struct hci_dev *hdev, struct sk_buff *skb)
2695{
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002696 struct hci_ev_sniff_subrate *ev = (void *) skb->data;
Marcel Holtmann04837f62006-07-03 10:02:33 +02002697
2698 BT_DBG("%s status %d", hdev->name, ev->status);
Marcel Holtmann04837f62006-07-03 10:02:33 +02002699}
2700
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002701static inline void hci_extended_inquiry_result_evt(struct hci_dev *hdev, struct sk_buff *skb)
2702{
2703 struct inquiry_data data;
2704 struct extended_inquiry_info *info = (void *) (skb->data + 1);
2705 int num_rsp = *((__u8 *) skb->data);
2706
2707 BT_DBG("%s num_rsp %d", hdev->name, num_rsp);
2708
2709 if (!num_rsp)
2710 return;
2711
2712 hci_dev_lock(hdev);
2713
Johan Hedberge17acd42011-03-30 23:57:16 +03002714 for (; num_rsp; num_rsp--, info++) {
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002715 bacpy(&data.bdaddr, &info->bdaddr);
Szymon Janc138d22e2011-02-17 16:44:23 +01002716 data.pscan_rep_mode = info->pscan_rep_mode;
2717 data.pscan_period_mode = info->pscan_period_mode;
2718 data.pscan_mode = 0x00;
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002719 memcpy(data.dev_class, info->dev_class, 3);
Szymon Janc138d22e2011-02-17 16:44:23 +01002720 data.clock_offset = info->clock_offset;
2721 data.rssi = info->rssi;
Marcel Holtmann41a96212008-07-14 20:13:48 +02002722 data.ssp_mode = 0x01;
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002723 hci_inquiry_cache_update(hdev, &data);
Johan Hedberg48264f02011-11-09 13:58:58 +02002724 mgmt_device_found(hdev, &info->bdaddr, ACL_LINK, 0x00,
Johan Hedberg4c659c32011-11-07 23:13:39 +02002725 info->dev_class, info->rssi, info->data);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002726 }
2727
2728 hci_dev_unlock(hdev);
2729}
2730
Johan Hedberg17fa4b92011-01-25 13:28:33 +02002731static inline u8 hci_get_auth_req(struct hci_conn *conn)
2732{
2733 /* If remote requests dedicated bonding follow that lead */
2734 if (conn->remote_auth == 0x02 || conn->remote_auth == 0x03) {
2735 /* If both remote and local IO capabilities allow MITM
2736 * protection then require it, otherwise don't */
2737 if (conn->remote_cap == 0x03 || conn->io_capability == 0x03)
2738 return 0x02;
2739 else
2740 return 0x03;
2741 }
2742
2743 /* If remote requests no-bonding follow that lead */
2744 if (conn->remote_auth == 0x00 || conn->remote_auth == 0x01)
Waldemar Rymarkiewicz58797bf2011-04-28 12:07:58 +02002745 return conn->remote_auth | (conn->auth_type & 0x01);
Johan Hedberg17fa4b92011-01-25 13:28:33 +02002746
2747 return conn->auth_type;
2748}
2749
Marcel Holtmann04936842008-07-14 20:13:48 +02002750static inline void hci_io_capa_request_evt(struct hci_dev *hdev, struct sk_buff *skb)
2751{
2752 struct hci_ev_io_capa_request *ev = (void *) skb->data;
2753 struct hci_conn *conn;
2754
2755 BT_DBG("%s", hdev->name);
2756
2757 hci_dev_lock(hdev);
2758
2759 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
Johan Hedberg03b555e2011-01-04 15:40:05 +02002760 if (!conn)
2761 goto unlock;
Marcel Holtmann04936842008-07-14 20:13:48 +02002762
Johan Hedberg03b555e2011-01-04 15:40:05 +02002763 hci_conn_hold(conn);
2764
2765 if (!test_bit(HCI_MGMT, &hdev->flags))
2766 goto unlock;
2767
2768 if (test_bit(HCI_PAIRABLE, &hdev->flags) ||
2769 (conn->remote_auth & ~0x01) == HCI_AT_NO_BONDING) {
Johan Hedberg17fa4b92011-01-25 13:28:33 +02002770 struct hci_cp_io_capability_reply cp;
2771
2772 bacpy(&cp.bdaddr, &ev->bdaddr);
2773 cp.capability = conn->io_capability;
Johan Hedberg7cbc9bd2011-04-28 11:29:04 -07002774 conn->auth_type = hci_get_auth_req(conn);
2775 cp.authentication = conn->auth_type;
Johan Hedberg17fa4b92011-01-25 13:28:33 +02002776
Szymon Jancce85ee12011-03-22 13:12:23 +01002777 if ((conn->out == 0x01 || conn->remote_oob == 0x01) &&
2778 hci_find_remote_oob_data(hdev, &conn->dst))
2779 cp.oob_data = 0x01;
2780 else
2781 cp.oob_data = 0x00;
2782
Johan Hedberg17fa4b92011-01-25 13:28:33 +02002783 hci_send_cmd(hdev, HCI_OP_IO_CAPABILITY_REPLY,
2784 sizeof(cp), &cp);
Johan Hedberg03b555e2011-01-04 15:40:05 +02002785 } else {
2786 struct hci_cp_io_capability_neg_reply cp;
2787
2788 bacpy(&cp.bdaddr, &ev->bdaddr);
Andrei Emeltchenko9f5a0d72011-11-07 14:20:25 +02002789 cp.reason = HCI_ERROR_PAIRING_NOT_ALLOWED;
Johan Hedberg03b555e2011-01-04 15:40:05 +02002790
2791 hci_send_cmd(hdev, HCI_OP_IO_CAPABILITY_NEG_REPLY,
2792 sizeof(cp), &cp);
2793 }
2794
2795unlock:
2796 hci_dev_unlock(hdev);
2797}
2798
2799static inline void hci_io_capa_reply_evt(struct hci_dev *hdev, struct sk_buff *skb)
2800{
2801 struct hci_ev_io_capa_reply *ev = (void *) skb->data;
2802 struct hci_conn *conn;
2803
2804 BT_DBG("%s", hdev->name);
2805
2806 hci_dev_lock(hdev);
2807
2808 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
2809 if (!conn)
2810 goto unlock;
2811
Johan Hedberg03b555e2011-01-04 15:40:05 +02002812 conn->remote_cap = ev->capability;
2813 conn->remote_oob = ev->oob_data;
2814 conn->remote_auth = ev->authentication;
2815
2816unlock:
Marcel Holtmann04936842008-07-14 20:13:48 +02002817 hci_dev_unlock(hdev);
2818}
2819
Johan Hedberga5c29682011-02-19 12:05:57 -03002820static inline void hci_user_confirm_request_evt(struct hci_dev *hdev,
2821 struct sk_buff *skb)
2822{
2823 struct hci_ev_user_confirm_req *ev = (void *) skb->data;
Johan Hedberg55bc1a32011-04-28 11:28:56 -07002824 int loc_mitm, rem_mitm, confirm_hint = 0;
Johan Hedberg7a828902011-04-28 11:28:53 -07002825 struct hci_conn *conn;
Johan Hedberga5c29682011-02-19 12:05:57 -03002826
2827 BT_DBG("%s", hdev->name);
2828
2829 hci_dev_lock(hdev);
2830
Johan Hedberg7a828902011-04-28 11:28:53 -07002831 if (!test_bit(HCI_MGMT, &hdev->flags))
2832 goto unlock;
Johan Hedberga5c29682011-02-19 12:05:57 -03002833
Johan Hedberg7a828902011-04-28 11:28:53 -07002834 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
2835 if (!conn)
2836 goto unlock;
2837
2838 loc_mitm = (conn->auth_type & 0x01);
2839 rem_mitm = (conn->remote_auth & 0x01);
2840
2841 /* If we require MITM but the remote device can't provide that
2842 * (it has NoInputNoOutput) then reject the confirmation
2843 * request. The only exception is when we're dedicated bonding
2844 * initiators (connect_cfm_cb set) since then we always have the MITM
2845 * bit set. */
2846 if (!conn->connect_cfm_cb && loc_mitm && conn->remote_cap == 0x03) {
2847 BT_DBG("Rejecting request: remote device can't provide MITM");
2848 hci_send_cmd(hdev, HCI_OP_USER_CONFIRM_NEG_REPLY,
2849 sizeof(ev->bdaddr), &ev->bdaddr);
2850 goto unlock;
2851 }
2852
2853 /* If no side requires MITM protection; auto-accept */
2854 if ((!loc_mitm || conn->remote_cap == 0x03) &&
2855 (!rem_mitm || conn->io_capability == 0x03)) {
Johan Hedberg55bc1a32011-04-28 11:28:56 -07002856
2857 /* If we're not the initiators request authorization to
2858 * proceed from user space (mgmt_user_confirm with
2859 * confirm_hint set to 1). */
2860 if (!test_bit(HCI_CONN_AUTH_PEND, &conn->pend)) {
2861 BT_DBG("Confirming auto-accept as acceptor");
2862 confirm_hint = 1;
2863 goto confirm;
2864 }
2865
Johan Hedberg9f616562011-04-28 11:28:54 -07002866 BT_DBG("Auto-accept of user confirmation with %ums delay",
2867 hdev->auto_accept_delay);
2868
2869 if (hdev->auto_accept_delay > 0) {
2870 int delay = msecs_to_jiffies(hdev->auto_accept_delay);
2871 mod_timer(&conn->auto_accept_timer, jiffies + delay);
2872 goto unlock;
2873 }
2874
Johan Hedberg7a828902011-04-28 11:28:53 -07002875 hci_send_cmd(hdev, HCI_OP_USER_CONFIRM_REPLY,
2876 sizeof(ev->bdaddr), &ev->bdaddr);
2877 goto unlock;
2878 }
2879
Johan Hedberg55bc1a32011-04-28 11:28:56 -07002880confirm:
Johan Hedberg744cf192011-11-08 20:40:14 +02002881 mgmt_user_confirm_request(hdev, &ev->bdaddr, ev->passkey,
Johan Hedberg55bc1a32011-04-28 11:28:56 -07002882 confirm_hint);
Johan Hedberg7a828902011-04-28 11:28:53 -07002883
2884unlock:
Johan Hedberga5c29682011-02-19 12:05:57 -03002885 hci_dev_unlock(hdev);
2886}
2887
Brian Gix1143d452011-11-23 08:28:34 -08002888static inline void hci_user_passkey_request_evt(struct hci_dev *hdev,
2889 struct sk_buff *skb)
2890{
2891 struct hci_ev_user_passkey_req *ev = (void *) skb->data;
2892
2893 BT_DBG("%s", hdev->name);
2894
2895 hci_dev_lock(hdev);
2896
2897 if (test_bit(HCI_MGMT, &hdev->flags))
2898 mgmt_user_passkey_request(hdev, &ev->bdaddr);
2899
2900 hci_dev_unlock(hdev);
2901}
2902
Marcel Holtmann04936842008-07-14 20:13:48 +02002903static inline void hci_simple_pair_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
2904{
2905 struct hci_ev_simple_pair_complete *ev = (void *) skb->data;
2906 struct hci_conn *conn;
2907
2908 BT_DBG("%s", hdev->name);
2909
2910 hci_dev_lock(hdev);
2911
2912 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
Johan Hedberg2a611692011-02-19 12:06:00 -03002913 if (!conn)
2914 goto unlock;
Marcel Holtmann04936842008-07-14 20:13:48 +02002915
Johan Hedberg2a611692011-02-19 12:06:00 -03002916 /* To avoid duplicate auth_failed events to user space we check
2917 * the HCI_CONN_AUTH_PEND flag which will be set if we
2918 * initiated the authentication. A traditional auth_complete
2919 * event gets always produced as initiator and is also mapped to
2920 * the mgmt_auth_failed event */
2921 if (!test_bit(HCI_CONN_AUTH_PEND, &conn->pend) && ev->status != 0)
Johan Hedberg744cf192011-11-08 20:40:14 +02002922 mgmt_auth_failed(hdev, &conn->dst, ev->status);
Johan Hedberg2a611692011-02-19 12:06:00 -03002923
2924 hci_conn_put(conn);
2925
2926unlock:
Marcel Holtmann04936842008-07-14 20:13:48 +02002927 hci_dev_unlock(hdev);
2928}
2929
Marcel Holtmann41a96212008-07-14 20:13:48 +02002930static inline void hci_remote_host_features_evt(struct hci_dev *hdev, struct sk_buff *skb)
2931{
2932 struct hci_ev_remote_host_features *ev = (void *) skb->data;
2933 struct inquiry_entry *ie;
2934
2935 BT_DBG("%s", hdev->name);
2936
2937 hci_dev_lock(hdev);
2938
Andrei Emeltchenkocc11b9c2010-11-22 13:21:37 +02002939 ie = hci_inquiry_cache_lookup(hdev, &ev->bdaddr);
2940 if (ie)
Marcel Holtmann41a96212008-07-14 20:13:48 +02002941 ie->data.ssp_mode = (ev->features[0] & 0x01);
2942
2943 hci_dev_unlock(hdev);
2944}
2945
Szymon Janc2763eda2011-03-22 13:12:22 +01002946static inline void hci_remote_oob_data_request_evt(struct hci_dev *hdev,
2947 struct sk_buff *skb)
2948{
2949 struct hci_ev_remote_oob_data_request *ev = (void *) skb->data;
2950 struct oob_data *data;
2951
2952 BT_DBG("%s", hdev->name);
2953
2954 hci_dev_lock(hdev);
2955
Szymon Jance1ba1f12011-04-06 13:01:59 +02002956 if (!test_bit(HCI_MGMT, &hdev->flags))
2957 goto unlock;
2958
Szymon Janc2763eda2011-03-22 13:12:22 +01002959 data = hci_find_remote_oob_data(hdev, &ev->bdaddr);
2960 if (data) {
2961 struct hci_cp_remote_oob_data_reply cp;
2962
2963 bacpy(&cp.bdaddr, &ev->bdaddr);
2964 memcpy(cp.hash, data->hash, sizeof(cp.hash));
2965 memcpy(cp.randomizer, data->randomizer, sizeof(cp.randomizer));
2966
2967 hci_send_cmd(hdev, HCI_OP_REMOTE_OOB_DATA_REPLY, sizeof(cp),
2968 &cp);
2969 } else {
2970 struct hci_cp_remote_oob_data_neg_reply cp;
2971
2972 bacpy(&cp.bdaddr, &ev->bdaddr);
2973 hci_send_cmd(hdev, HCI_OP_REMOTE_OOB_DATA_NEG_REPLY, sizeof(cp),
2974 &cp);
2975 }
2976
Szymon Jance1ba1f12011-04-06 13:01:59 +02002977unlock:
Szymon Janc2763eda2011-03-22 13:12:22 +01002978 hci_dev_unlock(hdev);
2979}
2980
Ville Tervofcd89c02011-02-10 22:38:47 -03002981static inline void hci_le_conn_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
2982{
2983 struct hci_ev_le_conn_complete *ev = (void *) skb->data;
2984 struct hci_conn *conn;
2985
2986 BT_DBG("%s status %d", hdev->name, ev->status);
2987
2988 hci_dev_lock(hdev);
2989
2990 conn = hci_conn_hash_lookup_ba(hdev, LE_LINK, &ev->bdaddr);
Ville Tervob62f3282011-02-10 22:38:50 -03002991 if (!conn) {
2992 conn = hci_conn_add(hdev, LE_LINK, &ev->bdaddr);
2993 if (!conn) {
2994 BT_ERR("No memory for new connection");
2995 hci_dev_unlock(hdev);
2996 return;
2997 }
Andre Guedes29b79882011-05-31 14:20:54 -03002998
2999 conn->dst_type = ev->bdaddr_type;
Ville Tervob62f3282011-02-10 22:38:50 -03003000 }
Ville Tervofcd89c02011-02-10 22:38:47 -03003001
3002 if (ev->status) {
Johan Hedberg48264f02011-11-09 13:58:58 +02003003 mgmt_connect_failed(hdev, &ev->bdaddr, conn->type,
3004 conn->dst_type, ev->status);
Ville Tervofcd89c02011-02-10 22:38:47 -03003005 hci_proto_connect_cfm(conn, ev->status);
3006 conn->state = BT_CLOSED;
3007 hci_conn_del(conn);
3008 goto unlock;
3009 }
3010
Johan Hedberg48264f02011-11-09 13:58:58 +02003011 mgmt_connected(hdev, &ev->bdaddr, conn->type, conn->dst_type);
Vinicius Costa Gomes83bc71b2011-05-06 18:41:43 -03003012
Vinicius Costa Gomes7b5c0d52011-06-09 18:50:50 -03003013 conn->sec_level = BT_SECURITY_LOW;
Ville Tervofcd89c02011-02-10 22:38:47 -03003014 conn->handle = __le16_to_cpu(ev->handle);
3015 conn->state = BT_CONNECTED;
3016
3017 hci_conn_hold_device(conn);
3018 hci_conn_add_sysfs(conn);
3019
3020 hci_proto_connect_cfm(conn, ev->status);
3021
3022unlock:
3023 hci_dev_unlock(hdev);
3024}
3025
Andre Guedes9aa04c92011-05-26 16:23:51 -03003026static inline void hci_le_adv_report_evt(struct hci_dev *hdev,
3027 struct sk_buff *skb)
3028{
Andre Guedese95beb42011-09-26 20:48:35 -03003029 u8 num_reports = skb->data[0];
3030 void *ptr = &skb->data[1];
Andre Guedes9aa04c92011-05-26 16:23:51 -03003031
3032 hci_dev_lock(hdev);
3033
Andre Guedese95beb42011-09-26 20:48:35 -03003034 while (num_reports--) {
3035 struct hci_ev_le_advertising_info *ev = ptr;
Andre Guedes9aa04c92011-05-26 16:23:51 -03003036
Andre Guedes9aa04c92011-05-26 16:23:51 -03003037 hci_add_adv_entry(hdev, ev);
Andre Guedese95beb42011-09-26 20:48:35 -03003038
3039 ptr += sizeof(*ev) + ev->length + 1;
Andre Guedes9aa04c92011-05-26 16:23:51 -03003040 }
3041
3042 hci_dev_unlock(hdev);
3043}
3044
Vinicius Costa Gomesa7a595f2011-06-09 18:50:47 -03003045static inline void hci_le_ltk_request_evt(struct hci_dev *hdev,
3046 struct sk_buff *skb)
3047{
3048 struct hci_ev_le_ltk_req *ev = (void *) skb->data;
3049 struct hci_cp_le_ltk_reply cp;
Vinicius Costa Gomesbea710f2011-07-07 18:59:37 -03003050 struct hci_cp_le_ltk_neg_reply neg;
Vinicius Costa Gomesa7a595f2011-06-09 18:50:47 -03003051 struct hci_conn *conn;
Vinicius Costa Gomesbea710f2011-07-07 18:59:37 -03003052 struct link_key *ltk;
Vinicius Costa Gomesa7a595f2011-06-09 18:50:47 -03003053
3054 BT_DBG("%s handle %d", hdev->name, cpu_to_le16(ev->handle));
3055
3056 hci_dev_lock(hdev);
3057
3058 conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
Vinicius Costa Gomesbea710f2011-07-07 18:59:37 -03003059 if (conn == NULL)
3060 goto not_found;
Vinicius Costa Gomesa7a595f2011-06-09 18:50:47 -03003061
Vinicius Costa Gomesbea710f2011-07-07 18:59:37 -03003062 ltk = hci_find_ltk(hdev, ev->ediv, ev->random);
3063 if (ltk == NULL)
3064 goto not_found;
3065
3066 memcpy(cp.ltk, ltk->val, sizeof(ltk->val));
Vinicius Costa Gomesa7a595f2011-06-09 18:50:47 -03003067 cp.handle = cpu_to_le16(conn->handle);
Vinicius Costa Gomes726b4ff2011-07-08 18:31:45 -03003068 conn->pin_length = ltk->pin_len;
Vinicius Costa Gomesa7a595f2011-06-09 18:50:47 -03003069
3070 hci_send_cmd(hdev, HCI_OP_LE_LTK_REPLY, sizeof(cp), &cp);
3071
3072 hci_dev_unlock(hdev);
Vinicius Costa Gomesbea710f2011-07-07 18:59:37 -03003073
3074 return;
3075
3076not_found:
3077 neg.handle = ev->handle;
3078 hci_send_cmd(hdev, HCI_OP_LE_LTK_NEG_REPLY, sizeof(neg), &neg);
3079 hci_dev_unlock(hdev);
Vinicius Costa Gomesa7a595f2011-06-09 18:50:47 -03003080}
3081
Ville Tervofcd89c02011-02-10 22:38:47 -03003082static inline void hci_le_meta_evt(struct hci_dev *hdev, struct sk_buff *skb)
3083{
3084 struct hci_ev_le_meta *le_ev = (void *) skb->data;
3085
3086 skb_pull(skb, sizeof(*le_ev));
3087
3088 switch (le_ev->subevent) {
3089 case HCI_EV_LE_CONN_COMPLETE:
3090 hci_le_conn_complete_evt(hdev, skb);
3091 break;
3092
Andre Guedes9aa04c92011-05-26 16:23:51 -03003093 case HCI_EV_LE_ADVERTISING_REPORT:
3094 hci_le_adv_report_evt(hdev, skb);
3095 break;
3096
Vinicius Costa Gomesa7a595f2011-06-09 18:50:47 -03003097 case HCI_EV_LE_LTK_REQ:
3098 hci_le_ltk_request_evt(hdev, skb);
3099 break;
3100
Ville Tervofcd89c02011-02-10 22:38:47 -03003101 default:
3102 break;
3103 }
3104}
3105
Linus Torvalds1da177e2005-04-16 15:20:36 -07003106void hci_event_packet(struct hci_dev *hdev, struct sk_buff *skb)
3107{
Marcel Holtmanna9de9242007-10-20 13:33:56 +02003108 struct hci_event_hdr *hdr = (void *) skb->data;
3109 __u8 event = hdr->evt;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003110
3111 skb_pull(skb, HCI_EVENT_HDR_SIZE);
3112
Marcel Holtmanna9de9242007-10-20 13:33:56 +02003113 switch (event) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003114 case HCI_EV_INQUIRY_COMPLETE:
3115 hci_inquiry_complete_evt(hdev, skb);
3116 break;
3117
3118 case HCI_EV_INQUIRY_RESULT:
3119 hci_inquiry_result_evt(hdev, skb);
3120 break;
3121
Marcel Holtmanna9de9242007-10-20 13:33:56 +02003122 case HCI_EV_CONN_COMPLETE:
3123 hci_conn_complete_evt(hdev, skb);
Marcel Holtmann21d9e302005-09-13 01:32:25 +02003124 break;
3125
Linus Torvalds1da177e2005-04-16 15:20:36 -07003126 case HCI_EV_CONN_REQUEST:
3127 hci_conn_request_evt(hdev, skb);
3128 break;
3129
Linus Torvalds1da177e2005-04-16 15:20:36 -07003130 case HCI_EV_DISCONN_COMPLETE:
3131 hci_disconn_complete_evt(hdev, skb);
3132 break;
3133
Linus Torvalds1da177e2005-04-16 15:20:36 -07003134 case HCI_EV_AUTH_COMPLETE:
3135 hci_auth_complete_evt(hdev, skb);
3136 break;
3137
Marcel Holtmanna9de9242007-10-20 13:33:56 +02003138 case HCI_EV_REMOTE_NAME:
3139 hci_remote_name_evt(hdev, skb);
3140 break;
3141
Linus Torvalds1da177e2005-04-16 15:20:36 -07003142 case HCI_EV_ENCRYPT_CHANGE:
3143 hci_encrypt_change_evt(hdev, skb);
3144 break;
3145
Marcel Holtmanna9de9242007-10-20 13:33:56 +02003146 case HCI_EV_CHANGE_LINK_KEY_COMPLETE:
3147 hci_change_link_key_complete_evt(hdev, skb);
3148 break;
3149
3150 case HCI_EV_REMOTE_FEATURES:
3151 hci_remote_features_evt(hdev, skb);
3152 break;
3153
3154 case HCI_EV_REMOTE_VERSION:
3155 hci_remote_version_evt(hdev, skb);
3156 break;
3157
3158 case HCI_EV_QOS_SETUP_COMPLETE:
3159 hci_qos_setup_complete_evt(hdev, skb);
3160 break;
3161
3162 case HCI_EV_CMD_COMPLETE:
3163 hci_cmd_complete_evt(hdev, skb);
3164 break;
3165
3166 case HCI_EV_CMD_STATUS:
3167 hci_cmd_status_evt(hdev, skb);
3168 break;
3169
3170 case HCI_EV_ROLE_CHANGE:
3171 hci_role_change_evt(hdev, skb);
3172 break;
3173
3174 case HCI_EV_NUM_COMP_PKTS:
3175 hci_num_comp_pkts_evt(hdev, skb);
3176 break;
3177
3178 case HCI_EV_MODE_CHANGE:
3179 hci_mode_change_evt(hdev, skb);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003180 break;
3181
3182 case HCI_EV_PIN_CODE_REQ:
3183 hci_pin_code_request_evt(hdev, skb);
3184 break;
3185
3186 case HCI_EV_LINK_KEY_REQ:
3187 hci_link_key_request_evt(hdev, skb);
3188 break;
3189
3190 case HCI_EV_LINK_KEY_NOTIFY:
3191 hci_link_key_notify_evt(hdev, skb);
3192 break;
3193
3194 case HCI_EV_CLOCK_OFFSET:
3195 hci_clock_offset_evt(hdev, skb);
3196 break;
3197
Marcel Holtmanna8746412008-07-14 20:13:46 +02003198 case HCI_EV_PKT_TYPE_CHANGE:
3199 hci_pkt_type_change_evt(hdev, skb);
3200 break;
3201
Marcel Holtmann85a1e932005-08-09 20:28:02 -07003202 case HCI_EV_PSCAN_REP_MODE:
3203 hci_pscan_rep_mode_evt(hdev, skb);
3204 break;
3205
Marcel Holtmanna9de9242007-10-20 13:33:56 +02003206 case HCI_EV_INQUIRY_RESULT_WITH_RSSI:
3207 hci_inquiry_result_with_rssi_evt(hdev, skb);
3208 break;
3209
3210 case HCI_EV_REMOTE_EXT_FEATURES:
3211 hci_remote_ext_features_evt(hdev, skb);
3212 break;
3213
3214 case HCI_EV_SYNC_CONN_COMPLETE:
3215 hci_sync_conn_complete_evt(hdev, skb);
3216 break;
3217
3218 case HCI_EV_SYNC_CONN_CHANGED:
3219 hci_sync_conn_changed_evt(hdev, skb);
3220 break;
3221
Marcel Holtmann04837f62006-07-03 10:02:33 +02003222 case HCI_EV_SNIFF_SUBRATE:
3223 hci_sniff_subrate_evt(hdev, skb);
3224 break;
3225
Marcel Holtmanna9de9242007-10-20 13:33:56 +02003226 case HCI_EV_EXTENDED_INQUIRY_RESULT:
3227 hci_extended_inquiry_result_evt(hdev, skb);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003228 break;
3229
Marcel Holtmann04936842008-07-14 20:13:48 +02003230 case HCI_EV_IO_CAPA_REQUEST:
3231 hci_io_capa_request_evt(hdev, skb);
3232 break;
3233
Johan Hedberg03b555e2011-01-04 15:40:05 +02003234 case HCI_EV_IO_CAPA_REPLY:
3235 hci_io_capa_reply_evt(hdev, skb);
3236 break;
3237
Johan Hedberga5c29682011-02-19 12:05:57 -03003238 case HCI_EV_USER_CONFIRM_REQUEST:
3239 hci_user_confirm_request_evt(hdev, skb);
3240 break;
3241
Brian Gix1143d452011-11-23 08:28:34 -08003242 case HCI_EV_USER_PASSKEY_REQUEST:
3243 hci_user_passkey_request_evt(hdev, skb);
3244 break;
3245
Marcel Holtmann04936842008-07-14 20:13:48 +02003246 case HCI_EV_SIMPLE_PAIR_COMPLETE:
3247 hci_simple_pair_complete_evt(hdev, skb);
3248 break;
3249
Marcel Holtmann41a96212008-07-14 20:13:48 +02003250 case HCI_EV_REMOTE_HOST_FEATURES:
3251 hci_remote_host_features_evt(hdev, skb);
3252 break;
3253
Ville Tervofcd89c02011-02-10 22:38:47 -03003254 case HCI_EV_LE_META:
3255 hci_le_meta_evt(hdev, skb);
3256 break;
3257
Szymon Janc2763eda2011-03-22 13:12:22 +01003258 case HCI_EV_REMOTE_OOB_DATA_REQUEST:
3259 hci_remote_oob_data_request_evt(hdev, skb);
3260 break;
3261
Marcel Holtmanna9de9242007-10-20 13:33:56 +02003262 default:
3263 BT_DBG("%s event 0x%x", hdev->name, event);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003264 break;
3265 }
3266
3267 kfree_skb(skb);
3268 hdev->stat.evt_rx++;
3269}
3270
3271/* Generate internal stack event */
3272void hci_si_event(struct hci_dev *hdev, int type, int dlen, void *data)
3273{
3274 struct hci_event_hdr *hdr;
3275 struct hci_ev_stack_internal *ev;
3276 struct sk_buff *skb;
3277
3278 skb = bt_skb_alloc(HCI_EVENT_HDR_SIZE + sizeof(*ev) + dlen, GFP_ATOMIC);
3279 if (!skb)
3280 return;
3281
3282 hdr = (void *) skb_put(skb, HCI_EVENT_HDR_SIZE);
3283 hdr->evt = HCI_EV_STACK_INTERNAL;
3284 hdr->plen = sizeof(*ev) + dlen;
3285
3286 ev = (void *) skb_put(skb, sizeof(*ev) + dlen);
3287 ev->type = type;
3288 memcpy(ev->data, data, dlen);
3289
Marcel Holtmann576c7d82005-08-06 12:36:54 +02003290 bt_cb(skb)->incoming = 1;
Patrick McHardya61bbcf2005-08-14 17:24:31 -07003291 __net_timestamp(skb);
Marcel Holtmann576c7d82005-08-06 12:36:54 +02003292
Marcel Holtmann0d48d932005-08-09 20:30:28 -07003293 bt_cb(skb)->pkt_type = HCI_EVENT_PKT;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003294 skb->dev = (void *) hdev;
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02003295 hci_send_to_sock(hdev, skb, NULL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003296 kfree_skb(skb);
3297}
Andre Guedese6100a22011-06-30 19:20:54 -03003298
Gustavo F. Padovan669bb392011-10-11 15:57:01 -03003299module_param(enable_le, bool, 0644);
Andre Guedese6100a22011-06-30 19:20:54 -03003300MODULE_PARM_DESC(enable_le, "Enable LE support");