blob: 0a9501f17366a5c43e297e1770d4bd87f9a409af [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
381 if (hdev->notify) {
382 tasklet_disable(&hdev->tx_task);
383 hdev->notify(hdev, HCI_NOTIFY_VOICE_SETTING);
384 tasklet_enable(&hdev->tx_task);
385 }
386}
387
388static void hci_cc_write_voice_setting(struct hci_dev *hdev, struct sk_buff *skb)
389{
390 __u8 status = *((__u8 *) skb->data);
Marcel Holtmannf383f272008-07-14 20:13:47 +0200391 __u16 setting;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700392 void *sent;
393
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200394 BT_DBG("%s status 0x%x", hdev->name, status);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700395
Marcel Holtmannf383f272008-07-14 20:13:47 +0200396 if (status)
397 return;
398
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200399 sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_VOICE_SETTING);
400 if (!sent)
401 return;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700402
Marcel Holtmannf383f272008-07-14 20:13:47 +0200403 setting = get_unaligned_le16(sent);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700404
Marcel Holtmannf383f272008-07-14 20:13:47 +0200405 if (hdev->voice_setting == setting)
406 return;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700407
Marcel Holtmannf383f272008-07-14 20:13:47 +0200408 hdev->voice_setting = setting;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700409
Marcel Holtmannf383f272008-07-14 20:13:47 +0200410 BT_DBG("%s voice setting 0x%04x", hdev->name, setting);
411
412 if (hdev->notify) {
413 tasklet_disable(&hdev->tx_task);
414 hdev->notify(hdev, HCI_NOTIFY_VOICE_SETTING);
415 tasklet_enable(&hdev->tx_task);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700416 }
417}
418
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200419static void hci_cc_host_buffer_size(struct hci_dev *hdev, struct sk_buff *skb)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700420{
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200421 __u8 status = *((__u8 *) skb->data);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700422
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200423 BT_DBG("%s status 0x%x", hdev->name, status);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700424
Johan Hedberg23bb5762010-12-21 23:01:27 +0200425 hci_req_complete(hdev, HCI_OP_HOST_BUFFER_SIZE, status);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700426}
427
Marcel Holtmann333140b2008-07-14 20:13:48 +0200428static void hci_cc_read_ssp_mode(struct hci_dev *hdev, struct sk_buff *skb)
429{
430 struct hci_rp_read_ssp_mode *rp = (void *) skb->data;
431
432 BT_DBG("%s status 0x%x", hdev->name, rp->status);
433
434 if (rp->status)
435 return;
436
437 hdev->ssp_mode = rp->mode;
438}
439
440static void hci_cc_write_ssp_mode(struct hci_dev *hdev, struct sk_buff *skb)
441{
442 __u8 status = *((__u8 *) skb->data);
443 void *sent;
444
445 BT_DBG("%s status 0x%x", hdev->name, status);
446
447 if (status)
448 return;
449
450 sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_SSP_MODE);
451 if (!sent)
452 return;
453
454 hdev->ssp_mode = *((__u8 *) sent);
455}
456
Johan Hedbergd5859e22011-01-25 01:19:58 +0200457static u8 hci_get_inquiry_mode(struct hci_dev *hdev)
458{
459 if (hdev->features[6] & LMP_EXT_INQ)
460 return 2;
461
462 if (hdev->features[3] & LMP_RSSI_INQ)
463 return 1;
464
465 if (hdev->manufacturer == 11 && hdev->hci_rev == 0x00 &&
466 hdev->lmp_subver == 0x0757)
467 return 1;
468
469 if (hdev->manufacturer == 15) {
470 if (hdev->hci_rev == 0x03 && hdev->lmp_subver == 0x6963)
471 return 1;
472 if (hdev->hci_rev == 0x09 && hdev->lmp_subver == 0x6963)
473 return 1;
474 if (hdev->hci_rev == 0x00 && hdev->lmp_subver == 0x6965)
475 return 1;
476 }
477
478 if (hdev->manufacturer == 31 && hdev->hci_rev == 0x2005 &&
479 hdev->lmp_subver == 0x1805)
480 return 1;
481
482 return 0;
483}
484
485static void hci_setup_inquiry_mode(struct hci_dev *hdev)
486{
487 u8 mode;
488
489 mode = hci_get_inquiry_mode(hdev);
490
491 hci_send_cmd(hdev, HCI_OP_WRITE_INQUIRY_MODE, 1, &mode);
492}
493
494static void hci_setup_event_mask(struct hci_dev *hdev)
495{
496 /* The second byte is 0xff instead of 0x9f (two reserved bits
497 * disabled) since a Broadcom 1.2 dongle doesn't respond to the
498 * command otherwise */
499 u8 events[8] = { 0xff, 0xff, 0xfb, 0xff, 0x00, 0x00, 0x00, 0x00 };
500
Ville Tervo6de6c182011-05-27 11:16:21 +0300501 /* CSR 1.1 dongles does not accept any bitfield so don't try to set
502 * any event mask for pre 1.2 devices */
Andrei Emeltchenko5a13b092011-12-01 14:33:28 +0200503 if (hdev->hci_ver < BLUETOOTH_VER_1_2)
Ville Tervo6de6c182011-05-27 11:16:21 +0300504 return;
505
506 events[4] |= 0x01; /* Flow Specification Complete */
507 events[4] |= 0x02; /* Inquiry Result with RSSI */
508 events[4] |= 0x04; /* Read Remote Extended Features Complete */
509 events[5] |= 0x08; /* Synchronous Connection Complete */
510 events[5] |= 0x10; /* Synchronous Connection Changed */
Johan Hedbergd5859e22011-01-25 01:19:58 +0200511
512 if (hdev->features[3] & LMP_RSSI_INQ)
513 events[4] |= 0x04; /* Inquiry Result with RSSI */
514
515 if (hdev->features[5] & LMP_SNIFF_SUBR)
516 events[5] |= 0x20; /* Sniff Subrating */
517
518 if (hdev->features[5] & LMP_PAUSE_ENC)
519 events[5] |= 0x80; /* Encryption Key Refresh Complete */
520
521 if (hdev->features[6] & LMP_EXT_INQ)
522 events[5] |= 0x40; /* Extended Inquiry Result */
523
524 if (hdev->features[6] & LMP_NO_FLUSH)
525 events[7] |= 0x01; /* Enhanced Flush Complete */
526
527 if (hdev->features[7] & LMP_LSTO)
528 events[6] |= 0x80; /* Link Supervision Timeout Changed */
529
530 if (hdev->features[6] & LMP_SIMPLE_PAIR) {
531 events[6] |= 0x01; /* IO Capability Request */
532 events[6] |= 0x02; /* IO Capability Response */
533 events[6] |= 0x04; /* User Confirmation Request */
534 events[6] |= 0x08; /* User Passkey Request */
535 events[6] |= 0x10; /* Remote OOB Data Request */
536 events[6] |= 0x20; /* Simple Pairing Complete */
537 events[7] |= 0x04; /* User Passkey Notification */
538 events[7] |= 0x08; /* Keypress Notification */
539 events[7] |= 0x10; /* Remote Host Supported
540 * Features Notification */
541 }
542
543 if (hdev->features[4] & LMP_LE)
544 events[7] |= 0x20; /* LE Meta-Event */
545
546 hci_send_cmd(hdev, HCI_OP_SET_EVENT_MASK, sizeof(events), events);
547}
548
Andre Guedese6100a22011-06-30 19:20:54 -0300549static void hci_set_le_support(struct hci_dev *hdev)
550{
551 struct hci_cp_write_le_host_supported cp;
552
553 memset(&cp, 0, sizeof(cp));
554
555 if (enable_le) {
556 cp.le = 1;
557 cp.simul = !!(hdev->features[6] & LMP_SIMUL_LE_BR);
558 }
559
560 hci_send_cmd(hdev, HCI_OP_WRITE_LE_HOST_SUPPORTED, sizeof(cp), &cp);
561}
562
Johan Hedbergd5859e22011-01-25 01:19:58 +0200563static void hci_setup(struct hci_dev *hdev)
564{
565 hci_setup_event_mask(hdev);
566
Andrei Emeltchenkod095c1e2011-12-01 14:33:27 +0200567 if (hdev->hci_ver > BLUETOOTH_VER_1_1)
Johan Hedbergd5859e22011-01-25 01:19:58 +0200568 hci_send_cmd(hdev, HCI_OP_READ_LOCAL_COMMANDS, 0, NULL);
569
570 if (hdev->features[6] & LMP_SIMPLE_PAIR) {
571 u8 mode = 0x01;
572 hci_send_cmd(hdev, HCI_OP_WRITE_SSP_MODE, sizeof(mode), &mode);
573 }
574
575 if (hdev->features[3] & LMP_RSSI_INQ)
576 hci_setup_inquiry_mode(hdev);
577
578 if (hdev->features[7] & LMP_INQ_TX_PWR)
579 hci_send_cmd(hdev, HCI_OP_READ_INQ_RSP_TX_POWER, 0, NULL);
Andre Guedes971e3a42011-06-30 19:20:52 -0300580
581 if (hdev->features[7] & LMP_EXTFEATURES) {
582 struct hci_cp_read_local_ext_features cp;
583
584 cp.page = 0x01;
585 hci_send_cmd(hdev, HCI_OP_READ_LOCAL_EXT_FEATURES,
586 sizeof(cp), &cp);
587 }
Andre Guedese6100a22011-06-30 19:20:54 -0300588
589 if (hdev->features[4] & LMP_LE)
590 hci_set_le_support(hdev);
Johan Hedbergd5859e22011-01-25 01:19:58 +0200591}
592
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200593static void hci_cc_read_local_version(struct hci_dev *hdev, struct sk_buff *skb)
594{
595 struct hci_rp_read_local_version *rp = (void *) skb->data;
596
597 BT_DBG("%s status 0x%x", hdev->name, rp->status);
598
599 if (rp->status)
600 return;
601
602 hdev->hci_ver = rp->hci_ver;
Marcel Holtmanne4e8e372008-07-14 20:13:47 +0200603 hdev->hci_rev = __le16_to_cpu(rp->hci_rev);
Johan Hedbergd5859e22011-01-25 01:19:58 +0200604 hdev->lmp_ver = rp->lmp_ver;
Marcel Holtmanne4e8e372008-07-14 20:13:47 +0200605 hdev->manufacturer = __le16_to_cpu(rp->manufacturer);
Johan Hedbergd5859e22011-01-25 01:19:58 +0200606 hdev->lmp_subver = __le16_to_cpu(rp->lmp_subver);
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200607
608 BT_DBG("%s manufacturer %d hci ver %d:%d", hdev->name,
609 hdev->manufacturer,
610 hdev->hci_ver, hdev->hci_rev);
Johan Hedbergd5859e22011-01-25 01:19:58 +0200611
612 if (test_bit(HCI_INIT, &hdev->flags))
613 hci_setup(hdev);
614}
615
616static void hci_setup_link_policy(struct hci_dev *hdev)
617{
618 u16 link_policy = 0;
619
620 if (hdev->features[0] & LMP_RSWITCH)
621 link_policy |= HCI_LP_RSWITCH;
622 if (hdev->features[0] & LMP_HOLD)
623 link_policy |= HCI_LP_HOLD;
624 if (hdev->features[0] & LMP_SNIFF)
625 link_policy |= HCI_LP_SNIFF;
626 if (hdev->features[1] & LMP_PARK)
627 link_policy |= HCI_LP_PARK;
628
629 link_policy = cpu_to_le16(link_policy);
630 hci_send_cmd(hdev, HCI_OP_WRITE_DEF_LINK_POLICY,
631 sizeof(link_policy), &link_policy);
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200632}
633
634static void hci_cc_read_local_commands(struct hci_dev *hdev, struct sk_buff *skb)
635{
636 struct hci_rp_read_local_commands *rp = (void *) skb->data;
637
638 BT_DBG("%s status 0x%x", hdev->name, rp->status);
639
640 if (rp->status)
Johan Hedbergd5859e22011-01-25 01:19:58 +0200641 goto done;
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200642
643 memcpy(hdev->commands, rp->commands, sizeof(hdev->commands));
Johan Hedbergd5859e22011-01-25 01:19:58 +0200644
645 if (test_bit(HCI_INIT, &hdev->flags) && (hdev->commands[5] & 0x10))
646 hci_setup_link_policy(hdev);
647
648done:
649 hci_req_complete(hdev, HCI_OP_READ_LOCAL_COMMANDS, rp->status);
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200650}
651
652static void hci_cc_read_local_features(struct hci_dev *hdev, struct sk_buff *skb)
653{
654 struct hci_rp_read_local_features *rp = (void *) skb->data;
655
656 BT_DBG("%s status 0x%x", hdev->name, rp->status);
657
658 if (rp->status)
659 return;
660
661 memcpy(hdev->features, rp->features, 8);
662
663 /* Adjust default settings according to features
664 * supported by device. */
665
666 if (hdev->features[0] & LMP_3SLOT)
667 hdev->pkt_type |= (HCI_DM3 | HCI_DH3);
668
669 if (hdev->features[0] & LMP_5SLOT)
670 hdev->pkt_type |= (HCI_DM5 | HCI_DH5);
671
672 if (hdev->features[1] & LMP_HV2) {
673 hdev->pkt_type |= (HCI_HV2);
674 hdev->esco_type |= (ESCO_HV2);
675 }
676
677 if (hdev->features[1] & LMP_HV3) {
678 hdev->pkt_type |= (HCI_HV3);
679 hdev->esco_type |= (ESCO_HV3);
680 }
681
682 if (hdev->features[3] & LMP_ESCO)
683 hdev->esco_type |= (ESCO_EV3);
684
685 if (hdev->features[4] & LMP_EV4)
686 hdev->esco_type |= (ESCO_EV4);
687
688 if (hdev->features[4] & LMP_EV5)
689 hdev->esco_type |= (ESCO_EV5);
690
Marcel Holtmannefc76882009-02-06 09:13:37 +0100691 if (hdev->features[5] & LMP_EDR_ESCO_2M)
692 hdev->esco_type |= (ESCO_2EV3);
693
694 if (hdev->features[5] & LMP_EDR_ESCO_3M)
695 hdev->esco_type |= (ESCO_3EV3);
696
697 if (hdev->features[5] & LMP_EDR_3S_ESCO)
698 hdev->esco_type |= (ESCO_2EV5 | ESCO_3EV5);
699
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200700 BT_DBG("%s features 0x%.2x%.2x%.2x%.2x%.2x%.2x%.2x%.2x", hdev->name,
701 hdev->features[0], hdev->features[1],
702 hdev->features[2], hdev->features[3],
703 hdev->features[4], hdev->features[5],
704 hdev->features[6], hdev->features[7]);
705}
706
Andre Guedes971e3a42011-06-30 19:20:52 -0300707static void hci_cc_read_local_ext_features(struct hci_dev *hdev,
708 struct sk_buff *skb)
709{
710 struct hci_rp_read_local_ext_features *rp = (void *) skb->data;
711
712 BT_DBG("%s status 0x%x", hdev->name, rp->status);
713
714 if (rp->status)
715 return;
716
717 memcpy(hdev->extfeatures, rp->features, 8);
718
719 hci_req_complete(hdev, HCI_OP_READ_LOCAL_EXT_FEATURES, rp->status);
720}
721
Andrei Emeltchenko1e89cff2011-11-24 14:52:02 +0200722static void hci_cc_read_flow_control_mode(struct hci_dev *hdev,
723 struct sk_buff *skb)
724{
725 struct hci_rp_read_flow_control_mode *rp = (void *) skb->data;
726
727 BT_DBG("%s status 0x%x", hdev->name, rp->status);
728
729 if (rp->status)
730 return;
731
732 hdev->flow_ctl_mode = rp->mode;
733
734 hci_req_complete(hdev, HCI_OP_READ_FLOW_CONTROL_MODE, rp->status);
735}
736
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200737static void hci_cc_read_buffer_size(struct hci_dev *hdev, struct sk_buff *skb)
738{
739 struct hci_rp_read_buffer_size *rp = (void *) skb->data;
740
741 BT_DBG("%s status 0x%x", hdev->name, rp->status);
742
743 if (rp->status)
744 return;
745
746 hdev->acl_mtu = __le16_to_cpu(rp->acl_mtu);
747 hdev->sco_mtu = rp->sco_mtu;
748 hdev->acl_pkts = __le16_to_cpu(rp->acl_max_pkt);
749 hdev->sco_pkts = __le16_to_cpu(rp->sco_max_pkt);
750
751 if (test_bit(HCI_QUIRK_FIXUP_BUFFER_SIZE, &hdev->quirks)) {
752 hdev->sco_mtu = 64;
753 hdev->sco_pkts = 8;
754 }
755
756 hdev->acl_cnt = hdev->acl_pkts;
757 hdev->sco_cnt = hdev->sco_pkts;
758
759 BT_DBG("%s acl mtu %d:%d sco mtu %d:%d", hdev->name,
760 hdev->acl_mtu, hdev->acl_pkts,
761 hdev->sco_mtu, hdev->sco_pkts);
762}
763
764static void hci_cc_read_bd_addr(struct hci_dev *hdev, struct sk_buff *skb)
765{
766 struct hci_rp_read_bd_addr *rp = (void *) skb->data;
767
768 BT_DBG("%s status 0x%x", hdev->name, rp->status);
769
770 if (!rp->status)
771 bacpy(&hdev->bdaddr, &rp->bdaddr);
772
Johan Hedberg23bb5762010-12-21 23:01:27 +0200773 hci_req_complete(hdev, HCI_OP_READ_BD_ADDR, rp->status);
774}
775
776static void hci_cc_write_ca_timeout(struct hci_dev *hdev, struct sk_buff *skb)
777{
778 __u8 status = *((__u8 *) skb->data);
779
780 BT_DBG("%s status 0x%x", hdev->name, status);
781
782 hci_req_complete(hdev, HCI_OP_WRITE_CA_TIMEOUT, status);
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200783}
784
Andrei Emeltchenko928abaa2011-10-12 10:53:57 +0300785static void hci_cc_read_local_amp_info(struct hci_dev *hdev,
786 struct sk_buff *skb)
787{
788 struct hci_rp_read_local_amp_info *rp = (void *) skb->data;
789
790 BT_DBG("%s status 0x%x", hdev->name, rp->status);
791
792 if (rp->status)
793 return;
794
795 hdev->amp_status = rp->amp_status;
796 hdev->amp_total_bw = __le32_to_cpu(rp->total_bw);
797 hdev->amp_max_bw = __le32_to_cpu(rp->max_bw);
798 hdev->amp_min_latency = __le32_to_cpu(rp->min_latency);
799 hdev->amp_max_pdu = __le32_to_cpu(rp->max_pdu);
800 hdev->amp_type = rp->amp_type;
801 hdev->amp_pal_cap = __le16_to_cpu(rp->pal_cap);
802 hdev->amp_assoc_size = __le16_to_cpu(rp->max_assoc_size);
803 hdev->amp_be_flush_to = __le32_to_cpu(rp->be_flush_to);
804 hdev->amp_max_flush_to = __le32_to_cpu(rp->max_flush_to);
805
806 hci_req_complete(hdev, HCI_OP_READ_LOCAL_AMP_INFO, rp->status);
807}
808
Johan Hedbergb0916ea2011-01-10 13:44:55 +0200809static void hci_cc_delete_stored_link_key(struct hci_dev *hdev,
810 struct sk_buff *skb)
811{
812 __u8 status = *((__u8 *) skb->data);
813
814 BT_DBG("%s status 0x%x", hdev->name, status);
815
816 hci_req_complete(hdev, HCI_OP_DELETE_STORED_LINK_KEY, status);
817}
818
Johan Hedbergd5859e22011-01-25 01:19:58 +0200819static void hci_cc_set_event_mask(struct hci_dev *hdev, struct sk_buff *skb)
820{
821 __u8 status = *((__u8 *) skb->data);
822
823 BT_DBG("%s status 0x%x", hdev->name, status);
824
825 hci_req_complete(hdev, HCI_OP_SET_EVENT_MASK, status);
826}
827
828static void hci_cc_write_inquiry_mode(struct hci_dev *hdev,
829 struct sk_buff *skb)
830{
831 __u8 status = *((__u8 *) skb->data);
832
833 BT_DBG("%s status 0x%x", hdev->name, status);
834
835 hci_req_complete(hdev, HCI_OP_WRITE_INQUIRY_MODE, status);
836}
837
838static void hci_cc_read_inq_rsp_tx_power(struct hci_dev *hdev,
839 struct sk_buff *skb)
840{
841 __u8 status = *((__u8 *) skb->data);
842
843 BT_DBG("%s status 0x%x", hdev->name, status);
844
845 hci_req_complete(hdev, HCI_OP_READ_INQ_RSP_TX_POWER, status);
846}
847
848static void hci_cc_set_event_flt(struct hci_dev *hdev, struct sk_buff *skb)
849{
850 __u8 status = *((__u8 *) skb->data);
851
852 BT_DBG("%s status 0x%x", hdev->name, status);
853
854 hci_req_complete(hdev, HCI_OP_SET_EVENT_FLT, status);
855}
856
Johan Hedberg980e1a52011-01-22 06:10:07 +0200857static void hci_cc_pin_code_reply(struct hci_dev *hdev, struct sk_buff *skb)
858{
859 struct hci_rp_pin_code_reply *rp = (void *) skb->data;
860 struct hci_cp_pin_code_reply *cp;
861 struct hci_conn *conn;
862
863 BT_DBG("%s status 0x%x", hdev->name, rp->status);
864
Johan Hedberg56e5cb82011-11-08 20:40:16 +0200865 hci_dev_lock(hdev);
866
Johan Hedberg980e1a52011-01-22 06:10:07 +0200867 if (test_bit(HCI_MGMT, &hdev->flags))
Johan Hedberg744cf192011-11-08 20:40:14 +0200868 mgmt_pin_code_reply_complete(hdev, &rp->bdaddr, rp->status);
Johan Hedberg980e1a52011-01-22 06:10:07 +0200869
870 if (rp->status != 0)
Johan Hedberg56e5cb82011-11-08 20:40:16 +0200871 goto unlock;
Johan Hedberg980e1a52011-01-22 06:10:07 +0200872
873 cp = hci_sent_cmd_data(hdev, HCI_OP_PIN_CODE_REPLY);
874 if (!cp)
Johan Hedberg56e5cb82011-11-08 20:40:16 +0200875 goto unlock;
Johan Hedberg980e1a52011-01-22 06:10:07 +0200876
877 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &cp->bdaddr);
878 if (conn)
879 conn->pin_length = cp->pin_len;
Johan Hedberg56e5cb82011-11-08 20:40:16 +0200880
881unlock:
882 hci_dev_unlock(hdev);
Johan Hedberg980e1a52011-01-22 06:10:07 +0200883}
884
885static void hci_cc_pin_code_neg_reply(struct hci_dev *hdev, struct sk_buff *skb)
886{
887 struct hci_rp_pin_code_neg_reply *rp = (void *) skb->data;
888
889 BT_DBG("%s status 0x%x", hdev->name, rp->status);
890
Johan Hedberg56e5cb82011-11-08 20:40:16 +0200891 hci_dev_lock(hdev);
892
Johan Hedberg980e1a52011-01-22 06:10:07 +0200893 if (test_bit(HCI_MGMT, &hdev->flags))
Johan Hedberg744cf192011-11-08 20:40:14 +0200894 mgmt_pin_code_neg_reply_complete(hdev, &rp->bdaddr,
Johan Hedberg980e1a52011-01-22 06:10:07 +0200895 rp->status);
Johan Hedberg56e5cb82011-11-08 20:40:16 +0200896
897 hci_dev_unlock(hdev);
Johan Hedberg980e1a52011-01-22 06:10:07 +0200898}
Johan Hedberg56e5cb82011-11-08 20:40:16 +0200899
Ville Tervo6ed58ec2011-02-10 22:38:48 -0300900static void hci_cc_le_read_buffer_size(struct hci_dev *hdev,
901 struct sk_buff *skb)
902{
903 struct hci_rp_le_read_buffer_size *rp = (void *) skb->data;
904
905 BT_DBG("%s status 0x%x", hdev->name, rp->status);
906
907 if (rp->status)
908 return;
909
910 hdev->le_mtu = __le16_to_cpu(rp->le_mtu);
911 hdev->le_pkts = rp->le_max_pkt;
912
913 hdev->le_cnt = hdev->le_pkts;
914
915 BT_DBG("%s le mtu %d:%d", hdev->name, hdev->le_mtu, hdev->le_pkts);
916
917 hci_req_complete(hdev, HCI_OP_LE_READ_BUFFER_SIZE, rp->status);
918}
Johan Hedberg980e1a52011-01-22 06:10:07 +0200919
Johan Hedberga5c29682011-02-19 12:05:57 -0300920static void hci_cc_user_confirm_reply(struct hci_dev *hdev, struct sk_buff *skb)
921{
922 struct hci_rp_user_confirm_reply *rp = (void *) skb->data;
923
924 BT_DBG("%s status 0x%x", hdev->name, rp->status);
925
Johan Hedberg56e5cb82011-11-08 20:40:16 +0200926 hci_dev_lock(hdev);
927
Johan Hedberga5c29682011-02-19 12:05:57 -0300928 if (test_bit(HCI_MGMT, &hdev->flags))
Johan Hedberg744cf192011-11-08 20:40:14 +0200929 mgmt_user_confirm_reply_complete(hdev, &rp->bdaddr,
Johan Hedberga5c29682011-02-19 12:05:57 -0300930 rp->status);
Johan Hedberg56e5cb82011-11-08 20:40:16 +0200931
932 hci_dev_unlock(hdev);
Johan Hedberga5c29682011-02-19 12:05:57 -0300933}
934
935static void hci_cc_user_confirm_neg_reply(struct hci_dev *hdev,
936 struct sk_buff *skb)
937{
938 struct hci_rp_user_confirm_reply *rp = (void *) skb->data;
939
940 BT_DBG("%s status 0x%x", hdev->name, rp->status);
941
Johan Hedberg56e5cb82011-11-08 20:40:16 +0200942 hci_dev_lock(hdev);
943
Johan Hedberga5c29682011-02-19 12:05:57 -0300944 if (test_bit(HCI_MGMT, &hdev->flags))
Johan Hedberg744cf192011-11-08 20:40:14 +0200945 mgmt_user_confirm_neg_reply_complete(hdev, &rp->bdaddr,
Johan Hedberga5c29682011-02-19 12:05:57 -0300946 rp->status);
Johan Hedberg56e5cb82011-11-08 20:40:16 +0200947
948 hci_dev_unlock(hdev);
Johan Hedberga5c29682011-02-19 12:05:57 -0300949}
950
Brian Gix1143d452011-11-23 08:28:34 -0800951static void hci_cc_user_passkey_reply(struct hci_dev *hdev, struct sk_buff *skb)
952{
953 struct hci_rp_user_confirm_reply *rp = (void *) skb->data;
954
955 BT_DBG("%s status 0x%x", hdev->name, rp->status);
956
957 hci_dev_lock(hdev);
958
959 if (test_bit(HCI_MGMT, &hdev->flags))
960 mgmt_user_passkey_reply_complete(hdev, &rp->bdaddr,
961 rp->status);
962
963 hci_dev_unlock(hdev);
964}
965
966static void hci_cc_user_passkey_neg_reply(struct hci_dev *hdev,
967 struct sk_buff *skb)
968{
969 struct hci_rp_user_confirm_reply *rp = (void *) skb->data;
970
971 BT_DBG("%s status 0x%x", hdev->name, rp->status);
972
973 hci_dev_lock(hdev);
974
975 if (test_bit(HCI_MGMT, &hdev->flags))
976 mgmt_user_passkey_neg_reply_complete(hdev, &rp->bdaddr,
977 rp->status);
978
979 hci_dev_unlock(hdev);
980}
981
Szymon Jancc35938b2011-03-22 13:12:21 +0100982static void hci_cc_read_local_oob_data_reply(struct hci_dev *hdev,
983 struct sk_buff *skb)
984{
985 struct hci_rp_read_local_oob_data *rp = (void *) skb->data;
986
987 BT_DBG("%s status 0x%x", hdev->name, rp->status);
988
Johan Hedberg56e5cb82011-11-08 20:40:16 +0200989 hci_dev_lock(hdev);
Johan Hedberg744cf192011-11-08 20:40:14 +0200990 mgmt_read_local_oob_data_reply_complete(hdev, rp->hash,
Szymon Jancc35938b2011-03-22 13:12:21 +0100991 rp->randomizer, rp->status);
Johan Hedberg56e5cb82011-11-08 20:40:16 +0200992 hci_dev_unlock(hdev);
Szymon Jancc35938b2011-03-22 13:12:21 +0100993}
994
Andre Guedes07f7fa52011-12-02 21:13:31 +0900995static void hci_cc_le_set_scan_param(struct hci_dev *hdev, struct sk_buff *skb)
996{
997 __u8 status = *((__u8 *) skb->data);
998
999 BT_DBG("%s status 0x%x", hdev->name, status);
1000}
1001
Andre Guedeseb9d91f2011-05-26 16:23:52 -03001002static void hci_cc_le_set_scan_enable(struct hci_dev *hdev,
1003 struct sk_buff *skb)
1004{
1005 struct hci_cp_le_set_scan_enable *cp;
1006 __u8 status = *((__u8 *) skb->data);
1007
1008 BT_DBG("%s status 0x%x", hdev->name, status);
1009
1010 if (status)
1011 return;
1012
1013 cp = hci_sent_cmd_data(hdev, HCI_OP_LE_SET_SCAN_ENABLE);
1014 if (!cp)
1015 return;
1016
Andre Guedes35815082011-05-26 16:23:53 -03001017 if (cp->enable == 0x01) {
Andre Guedesd23264a2011-11-25 20:53:38 -03001018 set_bit(HCI_LE_SCAN, &hdev->dev_flags);
1019
Gustavo F. Padovandb323f22011-06-20 16:39:29 -03001020 cancel_delayed_work_sync(&hdev->adv_work);
Andre Guedesa8f13c82011-09-09 18:56:24 -03001021
1022 hci_dev_lock(hdev);
Andre Guedeseb9d91f2011-05-26 16:23:52 -03001023 hci_adv_entries_clear(hdev);
Andre Guedesa8f13c82011-09-09 18:56:24 -03001024 hci_dev_unlock(hdev);
Andre Guedes35815082011-05-26 16:23:53 -03001025 } else if (cp->enable == 0x00) {
Andre Guedesd23264a2011-11-25 20:53:38 -03001026 clear_bit(HCI_LE_SCAN, &hdev->dev_flags);
1027
Gustavo F. Padovandb323f22011-06-20 16:39:29 -03001028 cancel_delayed_work_sync(&hdev->adv_work);
1029 queue_delayed_work(hdev->workqueue, &hdev->adv_work,
1030 jiffies + ADV_CLEAR_TIMEOUT);
Andre Guedes35815082011-05-26 16:23:53 -03001031 }
Andre Guedeseb9d91f2011-05-26 16:23:52 -03001032}
1033
Vinicius Costa Gomesa7a595f2011-06-09 18:50:47 -03001034static void hci_cc_le_ltk_reply(struct hci_dev *hdev, struct sk_buff *skb)
1035{
1036 struct hci_rp_le_ltk_reply *rp = (void *) skb->data;
1037
1038 BT_DBG("%s status 0x%x", hdev->name, rp->status);
1039
1040 if (rp->status)
1041 return;
1042
1043 hci_req_complete(hdev, HCI_OP_LE_LTK_REPLY, rp->status);
1044}
1045
1046static void hci_cc_le_ltk_neg_reply(struct hci_dev *hdev, struct sk_buff *skb)
1047{
1048 struct hci_rp_le_ltk_neg_reply *rp = (void *) skb->data;
1049
1050 BT_DBG("%s status 0x%x", hdev->name, rp->status);
1051
1052 if (rp->status)
1053 return;
1054
1055 hci_req_complete(hdev, HCI_OP_LE_LTK_NEG_REPLY, rp->status);
1056}
1057
Andre Guedesf9b49302011-06-30 19:20:53 -03001058static inline void hci_cc_write_le_host_supported(struct hci_dev *hdev,
1059 struct sk_buff *skb)
1060{
1061 struct hci_cp_read_local_ext_features cp;
1062 __u8 status = *((__u8 *) skb->data);
1063
1064 BT_DBG("%s status 0x%x", hdev->name, status);
1065
1066 if (status)
1067 return;
1068
1069 cp.page = 0x01;
1070 hci_send_cmd(hdev, HCI_OP_READ_LOCAL_EXT_FEATURES, sizeof(cp), &cp);
1071}
1072
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001073static inline void hci_cs_inquiry(struct hci_dev *hdev, __u8 status)
1074{
1075 BT_DBG("%s status 0x%x", hdev->name, status);
1076
1077 if (status) {
Johan Hedberg23bb5762010-12-21 23:01:27 +02001078 hci_req_complete(hdev, HCI_OP_INQUIRY, status);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001079 hci_conn_check_pending(hdev);
Johan Hedberg56e5cb82011-11-08 20:40:16 +02001080 hci_dev_lock(hdev);
Johan Hedberg164a6e72011-11-01 17:06:44 +02001081 if (test_bit(HCI_MGMT, &hdev->flags))
Andre Guedes7a135102011-11-09 17:14:25 -03001082 mgmt_start_discovery_failed(hdev, status);
Johan Hedberg56e5cb82011-11-08 20:40:16 +02001083 hci_dev_unlock(hdev);
Johan Hedberg314b2382011-04-27 10:29:57 -04001084 return;
1085 }
1086
Andre Guedes89352e72011-11-04 14:16:53 -03001087 set_bit(HCI_INQUIRY, &hdev->flags);
1088
Johan Hedberg56e5cb82011-11-08 20:40:16 +02001089 hci_dev_lock(hdev);
Johan Hedberg744cf192011-11-08 20:40:14 +02001090 mgmt_discovering(hdev, 1);
Johan Hedberg56e5cb82011-11-08 20:40:16 +02001091 hci_dev_unlock(hdev);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001092}
1093
Linus Torvalds1da177e2005-04-16 15:20:36 -07001094static inline void hci_cs_create_conn(struct hci_dev *hdev, __u8 status)
1095{
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001096 struct hci_cp_create_conn *cp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001097 struct hci_conn *conn;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001098
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001099 BT_DBG("%s status 0x%x", hdev->name, status);
1100
1101 cp = hci_sent_cmd_data(hdev, HCI_OP_CREATE_CONN);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001102 if (!cp)
1103 return;
1104
1105 hci_dev_lock(hdev);
1106
1107 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &cp->bdaddr);
1108
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001109 BT_DBG("%s bdaddr %s conn %p", hdev->name, batostr(&cp->bdaddr), conn);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001110
1111 if (status) {
1112 if (conn && conn->state == BT_CONNECT) {
Marcel Holtmann4c67bc72006-10-15 17:30:56 +02001113 if (status != 0x0c || conn->attempt > 2) {
1114 conn->state = BT_CLOSED;
1115 hci_proto_connect_cfm(conn, status);
1116 hci_conn_del(conn);
1117 } else
1118 conn->state = BT_CONNECT2;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001119 }
1120 } else {
1121 if (!conn) {
1122 conn = hci_conn_add(hdev, ACL_LINK, &cp->bdaddr);
1123 if (conn) {
1124 conn->out = 1;
1125 conn->link_mode |= HCI_LM_MASTER;
1126 } else
Gustavo F. Padovan893ef972010-07-18 15:13:37 -03001127 BT_ERR("No memory for new connection");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001128 }
1129 }
1130
1131 hci_dev_unlock(hdev);
1132}
1133
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001134static void hci_cs_add_sco(struct hci_dev *hdev, __u8 status)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001135{
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001136 struct hci_cp_add_sco *cp;
1137 struct hci_conn *acl, *sco;
1138 __u16 handle;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001139
Marcel Holtmannb6a0dc82007-10-20 14:55:10 +02001140 BT_DBG("%s status 0x%x", hdev->name, status);
1141
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001142 if (!status)
1143 return;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001144
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001145 cp = hci_sent_cmd_data(hdev, HCI_OP_ADD_SCO);
1146 if (!cp)
1147 return;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001148
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001149 handle = __le16_to_cpu(cp->handle);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001150
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001151 BT_DBG("%s handle %d", hdev->name, handle);
Marcel Holtmann6bd57412006-11-18 22:14:22 +01001152
1153 hci_dev_lock(hdev);
1154
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001155 acl = hci_conn_hash_lookup_handle(hdev, handle);
Andrei Emeltchenko5a08ecc2011-01-11 17:20:20 +02001156 if (acl) {
1157 sco = acl->link;
1158 if (sco) {
1159 sco->state = BT_CLOSED;
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001160
Andrei Emeltchenko5a08ecc2011-01-11 17:20:20 +02001161 hci_proto_connect_cfm(sco, status);
1162 hci_conn_del(sco);
1163 }
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001164 }
Marcel Holtmann6bd57412006-11-18 22:14:22 +01001165
1166 hci_dev_unlock(hdev);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001167}
1168
Marcel Holtmannf8558552008-07-14 20:13:49 +02001169static void hci_cs_auth_requested(struct hci_dev *hdev, __u8 status)
1170{
1171 struct hci_cp_auth_requested *cp;
1172 struct hci_conn *conn;
1173
1174 BT_DBG("%s status 0x%x", hdev->name, status);
1175
1176 if (!status)
1177 return;
1178
1179 cp = hci_sent_cmd_data(hdev, HCI_OP_AUTH_REQUESTED);
1180 if (!cp)
1181 return;
1182
1183 hci_dev_lock(hdev);
1184
1185 conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(cp->handle));
1186 if (conn) {
1187 if (conn->state == BT_CONFIG) {
1188 hci_proto_connect_cfm(conn, status);
1189 hci_conn_put(conn);
1190 }
1191 }
1192
1193 hci_dev_unlock(hdev);
1194}
1195
1196static void hci_cs_set_conn_encrypt(struct hci_dev *hdev, __u8 status)
1197{
1198 struct hci_cp_set_conn_encrypt *cp;
1199 struct hci_conn *conn;
1200
1201 BT_DBG("%s status 0x%x", hdev->name, status);
1202
1203 if (!status)
1204 return;
1205
1206 cp = hci_sent_cmd_data(hdev, HCI_OP_SET_CONN_ENCRYPT);
1207 if (!cp)
1208 return;
1209
1210 hci_dev_lock(hdev);
1211
1212 conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(cp->handle));
1213 if (conn) {
1214 if (conn->state == BT_CONFIG) {
1215 hci_proto_connect_cfm(conn, status);
1216 hci_conn_put(conn);
1217 }
1218 }
1219
1220 hci_dev_unlock(hdev);
1221}
1222
Johan Hedberg127178d2010-11-18 22:22:29 +02001223static int hci_outgoing_auth_needed(struct hci_dev *hdev,
Szymon Janc138d22e2011-02-17 16:44:23 +01001224 struct hci_conn *conn)
Johan Hedberg392599b2010-11-18 22:22:28 +02001225{
Johan Hedberg392599b2010-11-18 22:22:28 +02001226 if (conn->state != BT_CONFIG || !conn->out)
1227 return 0;
1228
Johan Hedberg765c2a92011-01-19 12:06:52 +05301229 if (conn->pending_sec_level == BT_SECURITY_SDP)
Johan Hedberg392599b2010-11-18 22:22:28 +02001230 return 0;
1231
1232 /* Only request authentication for SSP connections or non-SSP
Vinicius Costa Gomese9bf2bf2011-09-02 14:51:20 -03001233 * devices with sec_level HIGH or if MITM protection is requested */
Johan Hedberg392599b2010-11-18 22:22:28 +02001234 if (!(hdev->ssp_mode > 0 && conn->ssp_mode > 0) &&
Vinicius Costa Gomese9bf2bf2011-09-02 14:51:20 -03001235 conn->pending_sec_level != BT_SECURITY_HIGH &&
1236 !(conn->auth_type & 0x01))
Johan Hedberg392599b2010-11-18 22:22:28 +02001237 return 0;
1238
Johan Hedberg392599b2010-11-18 22:22:28 +02001239 return 1;
1240}
1241
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001242static void hci_cs_remote_name_req(struct hci_dev *hdev, __u8 status)
1243{
Johan Hedberg127178d2010-11-18 22:22:29 +02001244 struct hci_cp_remote_name_req *cp;
1245 struct hci_conn *conn;
1246
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001247 BT_DBG("%s status 0x%x", hdev->name, status);
Johan Hedberg127178d2010-11-18 22:22:29 +02001248
1249 /* If successful wait for the name req complete event before
1250 * checking for the need to do authentication */
1251 if (!status)
1252 return;
1253
1254 cp = hci_sent_cmd_data(hdev, HCI_OP_REMOTE_NAME_REQ);
1255 if (!cp)
1256 return;
1257
1258 hci_dev_lock(hdev);
1259
1260 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &cp->bdaddr);
Johan Hedberg79c6c702011-04-28 11:28:55 -07001261 if (!conn)
1262 goto unlock;
1263
1264 if (!hci_outgoing_auth_needed(hdev, conn))
1265 goto unlock;
1266
1267 if (!test_and_set_bit(HCI_CONN_AUTH_PEND, &conn->pend)) {
Johan Hedberg127178d2010-11-18 22:22:29 +02001268 struct hci_cp_auth_requested cp;
1269 cp.handle = __cpu_to_le16(conn->handle);
1270 hci_send_cmd(hdev, HCI_OP_AUTH_REQUESTED, sizeof(cp), &cp);
1271 }
1272
Johan Hedberg79c6c702011-04-28 11:28:55 -07001273unlock:
Johan Hedberg127178d2010-11-18 22:22:29 +02001274 hci_dev_unlock(hdev);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001275}
1276
Marcel Holtmann769be972008-07-14 20:13:49 +02001277static void hci_cs_read_remote_features(struct hci_dev *hdev, __u8 status)
1278{
1279 struct hci_cp_read_remote_features *cp;
1280 struct hci_conn *conn;
1281
1282 BT_DBG("%s status 0x%x", hdev->name, status);
1283
1284 if (!status)
1285 return;
1286
1287 cp = hci_sent_cmd_data(hdev, HCI_OP_READ_REMOTE_FEATURES);
1288 if (!cp)
1289 return;
1290
1291 hci_dev_lock(hdev);
1292
1293 conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(cp->handle));
1294 if (conn) {
1295 if (conn->state == BT_CONFIG) {
Marcel Holtmann769be972008-07-14 20:13:49 +02001296 hci_proto_connect_cfm(conn, status);
1297 hci_conn_put(conn);
1298 }
1299 }
1300
1301 hci_dev_unlock(hdev);
1302}
1303
1304static void hci_cs_read_remote_ext_features(struct hci_dev *hdev, __u8 status)
1305{
1306 struct hci_cp_read_remote_ext_features *cp;
1307 struct hci_conn *conn;
1308
1309 BT_DBG("%s status 0x%x", hdev->name, status);
1310
1311 if (!status)
1312 return;
1313
1314 cp = hci_sent_cmd_data(hdev, HCI_OP_READ_REMOTE_EXT_FEATURES);
1315 if (!cp)
1316 return;
1317
1318 hci_dev_lock(hdev);
1319
1320 conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(cp->handle));
1321 if (conn) {
1322 if (conn->state == BT_CONFIG) {
Marcel Holtmann769be972008-07-14 20:13:49 +02001323 hci_proto_connect_cfm(conn, status);
1324 hci_conn_put(conn);
1325 }
1326 }
1327
1328 hci_dev_unlock(hdev);
1329}
1330
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001331static void hci_cs_setup_sync_conn(struct hci_dev *hdev, __u8 status)
1332{
Marcel Holtmannb6a0dc82007-10-20 14:55:10 +02001333 struct hci_cp_setup_sync_conn *cp;
1334 struct hci_conn *acl, *sco;
1335 __u16 handle;
1336
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001337 BT_DBG("%s status 0x%x", hdev->name, status);
Marcel Holtmannb6a0dc82007-10-20 14:55:10 +02001338
1339 if (!status)
1340 return;
1341
1342 cp = hci_sent_cmd_data(hdev, HCI_OP_SETUP_SYNC_CONN);
1343 if (!cp)
1344 return;
1345
1346 handle = __le16_to_cpu(cp->handle);
1347
1348 BT_DBG("%s handle %d", hdev->name, handle);
1349
1350 hci_dev_lock(hdev);
1351
1352 acl = hci_conn_hash_lookup_handle(hdev, handle);
Andrei Emeltchenko5a08ecc2011-01-11 17:20:20 +02001353 if (acl) {
1354 sco = acl->link;
1355 if (sco) {
1356 sco->state = BT_CLOSED;
Marcel Holtmannb6a0dc82007-10-20 14:55:10 +02001357
Andrei Emeltchenko5a08ecc2011-01-11 17:20:20 +02001358 hci_proto_connect_cfm(sco, status);
1359 hci_conn_del(sco);
1360 }
Marcel Holtmannb6a0dc82007-10-20 14:55:10 +02001361 }
1362
1363 hci_dev_unlock(hdev);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001364}
1365
1366static void hci_cs_sniff_mode(struct hci_dev *hdev, __u8 status)
1367{
1368 struct hci_cp_sniff_mode *cp;
1369 struct hci_conn *conn;
1370
1371 BT_DBG("%s status 0x%x", hdev->name, status);
1372
1373 if (!status)
1374 return;
1375
1376 cp = hci_sent_cmd_data(hdev, HCI_OP_SNIFF_MODE);
1377 if (!cp)
1378 return;
1379
1380 hci_dev_lock(hdev);
1381
1382 conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(cp->handle));
Marcel Holtmanne73439d2010-07-26 10:06:00 -04001383 if (conn) {
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001384 clear_bit(HCI_CONN_MODE_CHANGE_PEND, &conn->pend);
1385
Marcel Holtmanne73439d2010-07-26 10:06:00 -04001386 if (test_and_clear_bit(HCI_CONN_SCO_SETUP_PEND, &conn->pend))
1387 hci_sco_setup(conn, status);
1388 }
1389
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001390 hci_dev_unlock(hdev);
1391}
1392
1393static void hci_cs_exit_sniff_mode(struct hci_dev *hdev, __u8 status)
1394{
1395 struct hci_cp_exit_sniff_mode *cp;
1396 struct hci_conn *conn;
1397
1398 BT_DBG("%s status 0x%x", hdev->name, status);
1399
1400 if (!status)
1401 return;
1402
1403 cp = hci_sent_cmd_data(hdev, HCI_OP_EXIT_SNIFF_MODE);
1404 if (!cp)
1405 return;
1406
1407 hci_dev_lock(hdev);
1408
1409 conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(cp->handle));
Marcel Holtmanne73439d2010-07-26 10:06:00 -04001410 if (conn) {
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001411 clear_bit(HCI_CONN_MODE_CHANGE_PEND, &conn->pend);
1412
Marcel Holtmanne73439d2010-07-26 10:06:00 -04001413 if (test_and_clear_bit(HCI_CONN_SCO_SETUP_PEND, &conn->pend))
1414 hci_sco_setup(conn, status);
1415 }
1416
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001417 hci_dev_unlock(hdev);
1418}
1419
Ville Tervofcd89c02011-02-10 22:38:47 -03001420static void hci_cs_le_create_conn(struct hci_dev *hdev, __u8 status)
1421{
1422 struct hci_cp_le_create_conn *cp;
1423 struct hci_conn *conn;
1424
1425 BT_DBG("%s status 0x%x", hdev->name, status);
1426
1427 cp = hci_sent_cmd_data(hdev, HCI_OP_LE_CREATE_CONN);
1428 if (!cp)
1429 return;
1430
1431 hci_dev_lock(hdev);
1432
1433 conn = hci_conn_hash_lookup_ba(hdev, LE_LINK, &cp->peer_addr);
1434
1435 BT_DBG("%s bdaddr %s conn %p", hdev->name, batostr(&cp->peer_addr),
1436 conn);
1437
1438 if (status) {
1439 if (conn && conn->state == BT_CONNECT) {
1440 conn->state = BT_CLOSED;
1441 hci_proto_connect_cfm(conn, status);
1442 hci_conn_del(conn);
1443 }
1444 } else {
1445 if (!conn) {
1446 conn = hci_conn_add(hdev, LE_LINK, &cp->peer_addr);
Andre Guedes29b79882011-05-31 14:20:54 -03001447 if (conn) {
1448 conn->dst_type = cp->peer_addr_type;
Ville Tervofcd89c02011-02-10 22:38:47 -03001449 conn->out = 1;
Andre Guedes29b79882011-05-31 14:20:54 -03001450 } else {
Ville Tervofcd89c02011-02-10 22:38:47 -03001451 BT_ERR("No memory for new connection");
Andre Guedes29b79882011-05-31 14:20:54 -03001452 }
Ville Tervofcd89c02011-02-10 22:38:47 -03001453 }
1454 }
1455
1456 hci_dev_unlock(hdev);
1457}
1458
Vinicius Costa Gomesa7a595f2011-06-09 18:50:47 -03001459static void hci_cs_le_start_enc(struct hci_dev *hdev, u8 status)
1460{
1461 BT_DBG("%s status 0x%x", hdev->name, status);
1462}
1463
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001464static inline void hci_inquiry_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
1465{
1466 __u8 status = *((__u8 *) skb->data);
1467
1468 BT_DBG("%s status %d", hdev->name, status);
1469
Johan Hedberg23bb5762010-12-21 23:01:27 +02001470 hci_req_complete(hdev, HCI_OP_INQUIRY, status);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001471
1472 hci_conn_check_pending(hdev);
Andre Guedes89352e72011-11-04 14:16:53 -03001473
1474 if (!test_and_clear_bit(HCI_INQUIRY, &hdev->flags))
1475 return;
1476
Johan Hedberg56e5cb82011-11-08 20:40:16 +02001477 hci_dev_lock(hdev);
Johan Hedberg744cf192011-11-08 20:40:14 +02001478 mgmt_discovering(hdev, 0);
Johan Hedberg56e5cb82011-11-08 20:40:16 +02001479 hci_dev_unlock(hdev);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001480}
1481
Linus Torvalds1da177e2005-04-16 15:20:36 -07001482static inline void hci_inquiry_result_evt(struct hci_dev *hdev, struct sk_buff *skb)
1483{
Marcel Holtmann45bb4bf2005-08-09 20:27:49 -07001484 struct inquiry_data data;
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001485 struct inquiry_info *info = (void *) (skb->data + 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001486 int num_rsp = *((__u8 *) skb->data);
1487
1488 BT_DBG("%s num_rsp %d", hdev->name, num_rsp);
1489
Marcel Holtmann45bb4bf2005-08-09 20:27:49 -07001490 if (!num_rsp)
1491 return;
1492
Linus Torvalds1da177e2005-04-16 15:20:36 -07001493 hci_dev_lock(hdev);
Marcel Holtmann45bb4bf2005-08-09 20:27:49 -07001494
Johan Hedberge17acd42011-03-30 23:57:16 +03001495 for (; num_rsp; num_rsp--, info++) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001496 bacpy(&data.bdaddr, &info->bdaddr);
1497 data.pscan_rep_mode = info->pscan_rep_mode;
1498 data.pscan_period_mode = info->pscan_period_mode;
1499 data.pscan_mode = info->pscan_mode;
1500 memcpy(data.dev_class, info->dev_class, 3);
1501 data.clock_offset = info->clock_offset;
1502 data.rssi = 0x00;
Marcel Holtmann41a96212008-07-14 20:13:48 +02001503 data.ssp_mode = 0x00;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001504 hci_inquiry_cache_update(hdev, &data);
Johan Hedberg48264f02011-11-09 13:58:58 +02001505 mgmt_device_found(hdev, &info->bdaddr, ACL_LINK, 0x00,
Johan Hedberg4c659c32011-11-07 23:13:39 +02001506 info->dev_class, 0, NULL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001507 }
Marcel Holtmann45bb4bf2005-08-09 20:27:49 -07001508
Linus Torvalds1da177e2005-04-16 15:20:36 -07001509 hci_dev_unlock(hdev);
1510}
1511
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001512static inline void hci_conn_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001513{
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001514 struct hci_ev_conn_complete *ev = (void *) skb->data;
1515 struct hci_conn *conn;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001516
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001517 BT_DBG("%s", hdev->name);
Marcel Holtmann45bb4bf2005-08-09 20:27:49 -07001518
Linus Torvalds1da177e2005-04-16 15:20:36 -07001519 hci_dev_lock(hdev);
Marcel Holtmann45bb4bf2005-08-09 20:27:49 -07001520
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001521 conn = hci_conn_hash_lookup_ba(hdev, ev->link_type, &ev->bdaddr);
Marcel Holtmann94992372009-04-19 19:30:03 +02001522 if (!conn) {
1523 if (ev->link_type != SCO_LINK)
1524 goto unlock;
1525
1526 conn = hci_conn_hash_lookup_ba(hdev, ESCO_LINK, &ev->bdaddr);
1527 if (!conn)
1528 goto unlock;
1529
1530 conn->type = SCO_LINK;
1531 }
Marcel Holtmann45bb4bf2005-08-09 20:27:49 -07001532
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001533 if (!ev->status) {
1534 conn->handle = __le16_to_cpu(ev->handle);
Marcel Holtmann769be972008-07-14 20:13:49 +02001535
1536 if (conn->type == ACL_LINK) {
1537 conn->state = BT_CONFIG;
1538 hci_conn_hold(conn);
Marcel Holtmann052b30b2009-04-26 20:01:22 +02001539 conn->disc_timeout = HCI_DISCONN_TIMEOUT;
Johan Hedberg48264f02011-11-09 13:58:58 +02001540 mgmt_connected(hdev, &ev->bdaddr, conn->type,
1541 conn->dst_type);
Marcel Holtmann769be972008-07-14 20:13:49 +02001542 } else
1543 conn->state = BT_CONNECTED;
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001544
Marcel Holtmann9eba32b2009-08-22 14:19:26 -07001545 hci_conn_hold_device(conn);
Marcel Holtmann7d0db0a2008-07-14 20:13:51 +02001546 hci_conn_add_sysfs(conn);
1547
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001548 if (test_bit(HCI_AUTH, &hdev->flags))
1549 conn->link_mode |= HCI_LM_AUTH;
1550
1551 if (test_bit(HCI_ENCRYPT, &hdev->flags))
1552 conn->link_mode |= HCI_LM_ENCRYPT;
1553
1554 /* Get remote features */
1555 if (conn->type == ACL_LINK) {
1556 struct hci_cp_read_remote_features cp;
1557 cp.handle = ev->handle;
Marcel Holtmann769be972008-07-14 20:13:49 +02001558 hci_send_cmd(hdev, HCI_OP_READ_REMOTE_FEATURES,
1559 sizeof(cp), &cp);
Marcel Holtmann45bb4bf2005-08-09 20:27:49 -07001560 }
Marcel Holtmann45bb4bf2005-08-09 20:27:49 -07001561
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001562 /* Set packet type for incoming connection */
Andrei Emeltchenkod095c1e2011-12-01 14:33:27 +02001563 if (!conn->out && hdev->hci_ver < BLUETOOTH_VER_2_0) {
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001564 struct hci_cp_change_conn_ptype cp;
1565 cp.handle = ev->handle;
Marcel Holtmanna8746412008-07-14 20:13:46 +02001566 cp.pkt_type = cpu_to_le16(conn->pkt_type);
1567 hci_send_cmd(hdev, HCI_OP_CHANGE_CONN_PTYPE,
1568 sizeof(cp), &cp);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001569 }
Johan Hedberg17d5c042011-01-22 06:09:08 +02001570 } else {
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001571 conn->state = BT_CLOSED;
Johan Hedberg17d5c042011-01-22 06:09:08 +02001572 if (conn->type == ACL_LINK)
Johan Hedberg744cf192011-11-08 20:40:14 +02001573 mgmt_connect_failed(hdev, &ev->bdaddr, conn->type,
Johan Hedberg48264f02011-11-09 13:58:58 +02001574 conn->dst_type, ev->status);
Johan Hedberg17d5c042011-01-22 06:09:08 +02001575 }
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001576
Marcel Holtmanne73439d2010-07-26 10:06:00 -04001577 if (conn->type == ACL_LINK)
1578 hci_sco_setup(conn, ev->status);
Marcel Holtmann45bb4bf2005-08-09 20:27:49 -07001579
Marcel Holtmann769be972008-07-14 20:13:49 +02001580 if (ev->status) {
1581 hci_proto_connect_cfm(conn, ev->status);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001582 hci_conn_del(conn);
Marcel Holtmannc89b6e62009-01-15 21:57:03 +01001583 } else if (ev->link_type != ACL_LINK)
1584 hci_proto_connect_cfm(conn, ev->status);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001585
1586unlock:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001587 hci_dev_unlock(hdev);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001588
1589 hci_conn_check_pending(hdev);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001590}
1591
Linus Torvalds1da177e2005-04-16 15:20:36 -07001592static inline void hci_conn_request_evt(struct hci_dev *hdev, struct sk_buff *skb)
1593{
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001594 struct hci_ev_conn_request *ev = (void *) skb->data;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001595 int mask = hdev->link_mode;
1596
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001597 BT_DBG("%s bdaddr %s type 0x%x", hdev->name,
1598 batostr(&ev->bdaddr), ev->link_type);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001599
1600 mask |= hci_proto_connect_ind(hdev, &ev->bdaddr, ev->link_type);
1601
Szymon Janc138d22e2011-02-17 16:44:23 +01001602 if ((mask & HCI_LM_ACCEPT) &&
1603 !hci_blacklist_lookup(hdev, &ev->bdaddr)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001604 /* Connection accepted */
Marcel Holtmannc7bdd502008-07-14 20:13:47 +02001605 struct inquiry_entry *ie;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001606 struct hci_conn *conn;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001607
1608 hci_dev_lock(hdev);
Marcel Holtmannb6a0dc82007-10-20 14:55:10 +02001609
Andrei Emeltchenkocc11b9c2010-11-22 13:21:37 +02001610 ie = hci_inquiry_cache_lookup(hdev, &ev->bdaddr);
1611 if (ie)
Marcel Holtmannc7bdd502008-07-14 20:13:47 +02001612 memcpy(ie->data.dev_class, ev->dev_class, 3);
1613
Linus Torvalds1da177e2005-04-16 15:20:36 -07001614 conn = hci_conn_hash_lookup_ba(hdev, ev->link_type, &ev->bdaddr);
1615 if (!conn) {
Andrei Emeltchenkocc11b9c2010-11-22 13:21:37 +02001616 conn = hci_conn_add(hdev, ev->link_type, &ev->bdaddr);
1617 if (!conn) {
Gustavo F. Padovan893ef972010-07-18 15:13:37 -03001618 BT_ERR("No memory for new connection");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001619 hci_dev_unlock(hdev);
1620 return;
1621 }
1622 }
Marcel Holtmannb6a0dc82007-10-20 14:55:10 +02001623
Linus Torvalds1da177e2005-04-16 15:20:36 -07001624 memcpy(conn->dev_class, ev->dev_class, 3);
1625 conn->state = BT_CONNECT;
Marcel Holtmannb6a0dc82007-10-20 14:55:10 +02001626
Linus Torvalds1da177e2005-04-16 15:20:36 -07001627 hci_dev_unlock(hdev);
1628
Marcel Holtmannb6a0dc82007-10-20 14:55:10 +02001629 if (ev->link_type == ACL_LINK || !lmp_esco_capable(hdev)) {
1630 struct hci_cp_accept_conn_req cp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001631
Marcel Holtmannb6a0dc82007-10-20 14:55:10 +02001632 bacpy(&cp.bdaddr, &ev->bdaddr);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001633
Marcel Holtmannb6a0dc82007-10-20 14:55:10 +02001634 if (lmp_rswitch_capable(hdev) && (mask & HCI_LM_MASTER))
1635 cp.role = 0x00; /* Become master */
1636 else
1637 cp.role = 0x01; /* Remain slave */
1638
1639 hci_send_cmd(hdev, HCI_OP_ACCEPT_CONN_REQ,
1640 sizeof(cp), &cp);
1641 } else {
1642 struct hci_cp_accept_sync_conn_req cp;
1643
1644 bacpy(&cp.bdaddr, &ev->bdaddr);
Marcel Holtmanna8746412008-07-14 20:13:46 +02001645 cp.pkt_type = cpu_to_le16(conn->pkt_type);
Marcel Holtmannb6a0dc82007-10-20 14:55:10 +02001646
1647 cp.tx_bandwidth = cpu_to_le32(0x00001f40);
1648 cp.rx_bandwidth = cpu_to_le32(0x00001f40);
1649 cp.max_latency = cpu_to_le16(0xffff);
1650 cp.content_format = cpu_to_le16(hdev->voice_setting);
1651 cp.retrans_effort = 0xff;
1652
1653 hci_send_cmd(hdev, HCI_OP_ACCEPT_SYNC_CONN_REQ,
1654 sizeof(cp), &cp);
1655 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001656 } else {
1657 /* Connection rejected */
1658 struct hci_cp_reject_conn_req cp;
1659
1660 bacpy(&cp.bdaddr, &ev->bdaddr);
Andrei Emeltchenko9f5a0d72011-11-07 14:20:25 +02001661 cp.reason = HCI_ERROR_REJ_BAD_ADDR;
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001662 hci_send_cmd(hdev, HCI_OP_REJECT_CONN_REQ, sizeof(cp), &cp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001663 }
1664}
1665
Linus Torvalds1da177e2005-04-16 15:20:36 -07001666static inline void hci_disconn_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
1667{
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001668 struct hci_ev_disconn_complete *ev = (void *) skb->data;
Marcel Holtmann04837f62006-07-03 10:02:33 +02001669 struct hci_conn *conn;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001670
1671 BT_DBG("%s status %d", hdev->name, ev->status);
1672
Linus Torvalds1da177e2005-04-16 15:20:36 -07001673 hci_dev_lock(hdev);
1674
Marcel Holtmann04837f62006-07-03 10:02:33 +02001675 conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
Johan Hedbergf7520542011-01-20 12:34:39 +02001676 if (!conn)
1677 goto unlock;
Marcel Holtmann7d0db0a2008-07-14 20:13:51 +02001678
Johan Hedberg37d9ef72011-11-10 15:54:39 +02001679 if (ev->status == 0)
1680 conn->state = BT_CLOSED;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001681
Johan Hedberg37d9ef72011-11-10 15:54:39 +02001682 if (conn->type == ACL_LINK || conn->type == LE_LINK) {
1683 if (ev->status != 0)
1684 mgmt_disconnect_failed(hdev, &conn->dst, ev->status);
1685 else
1686 mgmt_disconnected(hdev, &conn->dst, conn->type,
Johan Hedberg48264f02011-11-09 13:58:58 +02001687 conn->dst_type);
Johan Hedberg37d9ef72011-11-10 15:54:39 +02001688 }
Johan Hedbergf7520542011-01-20 12:34:39 +02001689
Johan Hedberg37d9ef72011-11-10 15:54:39 +02001690 if (ev->status == 0) {
1691 hci_proto_disconn_cfm(conn, ev->reason);
1692 hci_conn_del(conn);
1693 }
Johan Hedbergf7520542011-01-20 12:34:39 +02001694
1695unlock:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001696 hci_dev_unlock(hdev);
1697}
1698
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001699static inline void hci_auth_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
1700{
1701 struct hci_ev_auth_complete *ev = (void *) skb->data;
1702 struct hci_conn *conn;
1703
1704 BT_DBG("%s status %d", hdev->name, ev->status);
1705
1706 hci_dev_lock(hdev);
1707
1708 conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
Waldemar Rymarkiewiczd7556e22011-05-31 15:49:26 +02001709 if (!conn)
1710 goto unlock;
1711
1712 if (!ev->status) {
1713 if (!(conn->ssp_mode > 0 && hdev->ssp_mode > 0) &&
1714 test_bit(HCI_CONN_REAUTH_PEND, &conn->pend)) {
1715 BT_INFO("re-auth of legacy device is not possible.");
Johan Hedberg2a611692011-02-19 12:06:00 -03001716 } else {
Waldemar Rymarkiewiczd7556e22011-05-31 15:49:26 +02001717 conn->link_mode |= HCI_LM_AUTH;
1718 conn->sec_level = conn->pending_sec_level;
Johan Hedberg2a611692011-02-19 12:06:00 -03001719 }
Waldemar Rymarkiewiczd7556e22011-05-31 15:49:26 +02001720 } else {
Johan Hedberg744cf192011-11-08 20:40:14 +02001721 mgmt_auth_failed(hdev, &conn->dst, ev->status);
Waldemar Rymarkiewiczd7556e22011-05-31 15:49:26 +02001722 }
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001723
Waldemar Rymarkiewiczd7556e22011-05-31 15:49:26 +02001724 clear_bit(HCI_CONN_AUTH_PEND, &conn->pend);
1725 clear_bit(HCI_CONN_REAUTH_PEND, &conn->pend);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001726
Waldemar Rymarkiewiczd7556e22011-05-31 15:49:26 +02001727 if (conn->state == BT_CONFIG) {
1728 if (!ev->status && hdev->ssp_mode > 0 && conn->ssp_mode > 0) {
1729 struct hci_cp_set_conn_encrypt cp;
1730 cp.handle = ev->handle;
1731 cp.encrypt = 0x01;
1732 hci_send_cmd(hdev, HCI_OP_SET_CONN_ENCRYPT, sizeof(cp),
1733 &cp);
Marcel Holtmann052b30b2009-04-26 20:01:22 +02001734 } else {
Waldemar Rymarkiewiczd7556e22011-05-31 15:49:26 +02001735 conn->state = BT_CONNECTED;
1736 hci_proto_connect_cfm(conn, ev->status);
Marcel Holtmann052b30b2009-04-26 20:01:22 +02001737 hci_conn_put(conn);
1738 }
Waldemar Rymarkiewiczd7556e22011-05-31 15:49:26 +02001739 } else {
1740 hci_auth_cfm(conn, ev->status);
Marcel Holtmann052b30b2009-04-26 20:01:22 +02001741
Waldemar Rymarkiewiczd7556e22011-05-31 15:49:26 +02001742 hci_conn_hold(conn);
1743 conn->disc_timeout = HCI_DISCONN_TIMEOUT;
1744 hci_conn_put(conn);
1745 }
1746
1747 if (test_bit(HCI_CONN_ENCRYPT_PEND, &conn->pend)) {
1748 if (!ev->status) {
1749 struct hci_cp_set_conn_encrypt cp;
1750 cp.handle = ev->handle;
1751 cp.encrypt = 0x01;
1752 hci_send_cmd(hdev, HCI_OP_SET_CONN_ENCRYPT, sizeof(cp),
1753 &cp);
1754 } else {
1755 clear_bit(HCI_CONN_ENCRYPT_PEND, &conn->pend);
1756 hci_encrypt_cfm(conn, ev->status, 0x00);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001757 }
1758 }
1759
Waldemar Rymarkiewiczd7556e22011-05-31 15:49:26 +02001760unlock:
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001761 hci_dev_unlock(hdev);
1762}
1763
1764static inline void hci_remote_name_evt(struct hci_dev *hdev, struct sk_buff *skb)
1765{
Johan Hedberg127178d2010-11-18 22:22:29 +02001766 struct hci_ev_remote_name *ev = (void *) skb->data;
1767 struct hci_conn *conn;
1768
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001769 BT_DBG("%s", hdev->name);
1770
1771 hci_conn_check_pending(hdev);
Johan Hedberg127178d2010-11-18 22:22:29 +02001772
1773 hci_dev_lock(hdev);
1774
Johan Hedberga88a9652011-03-30 13:18:12 +03001775 if (ev->status == 0 && test_bit(HCI_MGMT, &hdev->flags))
Johan Hedberg744cf192011-11-08 20:40:14 +02001776 mgmt_remote_name(hdev, &ev->bdaddr, ev->name);
Johan Hedberga88a9652011-03-30 13:18:12 +03001777
Johan Hedberg127178d2010-11-18 22:22:29 +02001778 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
Johan Hedberg79c6c702011-04-28 11:28:55 -07001779 if (!conn)
1780 goto unlock;
1781
1782 if (!hci_outgoing_auth_needed(hdev, conn))
1783 goto unlock;
1784
1785 if (!test_and_set_bit(HCI_CONN_AUTH_PEND, &conn->pend)) {
Johan Hedberg127178d2010-11-18 22:22:29 +02001786 struct hci_cp_auth_requested cp;
1787 cp.handle = __cpu_to_le16(conn->handle);
1788 hci_send_cmd(hdev, HCI_OP_AUTH_REQUESTED, sizeof(cp), &cp);
1789 }
1790
Johan Hedberg79c6c702011-04-28 11:28:55 -07001791unlock:
Johan Hedberg127178d2010-11-18 22:22:29 +02001792 hci_dev_unlock(hdev);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001793}
1794
1795static inline void hci_encrypt_change_evt(struct hci_dev *hdev, struct sk_buff *skb)
1796{
1797 struct hci_ev_encrypt_change *ev = (void *) skb->data;
1798 struct hci_conn *conn;
1799
1800 BT_DBG("%s status %d", hdev->name, ev->status);
1801
1802 hci_dev_lock(hdev);
1803
1804 conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
1805 if (conn) {
1806 if (!ev->status) {
Marcel Holtmannae293192008-07-14 20:13:45 +02001807 if (ev->encrypt) {
1808 /* Encryption implies authentication */
1809 conn->link_mode |= HCI_LM_AUTH;
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001810 conn->link_mode |= HCI_LM_ENCRYPT;
Vinicius Costa Gomesda85e5e2011-06-09 18:50:53 -03001811 conn->sec_level = conn->pending_sec_level;
Marcel Holtmannae293192008-07-14 20:13:45 +02001812 } else
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001813 conn->link_mode &= ~HCI_LM_ENCRYPT;
1814 }
1815
1816 clear_bit(HCI_CONN_ENCRYPT_PEND, &conn->pend);
1817
Marcel Holtmannf8558552008-07-14 20:13:49 +02001818 if (conn->state == BT_CONFIG) {
1819 if (!ev->status)
1820 conn->state = BT_CONNECTED;
1821
1822 hci_proto_connect_cfm(conn, ev->status);
1823 hci_conn_put(conn);
1824 } else
1825 hci_encrypt_cfm(conn, ev->status, ev->encrypt);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001826 }
1827
1828 hci_dev_unlock(hdev);
1829}
1830
1831static inline void hci_change_link_key_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
1832{
1833 struct hci_ev_change_link_key_complete *ev = (void *) skb->data;
1834 struct hci_conn *conn;
1835
1836 BT_DBG("%s status %d", hdev->name, ev->status);
1837
1838 hci_dev_lock(hdev);
1839
1840 conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
1841 if (conn) {
1842 if (!ev->status)
1843 conn->link_mode |= HCI_LM_SECURE;
1844
1845 clear_bit(HCI_CONN_AUTH_PEND, &conn->pend);
1846
1847 hci_key_change_cfm(conn, ev->status);
1848 }
1849
1850 hci_dev_unlock(hdev);
1851}
1852
1853static inline void hci_remote_features_evt(struct hci_dev *hdev, struct sk_buff *skb)
1854{
1855 struct hci_ev_remote_features *ev = (void *) skb->data;
1856 struct hci_conn *conn;
1857
1858 BT_DBG("%s status %d", hdev->name, ev->status);
1859
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001860 hci_dev_lock(hdev);
1861
1862 conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
Johan Hedbergccd556f2010-11-10 17:11:51 +02001863 if (!conn)
1864 goto unlock;
Marcel Holtmann769be972008-07-14 20:13:49 +02001865
Johan Hedbergccd556f2010-11-10 17:11:51 +02001866 if (!ev->status)
1867 memcpy(conn->features, ev->features, 8);
1868
1869 if (conn->state != BT_CONFIG)
1870 goto unlock;
1871
1872 if (!ev->status && lmp_ssp_capable(hdev) && lmp_ssp_capable(conn)) {
1873 struct hci_cp_read_remote_ext_features cp;
1874 cp.handle = ev->handle;
1875 cp.page = 0x01;
1876 hci_send_cmd(hdev, HCI_OP_READ_REMOTE_EXT_FEATURES,
Marcel Holtmann769be972008-07-14 20:13:49 +02001877 sizeof(cp), &cp);
Johan Hedberg392599b2010-11-18 22:22:28 +02001878 goto unlock;
1879 }
1880
Johan Hedberg127178d2010-11-18 22:22:29 +02001881 if (!ev->status) {
1882 struct hci_cp_remote_name_req cp;
1883 memset(&cp, 0, sizeof(cp));
1884 bacpy(&cp.bdaddr, &conn->dst);
1885 cp.pscan_rep_mode = 0x02;
1886 hci_send_cmd(hdev, HCI_OP_REMOTE_NAME_REQ, sizeof(cp), &cp);
1887 }
Johan Hedberg392599b2010-11-18 22:22:28 +02001888
Johan Hedberg127178d2010-11-18 22:22:29 +02001889 if (!hci_outgoing_auth_needed(hdev, conn)) {
Johan Hedbergccd556f2010-11-10 17:11:51 +02001890 conn->state = BT_CONNECTED;
1891 hci_proto_connect_cfm(conn, ev->status);
1892 hci_conn_put(conn);
Marcel Holtmann769be972008-07-14 20:13:49 +02001893 }
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001894
Johan Hedbergccd556f2010-11-10 17:11:51 +02001895unlock:
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001896 hci_dev_unlock(hdev);
1897}
1898
1899static inline void hci_remote_version_evt(struct hci_dev *hdev, struct sk_buff *skb)
1900{
1901 BT_DBG("%s", hdev->name);
1902}
1903
1904static inline void hci_qos_setup_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
1905{
1906 BT_DBG("%s", hdev->name);
1907}
1908
1909static inline void hci_cmd_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
1910{
1911 struct hci_ev_cmd_complete *ev = (void *) skb->data;
1912 __u16 opcode;
1913
1914 skb_pull(skb, sizeof(*ev));
1915
1916 opcode = __le16_to_cpu(ev->opcode);
1917
1918 switch (opcode) {
1919 case HCI_OP_INQUIRY_CANCEL:
1920 hci_cc_inquiry_cancel(hdev, skb);
1921 break;
1922
1923 case HCI_OP_EXIT_PERIODIC_INQ:
1924 hci_cc_exit_periodic_inq(hdev, skb);
1925 break;
1926
1927 case HCI_OP_REMOTE_NAME_REQ_CANCEL:
1928 hci_cc_remote_name_req_cancel(hdev, skb);
1929 break;
1930
1931 case HCI_OP_ROLE_DISCOVERY:
1932 hci_cc_role_discovery(hdev, skb);
1933 break;
1934
Marcel Holtmanne4e8e372008-07-14 20:13:47 +02001935 case HCI_OP_READ_LINK_POLICY:
1936 hci_cc_read_link_policy(hdev, skb);
1937 break;
1938
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001939 case HCI_OP_WRITE_LINK_POLICY:
1940 hci_cc_write_link_policy(hdev, skb);
1941 break;
1942
Marcel Holtmanne4e8e372008-07-14 20:13:47 +02001943 case HCI_OP_READ_DEF_LINK_POLICY:
1944 hci_cc_read_def_link_policy(hdev, skb);
1945 break;
1946
1947 case HCI_OP_WRITE_DEF_LINK_POLICY:
1948 hci_cc_write_def_link_policy(hdev, skb);
1949 break;
1950
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001951 case HCI_OP_RESET:
1952 hci_cc_reset(hdev, skb);
1953 break;
1954
1955 case HCI_OP_WRITE_LOCAL_NAME:
1956 hci_cc_write_local_name(hdev, skb);
1957 break;
1958
1959 case HCI_OP_READ_LOCAL_NAME:
1960 hci_cc_read_local_name(hdev, skb);
1961 break;
1962
1963 case HCI_OP_WRITE_AUTH_ENABLE:
1964 hci_cc_write_auth_enable(hdev, skb);
1965 break;
1966
1967 case HCI_OP_WRITE_ENCRYPT_MODE:
1968 hci_cc_write_encrypt_mode(hdev, skb);
1969 break;
1970
1971 case HCI_OP_WRITE_SCAN_ENABLE:
1972 hci_cc_write_scan_enable(hdev, skb);
1973 break;
1974
1975 case HCI_OP_READ_CLASS_OF_DEV:
1976 hci_cc_read_class_of_dev(hdev, skb);
1977 break;
1978
1979 case HCI_OP_WRITE_CLASS_OF_DEV:
1980 hci_cc_write_class_of_dev(hdev, skb);
1981 break;
1982
1983 case HCI_OP_READ_VOICE_SETTING:
1984 hci_cc_read_voice_setting(hdev, skb);
1985 break;
1986
1987 case HCI_OP_WRITE_VOICE_SETTING:
1988 hci_cc_write_voice_setting(hdev, skb);
1989 break;
1990
1991 case HCI_OP_HOST_BUFFER_SIZE:
1992 hci_cc_host_buffer_size(hdev, skb);
1993 break;
1994
Marcel Holtmann333140b2008-07-14 20:13:48 +02001995 case HCI_OP_READ_SSP_MODE:
1996 hci_cc_read_ssp_mode(hdev, skb);
1997 break;
1998
1999 case HCI_OP_WRITE_SSP_MODE:
2000 hci_cc_write_ssp_mode(hdev, skb);
2001 break;
2002
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002003 case HCI_OP_READ_LOCAL_VERSION:
2004 hci_cc_read_local_version(hdev, skb);
2005 break;
2006
2007 case HCI_OP_READ_LOCAL_COMMANDS:
2008 hci_cc_read_local_commands(hdev, skb);
2009 break;
2010
2011 case HCI_OP_READ_LOCAL_FEATURES:
2012 hci_cc_read_local_features(hdev, skb);
2013 break;
2014
Andre Guedes971e3a42011-06-30 19:20:52 -03002015 case HCI_OP_READ_LOCAL_EXT_FEATURES:
2016 hci_cc_read_local_ext_features(hdev, skb);
2017 break;
2018
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002019 case HCI_OP_READ_BUFFER_SIZE:
2020 hci_cc_read_buffer_size(hdev, skb);
2021 break;
2022
2023 case HCI_OP_READ_BD_ADDR:
2024 hci_cc_read_bd_addr(hdev, skb);
2025 break;
2026
Johan Hedberg23bb5762010-12-21 23:01:27 +02002027 case HCI_OP_WRITE_CA_TIMEOUT:
2028 hci_cc_write_ca_timeout(hdev, skb);
2029 break;
2030
Andrei Emeltchenko1e89cff2011-11-24 14:52:02 +02002031 case HCI_OP_READ_FLOW_CONTROL_MODE:
2032 hci_cc_read_flow_control_mode(hdev, skb);
2033 break;
2034
Andrei Emeltchenko928abaa2011-10-12 10:53:57 +03002035 case HCI_OP_READ_LOCAL_AMP_INFO:
2036 hci_cc_read_local_amp_info(hdev, skb);
2037 break;
2038
Johan Hedbergb0916ea2011-01-10 13:44:55 +02002039 case HCI_OP_DELETE_STORED_LINK_KEY:
2040 hci_cc_delete_stored_link_key(hdev, skb);
2041 break;
2042
Johan Hedbergd5859e22011-01-25 01:19:58 +02002043 case HCI_OP_SET_EVENT_MASK:
2044 hci_cc_set_event_mask(hdev, skb);
2045 break;
2046
2047 case HCI_OP_WRITE_INQUIRY_MODE:
2048 hci_cc_write_inquiry_mode(hdev, skb);
2049 break;
2050
2051 case HCI_OP_READ_INQ_RSP_TX_POWER:
2052 hci_cc_read_inq_rsp_tx_power(hdev, skb);
2053 break;
2054
2055 case HCI_OP_SET_EVENT_FLT:
2056 hci_cc_set_event_flt(hdev, skb);
2057 break;
2058
Johan Hedberg980e1a52011-01-22 06:10:07 +02002059 case HCI_OP_PIN_CODE_REPLY:
2060 hci_cc_pin_code_reply(hdev, skb);
2061 break;
2062
2063 case HCI_OP_PIN_CODE_NEG_REPLY:
2064 hci_cc_pin_code_neg_reply(hdev, skb);
2065 break;
2066
Szymon Jancc35938b2011-03-22 13:12:21 +01002067 case HCI_OP_READ_LOCAL_OOB_DATA:
2068 hci_cc_read_local_oob_data_reply(hdev, skb);
2069 break;
2070
Ville Tervo6ed58ec2011-02-10 22:38:48 -03002071 case HCI_OP_LE_READ_BUFFER_SIZE:
2072 hci_cc_le_read_buffer_size(hdev, skb);
2073 break;
2074
Johan Hedberga5c29682011-02-19 12:05:57 -03002075 case HCI_OP_USER_CONFIRM_REPLY:
2076 hci_cc_user_confirm_reply(hdev, skb);
2077 break;
2078
2079 case HCI_OP_USER_CONFIRM_NEG_REPLY:
2080 hci_cc_user_confirm_neg_reply(hdev, skb);
2081 break;
2082
Brian Gix1143d452011-11-23 08:28:34 -08002083 case HCI_OP_USER_PASSKEY_REPLY:
2084 hci_cc_user_passkey_reply(hdev, skb);
2085 break;
2086
2087 case HCI_OP_USER_PASSKEY_NEG_REPLY:
2088 hci_cc_user_passkey_neg_reply(hdev, skb);
Andre Guedes07f7fa52011-12-02 21:13:31 +09002089
2090 case HCI_OP_LE_SET_SCAN_PARAM:
2091 hci_cc_le_set_scan_param(hdev, skb);
Brian Gix1143d452011-11-23 08:28:34 -08002092 break;
2093
Andre Guedeseb9d91f2011-05-26 16:23:52 -03002094 case HCI_OP_LE_SET_SCAN_ENABLE:
2095 hci_cc_le_set_scan_enable(hdev, skb);
2096 break;
2097
Vinicius Costa Gomesa7a595f2011-06-09 18:50:47 -03002098 case HCI_OP_LE_LTK_REPLY:
2099 hci_cc_le_ltk_reply(hdev, skb);
2100 break;
2101
2102 case HCI_OP_LE_LTK_NEG_REPLY:
2103 hci_cc_le_ltk_neg_reply(hdev, skb);
2104 break;
2105
Andre Guedesf9b49302011-06-30 19:20:53 -03002106 case HCI_OP_WRITE_LE_HOST_SUPPORTED:
2107 hci_cc_write_le_host_supported(hdev, skb);
2108 break;
2109
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002110 default:
2111 BT_DBG("%s opcode 0x%x", hdev->name, opcode);
2112 break;
2113 }
2114
Ville Tervo6bd32322011-02-16 16:32:41 +02002115 if (ev->opcode != HCI_OP_NOP)
2116 del_timer(&hdev->cmd_timer);
2117
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002118 if (ev->ncmd) {
2119 atomic_set(&hdev->cmd_cnt, 1);
2120 if (!skb_queue_empty(&hdev->cmd_q))
Marcel Holtmannc78ae282009-11-18 01:02:54 +01002121 tasklet_schedule(&hdev->cmd_task);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002122 }
2123}
2124
2125static inline void hci_cmd_status_evt(struct hci_dev *hdev, struct sk_buff *skb)
2126{
2127 struct hci_ev_cmd_status *ev = (void *) skb->data;
2128 __u16 opcode;
2129
2130 skb_pull(skb, sizeof(*ev));
2131
2132 opcode = __le16_to_cpu(ev->opcode);
2133
2134 switch (opcode) {
2135 case HCI_OP_INQUIRY:
2136 hci_cs_inquiry(hdev, ev->status);
2137 break;
2138
2139 case HCI_OP_CREATE_CONN:
2140 hci_cs_create_conn(hdev, ev->status);
2141 break;
2142
2143 case HCI_OP_ADD_SCO:
2144 hci_cs_add_sco(hdev, ev->status);
2145 break;
2146
Marcel Holtmannf8558552008-07-14 20:13:49 +02002147 case HCI_OP_AUTH_REQUESTED:
2148 hci_cs_auth_requested(hdev, ev->status);
2149 break;
2150
2151 case HCI_OP_SET_CONN_ENCRYPT:
2152 hci_cs_set_conn_encrypt(hdev, ev->status);
2153 break;
2154
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002155 case HCI_OP_REMOTE_NAME_REQ:
2156 hci_cs_remote_name_req(hdev, ev->status);
2157 break;
2158
Marcel Holtmann769be972008-07-14 20:13:49 +02002159 case HCI_OP_READ_REMOTE_FEATURES:
2160 hci_cs_read_remote_features(hdev, ev->status);
2161 break;
2162
2163 case HCI_OP_READ_REMOTE_EXT_FEATURES:
2164 hci_cs_read_remote_ext_features(hdev, ev->status);
2165 break;
2166
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002167 case HCI_OP_SETUP_SYNC_CONN:
2168 hci_cs_setup_sync_conn(hdev, ev->status);
2169 break;
2170
2171 case HCI_OP_SNIFF_MODE:
2172 hci_cs_sniff_mode(hdev, ev->status);
2173 break;
2174
2175 case HCI_OP_EXIT_SNIFF_MODE:
2176 hci_cs_exit_sniff_mode(hdev, ev->status);
2177 break;
2178
Johan Hedberg8962ee72011-01-20 12:40:27 +02002179 case HCI_OP_DISCONNECT:
2180 if (ev->status != 0)
Johan Hedberg37d9ef72011-11-10 15:54:39 +02002181 mgmt_disconnect_failed(hdev, NULL, ev->status);
Johan Hedberg8962ee72011-01-20 12:40:27 +02002182 break;
2183
Ville Tervofcd89c02011-02-10 22:38:47 -03002184 case HCI_OP_LE_CREATE_CONN:
2185 hci_cs_le_create_conn(hdev, ev->status);
2186 break;
2187
Vinicius Costa Gomesa7a595f2011-06-09 18:50:47 -03002188 case HCI_OP_LE_START_ENC:
2189 hci_cs_le_start_enc(hdev, ev->status);
2190 break;
2191
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002192 default:
2193 BT_DBG("%s opcode 0x%x", hdev->name, opcode);
2194 break;
2195 }
2196
Ville Tervo6bd32322011-02-16 16:32:41 +02002197 if (ev->opcode != HCI_OP_NOP)
2198 del_timer(&hdev->cmd_timer);
2199
Gustavo F. Padovan10572132011-03-16 15:36:29 -03002200 if (ev->ncmd && !test_bit(HCI_RESET, &hdev->flags)) {
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002201 atomic_set(&hdev->cmd_cnt, 1);
2202 if (!skb_queue_empty(&hdev->cmd_q))
Marcel Holtmannc78ae282009-11-18 01:02:54 +01002203 tasklet_schedule(&hdev->cmd_task);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002204 }
2205}
2206
2207static inline void hci_role_change_evt(struct hci_dev *hdev, struct sk_buff *skb)
2208{
2209 struct hci_ev_role_change *ev = (void *) skb->data;
2210 struct hci_conn *conn;
2211
2212 BT_DBG("%s status %d", hdev->name, ev->status);
2213
2214 hci_dev_lock(hdev);
2215
2216 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
2217 if (conn) {
2218 if (!ev->status) {
2219 if (ev->role)
2220 conn->link_mode &= ~HCI_LM_MASTER;
2221 else
2222 conn->link_mode |= HCI_LM_MASTER;
2223 }
2224
2225 clear_bit(HCI_CONN_RSWITCH_PEND, &conn->pend);
2226
2227 hci_role_switch_cfm(conn, ev->status, ev->role);
2228 }
2229
2230 hci_dev_unlock(hdev);
2231}
2232
Linus Torvalds1da177e2005-04-16 15:20:36 -07002233static inline void hci_num_comp_pkts_evt(struct hci_dev *hdev, struct sk_buff *skb)
2234{
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002235 struct hci_ev_num_comp_pkts *ev = (void *) skb->data;
Marcel Holtmann1ebb9252005-11-08 09:57:21 -08002236 __le16 *ptr;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002237 int i;
2238
2239 skb_pull(skb, sizeof(*ev));
2240
2241 BT_DBG("%s num_hndl %d", hdev->name, ev->num_hndl);
2242
2243 if (skb->len < ev->num_hndl * 4) {
2244 BT_DBG("%s bad parameters", hdev->name);
2245 return;
2246 }
2247
2248 tasklet_disable(&hdev->tx_task);
2249
Marcel Holtmann1ebb9252005-11-08 09:57:21 -08002250 for (i = 0, ptr = (__le16 *) skb->data; i < ev->num_hndl; i++) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002251 struct hci_conn *conn;
2252 __u16 handle, count;
2253
Harvey Harrison83985312008-05-02 16:25:46 -07002254 handle = get_unaligned_le16(ptr++);
2255 count = get_unaligned_le16(ptr++);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002256
2257 conn = hci_conn_hash_lookup_handle(hdev, handle);
2258 if (conn) {
2259 conn->sent -= count;
2260
Marcel Holtmann5b7f9902007-07-11 09:51:55 +02002261 if (conn->type == ACL_LINK) {
Andrei Emeltchenko70f230202010-12-01 16:58:25 +02002262 hdev->acl_cnt += count;
2263 if (hdev->acl_cnt > hdev->acl_pkts)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002264 hdev->acl_cnt = hdev->acl_pkts;
Ville Tervo6ed58ec2011-02-10 22:38:48 -03002265 } else if (conn->type == LE_LINK) {
2266 if (hdev->le_pkts) {
2267 hdev->le_cnt += count;
2268 if (hdev->le_cnt > hdev->le_pkts)
2269 hdev->le_cnt = hdev->le_pkts;
2270 } else {
2271 hdev->acl_cnt += count;
2272 if (hdev->acl_cnt > hdev->acl_pkts)
2273 hdev->acl_cnt = hdev->acl_pkts;
2274 }
Marcel Holtmann5b7f9902007-07-11 09:51:55 +02002275 } else {
Andrei Emeltchenko70f230202010-12-01 16:58:25 +02002276 hdev->sco_cnt += count;
2277 if (hdev->sco_cnt > hdev->sco_pkts)
Marcel Holtmann5b7f9902007-07-11 09:51:55 +02002278 hdev->sco_cnt = hdev->sco_pkts;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002279 }
2280 }
2281 }
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002282
Marcel Holtmannc78ae282009-11-18 01:02:54 +01002283 tasklet_schedule(&hdev->tx_task);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002284
2285 tasklet_enable(&hdev->tx_task);
2286}
2287
Marcel Holtmann04837f62006-07-03 10:02:33 +02002288static inline void hci_mode_change_evt(struct hci_dev *hdev, struct sk_buff *skb)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002289{
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002290 struct hci_ev_mode_change *ev = (void *) skb->data;
Marcel Holtmann04837f62006-07-03 10:02:33 +02002291 struct hci_conn *conn;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002292
2293 BT_DBG("%s status %d", hdev->name, ev->status);
2294
2295 hci_dev_lock(hdev);
2296
Marcel Holtmann04837f62006-07-03 10:02:33 +02002297 conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
2298 if (conn) {
2299 conn->mode = ev->mode;
2300 conn->interval = __le16_to_cpu(ev->interval);
2301
2302 if (!test_and_clear_bit(HCI_CONN_MODE_CHANGE_PEND, &conn->pend)) {
2303 if (conn->mode == HCI_CM_ACTIVE)
2304 conn->power_save = 1;
2305 else
2306 conn->power_save = 0;
2307 }
Marcel Holtmanne73439d2010-07-26 10:06:00 -04002308
2309 if (test_and_clear_bit(HCI_CONN_SCO_SETUP_PEND, &conn->pend))
2310 hci_sco_setup(conn, ev->status);
Marcel Holtmann04837f62006-07-03 10:02:33 +02002311 }
2312
2313 hci_dev_unlock(hdev);
2314}
2315
Linus Torvalds1da177e2005-04-16 15:20:36 -07002316static inline void hci_pin_code_request_evt(struct hci_dev *hdev, struct sk_buff *skb)
2317{
Marcel Holtmann052b30b2009-04-26 20:01:22 +02002318 struct hci_ev_pin_code_req *ev = (void *) skb->data;
2319 struct hci_conn *conn;
2320
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002321 BT_DBG("%s", hdev->name);
Marcel Holtmann052b30b2009-04-26 20:01:22 +02002322
2323 hci_dev_lock(hdev);
2324
2325 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
Waldemar Rymarkiewiczb6f98042011-09-23 10:01:30 +02002326 if (!conn)
2327 goto unlock;
2328
2329 if (conn->state == BT_CONNECTED) {
Marcel Holtmann052b30b2009-04-26 20:01:22 +02002330 hci_conn_hold(conn);
2331 conn->disc_timeout = HCI_PAIRING_TIMEOUT;
2332 hci_conn_put(conn);
2333 }
2334
Johan Hedberg03b555e2011-01-04 15:40:05 +02002335 if (!test_bit(HCI_PAIRABLE, &hdev->flags))
2336 hci_send_cmd(hdev, HCI_OP_PIN_CODE_NEG_REPLY,
2337 sizeof(ev->bdaddr), &ev->bdaddr);
Johan Hedberg582fbe92011-04-28 11:28:58 -07002338 else if (test_bit(HCI_MGMT, &hdev->flags)) {
Waldemar Rymarkiewicza770bb52011-04-28 12:07:59 +02002339 u8 secure;
2340
2341 if (conn->pending_sec_level == BT_SECURITY_HIGH)
2342 secure = 1;
2343 else
2344 secure = 0;
2345
Johan Hedberg744cf192011-11-08 20:40:14 +02002346 mgmt_pin_code_request(hdev, &ev->bdaddr, secure);
Waldemar Rymarkiewicza770bb52011-04-28 12:07:59 +02002347 }
Johan Hedberg980e1a52011-01-22 06:10:07 +02002348
Waldemar Rymarkiewiczb6f98042011-09-23 10:01:30 +02002349unlock:
Marcel Holtmann052b30b2009-04-26 20:01:22 +02002350 hci_dev_unlock(hdev);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002351}
2352
Linus Torvalds1da177e2005-04-16 15:20:36 -07002353static inline void hci_link_key_request_evt(struct hci_dev *hdev, struct sk_buff *skb)
2354{
Johan Hedberg55ed8ca2011-01-17 14:41:05 +02002355 struct hci_ev_link_key_req *ev = (void *) skb->data;
2356 struct hci_cp_link_key_reply cp;
2357 struct hci_conn *conn;
2358 struct link_key *key;
2359
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002360 BT_DBG("%s", hdev->name);
Johan Hedberg55ed8ca2011-01-17 14:41:05 +02002361
2362 if (!test_bit(HCI_LINK_KEYS, &hdev->flags))
2363 return;
2364
2365 hci_dev_lock(hdev);
2366
2367 key = hci_find_link_key(hdev, &ev->bdaddr);
2368 if (!key) {
2369 BT_DBG("%s link key not found for %s", hdev->name,
2370 batostr(&ev->bdaddr));
2371 goto not_found;
2372 }
2373
2374 BT_DBG("%s found key type %u for %s", hdev->name, key->type,
2375 batostr(&ev->bdaddr));
2376
Waldemar Rymarkiewiczb6020ba2011-04-28 12:07:53 +02002377 if (!test_bit(HCI_DEBUG_KEYS, &hdev->flags) &&
2378 key->type == HCI_LK_DEBUG_COMBINATION) {
Johan Hedberg55ed8ca2011-01-17 14:41:05 +02002379 BT_DBG("%s ignoring debug key", hdev->name);
2380 goto not_found;
2381 }
2382
2383 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
Waldemar Rymarkiewicz60b83f52011-04-28 12:07:56 +02002384 if (conn) {
2385 if (key->type == HCI_LK_UNAUTH_COMBINATION &&
2386 conn->auth_type != 0xff &&
2387 (conn->auth_type & 0x01)) {
2388 BT_DBG("%s ignoring unauthenticated key", hdev->name);
2389 goto not_found;
2390 }
Johan Hedberg55ed8ca2011-01-17 14:41:05 +02002391
Waldemar Rymarkiewicz60b83f52011-04-28 12:07:56 +02002392 if (key->type == HCI_LK_COMBINATION && key->pin_len < 16 &&
2393 conn->pending_sec_level == BT_SECURITY_HIGH) {
2394 BT_DBG("%s ignoring key unauthenticated for high \
2395 security", hdev->name);
2396 goto not_found;
2397 }
2398
2399 conn->key_type = key->type;
2400 conn->pin_length = key->pin_len;
Johan Hedberg55ed8ca2011-01-17 14:41:05 +02002401 }
2402
2403 bacpy(&cp.bdaddr, &ev->bdaddr);
2404 memcpy(cp.link_key, key->val, 16);
2405
2406 hci_send_cmd(hdev, HCI_OP_LINK_KEY_REPLY, sizeof(cp), &cp);
2407
2408 hci_dev_unlock(hdev);
2409
2410 return;
2411
2412not_found:
2413 hci_send_cmd(hdev, HCI_OP_LINK_KEY_NEG_REPLY, 6, &ev->bdaddr);
2414 hci_dev_unlock(hdev);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002415}
2416
Linus Torvalds1da177e2005-04-16 15:20:36 -07002417static inline void hci_link_key_notify_evt(struct hci_dev *hdev, struct sk_buff *skb)
2418{
Marcel Holtmann052b30b2009-04-26 20:01:22 +02002419 struct hci_ev_link_key_notify *ev = (void *) skb->data;
2420 struct hci_conn *conn;
Johan Hedberg55ed8ca2011-01-17 14:41:05 +02002421 u8 pin_len = 0;
Marcel Holtmann052b30b2009-04-26 20:01:22 +02002422
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002423 BT_DBG("%s", hdev->name);
Marcel Holtmann052b30b2009-04-26 20:01:22 +02002424
2425 hci_dev_lock(hdev);
2426
2427 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
2428 if (conn) {
2429 hci_conn_hold(conn);
2430 conn->disc_timeout = HCI_DISCONN_TIMEOUT;
Johan Hedberg980e1a52011-01-22 06:10:07 +02002431 pin_len = conn->pin_length;
Waldemar Rymarkiewicz13d39312011-04-28 12:07:55 +02002432
2433 if (ev->key_type != HCI_LK_CHANGED_COMBINATION)
2434 conn->key_type = ev->key_type;
2435
Marcel Holtmann052b30b2009-04-26 20:01:22 +02002436 hci_conn_put(conn);
2437 }
2438
Johan Hedberg55ed8ca2011-01-17 14:41:05 +02002439 if (test_bit(HCI_LINK_KEYS, &hdev->flags))
Johan Hedbergd25e28a2011-04-28 11:28:59 -07002440 hci_add_link_key(hdev, conn, 1, &ev->bdaddr, ev->link_key,
Johan Hedberg55ed8ca2011-01-17 14:41:05 +02002441 ev->key_type, pin_len);
2442
Marcel Holtmann052b30b2009-04-26 20:01:22 +02002443 hci_dev_unlock(hdev);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002444}
2445
Marcel Holtmann04837f62006-07-03 10:02:33 +02002446static inline void hci_clock_offset_evt(struct hci_dev *hdev, struct sk_buff *skb)
2447{
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002448 struct hci_ev_clock_offset *ev = (void *) skb->data;
Marcel Holtmann04837f62006-07-03 10:02:33 +02002449 struct hci_conn *conn;
2450
2451 BT_DBG("%s status %d", hdev->name, ev->status);
2452
2453 hci_dev_lock(hdev);
2454
2455 conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
Linus Torvalds1da177e2005-04-16 15:20:36 -07002456 if (conn && !ev->status) {
2457 struct inquiry_entry *ie;
2458
Andrei Emeltchenkocc11b9c2010-11-22 13:21:37 +02002459 ie = hci_inquiry_cache_lookup(hdev, &conn->dst);
2460 if (ie) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002461 ie->data.clock_offset = ev->clock_offset;
2462 ie->timestamp = jiffies;
2463 }
2464 }
2465
2466 hci_dev_unlock(hdev);
2467}
2468
Marcel Holtmanna8746412008-07-14 20:13:46 +02002469static inline void hci_pkt_type_change_evt(struct hci_dev *hdev, struct sk_buff *skb)
2470{
2471 struct hci_ev_pkt_type_change *ev = (void *) skb->data;
2472 struct hci_conn *conn;
2473
2474 BT_DBG("%s status %d", hdev->name, ev->status);
2475
2476 hci_dev_lock(hdev);
2477
2478 conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
2479 if (conn && !ev->status)
2480 conn->pkt_type = __le16_to_cpu(ev->pkt_type);
2481
2482 hci_dev_unlock(hdev);
2483}
2484
Marcel Holtmann85a1e932005-08-09 20:28:02 -07002485static inline void hci_pscan_rep_mode_evt(struct hci_dev *hdev, struct sk_buff *skb)
2486{
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002487 struct hci_ev_pscan_rep_mode *ev = (void *) skb->data;
Marcel Holtmann85a1e932005-08-09 20:28:02 -07002488 struct inquiry_entry *ie;
2489
2490 BT_DBG("%s", hdev->name);
2491
2492 hci_dev_lock(hdev);
2493
Andrei Emeltchenkocc11b9c2010-11-22 13:21:37 +02002494 ie = hci_inquiry_cache_lookup(hdev, &ev->bdaddr);
2495 if (ie) {
Marcel Holtmann85a1e932005-08-09 20:28:02 -07002496 ie->data.pscan_rep_mode = ev->pscan_rep_mode;
2497 ie->timestamp = jiffies;
2498 }
2499
2500 hci_dev_unlock(hdev);
2501}
2502
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002503static inline void hci_inquiry_result_with_rssi_evt(struct hci_dev *hdev, struct sk_buff *skb)
2504{
2505 struct inquiry_data data;
2506 int num_rsp = *((__u8 *) skb->data);
2507
2508 BT_DBG("%s num_rsp %d", hdev->name, num_rsp);
2509
2510 if (!num_rsp)
2511 return;
2512
2513 hci_dev_lock(hdev);
2514
2515 if ((skb->len - 1) / num_rsp != sizeof(struct inquiry_info_with_rssi)) {
Szymon Janc138d22e2011-02-17 16:44:23 +01002516 struct inquiry_info_with_rssi_and_pscan_mode *info;
2517 info = (void *) (skb->data + 1);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002518
Johan Hedberge17acd42011-03-30 23:57:16 +03002519 for (; num_rsp; num_rsp--, info++) {
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002520 bacpy(&data.bdaddr, &info->bdaddr);
2521 data.pscan_rep_mode = info->pscan_rep_mode;
2522 data.pscan_period_mode = info->pscan_period_mode;
2523 data.pscan_mode = info->pscan_mode;
2524 memcpy(data.dev_class, info->dev_class, 3);
2525 data.clock_offset = info->clock_offset;
2526 data.rssi = info->rssi;
Marcel Holtmann41a96212008-07-14 20:13:48 +02002527 data.ssp_mode = 0x00;
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002528 hci_inquiry_cache_update(hdev, &data);
Johan Hedberg48264f02011-11-09 13:58:58 +02002529 mgmt_device_found(hdev, &info->bdaddr, ACL_LINK, 0x00,
Johan Hedberge17acd42011-03-30 23:57:16 +03002530 info->dev_class, info->rssi,
2531 NULL);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002532 }
2533 } else {
2534 struct inquiry_info_with_rssi *info = (void *) (skb->data + 1);
2535
Johan Hedberge17acd42011-03-30 23:57:16 +03002536 for (; num_rsp; num_rsp--, info++) {
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002537 bacpy(&data.bdaddr, &info->bdaddr);
2538 data.pscan_rep_mode = info->pscan_rep_mode;
2539 data.pscan_period_mode = info->pscan_period_mode;
2540 data.pscan_mode = 0x00;
2541 memcpy(data.dev_class, info->dev_class, 3);
2542 data.clock_offset = info->clock_offset;
2543 data.rssi = info->rssi;
Marcel Holtmann41a96212008-07-14 20:13:48 +02002544 data.ssp_mode = 0x00;
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002545 hci_inquiry_cache_update(hdev, &data);
Johan Hedberg48264f02011-11-09 13:58:58 +02002546 mgmt_device_found(hdev, &info->bdaddr, ACL_LINK, 0x00,
Johan Hedberge17acd42011-03-30 23:57:16 +03002547 info->dev_class, info->rssi,
2548 NULL);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002549 }
2550 }
2551
2552 hci_dev_unlock(hdev);
2553}
2554
2555static inline void hci_remote_ext_features_evt(struct hci_dev *hdev, struct sk_buff *skb)
2556{
Marcel Holtmann41a96212008-07-14 20:13:48 +02002557 struct hci_ev_remote_ext_features *ev = (void *) skb->data;
2558 struct hci_conn *conn;
2559
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002560 BT_DBG("%s", hdev->name);
Marcel Holtmann41a96212008-07-14 20:13:48 +02002561
Marcel Holtmann41a96212008-07-14 20:13:48 +02002562 hci_dev_lock(hdev);
2563
2564 conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
Johan Hedbergccd556f2010-11-10 17:11:51 +02002565 if (!conn)
2566 goto unlock;
Marcel Holtmann41a96212008-07-14 20:13:48 +02002567
Johan Hedbergccd556f2010-11-10 17:11:51 +02002568 if (!ev->status && ev->page == 0x01) {
2569 struct inquiry_entry *ie;
Marcel Holtmann41a96212008-07-14 20:13:48 +02002570
Andrei Emeltchenkocc11b9c2010-11-22 13:21:37 +02002571 ie = hci_inquiry_cache_lookup(hdev, &conn->dst);
2572 if (ie)
Johan Hedbergccd556f2010-11-10 17:11:51 +02002573 ie->data.ssp_mode = (ev->features[0] & 0x01);
Marcel Holtmann769be972008-07-14 20:13:49 +02002574
Johan Hedbergccd556f2010-11-10 17:11:51 +02002575 conn->ssp_mode = (ev->features[0] & 0x01);
Marcel Holtmann41a96212008-07-14 20:13:48 +02002576 }
2577
Johan Hedbergccd556f2010-11-10 17:11:51 +02002578 if (conn->state != BT_CONFIG)
2579 goto unlock;
2580
Johan Hedberg127178d2010-11-18 22:22:29 +02002581 if (!ev->status) {
2582 struct hci_cp_remote_name_req cp;
2583 memset(&cp, 0, sizeof(cp));
2584 bacpy(&cp.bdaddr, &conn->dst);
2585 cp.pscan_rep_mode = 0x02;
2586 hci_send_cmd(hdev, HCI_OP_REMOTE_NAME_REQ, sizeof(cp), &cp);
2587 }
Johan Hedberg392599b2010-11-18 22:22:28 +02002588
Johan Hedberg127178d2010-11-18 22:22:29 +02002589 if (!hci_outgoing_auth_needed(hdev, conn)) {
Johan Hedbergccd556f2010-11-10 17:11:51 +02002590 conn->state = BT_CONNECTED;
2591 hci_proto_connect_cfm(conn, ev->status);
2592 hci_conn_put(conn);
2593 }
2594
2595unlock:
Marcel Holtmann41a96212008-07-14 20:13:48 +02002596 hci_dev_unlock(hdev);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002597}
2598
2599static inline void hci_sync_conn_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
2600{
Marcel Holtmannb6a0dc82007-10-20 14:55:10 +02002601 struct hci_ev_sync_conn_complete *ev = (void *) skb->data;
2602 struct hci_conn *conn;
2603
2604 BT_DBG("%s status %d", hdev->name, ev->status);
2605
2606 hci_dev_lock(hdev);
2607
2608 conn = hci_conn_hash_lookup_ba(hdev, ev->link_type, &ev->bdaddr);
Marcel Holtmann9dc0a3a2008-07-14 20:13:46 +02002609 if (!conn) {
2610 if (ev->link_type == ESCO_LINK)
2611 goto unlock;
2612
2613 conn = hci_conn_hash_lookup_ba(hdev, ESCO_LINK, &ev->bdaddr);
2614 if (!conn)
2615 goto unlock;
2616
2617 conn->type = SCO_LINK;
2618 }
Marcel Holtmannb6a0dc82007-10-20 14:55:10 +02002619
Marcel Holtmann732547f2009-04-19 19:14:14 +02002620 switch (ev->status) {
2621 case 0x00:
Marcel Holtmannb6a0dc82007-10-20 14:55:10 +02002622 conn->handle = __le16_to_cpu(ev->handle);
2623 conn->state = BT_CONNECTED;
Marcel Holtmann7d0db0a2008-07-14 20:13:51 +02002624
Marcel Holtmann9eba32b2009-08-22 14:19:26 -07002625 hci_conn_hold_device(conn);
Marcel Holtmann7d0db0a2008-07-14 20:13:51 +02002626 hci_conn_add_sysfs(conn);
Marcel Holtmann732547f2009-04-19 19:14:14 +02002627 break;
2628
Stephen Coe705e5712010-02-16 11:29:44 -05002629 case 0x11: /* Unsupported Feature or Parameter Value */
Marcel Holtmann732547f2009-04-19 19:14:14 +02002630 case 0x1c: /* SCO interval rejected */
Nick Pelly1038a002010-02-03 11:42:26 -08002631 case 0x1a: /* Unsupported Remote Feature */
Marcel Holtmann732547f2009-04-19 19:14:14 +02002632 case 0x1f: /* Unspecified error */
2633 if (conn->out && conn->attempt < 2) {
2634 conn->pkt_type = (hdev->esco_type & SCO_ESCO_MASK) |
2635 (hdev->esco_type & EDR_ESCO_MASK);
2636 hci_setup_sync(conn, conn->link->handle);
2637 goto unlock;
2638 }
2639 /* fall through */
2640
2641 default:
Marcel Holtmannb6a0dc82007-10-20 14:55:10 +02002642 conn->state = BT_CLOSED;
Marcel Holtmann732547f2009-04-19 19:14:14 +02002643 break;
2644 }
Marcel Holtmannb6a0dc82007-10-20 14:55:10 +02002645
2646 hci_proto_connect_cfm(conn, ev->status);
2647 if (ev->status)
2648 hci_conn_del(conn);
2649
2650unlock:
2651 hci_dev_unlock(hdev);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002652}
2653
2654static inline void hci_sync_conn_changed_evt(struct hci_dev *hdev, struct sk_buff *skb)
2655{
2656 BT_DBG("%s", hdev->name);
2657}
2658
Marcel Holtmann04837f62006-07-03 10:02:33 +02002659static inline void hci_sniff_subrate_evt(struct hci_dev *hdev, struct sk_buff *skb)
2660{
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002661 struct hci_ev_sniff_subrate *ev = (void *) skb->data;
Marcel Holtmann04837f62006-07-03 10:02:33 +02002662
2663 BT_DBG("%s status %d", hdev->name, ev->status);
Marcel Holtmann04837f62006-07-03 10:02:33 +02002664}
2665
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002666static inline void hci_extended_inquiry_result_evt(struct hci_dev *hdev, struct sk_buff *skb)
2667{
2668 struct inquiry_data data;
2669 struct extended_inquiry_info *info = (void *) (skb->data + 1);
2670 int num_rsp = *((__u8 *) skb->data);
2671
2672 BT_DBG("%s num_rsp %d", hdev->name, num_rsp);
2673
2674 if (!num_rsp)
2675 return;
2676
2677 hci_dev_lock(hdev);
2678
Johan Hedberge17acd42011-03-30 23:57:16 +03002679 for (; num_rsp; num_rsp--, info++) {
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002680 bacpy(&data.bdaddr, &info->bdaddr);
Szymon Janc138d22e2011-02-17 16:44:23 +01002681 data.pscan_rep_mode = info->pscan_rep_mode;
2682 data.pscan_period_mode = info->pscan_period_mode;
2683 data.pscan_mode = 0x00;
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002684 memcpy(data.dev_class, info->dev_class, 3);
Szymon Janc138d22e2011-02-17 16:44:23 +01002685 data.clock_offset = info->clock_offset;
2686 data.rssi = info->rssi;
Marcel Holtmann41a96212008-07-14 20:13:48 +02002687 data.ssp_mode = 0x01;
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002688 hci_inquiry_cache_update(hdev, &data);
Johan Hedberg48264f02011-11-09 13:58:58 +02002689 mgmt_device_found(hdev, &info->bdaddr, ACL_LINK, 0x00,
Johan Hedberg4c659c32011-11-07 23:13:39 +02002690 info->dev_class, info->rssi, info->data);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002691 }
2692
2693 hci_dev_unlock(hdev);
2694}
2695
Johan Hedberg17fa4b92011-01-25 13:28:33 +02002696static inline u8 hci_get_auth_req(struct hci_conn *conn)
2697{
2698 /* If remote requests dedicated bonding follow that lead */
2699 if (conn->remote_auth == 0x02 || conn->remote_auth == 0x03) {
2700 /* If both remote and local IO capabilities allow MITM
2701 * protection then require it, otherwise don't */
2702 if (conn->remote_cap == 0x03 || conn->io_capability == 0x03)
2703 return 0x02;
2704 else
2705 return 0x03;
2706 }
2707
2708 /* If remote requests no-bonding follow that lead */
2709 if (conn->remote_auth == 0x00 || conn->remote_auth == 0x01)
Waldemar Rymarkiewicz58797bf2011-04-28 12:07:58 +02002710 return conn->remote_auth | (conn->auth_type & 0x01);
Johan Hedberg17fa4b92011-01-25 13:28:33 +02002711
2712 return conn->auth_type;
2713}
2714
Marcel Holtmann04936842008-07-14 20:13:48 +02002715static inline void hci_io_capa_request_evt(struct hci_dev *hdev, struct sk_buff *skb)
2716{
2717 struct hci_ev_io_capa_request *ev = (void *) skb->data;
2718 struct hci_conn *conn;
2719
2720 BT_DBG("%s", hdev->name);
2721
2722 hci_dev_lock(hdev);
2723
2724 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
Johan Hedberg03b555e2011-01-04 15:40:05 +02002725 if (!conn)
2726 goto unlock;
Marcel Holtmann04936842008-07-14 20:13:48 +02002727
Johan Hedberg03b555e2011-01-04 15:40:05 +02002728 hci_conn_hold(conn);
2729
2730 if (!test_bit(HCI_MGMT, &hdev->flags))
2731 goto unlock;
2732
2733 if (test_bit(HCI_PAIRABLE, &hdev->flags) ||
2734 (conn->remote_auth & ~0x01) == HCI_AT_NO_BONDING) {
Johan Hedberg17fa4b92011-01-25 13:28:33 +02002735 struct hci_cp_io_capability_reply cp;
2736
2737 bacpy(&cp.bdaddr, &ev->bdaddr);
2738 cp.capability = conn->io_capability;
Johan Hedberg7cbc9bd2011-04-28 11:29:04 -07002739 conn->auth_type = hci_get_auth_req(conn);
2740 cp.authentication = conn->auth_type;
Johan Hedberg17fa4b92011-01-25 13:28:33 +02002741
Szymon Jancce85ee12011-03-22 13:12:23 +01002742 if ((conn->out == 0x01 || conn->remote_oob == 0x01) &&
2743 hci_find_remote_oob_data(hdev, &conn->dst))
2744 cp.oob_data = 0x01;
2745 else
2746 cp.oob_data = 0x00;
2747
Johan Hedberg17fa4b92011-01-25 13:28:33 +02002748 hci_send_cmd(hdev, HCI_OP_IO_CAPABILITY_REPLY,
2749 sizeof(cp), &cp);
Johan Hedberg03b555e2011-01-04 15:40:05 +02002750 } else {
2751 struct hci_cp_io_capability_neg_reply cp;
2752
2753 bacpy(&cp.bdaddr, &ev->bdaddr);
Andrei Emeltchenko9f5a0d72011-11-07 14:20:25 +02002754 cp.reason = HCI_ERROR_PAIRING_NOT_ALLOWED;
Johan Hedberg03b555e2011-01-04 15:40:05 +02002755
2756 hci_send_cmd(hdev, HCI_OP_IO_CAPABILITY_NEG_REPLY,
2757 sizeof(cp), &cp);
2758 }
2759
2760unlock:
2761 hci_dev_unlock(hdev);
2762}
2763
2764static inline void hci_io_capa_reply_evt(struct hci_dev *hdev, struct sk_buff *skb)
2765{
2766 struct hci_ev_io_capa_reply *ev = (void *) skb->data;
2767 struct hci_conn *conn;
2768
2769 BT_DBG("%s", hdev->name);
2770
2771 hci_dev_lock(hdev);
2772
2773 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
2774 if (!conn)
2775 goto unlock;
2776
Johan Hedberg03b555e2011-01-04 15:40:05 +02002777 conn->remote_cap = ev->capability;
2778 conn->remote_oob = ev->oob_data;
2779 conn->remote_auth = ev->authentication;
2780
2781unlock:
Marcel Holtmann04936842008-07-14 20:13:48 +02002782 hci_dev_unlock(hdev);
2783}
2784
Johan Hedberga5c29682011-02-19 12:05:57 -03002785static inline void hci_user_confirm_request_evt(struct hci_dev *hdev,
2786 struct sk_buff *skb)
2787{
2788 struct hci_ev_user_confirm_req *ev = (void *) skb->data;
Johan Hedberg55bc1a32011-04-28 11:28:56 -07002789 int loc_mitm, rem_mitm, confirm_hint = 0;
Johan Hedberg7a828902011-04-28 11:28:53 -07002790 struct hci_conn *conn;
Johan Hedberga5c29682011-02-19 12:05:57 -03002791
2792 BT_DBG("%s", hdev->name);
2793
2794 hci_dev_lock(hdev);
2795
Johan Hedberg7a828902011-04-28 11:28:53 -07002796 if (!test_bit(HCI_MGMT, &hdev->flags))
2797 goto unlock;
Johan Hedberga5c29682011-02-19 12:05:57 -03002798
Johan Hedberg7a828902011-04-28 11:28:53 -07002799 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
2800 if (!conn)
2801 goto unlock;
2802
2803 loc_mitm = (conn->auth_type & 0x01);
2804 rem_mitm = (conn->remote_auth & 0x01);
2805
2806 /* If we require MITM but the remote device can't provide that
2807 * (it has NoInputNoOutput) then reject the confirmation
2808 * request. The only exception is when we're dedicated bonding
2809 * initiators (connect_cfm_cb set) since then we always have the MITM
2810 * bit set. */
2811 if (!conn->connect_cfm_cb && loc_mitm && conn->remote_cap == 0x03) {
2812 BT_DBG("Rejecting request: remote device can't provide MITM");
2813 hci_send_cmd(hdev, HCI_OP_USER_CONFIRM_NEG_REPLY,
2814 sizeof(ev->bdaddr), &ev->bdaddr);
2815 goto unlock;
2816 }
2817
2818 /* If no side requires MITM protection; auto-accept */
2819 if ((!loc_mitm || conn->remote_cap == 0x03) &&
2820 (!rem_mitm || conn->io_capability == 0x03)) {
Johan Hedberg55bc1a32011-04-28 11:28:56 -07002821
2822 /* If we're not the initiators request authorization to
2823 * proceed from user space (mgmt_user_confirm with
2824 * confirm_hint set to 1). */
2825 if (!test_bit(HCI_CONN_AUTH_PEND, &conn->pend)) {
2826 BT_DBG("Confirming auto-accept as acceptor");
2827 confirm_hint = 1;
2828 goto confirm;
2829 }
2830
Johan Hedberg9f616562011-04-28 11:28:54 -07002831 BT_DBG("Auto-accept of user confirmation with %ums delay",
2832 hdev->auto_accept_delay);
2833
2834 if (hdev->auto_accept_delay > 0) {
2835 int delay = msecs_to_jiffies(hdev->auto_accept_delay);
2836 mod_timer(&conn->auto_accept_timer, jiffies + delay);
2837 goto unlock;
2838 }
2839
Johan Hedberg7a828902011-04-28 11:28:53 -07002840 hci_send_cmd(hdev, HCI_OP_USER_CONFIRM_REPLY,
2841 sizeof(ev->bdaddr), &ev->bdaddr);
2842 goto unlock;
2843 }
2844
Johan Hedberg55bc1a32011-04-28 11:28:56 -07002845confirm:
Johan Hedberg744cf192011-11-08 20:40:14 +02002846 mgmt_user_confirm_request(hdev, &ev->bdaddr, ev->passkey,
Johan Hedberg55bc1a32011-04-28 11:28:56 -07002847 confirm_hint);
Johan Hedberg7a828902011-04-28 11:28:53 -07002848
2849unlock:
Johan Hedberga5c29682011-02-19 12:05:57 -03002850 hci_dev_unlock(hdev);
2851}
2852
Brian Gix1143d452011-11-23 08:28:34 -08002853static inline void hci_user_passkey_request_evt(struct hci_dev *hdev,
2854 struct sk_buff *skb)
2855{
2856 struct hci_ev_user_passkey_req *ev = (void *) skb->data;
2857
2858 BT_DBG("%s", hdev->name);
2859
2860 hci_dev_lock(hdev);
2861
2862 if (test_bit(HCI_MGMT, &hdev->flags))
2863 mgmt_user_passkey_request(hdev, &ev->bdaddr);
2864
2865 hci_dev_unlock(hdev);
2866}
2867
Marcel Holtmann04936842008-07-14 20:13:48 +02002868static inline void hci_simple_pair_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
2869{
2870 struct hci_ev_simple_pair_complete *ev = (void *) skb->data;
2871 struct hci_conn *conn;
2872
2873 BT_DBG("%s", hdev->name);
2874
2875 hci_dev_lock(hdev);
2876
2877 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
Johan Hedberg2a611692011-02-19 12:06:00 -03002878 if (!conn)
2879 goto unlock;
Marcel Holtmann04936842008-07-14 20:13:48 +02002880
Johan Hedberg2a611692011-02-19 12:06:00 -03002881 /* To avoid duplicate auth_failed events to user space we check
2882 * the HCI_CONN_AUTH_PEND flag which will be set if we
2883 * initiated the authentication. A traditional auth_complete
2884 * event gets always produced as initiator and is also mapped to
2885 * the mgmt_auth_failed event */
2886 if (!test_bit(HCI_CONN_AUTH_PEND, &conn->pend) && ev->status != 0)
Johan Hedberg744cf192011-11-08 20:40:14 +02002887 mgmt_auth_failed(hdev, &conn->dst, ev->status);
Johan Hedberg2a611692011-02-19 12:06:00 -03002888
2889 hci_conn_put(conn);
2890
2891unlock:
Marcel Holtmann04936842008-07-14 20:13:48 +02002892 hci_dev_unlock(hdev);
2893}
2894
Marcel Holtmann41a96212008-07-14 20:13:48 +02002895static inline void hci_remote_host_features_evt(struct hci_dev *hdev, struct sk_buff *skb)
2896{
2897 struct hci_ev_remote_host_features *ev = (void *) skb->data;
2898 struct inquiry_entry *ie;
2899
2900 BT_DBG("%s", hdev->name);
2901
2902 hci_dev_lock(hdev);
2903
Andrei Emeltchenkocc11b9c2010-11-22 13:21:37 +02002904 ie = hci_inquiry_cache_lookup(hdev, &ev->bdaddr);
2905 if (ie)
Marcel Holtmann41a96212008-07-14 20:13:48 +02002906 ie->data.ssp_mode = (ev->features[0] & 0x01);
2907
2908 hci_dev_unlock(hdev);
2909}
2910
Szymon Janc2763eda2011-03-22 13:12:22 +01002911static inline void hci_remote_oob_data_request_evt(struct hci_dev *hdev,
2912 struct sk_buff *skb)
2913{
2914 struct hci_ev_remote_oob_data_request *ev = (void *) skb->data;
2915 struct oob_data *data;
2916
2917 BT_DBG("%s", hdev->name);
2918
2919 hci_dev_lock(hdev);
2920
Szymon Jance1ba1f12011-04-06 13:01:59 +02002921 if (!test_bit(HCI_MGMT, &hdev->flags))
2922 goto unlock;
2923
Szymon Janc2763eda2011-03-22 13:12:22 +01002924 data = hci_find_remote_oob_data(hdev, &ev->bdaddr);
2925 if (data) {
2926 struct hci_cp_remote_oob_data_reply cp;
2927
2928 bacpy(&cp.bdaddr, &ev->bdaddr);
2929 memcpy(cp.hash, data->hash, sizeof(cp.hash));
2930 memcpy(cp.randomizer, data->randomizer, sizeof(cp.randomizer));
2931
2932 hci_send_cmd(hdev, HCI_OP_REMOTE_OOB_DATA_REPLY, sizeof(cp),
2933 &cp);
2934 } else {
2935 struct hci_cp_remote_oob_data_neg_reply cp;
2936
2937 bacpy(&cp.bdaddr, &ev->bdaddr);
2938 hci_send_cmd(hdev, HCI_OP_REMOTE_OOB_DATA_NEG_REPLY, sizeof(cp),
2939 &cp);
2940 }
2941
Szymon Jance1ba1f12011-04-06 13:01:59 +02002942unlock:
Szymon Janc2763eda2011-03-22 13:12:22 +01002943 hci_dev_unlock(hdev);
2944}
2945
Ville Tervofcd89c02011-02-10 22:38:47 -03002946static inline void hci_le_conn_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
2947{
2948 struct hci_ev_le_conn_complete *ev = (void *) skb->data;
2949 struct hci_conn *conn;
2950
2951 BT_DBG("%s status %d", hdev->name, ev->status);
2952
2953 hci_dev_lock(hdev);
2954
2955 conn = hci_conn_hash_lookup_ba(hdev, LE_LINK, &ev->bdaddr);
Ville Tervob62f3282011-02-10 22:38:50 -03002956 if (!conn) {
2957 conn = hci_conn_add(hdev, LE_LINK, &ev->bdaddr);
2958 if (!conn) {
2959 BT_ERR("No memory for new connection");
2960 hci_dev_unlock(hdev);
2961 return;
2962 }
Andre Guedes29b79882011-05-31 14:20:54 -03002963
2964 conn->dst_type = ev->bdaddr_type;
Ville Tervob62f3282011-02-10 22:38:50 -03002965 }
Ville Tervofcd89c02011-02-10 22:38:47 -03002966
2967 if (ev->status) {
Johan Hedberg48264f02011-11-09 13:58:58 +02002968 mgmt_connect_failed(hdev, &ev->bdaddr, conn->type,
2969 conn->dst_type, ev->status);
Ville Tervofcd89c02011-02-10 22:38:47 -03002970 hci_proto_connect_cfm(conn, ev->status);
2971 conn->state = BT_CLOSED;
2972 hci_conn_del(conn);
2973 goto unlock;
2974 }
2975
Johan Hedberg48264f02011-11-09 13:58:58 +02002976 mgmt_connected(hdev, &ev->bdaddr, conn->type, conn->dst_type);
Vinicius Costa Gomes83bc71b2011-05-06 18:41:43 -03002977
Vinicius Costa Gomes7b5c0d52011-06-09 18:50:50 -03002978 conn->sec_level = BT_SECURITY_LOW;
Ville Tervofcd89c02011-02-10 22:38:47 -03002979 conn->handle = __le16_to_cpu(ev->handle);
2980 conn->state = BT_CONNECTED;
2981
2982 hci_conn_hold_device(conn);
2983 hci_conn_add_sysfs(conn);
2984
2985 hci_proto_connect_cfm(conn, ev->status);
2986
2987unlock:
2988 hci_dev_unlock(hdev);
2989}
2990
Andre Guedes9aa04c92011-05-26 16:23:51 -03002991static inline void hci_le_adv_report_evt(struct hci_dev *hdev,
2992 struct sk_buff *skb)
2993{
Andre Guedese95beb42011-09-26 20:48:35 -03002994 u8 num_reports = skb->data[0];
2995 void *ptr = &skb->data[1];
Andre Guedes9aa04c92011-05-26 16:23:51 -03002996
2997 hci_dev_lock(hdev);
2998
Andre Guedese95beb42011-09-26 20:48:35 -03002999 while (num_reports--) {
3000 struct hci_ev_le_advertising_info *ev = ptr;
Andre Guedes9aa04c92011-05-26 16:23:51 -03003001
Andre Guedes9aa04c92011-05-26 16:23:51 -03003002 hci_add_adv_entry(hdev, ev);
Andre Guedese95beb42011-09-26 20:48:35 -03003003
3004 ptr += sizeof(*ev) + ev->length + 1;
Andre Guedes9aa04c92011-05-26 16:23:51 -03003005 }
3006
3007 hci_dev_unlock(hdev);
3008}
3009
Vinicius Costa Gomesa7a595f2011-06-09 18:50:47 -03003010static inline void hci_le_ltk_request_evt(struct hci_dev *hdev,
3011 struct sk_buff *skb)
3012{
3013 struct hci_ev_le_ltk_req *ev = (void *) skb->data;
3014 struct hci_cp_le_ltk_reply cp;
Vinicius Costa Gomesbea710f2011-07-07 18:59:37 -03003015 struct hci_cp_le_ltk_neg_reply neg;
Vinicius Costa Gomesa7a595f2011-06-09 18:50:47 -03003016 struct hci_conn *conn;
Vinicius Costa Gomesbea710f2011-07-07 18:59:37 -03003017 struct link_key *ltk;
Vinicius Costa Gomesa7a595f2011-06-09 18:50:47 -03003018
3019 BT_DBG("%s handle %d", hdev->name, cpu_to_le16(ev->handle));
3020
3021 hci_dev_lock(hdev);
3022
3023 conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
Vinicius Costa Gomesbea710f2011-07-07 18:59:37 -03003024 if (conn == NULL)
3025 goto not_found;
Vinicius Costa Gomesa7a595f2011-06-09 18:50:47 -03003026
Vinicius Costa Gomesbea710f2011-07-07 18:59:37 -03003027 ltk = hci_find_ltk(hdev, ev->ediv, ev->random);
3028 if (ltk == NULL)
3029 goto not_found;
3030
3031 memcpy(cp.ltk, ltk->val, sizeof(ltk->val));
Vinicius Costa Gomesa7a595f2011-06-09 18:50:47 -03003032 cp.handle = cpu_to_le16(conn->handle);
Vinicius Costa Gomes726b4ff2011-07-08 18:31:45 -03003033 conn->pin_length = ltk->pin_len;
Vinicius Costa Gomesa7a595f2011-06-09 18:50:47 -03003034
3035 hci_send_cmd(hdev, HCI_OP_LE_LTK_REPLY, sizeof(cp), &cp);
3036
3037 hci_dev_unlock(hdev);
Vinicius Costa Gomesbea710f2011-07-07 18:59:37 -03003038
3039 return;
3040
3041not_found:
3042 neg.handle = ev->handle;
3043 hci_send_cmd(hdev, HCI_OP_LE_LTK_NEG_REPLY, sizeof(neg), &neg);
3044 hci_dev_unlock(hdev);
Vinicius Costa Gomesa7a595f2011-06-09 18:50:47 -03003045}
3046
Ville Tervofcd89c02011-02-10 22:38:47 -03003047static inline void hci_le_meta_evt(struct hci_dev *hdev, struct sk_buff *skb)
3048{
3049 struct hci_ev_le_meta *le_ev = (void *) skb->data;
3050
3051 skb_pull(skb, sizeof(*le_ev));
3052
3053 switch (le_ev->subevent) {
3054 case HCI_EV_LE_CONN_COMPLETE:
3055 hci_le_conn_complete_evt(hdev, skb);
3056 break;
3057
Andre Guedes9aa04c92011-05-26 16:23:51 -03003058 case HCI_EV_LE_ADVERTISING_REPORT:
3059 hci_le_adv_report_evt(hdev, skb);
3060 break;
3061
Vinicius Costa Gomesa7a595f2011-06-09 18:50:47 -03003062 case HCI_EV_LE_LTK_REQ:
3063 hci_le_ltk_request_evt(hdev, skb);
3064 break;
3065
Ville Tervofcd89c02011-02-10 22:38:47 -03003066 default:
3067 break;
3068 }
3069}
3070
Linus Torvalds1da177e2005-04-16 15:20:36 -07003071void hci_event_packet(struct hci_dev *hdev, struct sk_buff *skb)
3072{
Marcel Holtmanna9de9242007-10-20 13:33:56 +02003073 struct hci_event_hdr *hdr = (void *) skb->data;
3074 __u8 event = hdr->evt;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003075
3076 skb_pull(skb, HCI_EVENT_HDR_SIZE);
3077
Marcel Holtmanna9de9242007-10-20 13:33:56 +02003078 switch (event) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003079 case HCI_EV_INQUIRY_COMPLETE:
3080 hci_inquiry_complete_evt(hdev, skb);
3081 break;
3082
3083 case HCI_EV_INQUIRY_RESULT:
3084 hci_inquiry_result_evt(hdev, skb);
3085 break;
3086
Marcel Holtmanna9de9242007-10-20 13:33:56 +02003087 case HCI_EV_CONN_COMPLETE:
3088 hci_conn_complete_evt(hdev, skb);
Marcel Holtmann21d9e302005-09-13 01:32:25 +02003089 break;
3090
Linus Torvalds1da177e2005-04-16 15:20:36 -07003091 case HCI_EV_CONN_REQUEST:
3092 hci_conn_request_evt(hdev, skb);
3093 break;
3094
Linus Torvalds1da177e2005-04-16 15:20:36 -07003095 case HCI_EV_DISCONN_COMPLETE:
3096 hci_disconn_complete_evt(hdev, skb);
3097 break;
3098
Linus Torvalds1da177e2005-04-16 15:20:36 -07003099 case HCI_EV_AUTH_COMPLETE:
3100 hci_auth_complete_evt(hdev, skb);
3101 break;
3102
Marcel Holtmanna9de9242007-10-20 13:33:56 +02003103 case HCI_EV_REMOTE_NAME:
3104 hci_remote_name_evt(hdev, skb);
3105 break;
3106
Linus Torvalds1da177e2005-04-16 15:20:36 -07003107 case HCI_EV_ENCRYPT_CHANGE:
3108 hci_encrypt_change_evt(hdev, skb);
3109 break;
3110
Marcel Holtmanna9de9242007-10-20 13:33:56 +02003111 case HCI_EV_CHANGE_LINK_KEY_COMPLETE:
3112 hci_change_link_key_complete_evt(hdev, skb);
3113 break;
3114
3115 case HCI_EV_REMOTE_FEATURES:
3116 hci_remote_features_evt(hdev, skb);
3117 break;
3118
3119 case HCI_EV_REMOTE_VERSION:
3120 hci_remote_version_evt(hdev, skb);
3121 break;
3122
3123 case HCI_EV_QOS_SETUP_COMPLETE:
3124 hci_qos_setup_complete_evt(hdev, skb);
3125 break;
3126
3127 case HCI_EV_CMD_COMPLETE:
3128 hci_cmd_complete_evt(hdev, skb);
3129 break;
3130
3131 case HCI_EV_CMD_STATUS:
3132 hci_cmd_status_evt(hdev, skb);
3133 break;
3134
3135 case HCI_EV_ROLE_CHANGE:
3136 hci_role_change_evt(hdev, skb);
3137 break;
3138
3139 case HCI_EV_NUM_COMP_PKTS:
3140 hci_num_comp_pkts_evt(hdev, skb);
3141 break;
3142
3143 case HCI_EV_MODE_CHANGE:
3144 hci_mode_change_evt(hdev, skb);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003145 break;
3146
3147 case HCI_EV_PIN_CODE_REQ:
3148 hci_pin_code_request_evt(hdev, skb);
3149 break;
3150
3151 case HCI_EV_LINK_KEY_REQ:
3152 hci_link_key_request_evt(hdev, skb);
3153 break;
3154
3155 case HCI_EV_LINK_KEY_NOTIFY:
3156 hci_link_key_notify_evt(hdev, skb);
3157 break;
3158
3159 case HCI_EV_CLOCK_OFFSET:
3160 hci_clock_offset_evt(hdev, skb);
3161 break;
3162
Marcel Holtmanna8746412008-07-14 20:13:46 +02003163 case HCI_EV_PKT_TYPE_CHANGE:
3164 hci_pkt_type_change_evt(hdev, skb);
3165 break;
3166
Marcel Holtmann85a1e932005-08-09 20:28:02 -07003167 case HCI_EV_PSCAN_REP_MODE:
3168 hci_pscan_rep_mode_evt(hdev, skb);
3169 break;
3170
Marcel Holtmanna9de9242007-10-20 13:33:56 +02003171 case HCI_EV_INQUIRY_RESULT_WITH_RSSI:
3172 hci_inquiry_result_with_rssi_evt(hdev, skb);
3173 break;
3174
3175 case HCI_EV_REMOTE_EXT_FEATURES:
3176 hci_remote_ext_features_evt(hdev, skb);
3177 break;
3178
3179 case HCI_EV_SYNC_CONN_COMPLETE:
3180 hci_sync_conn_complete_evt(hdev, skb);
3181 break;
3182
3183 case HCI_EV_SYNC_CONN_CHANGED:
3184 hci_sync_conn_changed_evt(hdev, skb);
3185 break;
3186
Marcel Holtmann04837f62006-07-03 10:02:33 +02003187 case HCI_EV_SNIFF_SUBRATE:
3188 hci_sniff_subrate_evt(hdev, skb);
3189 break;
3190
Marcel Holtmanna9de9242007-10-20 13:33:56 +02003191 case HCI_EV_EXTENDED_INQUIRY_RESULT:
3192 hci_extended_inquiry_result_evt(hdev, skb);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003193 break;
3194
Marcel Holtmann04936842008-07-14 20:13:48 +02003195 case HCI_EV_IO_CAPA_REQUEST:
3196 hci_io_capa_request_evt(hdev, skb);
3197 break;
3198
Johan Hedberg03b555e2011-01-04 15:40:05 +02003199 case HCI_EV_IO_CAPA_REPLY:
3200 hci_io_capa_reply_evt(hdev, skb);
3201 break;
3202
Johan Hedberga5c29682011-02-19 12:05:57 -03003203 case HCI_EV_USER_CONFIRM_REQUEST:
3204 hci_user_confirm_request_evt(hdev, skb);
3205 break;
3206
Brian Gix1143d452011-11-23 08:28:34 -08003207 case HCI_EV_USER_PASSKEY_REQUEST:
3208 hci_user_passkey_request_evt(hdev, skb);
3209 break;
3210
Marcel Holtmann04936842008-07-14 20:13:48 +02003211 case HCI_EV_SIMPLE_PAIR_COMPLETE:
3212 hci_simple_pair_complete_evt(hdev, skb);
3213 break;
3214
Marcel Holtmann41a96212008-07-14 20:13:48 +02003215 case HCI_EV_REMOTE_HOST_FEATURES:
3216 hci_remote_host_features_evt(hdev, skb);
3217 break;
3218
Ville Tervofcd89c02011-02-10 22:38:47 -03003219 case HCI_EV_LE_META:
3220 hci_le_meta_evt(hdev, skb);
3221 break;
3222
Szymon Janc2763eda2011-03-22 13:12:22 +01003223 case HCI_EV_REMOTE_OOB_DATA_REQUEST:
3224 hci_remote_oob_data_request_evt(hdev, skb);
3225 break;
3226
Marcel Holtmanna9de9242007-10-20 13:33:56 +02003227 default:
3228 BT_DBG("%s event 0x%x", hdev->name, event);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003229 break;
3230 }
3231
3232 kfree_skb(skb);
3233 hdev->stat.evt_rx++;
3234}
3235
3236/* Generate internal stack event */
3237void hci_si_event(struct hci_dev *hdev, int type, int dlen, void *data)
3238{
3239 struct hci_event_hdr *hdr;
3240 struct hci_ev_stack_internal *ev;
3241 struct sk_buff *skb;
3242
3243 skb = bt_skb_alloc(HCI_EVENT_HDR_SIZE + sizeof(*ev) + dlen, GFP_ATOMIC);
3244 if (!skb)
3245 return;
3246
3247 hdr = (void *) skb_put(skb, HCI_EVENT_HDR_SIZE);
3248 hdr->evt = HCI_EV_STACK_INTERNAL;
3249 hdr->plen = sizeof(*ev) + dlen;
3250
3251 ev = (void *) skb_put(skb, sizeof(*ev) + dlen);
3252 ev->type = type;
3253 memcpy(ev->data, data, dlen);
3254
Marcel Holtmann576c7d82005-08-06 12:36:54 +02003255 bt_cb(skb)->incoming = 1;
Patrick McHardya61bbcf2005-08-14 17:24:31 -07003256 __net_timestamp(skb);
Marcel Holtmann576c7d82005-08-06 12:36:54 +02003257
Marcel Holtmann0d48d932005-08-09 20:30:28 -07003258 bt_cb(skb)->pkt_type = HCI_EVENT_PKT;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003259 skb->dev = (void *) hdev;
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02003260 hci_send_to_sock(hdev, skb, NULL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003261 kfree_skb(skb);
3262}
Andre Guedese6100a22011-06-30 19:20:54 -03003263
Gustavo F. Padovan669bb392011-10-11 15:57:01 -03003264module_param(enable_le, bool, 0644);
Andre Guedese6100a22011-06-30 19:20:54 -03003265MODULE_PARM_DESC(enable_le, "Enable LE support");