blob: 04fb1f02dfcca80cff400ddf9bcfc347b1278bd8 [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
Rusty Russelleb939922011-12-19 14:08:01 +000048static bool enable_le;
Andre Guedese6100a22011-06-30 19:20:54 -030049
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 Hedbergff9ef572012-01-04 14:23:45 +020068 hci_discovery_set_state(hdev, DISCOVERY_STOPPED);
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
Johan Hedberg7005ff1782012-01-18 16:14:43 +0200198 /* Reset all flags, except persistent ones */
Hemant Gupta95947a32012-01-23 15:36:11 +0530199 hdev->dev_flags &= BIT(HCI_MGMT) | BIT(HCI_SETUP) | BIT(HCI_AUTO_OFF) |
200 BIT(HCI_LINK_KEYS) | BIT(HCI_DEBUG_KEYS);
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200201}
202
203static void hci_cc_write_local_name(struct hci_dev *hdev, struct sk_buff *skb)
204{
205 __u8 status = *((__u8 *) skb->data);
206 void *sent;
207
208 BT_DBG("%s status 0x%x", hdev->name, status);
209
210 sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_LOCAL_NAME);
211 if (!sent)
212 return;
213
Johan Hedberg56e5cb82011-11-08 20:40:16 +0200214 hci_dev_lock(hdev);
215
Johan Hedberga8b2d5c2012-01-08 23:11:15 +0200216 if (test_bit(HCI_MGMT, &hdev->dev_flags))
Johan Hedberg744cf192011-11-08 20:40:14 +0200217 mgmt_set_local_name_complete(hdev, sent, status);
Johan Hedbergb312b1612011-03-16 14:29:37 +0200218
Johan Hedberg56e5cb82011-11-08 20:40:16 +0200219 if (status == 0)
220 memcpy(hdev->dev_name, sent, HCI_MAX_NAME_LENGTH);
Johan Hedbergb312b1612011-03-16 14:29:37 +0200221
Johan Hedberg56e5cb82011-11-08 20:40:16 +0200222 hci_dev_unlock(hdev);
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200223}
224
225static void hci_cc_read_local_name(struct hci_dev *hdev, struct sk_buff *skb)
226{
227 struct hci_rp_read_local_name *rp = (void *) skb->data;
228
229 BT_DBG("%s status 0x%x", hdev->name, rp->status);
230
231 if (rp->status)
232 return;
233
Johan Hedberg1f6c6372011-03-16 14:29:35 +0200234 memcpy(hdev->dev_name, rp->name, HCI_MAX_NAME_LENGTH);
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200235}
236
237static void hci_cc_write_auth_enable(struct hci_dev *hdev, struct sk_buff *skb)
238{
239 __u8 status = *((__u8 *) skb->data);
240 void *sent;
241
242 BT_DBG("%s status 0x%x", hdev->name, status);
243
244 sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_AUTH_ENABLE);
245 if (!sent)
246 return;
247
248 if (!status) {
249 __u8 param = *((__u8 *) sent);
250
251 if (param == AUTH_ENABLED)
252 set_bit(HCI_AUTH, &hdev->flags);
253 else
254 clear_bit(HCI_AUTH, &hdev->flags);
255 }
256
Johan Hedberg33ef95e2012-02-16 23:56:27 +0200257 if (test_bit(HCI_MGMT, &hdev->dev_flags))
258 mgmt_auth_enable_complete(hdev, status);
259
Johan Hedberg23bb5762010-12-21 23:01:27 +0200260 hci_req_complete(hdev, HCI_OP_WRITE_AUTH_ENABLE, status);
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200261}
262
263static void hci_cc_write_encrypt_mode(struct hci_dev *hdev, struct sk_buff *skb)
264{
265 __u8 status = *((__u8 *) skb->data);
266 void *sent;
267
268 BT_DBG("%s status 0x%x", hdev->name, status);
269
270 sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_ENCRYPT_MODE);
271 if (!sent)
272 return;
273
274 if (!status) {
275 __u8 param = *((__u8 *) sent);
276
277 if (param)
278 set_bit(HCI_ENCRYPT, &hdev->flags);
279 else
280 clear_bit(HCI_ENCRYPT, &hdev->flags);
281 }
282
Johan Hedberg23bb5762010-12-21 23:01:27 +0200283 hci_req_complete(hdev, HCI_OP_WRITE_ENCRYPT_MODE, status);
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200284}
285
286static void hci_cc_write_scan_enable(struct hci_dev *hdev, struct sk_buff *skb)
287{
Johan Hedberg36f7fc72011-11-04 00:17:45 +0200288 __u8 param, status = *((__u8 *) skb->data);
289 int old_pscan, old_iscan;
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200290 void *sent;
291
292 BT_DBG("%s status 0x%x", hdev->name, status);
293
294 sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_SCAN_ENABLE);
295 if (!sent)
296 return;
297
Johan Hedberg36f7fc72011-11-04 00:17:45 +0200298 param = *((__u8 *) sent);
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200299
Johan Hedberg56e5cb82011-11-08 20:40:16 +0200300 hci_dev_lock(hdev);
301
Johan Hedberg2d7cee52011-11-07 22:16:03 +0200302 if (status != 0) {
Johan Hedberg744cf192011-11-08 20:40:14 +0200303 mgmt_write_scan_failed(hdev, param, status);
Johan Hedberg2d7cee52011-11-07 22:16:03 +0200304 hdev->discov_timeout = 0;
305 goto done;
306 }
307
Johan Hedberg36f7fc72011-11-04 00:17:45 +0200308 old_pscan = test_and_clear_bit(HCI_PSCAN, &hdev->flags);
309 old_iscan = test_and_clear_bit(HCI_ISCAN, &hdev->flags);
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200310
Johan Hedberg36f7fc72011-11-04 00:17:45 +0200311 if (param & SCAN_INQUIRY) {
312 set_bit(HCI_ISCAN, &hdev->flags);
313 if (!old_iscan)
Johan Hedberg744cf192011-11-08 20:40:14 +0200314 mgmt_discoverable(hdev, 1);
Johan Hedberg16ab91a2011-11-07 22:16:02 +0200315 if (hdev->discov_timeout > 0) {
316 int to = msecs_to_jiffies(hdev->discov_timeout * 1000);
317 queue_delayed_work(hdev->workqueue, &hdev->discov_off,
318 to);
319 }
Johan Hedberg36f7fc72011-11-04 00:17:45 +0200320 } else if (old_iscan)
Johan Hedberg744cf192011-11-08 20:40:14 +0200321 mgmt_discoverable(hdev, 0);
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200322
Johan Hedberg36f7fc72011-11-04 00:17:45 +0200323 if (param & SCAN_PAGE) {
324 set_bit(HCI_PSCAN, &hdev->flags);
325 if (!old_pscan)
Johan Hedberg744cf192011-11-08 20:40:14 +0200326 mgmt_connectable(hdev, 1);
Johan Hedberg36f7fc72011-11-04 00:17:45 +0200327 } else if (old_pscan)
Johan Hedberg744cf192011-11-08 20:40:14 +0200328 mgmt_connectable(hdev, 0);
Johan Hedberg36f7fc72011-11-04 00:17:45 +0200329
330done:
Johan Hedberg56e5cb82011-11-08 20:40:16 +0200331 hci_dev_unlock(hdev);
Johan Hedberg23bb5762010-12-21 23:01:27 +0200332 hci_req_complete(hdev, HCI_OP_WRITE_SCAN_ENABLE, status);
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200333}
334
335static void hci_cc_read_class_of_dev(struct hci_dev *hdev, struct sk_buff *skb)
336{
337 struct hci_rp_read_class_of_dev *rp = (void *) skb->data;
338
339 BT_DBG("%s status 0x%x", hdev->name, rp->status);
340
341 if (rp->status)
342 return;
343
344 memcpy(hdev->dev_class, rp->dev_class, 3);
345
346 BT_DBG("%s class 0x%.2x%.2x%.2x", hdev->name,
347 hdev->dev_class[2], hdev->dev_class[1], hdev->dev_class[0]);
348}
349
350static void hci_cc_write_class_of_dev(struct hci_dev *hdev, struct sk_buff *skb)
351{
352 __u8 status = *((__u8 *) skb->data);
353 void *sent;
354
355 BT_DBG("%s status 0x%x", hdev->name, status);
356
Marcel Holtmannf383f272008-07-14 20:13:47 +0200357 if (status)
358 return;
359
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200360 sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_CLASS_OF_DEV);
361 if (!sent)
362 return;
363
Marcel Holtmannf383f272008-07-14 20:13:47 +0200364 memcpy(hdev->dev_class, sent, 3);
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200365}
366
367static void hci_cc_read_voice_setting(struct hci_dev *hdev, struct sk_buff *skb)
368{
369 struct hci_rp_read_voice_setting *rp = (void *) skb->data;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700370 __u16 setting;
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200371
372 BT_DBG("%s status 0x%x", hdev->name, rp->status);
373
374 if (rp->status)
375 return;
376
377 setting = __le16_to_cpu(rp->voice_setting);
378
Marcel Holtmannf383f272008-07-14 20:13:47 +0200379 if (hdev->voice_setting == setting)
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200380 return;
381
382 hdev->voice_setting = setting;
383
384 BT_DBG("%s voice setting 0x%04x", hdev->name, setting);
385
Gustavo F. Padovan3c547112011-12-14 22:58:44 -0200386 if (hdev->notify)
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200387 hdev->notify(hdev, HCI_NOTIFY_VOICE_SETTING);
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200388}
389
390static void hci_cc_write_voice_setting(struct hci_dev *hdev, struct sk_buff *skb)
391{
392 __u8 status = *((__u8 *) skb->data);
Marcel Holtmannf383f272008-07-14 20:13:47 +0200393 __u16 setting;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700394 void *sent;
395
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200396 BT_DBG("%s status 0x%x", hdev->name, status);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700397
Marcel Holtmannf383f272008-07-14 20:13:47 +0200398 if (status)
399 return;
400
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200401 sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_VOICE_SETTING);
402 if (!sent)
403 return;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700404
Marcel Holtmannf383f272008-07-14 20:13:47 +0200405 setting = get_unaligned_le16(sent);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700406
Marcel Holtmannf383f272008-07-14 20:13:47 +0200407 if (hdev->voice_setting == setting)
408 return;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700409
Marcel Holtmannf383f272008-07-14 20:13:47 +0200410 hdev->voice_setting = setting;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700411
Marcel Holtmannf383f272008-07-14 20:13:47 +0200412 BT_DBG("%s voice setting 0x%04x", hdev->name, setting);
413
Gustavo F. Padovan3c547112011-12-14 22:58:44 -0200414 if (hdev->notify)
Marcel Holtmannf383f272008-07-14 20:13:47 +0200415 hdev->notify(hdev, HCI_NOTIFY_VOICE_SETTING);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700416}
417
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200418static void hci_cc_host_buffer_size(struct hci_dev *hdev, struct sk_buff *skb)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700419{
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200420 __u8 status = *((__u8 *) skb->data);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700421
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200422 BT_DBG("%s status 0x%x", hdev->name, status);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700423
Johan Hedberg23bb5762010-12-21 23:01:27 +0200424 hci_req_complete(hdev, HCI_OP_HOST_BUFFER_SIZE, status);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700425}
426
Marcel Holtmann333140b2008-07-14 20:13:48 +0200427static void hci_cc_read_ssp_mode(struct hci_dev *hdev, struct sk_buff *skb)
428{
429 struct hci_rp_read_ssp_mode *rp = (void *) skb->data;
430
431 BT_DBG("%s status 0x%x", hdev->name, rp->status);
432
433 if (rp->status)
434 return;
435
Johan Hedberg84bde9d2012-01-25 14:21:06 +0200436 if (rp->mode)
437 set_bit(HCI_SSP_ENABLED, &hdev->dev_flags);
438 else
439 clear_bit(HCI_SSP_ENABLED, &hdev->dev_flags);
Marcel Holtmann333140b2008-07-14 20:13:48 +0200440}
441
442static void hci_cc_write_ssp_mode(struct hci_dev *hdev, struct sk_buff *skb)
443{
444 __u8 status = *((__u8 *) skb->data);
445 void *sent;
446
447 BT_DBG("%s status 0x%x", hdev->name, status);
448
449 if (status)
Johan Hedberged2c4ee2012-02-17 00:56:28 +0200450 goto done;
Marcel Holtmann333140b2008-07-14 20:13:48 +0200451
452 sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_SSP_MODE);
453 if (!sent)
454 return;
455
Johan Hedberg84bde9d2012-01-25 14:21:06 +0200456 if (*((u8 *) sent))
457 set_bit(HCI_SSP_ENABLED, &hdev->dev_flags);
458 else
459 clear_bit(HCI_SSP_ENABLED, &hdev->dev_flags);
Johan Hedberged2c4ee2012-02-17 00:56:28 +0200460
461done:
462 if (test_bit(HCI_MGMT, &hdev->dev_flags))
463 mgmt_ssp_enable_complete(hdev, status);
Marcel Holtmann333140b2008-07-14 20:13:48 +0200464}
465
Johan Hedbergd5859e22011-01-25 01:19:58 +0200466static u8 hci_get_inquiry_mode(struct hci_dev *hdev)
467{
468 if (hdev->features[6] & LMP_EXT_INQ)
469 return 2;
470
471 if (hdev->features[3] & LMP_RSSI_INQ)
472 return 1;
473
474 if (hdev->manufacturer == 11 && hdev->hci_rev == 0x00 &&
475 hdev->lmp_subver == 0x0757)
476 return 1;
477
478 if (hdev->manufacturer == 15) {
479 if (hdev->hci_rev == 0x03 && hdev->lmp_subver == 0x6963)
480 return 1;
481 if (hdev->hci_rev == 0x09 && hdev->lmp_subver == 0x6963)
482 return 1;
483 if (hdev->hci_rev == 0x00 && hdev->lmp_subver == 0x6965)
484 return 1;
485 }
486
487 if (hdev->manufacturer == 31 && hdev->hci_rev == 0x2005 &&
488 hdev->lmp_subver == 0x1805)
489 return 1;
490
491 return 0;
492}
493
494static void hci_setup_inquiry_mode(struct hci_dev *hdev)
495{
496 u8 mode;
497
498 mode = hci_get_inquiry_mode(hdev);
499
500 hci_send_cmd(hdev, HCI_OP_WRITE_INQUIRY_MODE, 1, &mode);
501}
502
503static void hci_setup_event_mask(struct hci_dev *hdev)
504{
505 /* The second byte is 0xff instead of 0x9f (two reserved bits
506 * disabled) since a Broadcom 1.2 dongle doesn't respond to the
507 * command otherwise */
508 u8 events[8] = { 0xff, 0xff, 0xfb, 0xff, 0x00, 0x00, 0x00, 0x00 };
509
Ville Tervo6de6c182011-05-27 11:16:21 +0300510 /* CSR 1.1 dongles does not accept any bitfield so don't try to set
511 * any event mask for pre 1.2 devices */
Andrei Emeltchenko5a13b092011-12-01 14:33:28 +0200512 if (hdev->hci_ver < BLUETOOTH_VER_1_2)
Ville Tervo6de6c182011-05-27 11:16:21 +0300513 return;
514
515 events[4] |= 0x01; /* Flow Specification Complete */
516 events[4] |= 0x02; /* Inquiry Result with RSSI */
517 events[4] |= 0x04; /* Read Remote Extended Features Complete */
518 events[5] |= 0x08; /* Synchronous Connection Complete */
519 events[5] |= 0x10; /* Synchronous Connection Changed */
Johan Hedbergd5859e22011-01-25 01:19:58 +0200520
521 if (hdev->features[3] & LMP_RSSI_INQ)
522 events[4] |= 0x04; /* Inquiry Result with RSSI */
523
524 if (hdev->features[5] & LMP_SNIFF_SUBR)
525 events[5] |= 0x20; /* Sniff Subrating */
526
527 if (hdev->features[5] & LMP_PAUSE_ENC)
528 events[5] |= 0x80; /* Encryption Key Refresh Complete */
529
530 if (hdev->features[6] & LMP_EXT_INQ)
531 events[5] |= 0x40; /* Extended Inquiry Result */
532
533 if (hdev->features[6] & LMP_NO_FLUSH)
534 events[7] |= 0x01; /* Enhanced Flush Complete */
535
536 if (hdev->features[7] & LMP_LSTO)
537 events[6] |= 0x80; /* Link Supervision Timeout Changed */
538
539 if (hdev->features[6] & LMP_SIMPLE_PAIR) {
540 events[6] |= 0x01; /* IO Capability Request */
541 events[6] |= 0x02; /* IO Capability Response */
542 events[6] |= 0x04; /* User Confirmation Request */
543 events[6] |= 0x08; /* User Passkey Request */
544 events[6] |= 0x10; /* Remote OOB Data Request */
545 events[6] |= 0x20; /* Simple Pairing Complete */
546 events[7] |= 0x04; /* User Passkey Notification */
547 events[7] |= 0x08; /* Keypress Notification */
548 events[7] |= 0x10; /* Remote Host Supported
549 * Features Notification */
550 }
551
552 if (hdev->features[4] & LMP_LE)
553 events[7] |= 0x20; /* LE Meta-Event */
554
555 hci_send_cmd(hdev, HCI_OP_SET_EVENT_MASK, sizeof(events), events);
556}
557
Andre Guedese6100a22011-06-30 19:20:54 -0300558static void hci_set_le_support(struct hci_dev *hdev)
559{
560 struct hci_cp_write_le_host_supported cp;
561
562 memset(&cp, 0, sizeof(cp));
563
564 if (enable_le) {
565 cp.le = 1;
566 cp.simul = !!(hdev->features[6] & LMP_SIMUL_LE_BR);
567 }
568
569 hci_send_cmd(hdev, HCI_OP_WRITE_LE_HOST_SUPPORTED, sizeof(cp), &cp);
570}
571
Johan Hedbergd5859e22011-01-25 01:19:58 +0200572static void hci_setup(struct hci_dev *hdev)
573{
Andrei Emeltchenkoe61ef492011-12-19 16:31:27 +0200574 if (hdev->dev_type != HCI_BREDR)
575 return;
576
Johan Hedbergd5859e22011-01-25 01:19:58 +0200577 hci_setup_event_mask(hdev);
578
Andrei Emeltchenkod095c1e2011-12-01 14:33:27 +0200579 if (hdev->hci_ver > BLUETOOTH_VER_1_1)
Johan Hedbergd5859e22011-01-25 01:19:58 +0200580 hci_send_cmd(hdev, HCI_OP_READ_LOCAL_COMMANDS, 0, NULL);
581
582 if (hdev->features[6] & LMP_SIMPLE_PAIR) {
583 u8 mode = 0x01;
584 hci_send_cmd(hdev, HCI_OP_WRITE_SSP_MODE, sizeof(mode), &mode);
585 }
586
587 if (hdev->features[3] & LMP_RSSI_INQ)
588 hci_setup_inquiry_mode(hdev);
589
590 if (hdev->features[7] & LMP_INQ_TX_PWR)
591 hci_send_cmd(hdev, HCI_OP_READ_INQ_RSP_TX_POWER, 0, NULL);
Andre Guedes971e3a42011-06-30 19:20:52 -0300592
593 if (hdev->features[7] & LMP_EXTFEATURES) {
594 struct hci_cp_read_local_ext_features cp;
595
596 cp.page = 0x01;
597 hci_send_cmd(hdev, HCI_OP_READ_LOCAL_EXT_FEATURES,
598 sizeof(cp), &cp);
599 }
Andre Guedese6100a22011-06-30 19:20:54 -0300600
601 if (hdev->features[4] & LMP_LE)
602 hci_set_le_support(hdev);
Johan Hedbergd5859e22011-01-25 01:19:58 +0200603}
604
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200605static void hci_cc_read_local_version(struct hci_dev *hdev, struct sk_buff *skb)
606{
607 struct hci_rp_read_local_version *rp = (void *) skb->data;
608
609 BT_DBG("%s status 0x%x", hdev->name, rp->status);
610
611 if (rp->status)
612 return;
613
614 hdev->hci_ver = rp->hci_ver;
Marcel Holtmanne4e8e372008-07-14 20:13:47 +0200615 hdev->hci_rev = __le16_to_cpu(rp->hci_rev);
Johan Hedbergd5859e22011-01-25 01:19:58 +0200616 hdev->lmp_ver = rp->lmp_ver;
Marcel Holtmanne4e8e372008-07-14 20:13:47 +0200617 hdev->manufacturer = __le16_to_cpu(rp->manufacturer);
Johan Hedbergd5859e22011-01-25 01:19:58 +0200618 hdev->lmp_subver = __le16_to_cpu(rp->lmp_subver);
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200619
620 BT_DBG("%s manufacturer %d hci ver %d:%d", hdev->name,
621 hdev->manufacturer,
622 hdev->hci_ver, hdev->hci_rev);
Johan Hedbergd5859e22011-01-25 01:19:58 +0200623
624 if (test_bit(HCI_INIT, &hdev->flags))
625 hci_setup(hdev);
626}
627
628static void hci_setup_link_policy(struct hci_dev *hdev)
629{
630 u16 link_policy = 0;
631
632 if (hdev->features[0] & LMP_RSWITCH)
633 link_policy |= HCI_LP_RSWITCH;
634 if (hdev->features[0] & LMP_HOLD)
635 link_policy |= HCI_LP_HOLD;
636 if (hdev->features[0] & LMP_SNIFF)
637 link_policy |= HCI_LP_SNIFF;
638 if (hdev->features[1] & LMP_PARK)
639 link_policy |= HCI_LP_PARK;
640
641 link_policy = cpu_to_le16(link_policy);
642 hci_send_cmd(hdev, HCI_OP_WRITE_DEF_LINK_POLICY,
643 sizeof(link_policy), &link_policy);
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200644}
645
646static void hci_cc_read_local_commands(struct hci_dev *hdev, struct sk_buff *skb)
647{
648 struct hci_rp_read_local_commands *rp = (void *) skb->data;
649
650 BT_DBG("%s status 0x%x", hdev->name, rp->status);
651
652 if (rp->status)
Johan Hedbergd5859e22011-01-25 01:19:58 +0200653 goto done;
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200654
655 memcpy(hdev->commands, rp->commands, sizeof(hdev->commands));
Johan Hedbergd5859e22011-01-25 01:19:58 +0200656
657 if (test_bit(HCI_INIT, &hdev->flags) && (hdev->commands[5] & 0x10))
658 hci_setup_link_policy(hdev);
659
660done:
661 hci_req_complete(hdev, HCI_OP_READ_LOCAL_COMMANDS, rp->status);
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200662}
663
664static void hci_cc_read_local_features(struct hci_dev *hdev, struct sk_buff *skb)
665{
666 struct hci_rp_read_local_features *rp = (void *) skb->data;
667
668 BT_DBG("%s status 0x%x", hdev->name, rp->status);
669
670 if (rp->status)
671 return;
672
673 memcpy(hdev->features, rp->features, 8);
674
675 /* Adjust default settings according to features
676 * supported by device. */
677
678 if (hdev->features[0] & LMP_3SLOT)
679 hdev->pkt_type |= (HCI_DM3 | HCI_DH3);
680
681 if (hdev->features[0] & LMP_5SLOT)
682 hdev->pkt_type |= (HCI_DM5 | HCI_DH5);
683
684 if (hdev->features[1] & LMP_HV2) {
685 hdev->pkt_type |= (HCI_HV2);
686 hdev->esco_type |= (ESCO_HV2);
687 }
688
689 if (hdev->features[1] & LMP_HV3) {
690 hdev->pkt_type |= (HCI_HV3);
691 hdev->esco_type |= (ESCO_HV3);
692 }
693
694 if (hdev->features[3] & LMP_ESCO)
695 hdev->esco_type |= (ESCO_EV3);
696
697 if (hdev->features[4] & LMP_EV4)
698 hdev->esco_type |= (ESCO_EV4);
699
700 if (hdev->features[4] & LMP_EV5)
701 hdev->esco_type |= (ESCO_EV5);
702
Marcel Holtmannefc76882009-02-06 09:13:37 +0100703 if (hdev->features[5] & LMP_EDR_ESCO_2M)
704 hdev->esco_type |= (ESCO_2EV3);
705
706 if (hdev->features[5] & LMP_EDR_ESCO_3M)
707 hdev->esco_type |= (ESCO_3EV3);
708
709 if (hdev->features[5] & LMP_EDR_3S_ESCO)
710 hdev->esco_type |= (ESCO_2EV5 | ESCO_3EV5);
711
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200712 BT_DBG("%s features 0x%.2x%.2x%.2x%.2x%.2x%.2x%.2x%.2x", hdev->name,
713 hdev->features[0], hdev->features[1],
714 hdev->features[2], hdev->features[3],
715 hdev->features[4], hdev->features[5],
716 hdev->features[6], hdev->features[7]);
717}
718
Andre Guedes971e3a42011-06-30 19:20:52 -0300719static void hci_cc_read_local_ext_features(struct hci_dev *hdev,
720 struct sk_buff *skb)
721{
722 struct hci_rp_read_local_ext_features *rp = (void *) skb->data;
723
724 BT_DBG("%s status 0x%x", hdev->name, rp->status);
725
726 if (rp->status)
727 return;
728
Andre Guedesb5b32b62011-12-30 10:34:04 -0300729 switch (rp->page) {
730 case 0:
731 memcpy(hdev->features, rp->features, 8);
732 break;
733 case 1:
734 memcpy(hdev->host_features, rp->features, 8);
735 break;
736 }
Andre Guedes971e3a42011-06-30 19:20:52 -0300737
738 hci_req_complete(hdev, HCI_OP_READ_LOCAL_EXT_FEATURES, rp->status);
739}
740
Andrei Emeltchenko1e89cff2011-11-24 14:52:02 +0200741static void hci_cc_read_flow_control_mode(struct hci_dev *hdev,
742 struct sk_buff *skb)
743{
744 struct hci_rp_read_flow_control_mode *rp = (void *) skb->data;
745
746 BT_DBG("%s status 0x%x", hdev->name, rp->status);
747
748 if (rp->status)
749 return;
750
751 hdev->flow_ctl_mode = rp->mode;
752
753 hci_req_complete(hdev, HCI_OP_READ_FLOW_CONTROL_MODE, rp->status);
754}
755
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200756static void hci_cc_read_buffer_size(struct hci_dev *hdev, struct sk_buff *skb)
757{
758 struct hci_rp_read_buffer_size *rp = (void *) skb->data;
759
760 BT_DBG("%s status 0x%x", hdev->name, rp->status);
761
762 if (rp->status)
763 return;
764
765 hdev->acl_mtu = __le16_to_cpu(rp->acl_mtu);
766 hdev->sco_mtu = rp->sco_mtu;
767 hdev->acl_pkts = __le16_to_cpu(rp->acl_max_pkt);
768 hdev->sco_pkts = __le16_to_cpu(rp->sco_max_pkt);
769
770 if (test_bit(HCI_QUIRK_FIXUP_BUFFER_SIZE, &hdev->quirks)) {
771 hdev->sco_mtu = 64;
772 hdev->sco_pkts = 8;
773 }
774
775 hdev->acl_cnt = hdev->acl_pkts;
776 hdev->sco_cnt = hdev->sco_pkts;
777
778 BT_DBG("%s acl mtu %d:%d sco mtu %d:%d", hdev->name,
779 hdev->acl_mtu, hdev->acl_pkts,
780 hdev->sco_mtu, hdev->sco_pkts);
781}
782
783static void hci_cc_read_bd_addr(struct hci_dev *hdev, struct sk_buff *skb)
784{
785 struct hci_rp_read_bd_addr *rp = (void *) skb->data;
786
787 BT_DBG("%s status 0x%x", hdev->name, rp->status);
788
789 if (!rp->status)
790 bacpy(&hdev->bdaddr, &rp->bdaddr);
791
Johan Hedberg23bb5762010-12-21 23:01:27 +0200792 hci_req_complete(hdev, HCI_OP_READ_BD_ADDR, rp->status);
793}
794
Andrei Emeltchenko350ee4c2011-12-07 15:56:51 +0200795static void hci_cc_read_data_block_size(struct hci_dev *hdev,
796 struct sk_buff *skb)
797{
798 struct hci_rp_read_data_block_size *rp = (void *) skb->data;
799
800 BT_DBG("%s status 0x%x", hdev->name, rp->status);
801
802 if (rp->status)
803 return;
804
805 hdev->block_mtu = __le16_to_cpu(rp->max_acl_len);
806 hdev->block_len = __le16_to_cpu(rp->block_len);
807 hdev->num_blocks = __le16_to_cpu(rp->num_blocks);
808
809 hdev->block_cnt = hdev->num_blocks;
810
811 BT_DBG("%s blk mtu %d cnt %d len %d", hdev->name, hdev->block_mtu,
812 hdev->block_cnt, hdev->block_len);
813
814 hci_req_complete(hdev, HCI_OP_READ_DATA_BLOCK_SIZE, rp->status);
815}
816
Johan Hedberg23bb5762010-12-21 23:01:27 +0200817static void hci_cc_write_ca_timeout(struct hci_dev *hdev, struct sk_buff *skb)
818{
819 __u8 status = *((__u8 *) skb->data);
820
821 BT_DBG("%s status 0x%x", hdev->name, status);
822
823 hci_req_complete(hdev, HCI_OP_WRITE_CA_TIMEOUT, status);
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200824}
825
Andrei Emeltchenko928abaa2011-10-12 10:53:57 +0300826static void hci_cc_read_local_amp_info(struct hci_dev *hdev,
827 struct sk_buff *skb)
828{
829 struct hci_rp_read_local_amp_info *rp = (void *) skb->data;
830
831 BT_DBG("%s status 0x%x", hdev->name, rp->status);
832
833 if (rp->status)
834 return;
835
836 hdev->amp_status = rp->amp_status;
837 hdev->amp_total_bw = __le32_to_cpu(rp->total_bw);
838 hdev->amp_max_bw = __le32_to_cpu(rp->max_bw);
839 hdev->amp_min_latency = __le32_to_cpu(rp->min_latency);
840 hdev->amp_max_pdu = __le32_to_cpu(rp->max_pdu);
841 hdev->amp_type = rp->amp_type;
842 hdev->amp_pal_cap = __le16_to_cpu(rp->pal_cap);
843 hdev->amp_assoc_size = __le16_to_cpu(rp->max_assoc_size);
844 hdev->amp_be_flush_to = __le32_to_cpu(rp->be_flush_to);
845 hdev->amp_max_flush_to = __le32_to_cpu(rp->max_flush_to);
846
847 hci_req_complete(hdev, HCI_OP_READ_LOCAL_AMP_INFO, rp->status);
848}
849
Johan Hedbergb0916ea2011-01-10 13:44:55 +0200850static void hci_cc_delete_stored_link_key(struct hci_dev *hdev,
851 struct sk_buff *skb)
852{
853 __u8 status = *((__u8 *) skb->data);
854
855 BT_DBG("%s status 0x%x", hdev->name, status);
856
857 hci_req_complete(hdev, HCI_OP_DELETE_STORED_LINK_KEY, status);
858}
859
Johan Hedbergd5859e22011-01-25 01:19:58 +0200860static void hci_cc_set_event_mask(struct hci_dev *hdev, struct sk_buff *skb)
861{
862 __u8 status = *((__u8 *) skb->data);
863
864 BT_DBG("%s status 0x%x", hdev->name, status);
865
866 hci_req_complete(hdev, HCI_OP_SET_EVENT_MASK, status);
867}
868
869static void hci_cc_write_inquiry_mode(struct hci_dev *hdev,
870 struct sk_buff *skb)
871{
872 __u8 status = *((__u8 *) skb->data);
873
874 BT_DBG("%s status 0x%x", hdev->name, status);
875
876 hci_req_complete(hdev, HCI_OP_WRITE_INQUIRY_MODE, status);
877}
878
879static void hci_cc_read_inq_rsp_tx_power(struct hci_dev *hdev,
880 struct sk_buff *skb)
881{
882 __u8 status = *((__u8 *) skb->data);
883
884 BT_DBG("%s status 0x%x", hdev->name, status);
885
886 hci_req_complete(hdev, HCI_OP_READ_INQ_RSP_TX_POWER, status);
887}
888
889static void hci_cc_set_event_flt(struct hci_dev *hdev, struct sk_buff *skb)
890{
891 __u8 status = *((__u8 *) skb->data);
892
893 BT_DBG("%s status 0x%x", hdev->name, status);
894
895 hci_req_complete(hdev, HCI_OP_SET_EVENT_FLT, status);
896}
897
Johan Hedberg980e1a52011-01-22 06:10:07 +0200898static void hci_cc_pin_code_reply(struct hci_dev *hdev, struct sk_buff *skb)
899{
900 struct hci_rp_pin_code_reply *rp = (void *) skb->data;
901 struct hci_cp_pin_code_reply *cp;
902 struct hci_conn *conn;
903
904 BT_DBG("%s status 0x%x", hdev->name, rp->status);
905
Johan Hedberg56e5cb82011-11-08 20:40:16 +0200906 hci_dev_lock(hdev);
907
Johan Hedberga8b2d5c2012-01-08 23:11:15 +0200908 if (test_bit(HCI_MGMT, &hdev->dev_flags))
Johan Hedberg744cf192011-11-08 20:40:14 +0200909 mgmt_pin_code_reply_complete(hdev, &rp->bdaddr, rp->status);
Johan Hedberg980e1a52011-01-22 06:10:07 +0200910
911 if (rp->status != 0)
Johan Hedberg56e5cb82011-11-08 20:40:16 +0200912 goto unlock;
Johan Hedberg980e1a52011-01-22 06:10:07 +0200913
914 cp = hci_sent_cmd_data(hdev, HCI_OP_PIN_CODE_REPLY);
915 if (!cp)
Johan Hedberg56e5cb82011-11-08 20:40:16 +0200916 goto unlock;
Johan Hedberg980e1a52011-01-22 06:10:07 +0200917
918 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &cp->bdaddr);
919 if (conn)
920 conn->pin_length = cp->pin_len;
Johan Hedberg56e5cb82011-11-08 20:40:16 +0200921
922unlock:
923 hci_dev_unlock(hdev);
Johan Hedberg980e1a52011-01-22 06:10:07 +0200924}
925
926static void hci_cc_pin_code_neg_reply(struct hci_dev *hdev, struct sk_buff *skb)
927{
928 struct hci_rp_pin_code_neg_reply *rp = (void *) skb->data;
929
930 BT_DBG("%s status 0x%x", hdev->name, rp->status);
931
Johan Hedberg56e5cb82011-11-08 20:40:16 +0200932 hci_dev_lock(hdev);
933
Johan Hedberga8b2d5c2012-01-08 23:11:15 +0200934 if (test_bit(HCI_MGMT, &hdev->dev_flags))
Johan Hedberg744cf192011-11-08 20:40:14 +0200935 mgmt_pin_code_neg_reply_complete(hdev, &rp->bdaddr,
Johan Hedberg980e1a52011-01-22 06:10:07 +0200936 rp->status);
Johan Hedberg56e5cb82011-11-08 20:40:16 +0200937
938 hci_dev_unlock(hdev);
Johan Hedberg980e1a52011-01-22 06:10:07 +0200939}
Johan Hedberg56e5cb82011-11-08 20:40:16 +0200940
Ville Tervo6ed58ec2011-02-10 22:38:48 -0300941static void hci_cc_le_read_buffer_size(struct hci_dev *hdev,
942 struct sk_buff *skb)
943{
944 struct hci_rp_le_read_buffer_size *rp = (void *) skb->data;
945
946 BT_DBG("%s status 0x%x", hdev->name, rp->status);
947
948 if (rp->status)
949 return;
950
951 hdev->le_mtu = __le16_to_cpu(rp->le_mtu);
952 hdev->le_pkts = rp->le_max_pkt;
953
954 hdev->le_cnt = hdev->le_pkts;
955
956 BT_DBG("%s le mtu %d:%d", hdev->name, hdev->le_mtu, hdev->le_pkts);
957
958 hci_req_complete(hdev, HCI_OP_LE_READ_BUFFER_SIZE, rp->status);
959}
Johan Hedberg980e1a52011-01-22 06:10:07 +0200960
Johan Hedberga5c29682011-02-19 12:05:57 -0300961static void hci_cc_user_confirm_reply(struct hci_dev *hdev, struct sk_buff *skb)
962{
963 struct hci_rp_user_confirm_reply *rp = (void *) skb->data;
964
965 BT_DBG("%s status 0x%x", hdev->name, rp->status);
966
Johan Hedberg56e5cb82011-11-08 20:40:16 +0200967 hci_dev_lock(hdev);
968
Johan Hedberga8b2d5c2012-01-08 23:11:15 +0200969 if (test_bit(HCI_MGMT, &hdev->dev_flags))
Johan Hedberg272d90d2012-02-09 15:26:12 +0200970 mgmt_user_confirm_reply_complete(hdev, &rp->bdaddr, ACL_LINK,
971 0, rp->status);
Johan Hedberg56e5cb82011-11-08 20:40:16 +0200972
973 hci_dev_unlock(hdev);
Johan Hedberga5c29682011-02-19 12:05:57 -0300974}
975
976static void hci_cc_user_confirm_neg_reply(struct hci_dev *hdev,
977 struct sk_buff *skb)
978{
979 struct hci_rp_user_confirm_reply *rp = (void *) skb->data;
980
981 BT_DBG("%s status 0x%x", hdev->name, rp->status);
982
Johan Hedberg56e5cb82011-11-08 20:40:16 +0200983 hci_dev_lock(hdev);
984
Johan Hedberga8b2d5c2012-01-08 23:11:15 +0200985 if (test_bit(HCI_MGMT, &hdev->dev_flags))
Johan Hedberg744cf192011-11-08 20:40:14 +0200986 mgmt_user_confirm_neg_reply_complete(hdev, &rp->bdaddr,
Johan Hedberg272d90d2012-02-09 15:26:12 +0200987 ACL_LINK, 0,
Johan Hedberga5c29682011-02-19 12:05:57 -0300988 rp->status);
Johan Hedberg56e5cb82011-11-08 20:40:16 +0200989
990 hci_dev_unlock(hdev);
Johan Hedberga5c29682011-02-19 12:05:57 -0300991}
992
Brian Gix1143d452011-11-23 08:28:34 -0800993static void hci_cc_user_passkey_reply(struct hci_dev *hdev, struct sk_buff *skb)
994{
995 struct hci_rp_user_confirm_reply *rp = (void *) skb->data;
996
997 BT_DBG("%s status 0x%x", hdev->name, rp->status);
998
999 hci_dev_lock(hdev);
1000
Johan Hedberga8b2d5c2012-01-08 23:11:15 +02001001 if (test_bit(HCI_MGMT, &hdev->dev_flags))
Johan Hedberg272d90d2012-02-09 15:26:12 +02001002 mgmt_user_passkey_reply_complete(hdev, &rp->bdaddr, ACL_LINK,
1003 0, rp->status);
Brian Gix1143d452011-11-23 08:28:34 -08001004
1005 hci_dev_unlock(hdev);
1006}
1007
1008static void hci_cc_user_passkey_neg_reply(struct hci_dev *hdev,
1009 struct sk_buff *skb)
1010{
1011 struct hci_rp_user_confirm_reply *rp = (void *) skb->data;
1012
1013 BT_DBG("%s status 0x%x", hdev->name, rp->status);
1014
1015 hci_dev_lock(hdev);
1016
Johan Hedberga8b2d5c2012-01-08 23:11:15 +02001017 if (test_bit(HCI_MGMT, &hdev->dev_flags))
Brian Gix1143d452011-11-23 08:28:34 -08001018 mgmt_user_passkey_neg_reply_complete(hdev, &rp->bdaddr,
Johan Hedberg272d90d2012-02-09 15:26:12 +02001019 ACL_LINK, 0,
Brian Gix1143d452011-11-23 08:28:34 -08001020 rp->status);
1021
1022 hci_dev_unlock(hdev);
1023}
1024
Szymon Jancc35938b2011-03-22 13:12:21 +01001025static void hci_cc_read_local_oob_data_reply(struct hci_dev *hdev,
1026 struct sk_buff *skb)
1027{
1028 struct hci_rp_read_local_oob_data *rp = (void *) skb->data;
1029
1030 BT_DBG("%s status 0x%x", hdev->name, rp->status);
1031
Johan Hedberg56e5cb82011-11-08 20:40:16 +02001032 hci_dev_lock(hdev);
Johan Hedberg744cf192011-11-08 20:40:14 +02001033 mgmt_read_local_oob_data_reply_complete(hdev, rp->hash,
Szymon Jancc35938b2011-03-22 13:12:21 +01001034 rp->randomizer, rp->status);
Johan Hedberg56e5cb82011-11-08 20:40:16 +02001035 hci_dev_unlock(hdev);
Szymon Jancc35938b2011-03-22 13:12:21 +01001036}
1037
Andre Guedes07f7fa52011-12-02 21:13:31 +09001038static void hci_cc_le_set_scan_param(struct hci_dev *hdev, struct sk_buff *skb)
1039{
1040 __u8 status = *((__u8 *) skb->data);
1041
1042 BT_DBG("%s status 0x%x", hdev->name, status);
Andre Guedes7ba8b4b2012-02-03 17:47:59 -03001043
1044 hci_req_complete(hdev, HCI_OP_LE_SET_SCAN_PARAM, status);
Andre Guedes3fd24152012-02-03 17:48:01 -03001045
1046 if (status) {
1047 hci_dev_lock(hdev);
1048 mgmt_start_discovery_failed(hdev, status);
1049 hci_dev_unlock(hdev);
1050 return;
1051 }
Andre Guedes07f7fa52011-12-02 21:13:31 +09001052}
1053
Andre Guedeseb9d91f2011-05-26 16:23:52 -03001054static void hci_cc_le_set_scan_enable(struct hci_dev *hdev,
1055 struct sk_buff *skb)
1056{
1057 struct hci_cp_le_set_scan_enable *cp;
1058 __u8 status = *((__u8 *) skb->data);
1059
1060 BT_DBG("%s status 0x%x", hdev->name, status);
1061
Andre Guedeseb9d91f2011-05-26 16:23:52 -03001062 cp = hci_sent_cmd_data(hdev, HCI_OP_LE_SET_SCAN_ENABLE);
1063 if (!cp)
1064 return;
1065
Andrei Emeltchenko68a8aea2011-12-19 16:14:18 +02001066 switch (cp->enable) {
1067 case LE_SCANNING_ENABLED:
Andre Guedes7ba8b4b2012-02-03 17:47:59 -03001068 hci_req_complete(hdev, HCI_OP_LE_SET_SCAN_ENABLE, status);
1069
Andre Guedes3fd24152012-02-03 17:48:01 -03001070 if (status) {
1071 hci_dev_lock(hdev);
1072 mgmt_start_discovery_failed(hdev, status);
1073 hci_dev_unlock(hdev);
Andre Guedes7ba8b4b2012-02-03 17:47:59 -03001074 return;
Andre Guedes3fd24152012-02-03 17:48:01 -03001075 }
Andre Guedes7ba8b4b2012-02-03 17:47:59 -03001076
Andre Guedesd23264a2011-11-25 20:53:38 -03001077 set_bit(HCI_LE_SCAN, &hdev->dev_flags);
1078
Gustavo F. Padovandb323f22011-06-20 16:39:29 -03001079 cancel_delayed_work_sync(&hdev->adv_work);
Andre Guedesa8f13c82011-09-09 18:56:24 -03001080
1081 hci_dev_lock(hdev);
Andre Guedeseb9d91f2011-05-26 16:23:52 -03001082 hci_adv_entries_clear(hdev);
Andre Guedes343f9352012-02-17 20:39:37 -03001083 hci_discovery_set_state(hdev, DISCOVERY_FINDING);
Andre Guedesa8f13c82011-09-09 18:56:24 -03001084 hci_dev_unlock(hdev);
Andrei Emeltchenko68a8aea2011-12-19 16:14:18 +02001085 break;
1086
1087 case LE_SCANNING_DISABLED:
Andre Guedes7ba8b4b2012-02-03 17:47:59 -03001088 if (status)
1089 return;
1090
Andre Guedesd23264a2011-11-25 20:53:38 -03001091 clear_bit(HCI_LE_SCAN, &hdev->dev_flags);
1092
Andre Guedesd0843292012-01-02 19:18:11 -03001093 schedule_delayed_work(&hdev->adv_work, ADV_CLEAR_TIMEOUT);
Andre Guedes5e0452c2012-02-17 20:39:38 -03001094
1095 if (hdev->discovery.type == DISCOV_TYPE_INTERLEAVED) {
1096 mgmt_interleaved_discovery(hdev);
1097 } else {
1098 hci_dev_lock(hdev);
1099 hci_discovery_set_state(hdev, DISCOVERY_STOPPED);
1100 hci_dev_unlock(hdev);
1101 }
1102
Andrei Emeltchenko68a8aea2011-12-19 16:14:18 +02001103 break;
1104
1105 default:
1106 BT_ERR("Used reserved LE_Scan_Enable param %d", cp->enable);
1107 break;
Andre Guedes35815082011-05-26 16:23:53 -03001108 }
Andre Guedeseb9d91f2011-05-26 16:23:52 -03001109}
1110
Vinicius Costa Gomesa7a595f2011-06-09 18:50:47 -03001111static void hci_cc_le_ltk_reply(struct hci_dev *hdev, struct sk_buff *skb)
1112{
1113 struct hci_rp_le_ltk_reply *rp = (void *) skb->data;
1114
1115 BT_DBG("%s status 0x%x", hdev->name, rp->status);
1116
1117 if (rp->status)
1118 return;
1119
1120 hci_req_complete(hdev, HCI_OP_LE_LTK_REPLY, rp->status);
1121}
1122
1123static void hci_cc_le_ltk_neg_reply(struct hci_dev *hdev, struct sk_buff *skb)
1124{
1125 struct hci_rp_le_ltk_neg_reply *rp = (void *) skb->data;
1126
1127 BT_DBG("%s status 0x%x", hdev->name, rp->status);
1128
1129 if (rp->status)
1130 return;
1131
1132 hci_req_complete(hdev, HCI_OP_LE_LTK_NEG_REPLY, rp->status);
1133}
1134
Andre Guedesf9b49302011-06-30 19:20:53 -03001135static inline void hci_cc_write_le_host_supported(struct hci_dev *hdev,
1136 struct sk_buff *skb)
1137{
1138 struct hci_cp_read_local_ext_features cp;
1139 __u8 status = *((__u8 *) skb->data);
1140
1141 BT_DBG("%s status 0x%x", hdev->name, status);
1142
1143 if (status)
1144 return;
1145
1146 cp.page = 0x01;
1147 hci_send_cmd(hdev, HCI_OP_READ_LOCAL_EXT_FEATURES, sizeof(cp), &cp);
1148}
1149
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001150static inline void hci_cs_inquiry(struct hci_dev *hdev, __u8 status)
1151{
1152 BT_DBG("%s status 0x%x", hdev->name, status);
1153
1154 if (status) {
Johan Hedberg23bb5762010-12-21 23:01:27 +02001155 hci_req_complete(hdev, HCI_OP_INQUIRY, status);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001156 hci_conn_check_pending(hdev);
Johan Hedberg56e5cb82011-11-08 20:40:16 +02001157 hci_dev_lock(hdev);
Johan Hedberga8b2d5c2012-01-08 23:11:15 +02001158 if (test_bit(HCI_MGMT, &hdev->dev_flags))
Andre Guedes7a135102011-11-09 17:14:25 -03001159 mgmt_start_discovery_failed(hdev, status);
Johan Hedberg56e5cb82011-11-08 20:40:16 +02001160 hci_dev_unlock(hdev);
Johan Hedberg314b2382011-04-27 10:29:57 -04001161 return;
1162 }
1163
Andre Guedes89352e72011-11-04 14:16:53 -03001164 set_bit(HCI_INQUIRY, &hdev->flags);
1165
Johan Hedberg56e5cb82011-11-08 20:40:16 +02001166 hci_dev_lock(hdev);
Andre Guedes343f9352012-02-17 20:39:37 -03001167 hci_discovery_set_state(hdev, DISCOVERY_FINDING);
Johan Hedberg56e5cb82011-11-08 20:40:16 +02001168 hci_dev_unlock(hdev);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001169}
1170
Linus Torvalds1da177e2005-04-16 15:20:36 -07001171static inline void hci_cs_create_conn(struct hci_dev *hdev, __u8 status)
1172{
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001173 struct hci_cp_create_conn *cp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001174 struct hci_conn *conn;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001175
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001176 BT_DBG("%s status 0x%x", hdev->name, status);
1177
1178 cp = hci_sent_cmd_data(hdev, HCI_OP_CREATE_CONN);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001179 if (!cp)
1180 return;
1181
1182 hci_dev_lock(hdev);
1183
1184 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &cp->bdaddr);
1185
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001186 BT_DBG("%s bdaddr %s conn %p", hdev->name, batostr(&cp->bdaddr), conn);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001187
1188 if (status) {
1189 if (conn && conn->state == BT_CONNECT) {
Marcel Holtmann4c67bc72006-10-15 17:30:56 +02001190 if (status != 0x0c || conn->attempt > 2) {
1191 conn->state = BT_CLOSED;
1192 hci_proto_connect_cfm(conn, status);
1193 hci_conn_del(conn);
1194 } else
1195 conn->state = BT_CONNECT2;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001196 }
1197 } else {
1198 if (!conn) {
1199 conn = hci_conn_add(hdev, ACL_LINK, &cp->bdaddr);
1200 if (conn) {
Johan Hedberga0c808b2012-01-16 09:49:58 +02001201 conn->out = true;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001202 conn->link_mode |= HCI_LM_MASTER;
1203 } else
Gustavo F. Padovan893ef972010-07-18 15:13:37 -03001204 BT_ERR("No memory for new connection");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001205 }
1206 }
1207
1208 hci_dev_unlock(hdev);
1209}
1210
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001211static void hci_cs_add_sco(struct hci_dev *hdev, __u8 status)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001212{
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001213 struct hci_cp_add_sco *cp;
1214 struct hci_conn *acl, *sco;
1215 __u16 handle;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001216
Marcel Holtmannb6a0dc82007-10-20 14:55:10 +02001217 BT_DBG("%s status 0x%x", hdev->name, status);
1218
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001219 if (!status)
1220 return;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001221
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001222 cp = hci_sent_cmd_data(hdev, HCI_OP_ADD_SCO);
1223 if (!cp)
1224 return;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001225
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001226 handle = __le16_to_cpu(cp->handle);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001227
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001228 BT_DBG("%s handle %d", hdev->name, handle);
Marcel Holtmann6bd57412006-11-18 22:14:22 +01001229
1230 hci_dev_lock(hdev);
1231
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001232 acl = hci_conn_hash_lookup_handle(hdev, handle);
Andrei Emeltchenko5a08ecc2011-01-11 17:20:20 +02001233 if (acl) {
1234 sco = acl->link;
1235 if (sco) {
1236 sco->state = BT_CLOSED;
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001237
Andrei Emeltchenko5a08ecc2011-01-11 17:20:20 +02001238 hci_proto_connect_cfm(sco, status);
1239 hci_conn_del(sco);
1240 }
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001241 }
Marcel Holtmann6bd57412006-11-18 22:14:22 +01001242
1243 hci_dev_unlock(hdev);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001244}
1245
Marcel Holtmannf8558552008-07-14 20:13:49 +02001246static void hci_cs_auth_requested(struct hci_dev *hdev, __u8 status)
1247{
1248 struct hci_cp_auth_requested *cp;
1249 struct hci_conn *conn;
1250
1251 BT_DBG("%s status 0x%x", hdev->name, status);
1252
1253 if (!status)
1254 return;
1255
1256 cp = hci_sent_cmd_data(hdev, HCI_OP_AUTH_REQUESTED);
1257 if (!cp)
1258 return;
1259
1260 hci_dev_lock(hdev);
1261
1262 conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(cp->handle));
1263 if (conn) {
1264 if (conn->state == BT_CONFIG) {
1265 hci_proto_connect_cfm(conn, status);
1266 hci_conn_put(conn);
1267 }
1268 }
1269
1270 hci_dev_unlock(hdev);
1271}
1272
1273static void hci_cs_set_conn_encrypt(struct hci_dev *hdev, __u8 status)
1274{
1275 struct hci_cp_set_conn_encrypt *cp;
1276 struct hci_conn *conn;
1277
1278 BT_DBG("%s status 0x%x", hdev->name, status);
1279
1280 if (!status)
1281 return;
1282
1283 cp = hci_sent_cmd_data(hdev, HCI_OP_SET_CONN_ENCRYPT);
1284 if (!cp)
1285 return;
1286
1287 hci_dev_lock(hdev);
1288
1289 conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(cp->handle));
1290 if (conn) {
1291 if (conn->state == BT_CONFIG) {
1292 hci_proto_connect_cfm(conn, status);
1293 hci_conn_put(conn);
1294 }
1295 }
1296
1297 hci_dev_unlock(hdev);
1298}
1299
Johan Hedberg127178d2010-11-18 22:22:29 +02001300static int hci_outgoing_auth_needed(struct hci_dev *hdev,
Szymon Janc138d22e2011-02-17 16:44:23 +01001301 struct hci_conn *conn)
Johan Hedberg392599b2010-11-18 22:22:28 +02001302{
Johan Hedberg392599b2010-11-18 22:22:28 +02001303 if (conn->state != BT_CONFIG || !conn->out)
1304 return 0;
1305
Johan Hedberg765c2a92011-01-19 12:06:52 +05301306 if (conn->pending_sec_level == BT_SECURITY_SDP)
Johan Hedberg392599b2010-11-18 22:22:28 +02001307 return 0;
1308
1309 /* Only request authentication for SSP connections or non-SSP
Vinicius Costa Gomese9bf2bf2011-09-02 14:51:20 -03001310 * devices with sec_level HIGH or if MITM protection is requested */
Johan Hedbergaa64a8b2012-01-18 21:33:12 +02001311 if (!hci_conn_ssp_enabled(conn) &&
Vinicius Costa Gomese9bf2bf2011-09-02 14:51:20 -03001312 conn->pending_sec_level != BT_SECURITY_HIGH &&
1313 !(conn->auth_type & 0x01))
Johan Hedberg392599b2010-11-18 22:22:28 +02001314 return 0;
1315
Johan Hedberg392599b2010-11-18 22:22:28 +02001316 return 1;
1317}
1318
Johan Hedberg30dc78e2012-01-04 15:44:20 +02001319static inline int hci_resolve_name(struct hci_dev *hdev, struct inquiry_entry *e)
1320{
1321 struct hci_cp_remote_name_req cp;
1322
1323 memset(&cp, 0, sizeof(cp));
1324
1325 bacpy(&cp.bdaddr, &e->data.bdaddr);
1326 cp.pscan_rep_mode = e->data.pscan_rep_mode;
1327 cp.pscan_mode = e->data.pscan_mode;
1328 cp.clock_offset = e->data.clock_offset;
1329
1330 return hci_send_cmd(hdev, HCI_OP_REMOTE_NAME_REQ, sizeof(cp), &cp);
1331}
1332
Johan Hedbergb644ba32012-01-17 21:48:47 +02001333static bool hci_resolve_next_name(struct hci_dev *hdev)
Johan Hedberg30dc78e2012-01-04 15:44:20 +02001334{
1335 struct discovery_state *discov = &hdev->discovery;
1336 struct inquiry_entry *e;
1337
Johan Hedbergb644ba32012-01-17 21:48:47 +02001338 if (list_empty(&discov->resolve))
1339 return false;
1340
1341 e = hci_inquiry_cache_lookup_resolve(hdev, BDADDR_ANY, NAME_NEEDED);
1342 if (hci_resolve_name(hdev, e) == 0) {
1343 e->name_state = NAME_PENDING;
1344 return true;
1345 }
1346
1347 return false;
1348}
1349
1350static void hci_check_pending_name(struct hci_dev *hdev, struct hci_conn *conn,
1351 bdaddr_t *bdaddr, u8 *name, u8 name_len)
1352{
1353 struct discovery_state *discov = &hdev->discovery;
1354 struct inquiry_entry *e;
1355
1356 if (conn && !test_and_set_bit(HCI_CONN_MGMT_CONNECTED, &conn->flags))
1357 mgmt_device_connected(hdev, bdaddr, ACL_LINK, 0x00,
1358 name, name_len, conn->dev_class);
1359
1360 if (discov->state == DISCOVERY_STOPPED)
1361 return;
1362
Johan Hedberg30dc78e2012-01-04 15:44:20 +02001363 if (discov->state == DISCOVERY_STOPPING)
1364 goto discov_complete;
1365
1366 if (discov->state != DISCOVERY_RESOLVING)
1367 return;
1368
1369 e = hci_inquiry_cache_lookup_resolve(hdev, bdaddr, NAME_PENDING);
1370 if (e) {
1371 e->name_state = NAME_KNOWN;
1372 list_del(&e->list);
Johan Hedbergb644ba32012-01-17 21:48:47 +02001373 if (name)
1374 mgmt_remote_name(hdev, bdaddr, ACL_LINK, 0x00,
1375 e->data.rssi, name, name_len);
Johan Hedberg30dc78e2012-01-04 15:44:20 +02001376 }
1377
Johan Hedbergb644ba32012-01-17 21:48:47 +02001378 if (hci_resolve_next_name(hdev))
Johan Hedberg30dc78e2012-01-04 15:44:20 +02001379 return;
Johan Hedberg30dc78e2012-01-04 15:44:20 +02001380
1381discov_complete:
1382 hci_discovery_set_state(hdev, DISCOVERY_STOPPED);
1383}
1384
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001385static void hci_cs_remote_name_req(struct hci_dev *hdev, __u8 status)
1386{
Johan Hedberg127178d2010-11-18 22:22:29 +02001387 struct hci_cp_remote_name_req *cp;
1388 struct hci_conn *conn;
1389
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001390 BT_DBG("%s status 0x%x", hdev->name, status);
Johan Hedberg127178d2010-11-18 22:22:29 +02001391
1392 /* If successful wait for the name req complete event before
1393 * checking for the need to do authentication */
1394 if (!status)
1395 return;
1396
1397 cp = hci_sent_cmd_data(hdev, HCI_OP_REMOTE_NAME_REQ);
1398 if (!cp)
1399 return;
1400
1401 hci_dev_lock(hdev);
1402
1403 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &cp->bdaddr);
Johan Hedbergb644ba32012-01-17 21:48:47 +02001404
1405 if (test_bit(HCI_MGMT, &hdev->dev_flags))
1406 hci_check_pending_name(hdev, conn, &cp->bdaddr, NULL, 0);
1407
Johan Hedberg79c6c702011-04-28 11:28:55 -07001408 if (!conn)
1409 goto unlock;
1410
1411 if (!hci_outgoing_auth_needed(hdev, conn))
1412 goto unlock;
1413
Johan Hedberg51a8efd2012-01-16 06:10:31 +02001414 if (!test_and_set_bit(HCI_CONN_AUTH_PEND, &conn->flags)) {
Johan Hedberg127178d2010-11-18 22:22:29 +02001415 struct hci_cp_auth_requested cp;
1416 cp.handle = __cpu_to_le16(conn->handle);
1417 hci_send_cmd(hdev, HCI_OP_AUTH_REQUESTED, sizeof(cp), &cp);
1418 }
1419
Johan Hedberg79c6c702011-04-28 11:28:55 -07001420unlock:
Johan Hedberg127178d2010-11-18 22:22:29 +02001421 hci_dev_unlock(hdev);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001422}
1423
Marcel Holtmann769be972008-07-14 20:13:49 +02001424static void hci_cs_read_remote_features(struct hci_dev *hdev, __u8 status)
1425{
1426 struct hci_cp_read_remote_features *cp;
1427 struct hci_conn *conn;
1428
1429 BT_DBG("%s status 0x%x", hdev->name, status);
1430
1431 if (!status)
1432 return;
1433
1434 cp = hci_sent_cmd_data(hdev, HCI_OP_READ_REMOTE_FEATURES);
1435 if (!cp)
1436 return;
1437
1438 hci_dev_lock(hdev);
1439
1440 conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(cp->handle));
1441 if (conn) {
1442 if (conn->state == BT_CONFIG) {
Marcel Holtmann769be972008-07-14 20:13:49 +02001443 hci_proto_connect_cfm(conn, status);
1444 hci_conn_put(conn);
1445 }
1446 }
1447
1448 hci_dev_unlock(hdev);
1449}
1450
1451static void hci_cs_read_remote_ext_features(struct hci_dev *hdev, __u8 status)
1452{
1453 struct hci_cp_read_remote_ext_features *cp;
1454 struct hci_conn *conn;
1455
1456 BT_DBG("%s status 0x%x", hdev->name, status);
1457
1458 if (!status)
1459 return;
1460
1461 cp = hci_sent_cmd_data(hdev, HCI_OP_READ_REMOTE_EXT_FEATURES);
1462 if (!cp)
1463 return;
1464
1465 hci_dev_lock(hdev);
1466
1467 conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(cp->handle));
1468 if (conn) {
1469 if (conn->state == BT_CONFIG) {
Marcel Holtmann769be972008-07-14 20:13:49 +02001470 hci_proto_connect_cfm(conn, status);
1471 hci_conn_put(conn);
1472 }
1473 }
1474
1475 hci_dev_unlock(hdev);
1476}
1477
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001478static void hci_cs_setup_sync_conn(struct hci_dev *hdev, __u8 status)
1479{
Marcel Holtmannb6a0dc82007-10-20 14:55:10 +02001480 struct hci_cp_setup_sync_conn *cp;
1481 struct hci_conn *acl, *sco;
1482 __u16 handle;
1483
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001484 BT_DBG("%s status 0x%x", hdev->name, status);
Marcel Holtmannb6a0dc82007-10-20 14:55:10 +02001485
1486 if (!status)
1487 return;
1488
1489 cp = hci_sent_cmd_data(hdev, HCI_OP_SETUP_SYNC_CONN);
1490 if (!cp)
1491 return;
1492
1493 handle = __le16_to_cpu(cp->handle);
1494
1495 BT_DBG("%s handle %d", hdev->name, handle);
1496
1497 hci_dev_lock(hdev);
1498
1499 acl = hci_conn_hash_lookup_handle(hdev, handle);
Andrei Emeltchenko5a08ecc2011-01-11 17:20:20 +02001500 if (acl) {
1501 sco = acl->link;
1502 if (sco) {
1503 sco->state = BT_CLOSED;
Marcel Holtmannb6a0dc82007-10-20 14:55:10 +02001504
Andrei Emeltchenko5a08ecc2011-01-11 17:20:20 +02001505 hci_proto_connect_cfm(sco, status);
1506 hci_conn_del(sco);
1507 }
Marcel Holtmannb6a0dc82007-10-20 14:55:10 +02001508 }
1509
1510 hci_dev_unlock(hdev);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001511}
1512
1513static void hci_cs_sniff_mode(struct hci_dev *hdev, __u8 status)
1514{
1515 struct hci_cp_sniff_mode *cp;
1516 struct hci_conn *conn;
1517
1518 BT_DBG("%s status 0x%x", hdev->name, status);
1519
1520 if (!status)
1521 return;
1522
1523 cp = hci_sent_cmd_data(hdev, HCI_OP_SNIFF_MODE);
1524 if (!cp)
1525 return;
1526
1527 hci_dev_lock(hdev);
1528
1529 conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(cp->handle));
Marcel Holtmanne73439d2010-07-26 10:06:00 -04001530 if (conn) {
Johan Hedberg51a8efd2012-01-16 06:10:31 +02001531 clear_bit(HCI_CONN_MODE_CHANGE_PEND, &conn->flags);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001532
Johan Hedberg51a8efd2012-01-16 06:10:31 +02001533 if (test_and_clear_bit(HCI_CONN_SCO_SETUP_PEND, &conn->flags))
Marcel Holtmanne73439d2010-07-26 10:06:00 -04001534 hci_sco_setup(conn, status);
1535 }
1536
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001537 hci_dev_unlock(hdev);
1538}
1539
1540static void hci_cs_exit_sniff_mode(struct hci_dev *hdev, __u8 status)
1541{
1542 struct hci_cp_exit_sniff_mode *cp;
1543 struct hci_conn *conn;
1544
1545 BT_DBG("%s status 0x%x", hdev->name, status);
1546
1547 if (!status)
1548 return;
1549
1550 cp = hci_sent_cmd_data(hdev, HCI_OP_EXIT_SNIFF_MODE);
1551 if (!cp)
1552 return;
1553
1554 hci_dev_lock(hdev);
1555
1556 conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(cp->handle));
Marcel Holtmanne73439d2010-07-26 10:06:00 -04001557 if (conn) {
Johan Hedberg51a8efd2012-01-16 06:10:31 +02001558 clear_bit(HCI_CONN_MODE_CHANGE_PEND, &conn->flags);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001559
Johan Hedberg51a8efd2012-01-16 06:10:31 +02001560 if (test_and_clear_bit(HCI_CONN_SCO_SETUP_PEND, &conn->flags))
Marcel Holtmanne73439d2010-07-26 10:06:00 -04001561 hci_sco_setup(conn, status);
1562 }
1563
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001564 hci_dev_unlock(hdev);
1565}
1566
Johan Hedberg88c3df12012-02-09 14:27:38 +02001567static void hci_cs_disconnect(struct hci_dev *hdev, u8 status)
1568{
1569 struct hci_cp_disconnect *cp;
1570 struct hci_conn *conn;
1571
1572 if (!status)
1573 return;
1574
1575 cp = hci_sent_cmd_data(hdev, HCI_OP_DISCONNECT);
1576 if (!cp)
1577 return;
1578
1579 hci_dev_lock(hdev);
1580
1581 conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(cp->handle));
1582 if (conn)
1583 mgmt_disconnect_failed(hdev, &conn->dst, conn->type,
1584 conn->dst_type, status);
1585
1586 hci_dev_unlock(hdev);
1587}
1588
Ville Tervofcd89c02011-02-10 22:38:47 -03001589static void hci_cs_le_create_conn(struct hci_dev *hdev, __u8 status)
1590{
1591 struct hci_cp_le_create_conn *cp;
1592 struct hci_conn *conn;
1593
1594 BT_DBG("%s status 0x%x", hdev->name, status);
1595
1596 cp = hci_sent_cmd_data(hdev, HCI_OP_LE_CREATE_CONN);
1597 if (!cp)
1598 return;
1599
1600 hci_dev_lock(hdev);
1601
1602 conn = hci_conn_hash_lookup_ba(hdev, LE_LINK, &cp->peer_addr);
1603
1604 BT_DBG("%s bdaddr %s conn %p", hdev->name, batostr(&cp->peer_addr),
1605 conn);
1606
1607 if (status) {
1608 if (conn && conn->state == BT_CONNECT) {
1609 conn->state = BT_CLOSED;
1610 hci_proto_connect_cfm(conn, status);
1611 hci_conn_del(conn);
1612 }
1613 } else {
1614 if (!conn) {
1615 conn = hci_conn_add(hdev, LE_LINK, &cp->peer_addr);
Andre Guedes29b79882011-05-31 14:20:54 -03001616 if (conn) {
1617 conn->dst_type = cp->peer_addr_type;
Johan Hedberga0c808b2012-01-16 09:49:58 +02001618 conn->out = true;
Andre Guedes29b79882011-05-31 14:20:54 -03001619 } else {
Ville Tervofcd89c02011-02-10 22:38:47 -03001620 BT_ERR("No memory for new connection");
Andre Guedes29b79882011-05-31 14:20:54 -03001621 }
Ville Tervofcd89c02011-02-10 22:38:47 -03001622 }
1623 }
1624
1625 hci_dev_unlock(hdev);
1626}
1627
Vinicius Costa Gomesa7a595f2011-06-09 18:50:47 -03001628static void hci_cs_le_start_enc(struct hci_dev *hdev, u8 status)
1629{
1630 BT_DBG("%s status 0x%x", hdev->name, status);
1631}
1632
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001633static inline void hci_inquiry_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
1634{
1635 __u8 status = *((__u8 *) skb->data);
Johan Hedberg30dc78e2012-01-04 15:44:20 +02001636 struct discovery_state *discov = &hdev->discovery;
1637 struct inquiry_entry *e;
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001638
1639 BT_DBG("%s status %d", hdev->name, status);
1640
Johan Hedberg23bb5762010-12-21 23:01:27 +02001641 hci_req_complete(hdev, HCI_OP_INQUIRY, status);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001642
1643 hci_conn_check_pending(hdev);
Andre Guedes89352e72011-11-04 14:16:53 -03001644
1645 if (!test_and_clear_bit(HCI_INQUIRY, &hdev->flags))
1646 return;
1647
Johan Hedberga8b2d5c2012-01-08 23:11:15 +02001648 if (!test_bit(HCI_MGMT, &hdev->dev_flags))
Johan Hedberg30dc78e2012-01-04 15:44:20 +02001649 return;
1650
Johan Hedberg56e5cb82011-11-08 20:40:16 +02001651 hci_dev_lock(hdev);
Johan Hedberg30dc78e2012-01-04 15:44:20 +02001652
Andre Guedes343f9352012-02-17 20:39:37 -03001653 if (discov->state != DISCOVERY_FINDING)
Johan Hedberg30dc78e2012-01-04 15:44:20 +02001654 goto unlock;
1655
1656 if (list_empty(&discov->resolve)) {
1657 hci_discovery_set_state(hdev, DISCOVERY_STOPPED);
1658 goto unlock;
1659 }
1660
1661 e = hci_inquiry_cache_lookup_resolve(hdev, BDADDR_ANY, NAME_NEEDED);
1662 if (e && hci_resolve_name(hdev, e) == 0) {
1663 e->name_state = NAME_PENDING;
1664 hci_discovery_set_state(hdev, DISCOVERY_RESOLVING);
1665 } else {
1666 hci_discovery_set_state(hdev, DISCOVERY_STOPPED);
1667 }
1668
1669unlock:
Johan Hedberg56e5cb82011-11-08 20:40:16 +02001670 hci_dev_unlock(hdev);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001671}
1672
Linus Torvalds1da177e2005-04-16 15:20:36 -07001673static inline void hci_inquiry_result_evt(struct hci_dev *hdev, struct sk_buff *skb)
1674{
Marcel Holtmann45bb4bf2005-08-09 20:27:49 -07001675 struct inquiry_data data;
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001676 struct inquiry_info *info = (void *) (skb->data + 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001677 int num_rsp = *((__u8 *) skb->data);
1678
1679 BT_DBG("%s num_rsp %d", hdev->name, num_rsp);
1680
Marcel Holtmann45bb4bf2005-08-09 20:27:49 -07001681 if (!num_rsp)
1682 return;
1683
Linus Torvalds1da177e2005-04-16 15:20:36 -07001684 hci_dev_lock(hdev);
Marcel Holtmann45bb4bf2005-08-09 20:27:49 -07001685
Johan Hedberge17acd42011-03-30 23:57:16 +03001686 for (; num_rsp; num_rsp--, info++) {
Johan Hedberg31754052012-01-04 13:39:52 +02001687 bool name_known;
1688
Linus Torvalds1da177e2005-04-16 15:20:36 -07001689 bacpy(&data.bdaddr, &info->bdaddr);
1690 data.pscan_rep_mode = info->pscan_rep_mode;
1691 data.pscan_period_mode = info->pscan_period_mode;
1692 data.pscan_mode = info->pscan_mode;
1693 memcpy(data.dev_class, info->dev_class, 3);
1694 data.clock_offset = info->clock_offset;
1695 data.rssi = 0x00;
Marcel Holtmann41a96212008-07-14 20:13:48 +02001696 data.ssp_mode = 0x00;
Johan Hedberg31754052012-01-04 13:39:52 +02001697
1698 name_known = hci_inquiry_cache_update(hdev, &data, false);
Johan Hedberg48264f02011-11-09 13:58:58 +02001699 mgmt_device_found(hdev, &info->bdaddr, ACL_LINK, 0x00,
Andre Guedes7d262f82012-01-10 18:20:49 -03001700 info->dev_class, 0, !name_known,
1701 NULL, 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001702 }
Marcel Holtmann45bb4bf2005-08-09 20:27:49 -07001703
Linus Torvalds1da177e2005-04-16 15:20:36 -07001704 hci_dev_unlock(hdev);
1705}
1706
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001707static inline void hci_conn_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001708{
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001709 struct hci_ev_conn_complete *ev = (void *) skb->data;
1710 struct hci_conn *conn;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001711
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001712 BT_DBG("%s", hdev->name);
Marcel Holtmann45bb4bf2005-08-09 20:27:49 -07001713
Linus Torvalds1da177e2005-04-16 15:20:36 -07001714 hci_dev_lock(hdev);
Marcel Holtmann45bb4bf2005-08-09 20:27:49 -07001715
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001716 conn = hci_conn_hash_lookup_ba(hdev, ev->link_type, &ev->bdaddr);
Marcel Holtmann94992372009-04-19 19:30:03 +02001717 if (!conn) {
1718 if (ev->link_type != SCO_LINK)
1719 goto unlock;
1720
1721 conn = hci_conn_hash_lookup_ba(hdev, ESCO_LINK, &ev->bdaddr);
1722 if (!conn)
1723 goto unlock;
1724
1725 conn->type = SCO_LINK;
1726 }
Marcel Holtmann45bb4bf2005-08-09 20:27:49 -07001727
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001728 if (!ev->status) {
1729 conn->handle = __le16_to_cpu(ev->handle);
Marcel Holtmann769be972008-07-14 20:13:49 +02001730
1731 if (conn->type == ACL_LINK) {
1732 conn->state = BT_CONFIG;
1733 hci_conn_hold(conn);
Marcel Holtmann052b30b2009-04-26 20:01:22 +02001734 conn->disc_timeout = HCI_DISCONN_TIMEOUT;
Marcel Holtmann769be972008-07-14 20:13:49 +02001735 } else
1736 conn->state = BT_CONNECTED;
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001737
Marcel Holtmann9eba32b2009-08-22 14:19:26 -07001738 hci_conn_hold_device(conn);
Marcel Holtmann7d0db0a2008-07-14 20:13:51 +02001739 hci_conn_add_sysfs(conn);
1740
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001741 if (test_bit(HCI_AUTH, &hdev->flags))
1742 conn->link_mode |= HCI_LM_AUTH;
1743
1744 if (test_bit(HCI_ENCRYPT, &hdev->flags))
1745 conn->link_mode |= HCI_LM_ENCRYPT;
1746
1747 /* Get remote features */
1748 if (conn->type == ACL_LINK) {
1749 struct hci_cp_read_remote_features cp;
1750 cp.handle = ev->handle;
Marcel Holtmann769be972008-07-14 20:13:49 +02001751 hci_send_cmd(hdev, HCI_OP_READ_REMOTE_FEATURES,
1752 sizeof(cp), &cp);
Marcel Holtmann45bb4bf2005-08-09 20:27:49 -07001753 }
Marcel Holtmann45bb4bf2005-08-09 20:27:49 -07001754
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001755 /* Set packet type for incoming connection */
Andrei Emeltchenkod095c1e2011-12-01 14:33:27 +02001756 if (!conn->out && hdev->hci_ver < BLUETOOTH_VER_2_0) {
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001757 struct hci_cp_change_conn_ptype cp;
1758 cp.handle = ev->handle;
Marcel Holtmanna8746412008-07-14 20:13:46 +02001759 cp.pkt_type = cpu_to_le16(conn->pkt_type);
1760 hci_send_cmd(hdev, HCI_OP_CHANGE_CONN_PTYPE,
1761 sizeof(cp), &cp);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001762 }
Johan Hedberg17d5c042011-01-22 06:09:08 +02001763 } else {
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001764 conn->state = BT_CLOSED;
Johan Hedberg17d5c042011-01-22 06:09:08 +02001765 if (conn->type == ACL_LINK)
Johan Hedberg744cf192011-11-08 20:40:14 +02001766 mgmt_connect_failed(hdev, &ev->bdaddr, conn->type,
Johan Hedberg48264f02011-11-09 13:58:58 +02001767 conn->dst_type, ev->status);
Johan Hedberg17d5c042011-01-22 06:09:08 +02001768 }
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001769
Marcel Holtmanne73439d2010-07-26 10:06:00 -04001770 if (conn->type == ACL_LINK)
1771 hci_sco_setup(conn, ev->status);
Marcel Holtmann45bb4bf2005-08-09 20:27:49 -07001772
Marcel Holtmann769be972008-07-14 20:13:49 +02001773 if (ev->status) {
1774 hci_proto_connect_cfm(conn, ev->status);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001775 hci_conn_del(conn);
Marcel Holtmannc89b6e62009-01-15 21:57:03 +01001776 } else if (ev->link_type != ACL_LINK)
1777 hci_proto_connect_cfm(conn, ev->status);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001778
1779unlock:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001780 hci_dev_unlock(hdev);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001781
1782 hci_conn_check_pending(hdev);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001783}
1784
Linus Torvalds1da177e2005-04-16 15:20:36 -07001785static inline void hci_conn_request_evt(struct hci_dev *hdev, struct sk_buff *skb)
1786{
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001787 struct hci_ev_conn_request *ev = (void *) skb->data;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001788 int mask = hdev->link_mode;
1789
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001790 BT_DBG("%s bdaddr %s type 0x%x", hdev->name,
1791 batostr(&ev->bdaddr), ev->link_type);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001792
1793 mask |= hci_proto_connect_ind(hdev, &ev->bdaddr, ev->link_type);
1794
Szymon Janc138d22e2011-02-17 16:44:23 +01001795 if ((mask & HCI_LM_ACCEPT) &&
1796 !hci_blacklist_lookup(hdev, &ev->bdaddr)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001797 /* Connection accepted */
Marcel Holtmannc7bdd502008-07-14 20:13:47 +02001798 struct inquiry_entry *ie;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001799 struct hci_conn *conn;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001800
1801 hci_dev_lock(hdev);
Marcel Holtmannb6a0dc82007-10-20 14:55:10 +02001802
Andrei Emeltchenkocc11b9c2010-11-22 13:21:37 +02001803 ie = hci_inquiry_cache_lookup(hdev, &ev->bdaddr);
1804 if (ie)
Marcel Holtmannc7bdd502008-07-14 20:13:47 +02001805 memcpy(ie->data.dev_class, ev->dev_class, 3);
1806
Linus Torvalds1da177e2005-04-16 15:20:36 -07001807 conn = hci_conn_hash_lookup_ba(hdev, ev->link_type, &ev->bdaddr);
1808 if (!conn) {
Andrei Emeltchenkocc11b9c2010-11-22 13:21:37 +02001809 conn = hci_conn_add(hdev, ev->link_type, &ev->bdaddr);
1810 if (!conn) {
Gustavo F. Padovan893ef972010-07-18 15:13:37 -03001811 BT_ERR("No memory for new connection");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001812 hci_dev_unlock(hdev);
1813 return;
1814 }
1815 }
Marcel Holtmannb6a0dc82007-10-20 14:55:10 +02001816
Linus Torvalds1da177e2005-04-16 15:20:36 -07001817 memcpy(conn->dev_class, ev->dev_class, 3);
1818 conn->state = BT_CONNECT;
Marcel Holtmannb6a0dc82007-10-20 14:55:10 +02001819
Linus Torvalds1da177e2005-04-16 15:20:36 -07001820 hci_dev_unlock(hdev);
1821
Marcel Holtmannb6a0dc82007-10-20 14:55:10 +02001822 if (ev->link_type == ACL_LINK || !lmp_esco_capable(hdev)) {
1823 struct hci_cp_accept_conn_req cp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001824
Marcel Holtmannb6a0dc82007-10-20 14:55:10 +02001825 bacpy(&cp.bdaddr, &ev->bdaddr);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001826
Marcel Holtmannb6a0dc82007-10-20 14:55:10 +02001827 if (lmp_rswitch_capable(hdev) && (mask & HCI_LM_MASTER))
1828 cp.role = 0x00; /* Become master */
1829 else
1830 cp.role = 0x01; /* Remain slave */
1831
1832 hci_send_cmd(hdev, HCI_OP_ACCEPT_CONN_REQ,
1833 sizeof(cp), &cp);
1834 } else {
1835 struct hci_cp_accept_sync_conn_req cp;
1836
1837 bacpy(&cp.bdaddr, &ev->bdaddr);
Marcel Holtmanna8746412008-07-14 20:13:46 +02001838 cp.pkt_type = cpu_to_le16(conn->pkt_type);
Marcel Holtmannb6a0dc82007-10-20 14:55:10 +02001839
1840 cp.tx_bandwidth = cpu_to_le32(0x00001f40);
1841 cp.rx_bandwidth = cpu_to_le32(0x00001f40);
1842 cp.max_latency = cpu_to_le16(0xffff);
1843 cp.content_format = cpu_to_le16(hdev->voice_setting);
1844 cp.retrans_effort = 0xff;
1845
1846 hci_send_cmd(hdev, HCI_OP_ACCEPT_SYNC_CONN_REQ,
1847 sizeof(cp), &cp);
1848 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001849 } else {
1850 /* Connection rejected */
1851 struct hci_cp_reject_conn_req cp;
1852
1853 bacpy(&cp.bdaddr, &ev->bdaddr);
Andrei Emeltchenko9f5a0d72011-11-07 14:20:25 +02001854 cp.reason = HCI_ERROR_REJ_BAD_ADDR;
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001855 hci_send_cmd(hdev, HCI_OP_REJECT_CONN_REQ, sizeof(cp), &cp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001856 }
1857}
1858
Linus Torvalds1da177e2005-04-16 15:20:36 -07001859static inline void hci_disconn_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
1860{
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001861 struct hci_ev_disconn_complete *ev = (void *) skb->data;
Marcel Holtmann04837f62006-07-03 10:02:33 +02001862 struct hci_conn *conn;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001863
1864 BT_DBG("%s status %d", hdev->name, ev->status);
1865
Linus Torvalds1da177e2005-04-16 15:20:36 -07001866 hci_dev_lock(hdev);
1867
Marcel Holtmann04837f62006-07-03 10:02:33 +02001868 conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
Johan Hedbergf7520542011-01-20 12:34:39 +02001869 if (!conn)
1870 goto unlock;
Marcel Holtmann7d0db0a2008-07-14 20:13:51 +02001871
Johan Hedberg37d9ef72011-11-10 15:54:39 +02001872 if (ev->status == 0)
1873 conn->state = BT_CLOSED;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001874
Johan Hedbergb644ba32012-01-17 21:48:47 +02001875 if (test_and_clear_bit(HCI_CONN_MGMT_CONNECTED, &conn->flags) &&
1876 (conn->type == ACL_LINK || conn->type == LE_LINK)) {
Johan Hedberg37d9ef72011-11-10 15:54:39 +02001877 if (ev->status != 0)
Johan Hedberg88c3df12012-02-09 14:27:38 +02001878 mgmt_disconnect_failed(hdev, &conn->dst, conn->type,
1879 conn->dst_type, ev->status);
Johan Hedberg37d9ef72011-11-10 15:54:39 +02001880 else
Johan Hedbergafc747a2012-01-15 18:11:07 +02001881 mgmt_device_disconnected(hdev, &conn->dst, conn->type,
Johan Hedberg48264f02011-11-09 13:58:58 +02001882 conn->dst_type);
Johan Hedberg37d9ef72011-11-10 15:54:39 +02001883 }
Johan Hedbergf7520542011-01-20 12:34:39 +02001884
Johan Hedberg37d9ef72011-11-10 15:54:39 +02001885 if (ev->status == 0) {
1886 hci_proto_disconn_cfm(conn, ev->reason);
1887 hci_conn_del(conn);
1888 }
Johan Hedbergf7520542011-01-20 12:34:39 +02001889
1890unlock:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001891 hci_dev_unlock(hdev);
1892}
1893
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001894static inline void hci_auth_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
1895{
1896 struct hci_ev_auth_complete *ev = (void *) skb->data;
1897 struct hci_conn *conn;
1898
1899 BT_DBG("%s status %d", hdev->name, ev->status);
1900
1901 hci_dev_lock(hdev);
1902
1903 conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
Waldemar Rymarkiewiczd7556e22011-05-31 15:49:26 +02001904 if (!conn)
1905 goto unlock;
1906
1907 if (!ev->status) {
Johan Hedbergaa64a8b2012-01-18 21:33:12 +02001908 if (!hci_conn_ssp_enabled(conn) &&
1909 test_bit(HCI_CONN_REAUTH_PEND, &conn->flags)) {
Waldemar Rymarkiewiczd7556e22011-05-31 15:49:26 +02001910 BT_INFO("re-auth of legacy device is not possible.");
Johan Hedberg2a611692011-02-19 12:06:00 -03001911 } else {
Waldemar Rymarkiewiczd7556e22011-05-31 15:49:26 +02001912 conn->link_mode |= HCI_LM_AUTH;
1913 conn->sec_level = conn->pending_sec_level;
Johan Hedberg2a611692011-02-19 12:06:00 -03001914 }
Waldemar Rymarkiewiczd7556e22011-05-31 15:49:26 +02001915 } else {
Johan Hedbergbab73cb2012-02-09 16:07:29 +02001916 mgmt_auth_failed(hdev, &conn->dst, conn->type, conn->dst_type,
1917 ev->status);
Waldemar Rymarkiewiczd7556e22011-05-31 15:49:26 +02001918 }
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001919
Johan Hedberg51a8efd2012-01-16 06:10:31 +02001920 clear_bit(HCI_CONN_AUTH_PEND, &conn->flags);
1921 clear_bit(HCI_CONN_REAUTH_PEND, &conn->flags);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001922
Waldemar Rymarkiewiczd7556e22011-05-31 15:49:26 +02001923 if (conn->state == BT_CONFIG) {
Johan Hedbergaa64a8b2012-01-18 21:33:12 +02001924 if (!ev->status && hci_conn_ssp_enabled(conn)) {
Waldemar Rymarkiewiczd7556e22011-05-31 15:49:26 +02001925 struct hci_cp_set_conn_encrypt cp;
1926 cp.handle = ev->handle;
1927 cp.encrypt = 0x01;
1928 hci_send_cmd(hdev, HCI_OP_SET_CONN_ENCRYPT, sizeof(cp),
1929 &cp);
Marcel Holtmann052b30b2009-04-26 20:01:22 +02001930 } else {
Waldemar Rymarkiewiczd7556e22011-05-31 15:49:26 +02001931 conn->state = BT_CONNECTED;
1932 hci_proto_connect_cfm(conn, ev->status);
Marcel Holtmann052b30b2009-04-26 20:01:22 +02001933 hci_conn_put(conn);
1934 }
Waldemar Rymarkiewiczd7556e22011-05-31 15:49:26 +02001935 } else {
1936 hci_auth_cfm(conn, ev->status);
Marcel Holtmann052b30b2009-04-26 20:01:22 +02001937
Waldemar Rymarkiewiczd7556e22011-05-31 15:49:26 +02001938 hci_conn_hold(conn);
1939 conn->disc_timeout = HCI_DISCONN_TIMEOUT;
1940 hci_conn_put(conn);
1941 }
1942
Johan Hedberg51a8efd2012-01-16 06:10:31 +02001943 if (test_bit(HCI_CONN_ENCRYPT_PEND, &conn->flags)) {
Waldemar Rymarkiewiczd7556e22011-05-31 15:49:26 +02001944 if (!ev->status) {
1945 struct hci_cp_set_conn_encrypt cp;
1946 cp.handle = ev->handle;
1947 cp.encrypt = 0x01;
1948 hci_send_cmd(hdev, HCI_OP_SET_CONN_ENCRYPT, sizeof(cp),
1949 &cp);
1950 } else {
Johan Hedberg51a8efd2012-01-16 06:10:31 +02001951 clear_bit(HCI_CONN_ENCRYPT_PEND, &conn->flags);
Waldemar Rymarkiewiczd7556e22011-05-31 15:49:26 +02001952 hci_encrypt_cfm(conn, ev->status, 0x00);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001953 }
1954 }
1955
Waldemar Rymarkiewiczd7556e22011-05-31 15:49:26 +02001956unlock:
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001957 hci_dev_unlock(hdev);
1958}
1959
1960static inline void hci_remote_name_evt(struct hci_dev *hdev, struct sk_buff *skb)
1961{
Johan Hedberg127178d2010-11-18 22:22:29 +02001962 struct hci_ev_remote_name *ev = (void *) skb->data;
1963 struct hci_conn *conn;
1964
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001965 BT_DBG("%s", hdev->name);
1966
1967 hci_conn_check_pending(hdev);
Johan Hedberg127178d2010-11-18 22:22:29 +02001968
1969 hci_dev_lock(hdev);
1970
1971 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
Johan Hedbergb644ba32012-01-17 21:48:47 +02001972
1973 if (!test_bit(HCI_MGMT, &hdev->dev_flags))
1974 goto check_auth;
1975
1976 if (ev->status == 0)
1977 hci_check_pending_name(hdev, conn, &ev->bdaddr, ev->name,
1978 strnlen(ev->name, HCI_MAX_NAME_LENGTH));
1979 else
1980 hci_check_pending_name(hdev, conn, &ev->bdaddr, NULL, 0);
1981
1982check_auth:
Johan Hedberg79c6c702011-04-28 11:28:55 -07001983 if (!conn)
1984 goto unlock;
1985
1986 if (!hci_outgoing_auth_needed(hdev, conn))
1987 goto unlock;
1988
Johan Hedberg51a8efd2012-01-16 06:10:31 +02001989 if (!test_and_set_bit(HCI_CONN_AUTH_PEND, &conn->flags)) {
Johan Hedberg127178d2010-11-18 22:22:29 +02001990 struct hci_cp_auth_requested cp;
1991 cp.handle = __cpu_to_le16(conn->handle);
1992 hci_send_cmd(hdev, HCI_OP_AUTH_REQUESTED, sizeof(cp), &cp);
1993 }
1994
Johan Hedberg79c6c702011-04-28 11:28:55 -07001995unlock:
Johan Hedberg127178d2010-11-18 22:22:29 +02001996 hci_dev_unlock(hdev);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001997}
1998
1999static inline void hci_encrypt_change_evt(struct hci_dev *hdev, struct sk_buff *skb)
2000{
2001 struct hci_ev_encrypt_change *ev = (void *) skb->data;
2002 struct hci_conn *conn;
2003
2004 BT_DBG("%s status %d", hdev->name, ev->status);
2005
2006 hci_dev_lock(hdev);
2007
2008 conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
2009 if (conn) {
2010 if (!ev->status) {
Marcel Holtmannae293192008-07-14 20:13:45 +02002011 if (ev->encrypt) {
2012 /* Encryption implies authentication */
2013 conn->link_mode |= HCI_LM_AUTH;
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002014 conn->link_mode |= HCI_LM_ENCRYPT;
Vinicius Costa Gomesda85e5e2011-06-09 18:50:53 -03002015 conn->sec_level = conn->pending_sec_level;
Marcel Holtmannae293192008-07-14 20:13:45 +02002016 } else
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002017 conn->link_mode &= ~HCI_LM_ENCRYPT;
2018 }
2019
Johan Hedberg51a8efd2012-01-16 06:10:31 +02002020 clear_bit(HCI_CONN_ENCRYPT_PEND, &conn->flags);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002021
Marcel Holtmannf8558552008-07-14 20:13:49 +02002022 if (conn->state == BT_CONFIG) {
2023 if (!ev->status)
2024 conn->state = BT_CONNECTED;
2025
2026 hci_proto_connect_cfm(conn, ev->status);
2027 hci_conn_put(conn);
2028 } else
2029 hci_encrypt_cfm(conn, ev->status, ev->encrypt);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002030 }
2031
2032 hci_dev_unlock(hdev);
2033}
2034
2035static inline void hci_change_link_key_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
2036{
2037 struct hci_ev_change_link_key_complete *ev = (void *) skb->data;
2038 struct hci_conn *conn;
2039
2040 BT_DBG("%s status %d", hdev->name, ev->status);
2041
2042 hci_dev_lock(hdev);
2043
2044 conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
2045 if (conn) {
2046 if (!ev->status)
2047 conn->link_mode |= HCI_LM_SECURE;
2048
Johan Hedberg51a8efd2012-01-16 06:10:31 +02002049 clear_bit(HCI_CONN_AUTH_PEND, &conn->flags);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002050
2051 hci_key_change_cfm(conn, ev->status);
2052 }
2053
2054 hci_dev_unlock(hdev);
2055}
2056
2057static inline void hci_remote_features_evt(struct hci_dev *hdev, struct sk_buff *skb)
2058{
2059 struct hci_ev_remote_features *ev = (void *) skb->data;
2060 struct hci_conn *conn;
2061
2062 BT_DBG("%s status %d", hdev->name, ev->status);
2063
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002064 hci_dev_lock(hdev);
2065
2066 conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
Johan Hedbergccd556f2010-11-10 17:11:51 +02002067 if (!conn)
2068 goto unlock;
Marcel Holtmann769be972008-07-14 20:13:49 +02002069
Johan Hedbergccd556f2010-11-10 17:11:51 +02002070 if (!ev->status)
2071 memcpy(conn->features, ev->features, 8);
2072
2073 if (conn->state != BT_CONFIG)
2074 goto unlock;
2075
2076 if (!ev->status && lmp_ssp_capable(hdev) && lmp_ssp_capable(conn)) {
2077 struct hci_cp_read_remote_ext_features cp;
2078 cp.handle = ev->handle;
2079 cp.page = 0x01;
2080 hci_send_cmd(hdev, HCI_OP_READ_REMOTE_EXT_FEATURES,
Marcel Holtmann769be972008-07-14 20:13:49 +02002081 sizeof(cp), &cp);
Johan Hedberg392599b2010-11-18 22:22:28 +02002082 goto unlock;
2083 }
2084
Johan Hedberg127178d2010-11-18 22:22:29 +02002085 if (!ev->status) {
2086 struct hci_cp_remote_name_req cp;
2087 memset(&cp, 0, sizeof(cp));
2088 bacpy(&cp.bdaddr, &conn->dst);
2089 cp.pscan_rep_mode = 0x02;
2090 hci_send_cmd(hdev, HCI_OP_REMOTE_NAME_REQ, sizeof(cp), &cp);
Johan Hedbergb644ba32012-01-17 21:48:47 +02002091 } else if (!test_and_set_bit(HCI_CONN_MGMT_CONNECTED, &conn->flags))
2092 mgmt_device_connected(hdev, &conn->dst, conn->type,
2093 conn->dst_type, NULL, 0,
2094 conn->dev_class);
Johan Hedberg392599b2010-11-18 22:22:28 +02002095
Johan Hedberg127178d2010-11-18 22:22:29 +02002096 if (!hci_outgoing_auth_needed(hdev, conn)) {
Johan Hedbergccd556f2010-11-10 17:11:51 +02002097 conn->state = BT_CONNECTED;
2098 hci_proto_connect_cfm(conn, ev->status);
2099 hci_conn_put(conn);
Marcel Holtmann769be972008-07-14 20:13:49 +02002100 }
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002101
Johan Hedbergccd556f2010-11-10 17:11:51 +02002102unlock:
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002103 hci_dev_unlock(hdev);
2104}
2105
2106static inline void hci_remote_version_evt(struct hci_dev *hdev, struct sk_buff *skb)
2107{
2108 BT_DBG("%s", hdev->name);
2109}
2110
2111static inline void hci_qos_setup_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
2112{
2113 BT_DBG("%s", hdev->name);
2114}
2115
2116static inline void hci_cmd_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
2117{
2118 struct hci_ev_cmd_complete *ev = (void *) skb->data;
2119 __u16 opcode;
2120
2121 skb_pull(skb, sizeof(*ev));
2122
2123 opcode = __le16_to_cpu(ev->opcode);
2124
2125 switch (opcode) {
2126 case HCI_OP_INQUIRY_CANCEL:
2127 hci_cc_inquiry_cancel(hdev, skb);
2128 break;
2129
2130 case HCI_OP_EXIT_PERIODIC_INQ:
2131 hci_cc_exit_periodic_inq(hdev, skb);
2132 break;
2133
2134 case HCI_OP_REMOTE_NAME_REQ_CANCEL:
2135 hci_cc_remote_name_req_cancel(hdev, skb);
2136 break;
2137
2138 case HCI_OP_ROLE_DISCOVERY:
2139 hci_cc_role_discovery(hdev, skb);
2140 break;
2141
Marcel Holtmanne4e8e372008-07-14 20:13:47 +02002142 case HCI_OP_READ_LINK_POLICY:
2143 hci_cc_read_link_policy(hdev, skb);
2144 break;
2145
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002146 case HCI_OP_WRITE_LINK_POLICY:
2147 hci_cc_write_link_policy(hdev, skb);
2148 break;
2149
Marcel Holtmanne4e8e372008-07-14 20:13:47 +02002150 case HCI_OP_READ_DEF_LINK_POLICY:
2151 hci_cc_read_def_link_policy(hdev, skb);
2152 break;
2153
2154 case HCI_OP_WRITE_DEF_LINK_POLICY:
2155 hci_cc_write_def_link_policy(hdev, skb);
2156 break;
2157
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002158 case HCI_OP_RESET:
2159 hci_cc_reset(hdev, skb);
2160 break;
2161
2162 case HCI_OP_WRITE_LOCAL_NAME:
2163 hci_cc_write_local_name(hdev, skb);
2164 break;
2165
2166 case HCI_OP_READ_LOCAL_NAME:
2167 hci_cc_read_local_name(hdev, skb);
2168 break;
2169
2170 case HCI_OP_WRITE_AUTH_ENABLE:
2171 hci_cc_write_auth_enable(hdev, skb);
2172 break;
2173
2174 case HCI_OP_WRITE_ENCRYPT_MODE:
2175 hci_cc_write_encrypt_mode(hdev, skb);
2176 break;
2177
2178 case HCI_OP_WRITE_SCAN_ENABLE:
2179 hci_cc_write_scan_enable(hdev, skb);
2180 break;
2181
2182 case HCI_OP_READ_CLASS_OF_DEV:
2183 hci_cc_read_class_of_dev(hdev, skb);
2184 break;
2185
2186 case HCI_OP_WRITE_CLASS_OF_DEV:
2187 hci_cc_write_class_of_dev(hdev, skb);
2188 break;
2189
2190 case HCI_OP_READ_VOICE_SETTING:
2191 hci_cc_read_voice_setting(hdev, skb);
2192 break;
2193
2194 case HCI_OP_WRITE_VOICE_SETTING:
2195 hci_cc_write_voice_setting(hdev, skb);
2196 break;
2197
2198 case HCI_OP_HOST_BUFFER_SIZE:
2199 hci_cc_host_buffer_size(hdev, skb);
2200 break;
2201
Marcel Holtmann333140b2008-07-14 20:13:48 +02002202 case HCI_OP_READ_SSP_MODE:
2203 hci_cc_read_ssp_mode(hdev, skb);
2204 break;
2205
2206 case HCI_OP_WRITE_SSP_MODE:
2207 hci_cc_write_ssp_mode(hdev, skb);
2208 break;
2209
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002210 case HCI_OP_READ_LOCAL_VERSION:
2211 hci_cc_read_local_version(hdev, skb);
2212 break;
2213
2214 case HCI_OP_READ_LOCAL_COMMANDS:
2215 hci_cc_read_local_commands(hdev, skb);
2216 break;
2217
2218 case HCI_OP_READ_LOCAL_FEATURES:
2219 hci_cc_read_local_features(hdev, skb);
2220 break;
2221
Andre Guedes971e3a42011-06-30 19:20:52 -03002222 case HCI_OP_READ_LOCAL_EXT_FEATURES:
2223 hci_cc_read_local_ext_features(hdev, skb);
2224 break;
2225
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002226 case HCI_OP_READ_BUFFER_SIZE:
2227 hci_cc_read_buffer_size(hdev, skb);
2228 break;
2229
2230 case HCI_OP_READ_BD_ADDR:
2231 hci_cc_read_bd_addr(hdev, skb);
2232 break;
2233
Andrei Emeltchenko350ee4c2011-12-07 15:56:51 +02002234 case HCI_OP_READ_DATA_BLOCK_SIZE:
2235 hci_cc_read_data_block_size(hdev, skb);
2236 break;
2237
Johan Hedberg23bb5762010-12-21 23:01:27 +02002238 case HCI_OP_WRITE_CA_TIMEOUT:
2239 hci_cc_write_ca_timeout(hdev, skb);
2240 break;
2241
Andrei Emeltchenko1e89cff2011-11-24 14:52:02 +02002242 case HCI_OP_READ_FLOW_CONTROL_MODE:
2243 hci_cc_read_flow_control_mode(hdev, skb);
2244 break;
2245
Andrei Emeltchenko928abaa2011-10-12 10:53:57 +03002246 case HCI_OP_READ_LOCAL_AMP_INFO:
2247 hci_cc_read_local_amp_info(hdev, skb);
2248 break;
2249
Johan Hedbergb0916ea2011-01-10 13:44:55 +02002250 case HCI_OP_DELETE_STORED_LINK_KEY:
2251 hci_cc_delete_stored_link_key(hdev, skb);
2252 break;
2253
Johan Hedbergd5859e22011-01-25 01:19:58 +02002254 case HCI_OP_SET_EVENT_MASK:
2255 hci_cc_set_event_mask(hdev, skb);
2256 break;
2257
2258 case HCI_OP_WRITE_INQUIRY_MODE:
2259 hci_cc_write_inquiry_mode(hdev, skb);
2260 break;
2261
2262 case HCI_OP_READ_INQ_RSP_TX_POWER:
2263 hci_cc_read_inq_rsp_tx_power(hdev, skb);
2264 break;
2265
2266 case HCI_OP_SET_EVENT_FLT:
2267 hci_cc_set_event_flt(hdev, skb);
2268 break;
2269
Johan Hedberg980e1a52011-01-22 06:10:07 +02002270 case HCI_OP_PIN_CODE_REPLY:
2271 hci_cc_pin_code_reply(hdev, skb);
2272 break;
2273
2274 case HCI_OP_PIN_CODE_NEG_REPLY:
2275 hci_cc_pin_code_neg_reply(hdev, skb);
2276 break;
2277
Szymon Jancc35938b2011-03-22 13:12:21 +01002278 case HCI_OP_READ_LOCAL_OOB_DATA:
2279 hci_cc_read_local_oob_data_reply(hdev, skb);
2280 break;
2281
Ville Tervo6ed58ec2011-02-10 22:38:48 -03002282 case HCI_OP_LE_READ_BUFFER_SIZE:
2283 hci_cc_le_read_buffer_size(hdev, skb);
2284 break;
2285
Johan Hedberga5c29682011-02-19 12:05:57 -03002286 case HCI_OP_USER_CONFIRM_REPLY:
2287 hci_cc_user_confirm_reply(hdev, skb);
2288 break;
2289
2290 case HCI_OP_USER_CONFIRM_NEG_REPLY:
2291 hci_cc_user_confirm_neg_reply(hdev, skb);
2292 break;
2293
Brian Gix1143d452011-11-23 08:28:34 -08002294 case HCI_OP_USER_PASSKEY_REPLY:
2295 hci_cc_user_passkey_reply(hdev, skb);
2296 break;
2297
2298 case HCI_OP_USER_PASSKEY_NEG_REPLY:
2299 hci_cc_user_passkey_neg_reply(hdev, skb);
Andre Guedes07f7fa52011-12-02 21:13:31 +09002300
2301 case HCI_OP_LE_SET_SCAN_PARAM:
2302 hci_cc_le_set_scan_param(hdev, skb);
Brian Gix1143d452011-11-23 08:28:34 -08002303 break;
2304
Andre Guedeseb9d91f2011-05-26 16:23:52 -03002305 case HCI_OP_LE_SET_SCAN_ENABLE:
2306 hci_cc_le_set_scan_enable(hdev, skb);
2307 break;
2308
Vinicius Costa Gomesa7a595f2011-06-09 18:50:47 -03002309 case HCI_OP_LE_LTK_REPLY:
2310 hci_cc_le_ltk_reply(hdev, skb);
2311 break;
2312
2313 case HCI_OP_LE_LTK_NEG_REPLY:
2314 hci_cc_le_ltk_neg_reply(hdev, skb);
2315 break;
2316
Andre Guedesf9b49302011-06-30 19:20:53 -03002317 case HCI_OP_WRITE_LE_HOST_SUPPORTED:
2318 hci_cc_write_le_host_supported(hdev, skb);
2319 break;
2320
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002321 default:
2322 BT_DBG("%s opcode 0x%x", hdev->name, opcode);
2323 break;
2324 }
2325
Ville Tervo6bd32322011-02-16 16:32:41 +02002326 if (ev->opcode != HCI_OP_NOP)
2327 del_timer(&hdev->cmd_timer);
2328
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002329 if (ev->ncmd) {
2330 atomic_set(&hdev->cmd_cnt, 1);
2331 if (!skb_queue_empty(&hdev->cmd_q))
Gustavo F. Padovanc347b762011-12-14 23:53:47 -02002332 queue_work(hdev->workqueue, &hdev->cmd_work);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002333 }
2334}
2335
2336static inline void hci_cmd_status_evt(struct hci_dev *hdev, struct sk_buff *skb)
2337{
2338 struct hci_ev_cmd_status *ev = (void *) skb->data;
2339 __u16 opcode;
2340
2341 skb_pull(skb, sizeof(*ev));
2342
2343 opcode = __le16_to_cpu(ev->opcode);
2344
2345 switch (opcode) {
2346 case HCI_OP_INQUIRY:
2347 hci_cs_inquiry(hdev, ev->status);
2348 break;
2349
2350 case HCI_OP_CREATE_CONN:
2351 hci_cs_create_conn(hdev, ev->status);
2352 break;
2353
2354 case HCI_OP_ADD_SCO:
2355 hci_cs_add_sco(hdev, ev->status);
2356 break;
2357
Marcel Holtmannf8558552008-07-14 20:13:49 +02002358 case HCI_OP_AUTH_REQUESTED:
2359 hci_cs_auth_requested(hdev, ev->status);
2360 break;
2361
2362 case HCI_OP_SET_CONN_ENCRYPT:
2363 hci_cs_set_conn_encrypt(hdev, ev->status);
2364 break;
2365
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002366 case HCI_OP_REMOTE_NAME_REQ:
2367 hci_cs_remote_name_req(hdev, ev->status);
2368 break;
2369
Marcel Holtmann769be972008-07-14 20:13:49 +02002370 case HCI_OP_READ_REMOTE_FEATURES:
2371 hci_cs_read_remote_features(hdev, ev->status);
2372 break;
2373
2374 case HCI_OP_READ_REMOTE_EXT_FEATURES:
2375 hci_cs_read_remote_ext_features(hdev, ev->status);
2376 break;
2377
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002378 case HCI_OP_SETUP_SYNC_CONN:
2379 hci_cs_setup_sync_conn(hdev, ev->status);
2380 break;
2381
2382 case HCI_OP_SNIFF_MODE:
2383 hci_cs_sniff_mode(hdev, ev->status);
2384 break;
2385
2386 case HCI_OP_EXIT_SNIFF_MODE:
2387 hci_cs_exit_sniff_mode(hdev, ev->status);
2388 break;
2389
Johan Hedberg8962ee72011-01-20 12:40:27 +02002390 case HCI_OP_DISCONNECT:
Johan Hedberg88c3df12012-02-09 14:27:38 +02002391 hci_cs_disconnect(hdev, ev->status);
Johan Hedberg8962ee72011-01-20 12:40:27 +02002392 break;
2393
Ville Tervofcd89c02011-02-10 22:38:47 -03002394 case HCI_OP_LE_CREATE_CONN:
2395 hci_cs_le_create_conn(hdev, ev->status);
2396 break;
2397
Vinicius Costa Gomesa7a595f2011-06-09 18:50:47 -03002398 case HCI_OP_LE_START_ENC:
2399 hci_cs_le_start_enc(hdev, ev->status);
2400 break;
2401
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002402 default:
2403 BT_DBG("%s opcode 0x%x", hdev->name, opcode);
2404 break;
2405 }
2406
Ville Tervo6bd32322011-02-16 16:32:41 +02002407 if (ev->opcode != HCI_OP_NOP)
2408 del_timer(&hdev->cmd_timer);
2409
Gustavo F. Padovan10572132011-03-16 15:36:29 -03002410 if (ev->ncmd && !test_bit(HCI_RESET, &hdev->flags)) {
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002411 atomic_set(&hdev->cmd_cnt, 1);
2412 if (!skb_queue_empty(&hdev->cmd_q))
Gustavo F. Padovanc347b762011-12-14 23:53:47 -02002413 queue_work(hdev->workqueue, &hdev->cmd_work);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002414 }
2415}
2416
2417static inline void hci_role_change_evt(struct hci_dev *hdev, struct sk_buff *skb)
2418{
2419 struct hci_ev_role_change *ev = (void *) skb->data;
2420 struct hci_conn *conn;
2421
2422 BT_DBG("%s status %d", hdev->name, ev->status);
2423
2424 hci_dev_lock(hdev);
2425
2426 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
2427 if (conn) {
2428 if (!ev->status) {
2429 if (ev->role)
2430 conn->link_mode &= ~HCI_LM_MASTER;
2431 else
2432 conn->link_mode |= HCI_LM_MASTER;
2433 }
2434
Johan Hedberg51a8efd2012-01-16 06:10:31 +02002435 clear_bit(HCI_CONN_RSWITCH_PEND, &conn->flags);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002436
2437 hci_role_switch_cfm(conn, ev->status, ev->role);
2438 }
2439
2440 hci_dev_unlock(hdev);
2441}
2442
Linus Torvalds1da177e2005-04-16 15:20:36 -07002443static inline void hci_num_comp_pkts_evt(struct hci_dev *hdev, struct sk_buff *skb)
2444{
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002445 struct hci_ev_num_comp_pkts *ev = (void *) skb->data;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002446 int i;
2447
Andrei Emeltchenko32ac5b92011-12-19 16:31:29 +02002448 if (hdev->flow_ctl_mode != HCI_FLOW_CTL_MODE_PACKET_BASED) {
2449 BT_ERR("Wrong event for mode %d", hdev->flow_ctl_mode);
2450 return;
2451 }
2452
Andrei Emeltchenkoc5993de2011-12-30 12:07:47 +02002453 if (skb->len < sizeof(*ev) || skb->len < sizeof(*ev) +
2454 ev->num_hndl * sizeof(struct hci_comp_pkts_info)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002455 BT_DBG("%s bad parameters", hdev->name);
2456 return;
2457 }
2458
Andrei Emeltchenkoc5993de2011-12-30 12:07:47 +02002459 BT_DBG("%s num_hndl %d", hdev->name, ev->num_hndl);
2460
Andrei Emeltchenko613a1c02011-12-19 16:31:30 +02002461 for (i = 0; i < ev->num_hndl; i++) {
2462 struct hci_comp_pkts_info *info = &ev->handles[i];
Linus Torvalds1da177e2005-04-16 15:20:36 -07002463 struct hci_conn *conn;
2464 __u16 handle, count;
2465
Andrei Emeltchenko613a1c02011-12-19 16:31:30 +02002466 handle = __le16_to_cpu(info->handle);
2467 count = __le16_to_cpu(info->count);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002468
2469 conn = hci_conn_hash_lookup_handle(hdev, handle);
Andrei Emeltchenkof4280912011-12-07 15:56:52 +02002470 if (!conn)
2471 continue;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002472
Andrei Emeltchenkof4280912011-12-07 15:56:52 +02002473 conn->sent -= count;
2474
2475 switch (conn->type) {
2476 case ACL_LINK:
2477 hdev->acl_cnt += count;
2478 if (hdev->acl_cnt > hdev->acl_pkts)
2479 hdev->acl_cnt = hdev->acl_pkts;
2480 break;
2481
2482 case LE_LINK:
2483 if (hdev->le_pkts) {
2484 hdev->le_cnt += count;
2485 if (hdev->le_cnt > hdev->le_pkts)
2486 hdev->le_cnt = hdev->le_pkts;
2487 } else {
Andrei Emeltchenko70f230202010-12-01 16:58:25 +02002488 hdev->acl_cnt += count;
2489 if (hdev->acl_cnt > hdev->acl_pkts)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002490 hdev->acl_cnt = hdev->acl_pkts;
2491 }
Andrei Emeltchenkof4280912011-12-07 15:56:52 +02002492 break;
2493
2494 case SCO_LINK:
2495 hdev->sco_cnt += count;
2496 if (hdev->sco_cnt > hdev->sco_pkts)
2497 hdev->sco_cnt = hdev->sco_pkts;
2498 break;
2499
2500 default:
2501 BT_ERR("Unknown type %d conn %p", conn->type, conn);
2502 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002503 }
2504 }
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002505
Gustavo F. Padovan3eff45e2011-12-15 00:50:02 -02002506 queue_work(hdev->workqueue, &hdev->tx_work);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002507}
2508
Andrei Emeltchenko25e89e92012-01-04 12:41:58 +02002509static inline void hci_num_comp_blocks_evt(struct hci_dev *hdev,
2510 struct sk_buff *skb)
2511{
2512 struct hci_ev_num_comp_blocks *ev = (void *) skb->data;
2513 int i;
2514
2515 if (hdev->flow_ctl_mode != HCI_FLOW_CTL_MODE_BLOCK_BASED) {
2516 BT_ERR("Wrong event for mode %d", hdev->flow_ctl_mode);
2517 return;
2518 }
2519
2520 if (skb->len < sizeof(*ev) || skb->len < sizeof(*ev) +
2521 ev->num_hndl * sizeof(struct hci_comp_blocks_info)) {
2522 BT_DBG("%s bad parameters", hdev->name);
2523 return;
2524 }
2525
2526 BT_DBG("%s num_blocks %d num_hndl %d", hdev->name, ev->num_blocks,
2527 ev->num_hndl);
2528
2529 for (i = 0; i < ev->num_hndl; i++) {
2530 struct hci_comp_blocks_info *info = &ev->handles[i];
2531 struct hci_conn *conn;
2532 __u16 handle, block_count;
2533
2534 handle = __le16_to_cpu(info->handle);
2535 block_count = __le16_to_cpu(info->blocks);
2536
2537 conn = hci_conn_hash_lookup_handle(hdev, handle);
2538 if (!conn)
2539 continue;
2540
2541 conn->sent -= block_count;
2542
2543 switch (conn->type) {
2544 case ACL_LINK:
2545 hdev->block_cnt += block_count;
2546 if (hdev->block_cnt > hdev->num_blocks)
2547 hdev->block_cnt = hdev->num_blocks;
2548 break;
2549
2550 default:
2551 BT_ERR("Unknown type %d conn %p", conn->type, conn);
2552 break;
2553 }
2554 }
2555
2556 queue_work(hdev->workqueue, &hdev->tx_work);
2557}
2558
Marcel Holtmann04837f62006-07-03 10:02:33 +02002559static inline void hci_mode_change_evt(struct hci_dev *hdev, struct sk_buff *skb)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002560{
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002561 struct hci_ev_mode_change *ev = (void *) skb->data;
Marcel Holtmann04837f62006-07-03 10:02:33 +02002562 struct hci_conn *conn;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002563
2564 BT_DBG("%s status %d", hdev->name, ev->status);
2565
2566 hci_dev_lock(hdev);
2567
Marcel Holtmann04837f62006-07-03 10:02:33 +02002568 conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
2569 if (conn) {
2570 conn->mode = ev->mode;
2571 conn->interval = __le16_to_cpu(ev->interval);
2572
Johan Hedberg51a8efd2012-01-16 06:10:31 +02002573 if (!test_and_clear_bit(HCI_CONN_MODE_CHANGE_PEND, &conn->flags)) {
Marcel Holtmann04837f62006-07-03 10:02:33 +02002574 if (conn->mode == HCI_CM_ACTIVE)
Johan Hedberg58a681e2012-01-16 06:47:28 +02002575 set_bit(HCI_CONN_POWER_SAVE, &conn->flags);
Marcel Holtmann04837f62006-07-03 10:02:33 +02002576 else
Johan Hedberg58a681e2012-01-16 06:47:28 +02002577 clear_bit(HCI_CONN_POWER_SAVE, &conn->flags);
Marcel Holtmann04837f62006-07-03 10:02:33 +02002578 }
Marcel Holtmanne73439d2010-07-26 10:06:00 -04002579
Johan Hedberg51a8efd2012-01-16 06:10:31 +02002580 if (test_and_clear_bit(HCI_CONN_SCO_SETUP_PEND, &conn->flags))
Marcel Holtmanne73439d2010-07-26 10:06:00 -04002581 hci_sco_setup(conn, ev->status);
Marcel Holtmann04837f62006-07-03 10:02:33 +02002582 }
2583
2584 hci_dev_unlock(hdev);
2585}
2586
Linus Torvalds1da177e2005-04-16 15:20:36 -07002587static inline void hci_pin_code_request_evt(struct hci_dev *hdev, struct sk_buff *skb)
2588{
Marcel Holtmann052b30b2009-04-26 20:01:22 +02002589 struct hci_ev_pin_code_req *ev = (void *) skb->data;
2590 struct hci_conn *conn;
2591
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002592 BT_DBG("%s", hdev->name);
Marcel Holtmann052b30b2009-04-26 20:01:22 +02002593
2594 hci_dev_lock(hdev);
2595
2596 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
Waldemar Rymarkiewiczb6f98042011-09-23 10:01:30 +02002597 if (!conn)
2598 goto unlock;
2599
2600 if (conn->state == BT_CONNECTED) {
Marcel Holtmann052b30b2009-04-26 20:01:22 +02002601 hci_conn_hold(conn);
2602 conn->disc_timeout = HCI_PAIRING_TIMEOUT;
2603 hci_conn_put(conn);
2604 }
2605
Johan Hedberga8b2d5c2012-01-08 23:11:15 +02002606 if (!test_bit(HCI_PAIRABLE, &hdev->dev_flags))
Johan Hedberg03b555e2011-01-04 15:40:05 +02002607 hci_send_cmd(hdev, HCI_OP_PIN_CODE_NEG_REPLY,
2608 sizeof(ev->bdaddr), &ev->bdaddr);
Johan Hedberga8b2d5c2012-01-08 23:11:15 +02002609 else if (test_bit(HCI_MGMT, &hdev->dev_flags)) {
Waldemar Rymarkiewicza770bb52011-04-28 12:07:59 +02002610 u8 secure;
2611
2612 if (conn->pending_sec_level == BT_SECURITY_HIGH)
2613 secure = 1;
2614 else
2615 secure = 0;
2616
Johan Hedberg744cf192011-11-08 20:40:14 +02002617 mgmt_pin_code_request(hdev, &ev->bdaddr, secure);
Waldemar Rymarkiewicza770bb52011-04-28 12:07:59 +02002618 }
Johan Hedberg980e1a52011-01-22 06:10:07 +02002619
Waldemar Rymarkiewiczb6f98042011-09-23 10:01:30 +02002620unlock:
Marcel Holtmann052b30b2009-04-26 20:01:22 +02002621 hci_dev_unlock(hdev);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002622}
2623
Linus Torvalds1da177e2005-04-16 15:20:36 -07002624static inline void hci_link_key_request_evt(struct hci_dev *hdev, struct sk_buff *skb)
2625{
Johan Hedberg55ed8ca2011-01-17 14:41:05 +02002626 struct hci_ev_link_key_req *ev = (void *) skb->data;
2627 struct hci_cp_link_key_reply cp;
2628 struct hci_conn *conn;
2629 struct link_key *key;
2630
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002631 BT_DBG("%s", hdev->name);
Johan Hedberg55ed8ca2011-01-17 14:41:05 +02002632
Johan Hedberga8b2d5c2012-01-08 23:11:15 +02002633 if (!test_bit(HCI_LINK_KEYS, &hdev->dev_flags))
Johan Hedberg55ed8ca2011-01-17 14:41:05 +02002634 return;
2635
2636 hci_dev_lock(hdev);
2637
2638 key = hci_find_link_key(hdev, &ev->bdaddr);
2639 if (!key) {
2640 BT_DBG("%s link key not found for %s", hdev->name,
2641 batostr(&ev->bdaddr));
2642 goto not_found;
2643 }
2644
2645 BT_DBG("%s found key type %u for %s", hdev->name, key->type,
2646 batostr(&ev->bdaddr));
2647
Johan Hedberga8b2d5c2012-01-08 23:11:15 +02002648 if (!test_bit(HCI_DEBUG_KEYS, &hdev->dev_flags) &&
Waldemar Rymarkiewiczb6020ba2011-04-28 12:07:53 +02002649 key->type == HCI_LK_DEBUG_COMBINATION) {
Johan Hedberg55ed8ca2011-01-17 14:41:05 +02002650 BT_DBG("%s ignoring debug key", hdev->name);
2651 goto not_found;
2652 }
2653
2654 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
Waldemar Rymarkiewicz60b83f52011-04-28 12:07:56 +02002655 if (conn) {
2656 if (key->type == HCI_LK_UNAUTH_COMBINATION &&
2657 conn->auth_type != 0xff &&
2658 (conn->auth_type & 0x01)) {
2659 BT_DBG("%s ignoring unauthenticated key", hdev->name);
2660 goto not_found;
2661 }
Johan Hedberg55ed8ca2011-01-17 14:41:05 +02002662
Waldemar Rymarkiewicz60b83f52011-04-28 12:07:56 +02002663 if (key->type == HCI_LK_COMBINATION && key->pin_len < 16 &&
2664 conn->pending_sec_level == BT_SECURITY_HIGH) {
2665 BT_DBG("%s ignoring key unauthenticated for high \
2666 security", hdev->name);
2667 goto not_found;
2668 }
2669
2670 conn->key_type = key->type;
2671 conn->pin_length = key->pin_len;
Johan Hedberg55ed8ca2011-01-17 14:41:05 +02002672 }
2673
2674 bacpy(&cp.bdaddr, &ev->bdaddr);
2675 memcpy(cp.link_key, key->val, 16);
2676
2677 hci_send_cmd(hdev, HCI_OP_LINK_KEY_REPLY, sizeof(cp), &cp);
2678
2679 hci_dev_unlock(hdev);
2680
2681 return;
2682
2683not_found:
2684 hci_send_cmd(hdev, HCI_OP_LINK_KEY_NEG_REPLY, 6, &ev->bdaddr);
2685 hci_dev_unlock(hdev);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002686}
2687
Linus Torvalds1da177e2005-04-16 15:20:36 -07002688static inline void hci_link_key_notify_evt(struct hci_dev *hdev, struct sk_buff *skb)
2689{
Marcel Holtmann052b30b2009-04-26 20:01:22 +02002690 struct hci_ev_link_key_notify *ev = (void *) skb->data;
2691 struct hci_conn *conn;
Johan Hedberg55ed8ca2011-01-17 14:41:05 +02002692 u8 pin_len = 0;
Marcel Holtmann052b30b2009-04-26 20:01:22 +02002693
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002694 BT_DBG("%s", hdev->name);
Marcel Holtmann052b30b2009-04-26 20:01:22 +02002695
2696 hci_dev_lock(hdev);
2697
2698 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
2699 if (conn) {
2700 hci_conn_hold(conn);
2701 conn->disc_timeout = HCI_DISCONN_TIMEOUT;
Johan Hedberg980e1a52011-01-22 06:10:07 +02002702 pin_len = conn->pin_length;
Waldemar Rymarkiewicz13d39312011-04-28 12:07:55 +02002703
2704 if (ev->key_type != HCI_LK_CHANGED_COMBINATION)
2705 conn->key_type = ev->key_type;
2706
Marcel Holtmann052b30b2009-04-26 20:01:22 +02002707 hci_conn_put(conn);
2708 }
2709
Johan Hedberga8b2d5c2012-01-08 23:11:15 +02002710 if (test_bit(HCI_LINK_KEYS, &hdev->dev_flags))
Johan Hedbergd25e28a2011-04-28 11:28:59 -07002711 hci_add_link_key(hdev, conn, 1, &ev->bdaddr, ev->link_key,
Johan Hedberg55ed8ca2011-01-17 14:41:05 +02002712 ev->key_type, pin_len);
2713
Marcel Holtmann052b30b2009-04-26 20:01:22 +02002714 hci_dev_unlock(hdev);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002715}
2716
Marcel Holtmann04837f62006-07-03 10:02:33 +02002717static inline void hci_clock_offset_evt(struct hci_dev *hdev, struct sk_buff *skb)
2718{
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002719 struct hci_ev_clock_offset *ev = (void *) skb->data;
Marcel Holtmann04837f62006-07-03 10:02:33 +02002720 struct hci_conn *conn;
2721
2722 BT_DBG("%s status %d", hdev->name, ev->status);
2723
2724 hci_dev_lock(hdev);
2725
2726 conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
Linus Torvalds1da177e2005-04-16 15:20:36 -07002727 if (conn && !ev->status) {
2728 struct inquiry_entry *ie;
2729
Andrei Emeltchenkocc11b9c2010-11-22 13:21:37 +02002730 ie = hci_inquiry_cache_lookup(hdev, &conn->dst);
2731 if (ie) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002732 ie->data.clock_offset = ev->clock_offset;
2733 ie->timestamp = jiffies;
2734 }
2735 }
2736
2737 hci_dev_unlock(hdev);
2738}
2739
Marcel Holtmanna8746412008-07-14 20:13:46 +02002740static inline void hci_pkt_type_change_evt(struct hci_dev *hdev, struct sk_buff *skb)
2741{
2742 struct hci_ev_pkt_type_change *ev = (void *) skb->data;
2743 struct hci_conn *conn;
2744
2745 BT_DBG("%s status %d", hdev->name, ev->status);
2746
2747 hci_dev_lock(hdev);
2748
2749 conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
2750 if (conn && !ev->status)
2751 conn->pkt_type = __le16_to_cpu(ev->pkt_type);
2752
2753 hci_dev_unlock(hdev);
2754}
2755
Marcel Holtmann85a1e932005-08-09 20:28:02 -07002756static inline void hci_pscan_rep_mode_evt(struct hci_dev *hdev, struct sk_buff *skb)
2757{
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002758 struct hci_ev_pscan_rep_mode *ev = (void *) skb->data;
Marcel Holtmann85a1e932005-08-09 20:28:02 -07002759 struct inquiry_entry *ie;
2760
2761 BT_DBG("%s", hdev->name);
2762
2763 hci_dev_lock(hdev);
2764
Andrei Emeltchenkocc11b9c2010-11-22 13:21:37 +02002765 ie = hci_inquiry_cache_lookup(hdev, &ev->bdaddr);
2766 if (ie) {
Marcel Holtmann85a1e932005-08-09 20:28:02 -07002767 ie->data.pscan_rep_mode = ev->pscan_rep_mode;
2768 ie->timestamp = jiffies;
2769 }
2770
2771 hci_dev_unlock(hdev);
2772}
2773
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002774static inline void hci_inquiry_result_with_rssi_evt(struct hci_dev *hdev, struct sk_buff *skb)
2775{
2776 struct inquiry_data data;
2777 int num_rsp = *((__u8 *) skb->data);
Johan Hedberg31754052012-01-04 13:39:52 +02002778 bool name_known;
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002779
2780 BT_DBG("%s num_rsp %d", hdev->name, num_rsp);
2781
2782 if (!num_rsp)
2783 return;
2784
2785 hci_dev_lock(hdev);
2786
2787 if ((skb->len - 1) / num_rsp != sizeof(struct inquiry_info_with_rssi)) {
Szymon Janc138d22e2011-02-17 16:44:23 +01002788 struct inquiry_info_with_rssi_and_pscan_mode *info;
2789 info = (void *) (skb->data + 1);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002790
Johan Hedberge17acd42011-03-30 23:57:16 +03002791 for (; num_rsp; num_rsp--, info++) {
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002792 bacpy(&data.bdaddr, &info->bdaddr);
2793 data.pscan_rep_mode = info->pscan_rep_mode;
2794 data.pscan_period_mode = info->pscan_period_mode;
2795 data.pscan_mode = info->pscan_mode;
2796 memcpy(data.dev_class, info->dev_class, 3);
2797 data.clock_offset = info->clock_offset;
2798 data.rssi = info->rssi;
Marcel Holtmann41a96212008-07-14 20:13:48 +02002799 data.ssp_mode = 0x00;
Johan Hedberg31754052012-01-04 13:39:52 +02002800
2801 name_known = hci_inquiry_cache_update(hdev, &data,
2802 false);
Johan Hedberg48264f02011-11-09 13:58:58 +02002803 mgmt_device_found(hdev, &info->bdaddr, ACL_LINK, 0x00,
Johan Hedberge17acd42011-03-30 23:57:16 +03002804 info->dev_class, info->rssi,
Andre Guedes7d262f82012-01-10 18:20:49 -03002805 !name_known, NULL, 0);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002806 }
2807 } else {
2808 struct inquiry_info_with_rssi *info = (void *) (skb->data + 1);
2809
Johan Hedberge17acd42011-03-30 23:57:16 +03002810 for (; num_rsp; num_rsp--, info++) {
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002811 bacpy(&data.bdaddr, &info->bdaddr);
2812 data.pscan_rep_mode = info->pscan_rep_mode;
2813 data.pscan_period_mode = info->pscan_period_mode;
2814 data.pscan_mode = 0x00;
2815 memcpy(data.dev_class, info->dev_class, 3);
2816 data.clock_offset = info->clock_offset;
2817 data.rssi = info->rssi;
Marcel Holtmann41a96212008-07-14 20:13:48 +02002818 data.ssp_mode = 0x00;
Johan Hedberg31754052012-01-04 13:39:52 +02002819 name_known = hci_inquiry_cache_update(hdev, &data,
2820 false);
Johan Hedberg48264f02011-11-09 13:58:58 +02002821 mgmt_device_found(hdev, &info->bdaddr, ACL_LINK, 0x00,
Johan Hedberge17acd42011-03-30 23:57:16 +03002822 info->dev_class, info->rssi,
Andre Guedes7d262f82012-01-10 18:20:49 -03002823 !name_known, NULL, 0);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002824 }
2825 }
2826
2827 hci_dev_unlock(hdev);
2828}
2829
2830static inline void hci_remote_ext_features_evt(struct hci_dev *hdev, struct sk_buff *skb)
2831{
Marcel Holtmann41a96212008-07-14 20:13:48 +02002832 struct hci_ev_remote_ext_features *ev = (void *) skb->data;
2833 struct hci_conn *conn;
2834
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002835 BT_DBG("%s", hdev->name);
Marcel Holtmann41a96212008-07-14 20:13:48 +02002836
Marcel Holtmann41a96212008-07-14 20:13:48 +02002837 hci_dev_lock(hdev);
2838
2839 conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
Johan Hedbergccd556f2010-11-10 17:11:51 +02002840 if (!conn)
2841 goto unlock;
Marcel Holtmann41a96212008-07-14 20:13:48 +02002842
Johan Hedbergccd556f2010-11-10 17:11:51 +02002843 if (!ev->status && ev->page == 0x01) {
2844 struct inquiry_entry *ie;
Marcel Holtmann41a96212008-07-14 20:13:48 +02002845
Andrei Emeltchenkocc11b9c2010-11-22 13:21:37 +02002846 ie = hci_inquiry_cache_lookup(hdev, &conn->dst);
2847 if (ie)
Johan Hedbergccd556f2010-11-10 17:11:51 +02002848 ie->data.ssp_mode = (ev->features[0] & 0x01);
Marcel Holtmann769be972008-07-14 20:13:49 +02002849
Johan Hedberg58a681e2012-01-16 06:47:28 +02002850 if (ev->features[0] & 0x01)
2851 set_bit(HCI_CONN_SSP_ENABLED, &conn->flags);
Marcel Holtmann41a96212008-07-14 20:13:48 +02002852 }
2853
Johan Hedbergccd556f2010-11-10 17:11:51 +02002854 if (conn->state != BT_CONFIG)
2855 goto unlock;
2856
Johan Hedberg127178d2010-11-18 22:22:29 +02002857 if (!ev->status) {
2858 struct hci_cp_remote_name_req cp;
2859 memset(&cp, 0, sizeof(cp));
2860 bacpy(&cp.bdaddr, &conn->dst);
2861 cp.pscan_rep_mode = 0x02;
2862 hci_send_cmd(hdev, HCI_OP_REMOTE_NAME_REQ, sizeof(cp), &cp);
Johan Hedbergb644ba32012-01-17 21:48:47 +02002863 } else if (!test_and_set_bit(HCI_CONN_MGMT_CONNECTED, &conn->flags))
2864 mgmt_device_connected(hdev, &conn->dst, conn->type,
2865 conn->dst_type, NULL, 0,
2866 conn->dev_class);
Johan Hedberg392599b2010-11-18 22:22:28 +02002867
Johan Hedberg127178d2010-11-18 22:22:29 +02002868 if (!hci_outgoing_auth_needed(hdev, conn)) {
Johan Hedbergccd556f2010-11-10 17:11:51 +02002869 conn->state = BT_CONNECTED;
2870 hci_proto_connect_cfm(conn, ev->status);
2871 hci_conn_put(conn);
2872 }
2873
2874unlock:
Marcel Holtmann41a96212008-07-14 20:13:48 +02002875 hci_dev_unlock(hdev);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002876}
2877
2878static inline void hci_sync_conn_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
2879{
Marcel Holtmannb6a0dc82007-10-20 14:55:10 +02002880 struct hci_ev_sync_conn_complete *ev = (void *) skb->data;
2881 struct hci_conn *conn;
2882
2883 BT_DBG("%s status %d", hdev->name, ev->status);
2884
2885 hci_dev_lock(hdev);
2886
2887 conn = hci_conn_hash_lookup_ba(hdev, ev->link_type, &ev->bdaddr);
Marcel Holtmann9dc0a3a2008-07-14 20:13:46 +02002888 if (!conn) {
2889 if (ev->link_type == ESCO_LINK)
2890 goto unlock;
2891
2892 conn = hci_conn_hash_lookup_ba(hdev, ESCO_LINK, &ev->bdaddr);
2893 if (!conn)
2894 goto unlock;
2895
2896 conn->type = SCO_LINK;
2897 }
Marcel Holtmannb6a0dc82007-10-20 14:55:10 +02002898
Marcel Holtmann732547f2009-04-19 19:14:14 +02002899 switch (ev->status) {
2900 case 0x00:
Marcel Holtmannb6a0dc82007-10-20 14:55:10 +02002901 conn->handle = __le16_to_cpu(ev->handle);
2902 conn->state = BT_CONNECTED;
Marcel Holtmann7d0db0a2008-07-14 20:13:51 +02002903
Marcel Holtmann9eba32b2009-08-22 14:19:26 -07002904 hci_conn_hold_device(conn);
Marcel Holtmann7d0db0a2008-07-14 20:13:51 +02002905 hci_conn_add_sysfs(conn);
Marcel Holtmann732547f2009-04-19 19:14:14 +02002906 break;
2907
Stephen Coe705e5712010-02-16 11:29:44 -05002908 case 0x11: /* Unsupported Feature or Parameter Value */
Marcel Holtmann732547f2009-04-19 19:14:14 +02002909 case 0x1c: /* SCO interval rejected */
Nick Pelly1038a002010-02-03 11:42:26 -08002910 case 0x1a: /* Unsupported Remote Feature */
Marcel Holtmann732547f2009-04-19 19:14:14 +02002911 case 0x1f: /* Unspecified error */
2912 if (conn->out && conn->attempt < 2) {
2913 conn->pkt_type = (hdev->esco_type & SCO_ESCO_MASK) |
2914 (hdev->esco_type & EDR_ESCO_MASK);
2915 hci_setup_sync(conn, conn->link->handle);
2916 goto unlock;
2917 }
2918 /* fall through */
2919
2920 default:
Marcel Holtmannb6a0dc82007-10-20 14:55:10 +02002921 conn->state = BT_CLOSED;
Marcel Holtmann732547f2009-04-19 19:14:14 +02002922 break;
2923 }
Marcel Holtmannb6a0dc82007-10-20 14:55:10 +02002924
2925 hci_proto_connect_cfm(conn, ev->status);
2926 if (ev->status)
2927 hci_conn_del(conn);
2928
2929unlock:
2930 hci_dev_unlock(hdev);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002931}
2932
2933static inline void hci_sync_conn_changed_evt(struct hci_dev *hdev, struct sk_buff *skb)
2934{
2935 BT_DBG("%s", hdev->name);
2936}
2937
Marcel Holtmann04837f62006-07-03 10:02:33 +02002938static inline void hci_sniff_subrate_evt(struct hci_dev *hdev, struct sk_buff *skb)
2939{
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002940 struct hci_ev_sniff_subrate *ev = (void *) skb->data;
Marcel Holtmann04837f62006-07-03 10:02:33 +02002941
2942 BT_DBG("%s status %d", hdev->name, ev->status);
Marcel Holtmann04837f62006-07-03 10:02:33 +02002943}
2944
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002945static inline void hci_extended_inquiry_result_evt(struct hci_dev *hdev, struct sk_buff *skb)
2946{
2947 struct inquiry_data data;
2948 struct extended_inquiry_info *info = (void *) (skb->data + 1);
2949 int num_rsp = *((__u8 *) skb->data);
2950
2951 BT_DBG("%s num_rsp %d", hdev->name, num_rsp);
2952
2953 if (!num_rsp)
2954 return;
2955
2956 hci_dev_lock(hdev);
2957
Johan Hedberge17acd42011-03-30 23:57:16 +03002958 for (; num_rsp; num_rsp--, info++) {
Johan Hedberg561aafb2012-01-04 13:31:59 +02002959 bool name_known;
2960
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002961 bacpy(&data.bdaddr, &info->bdaddr);
Szymon Janc138d22e2011-02-17 16:44:23 +01002962 data.pscan_rep_mode = info->pscan_rep_mode;
2963 data.pscan_period_mode = info->pscan_period_mode;
2964 data.pscan_mode = 0x00;
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002965 memcpy(data.dev_class, info->dev_class, 3);
Szymon Janc138d22e2011-02-17 16:44:23 +01002966 data.clock_offset = info->clock_offset;
2967 data.rssi = info->rssi;
Marcel Holtmann41a96212008-07-14 20:13:48 +02002968 data.ssp_mode = 0x01;
Johan Hedberg561aafb2012-01-04 13:31:59 +02002969
Johan Hedberga8b2d5c2012-01-08 23:11:15 +02002970 if (test_bit(HCI_MGMT, &hdev->dev_flags))
Johan Hedberg4ddb1932012-01-15 20:04:43 +02002971 name_known = eir_has_data_type(info->data,
2972 sizeof(info->data),
2973 EIR_NAME_COMPLETE);
Johan Hedberg561aafb2012-01-04 13:31:59 +02002974 else
2975 name_known = true;
2976
Johan Hedberg31754052012-01-04 13:39:52 +02002977 name_known = hci_inquiry_cache_update(hdev, &data, name_known);
Johan Hedberg48264f02011-11-09 13:58:58 +02002978 mgmt_device_found(hdev, &info->bdaddr, ACL_LINK, 0x00,
Johan Hedberg561aafb2012-01-04 13:31:59 +02002979 info->dev_class, info->rssi,
Andre Guedes7d262f82012-01-10 18:20:49 -03002980 !name_known, info->data,
2981 sizeof(info->data));
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002982 }
2983
2984 hci_dev_unlock(hdev);
2985}
2986
Johan Hedberg17fa4b92011-01-25 13:28:33 +02002987static inline u8 hci_get_auth_req(struct hci_conn *conn)
2988{
2989 /* If remote requests dedicated bonding follow that lead */
2990 if (conn->remote_auth == 0x02 || conn->remote_auth == 0x03) {
2991 /* If both remote and local IO capabilities allow MITM
2992 * protection then require it, otherwise don't */
2993 if (conn->remote_cap == 0x03 || conn->io_capability == 0x03)
2994 return 0x02;
2995 else
2996 return 0x03;
2997 }
2998
2999 /* If remote requests no-bonding follow that lead */
3000 if (conn->remote_auth == 0x00 || conn->remote_auth == 0x01)
Waldemar Rymarkiewicz58797bf2011-04-28 12:07:58 +02003001 return conn->remote_auth | (conn->auth_type & 0x01);
Johan Hedberg17fa4b92011-01-25 13:28:33 +02003002
3003 return conn->auth_type;
3004}
3005
Marcel Holtmann04936842008-07-14 20:13:48 +02003006static inline void hci_io_capa_request_evt(struct hci_dev *hdev, struct sk_buff *skb)
3007{
3008 struct hci_ev_io_capa_request *ev = (void *) skb->data;
3009 struct hci_conn *conn;
3010
3011 BT_DBG("%s", hdev->name);
3012
3013 hci_dev_lock(hdev);
3014
3015 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
Johan Hedberg03b555e2011-01-04 15:40:05 +02003016 if (!conn)
3017 goto unlock;
Marcel Holtmann04936842008-07-14 20:13:48 +02003018
Johan Hedberg03b555e2011-01-04 15:40:05 +02003019 hci_conn_hold(conn);
3020
Johan Hedberga8b2d5c2012-01-08 23:11:15 +02003021 if (!test_bit(HCI_MGMT, &hdev->dev_flags))
Johan Hedberg03b555e2011-01-04 15:40:05 +02003022 goto unlock;
3023
Johan Hedberga8b2d5c2012-01-08 23:11:15 +02003024 if (test_bit(HCI_PAIRABLE, &hdev->dev_flags) ||
Johan Hedberg03b555e2011-01-04 15:40:05 +02003025 (conn->remote_auth & ~0x01) == HCI_AT_NO_BONDING) {
Johan Hedberg17fa4b92011-01-25 13:28:33 +02003026 struct hci_cp_io_capability_reply cp;
3027
3028 bacpy(&cp.bdaddr, &ev->bdaddr);
Hemant Gupta7a7f1e72012-01-16 13:34:29 +05303029 /* Change the IO capability from KeyboardDisplay
3030 * to DisplayYesNo as it is not supported by BT spec. */
3031 cp.capability = (conn->io_capability == 0x04) ?
3032 0x01 : conn->io_capability;
Johan Hedberg7cbc9bd2011-04-28 11:29:04 -07003033 conn->auth_type = hci_get_auth_req(conn);
3034 cp.authentication = conn->auth_type;
Johan Hedberg17fa4b92011-01-25 13:28:33 +02003035
Johan Hedberg58a681e2012-01-16 06:47:28 +02003036 if ((conn->out || test_bit(HCI_CONN_REMOTE_OOB, &conn->flags)) &&
Szymon Jancce85ee12011-03-22 13:12:23 +01003037 hci_find_remote_oob_data(hdev, &conn->dst))
3038 cp.oob_data = 0x01;
3039 else
3040 cp.oob_data = 0x00;
3041
Johan Hedberg17fa4b92011-01-25 13:28:33 +02003042 hci_send_cmd(hdev, HCI_OP_IO_CAPABILITY_REPLY,
3043 sizeof(cp), &cp);
Johan Hedberg03b555e2011-01-04 15:40:05 +02003044 } else {
3045 struct hci_cp_io_capability_neg_reply cp;
3046
3047 bacpy(&cp.bdaddr, &ev->bdaddr);
Andrei Emeltchenko9f5a0d72011-11-07 14:20:25 +02003048 cp.reason = HCI_ERROR_PAIRING_NOT_ALLOWED;
Johan Hedberg03b555e2011-01-04 15:40:05 +02003049
3050 hci_send_cmd(hdev, HCI_OP_IO_CAPABILITY_NEG_REPLY,
3051 sizeof(cp), &cp);
3052 }
3053
3054unlock:
3055 hci_dev_unlock(hdev);
3056}
3057
3058static inline void hci_io_capa_reply_evt(struct hci_dev *hdev, struct sk_buff *skb)
3059{
3060 struct hci_ev_io_capa_reply *ev = (void *) skb->data;
3061 struct hci_conn *conn;
3062
3063 BT_DBG("%s", hdev->name);
3064
3065 hci_dev_lock(hdev);
3066
3067 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
3068 if (!conn)
3069 goto unlock;
3070
Johan Hedberg03b555e2011-01-04 15:40:05 +02003071 conn->remote_cap = ev->capability;
Johan Hedberg03b555e2011-01-04 15:40:05 +02003072 conn->remote_auth = ev->authentication;
Johan Hedberg58a681e2012-01-16 06:47:28 +02003073 if (ev->oob_data)
3074 set_bit(HCI_CONN_REMOTE_OOB, &conn->flags);
Johan Hedberg03b555e2011-01-04 15:40:05 +02003075
3076unlock:
Marcel Holtmann04936842008-07-14 20:13:48 +02003077 hci_dev_unlock(hdev);
3078}
3079
Johan Hedberga5c29682011-02-19 12:05:57 -03003080static inline void hci_user_confirm_request_evt(struct hci_dev *hdev,
3081 struct sk_buff *skb)
3082{
3083 struct hci_ev_user_confirm_req *ev = (void *) skb->data;
Johan Hedberg55bc1a32011-04-28 11:28:56 -07003084 int loc_mitm, rem_mitm, confirm_hint = 0;
Johan Hedberg7a828902011-04-28 11:28:53 -07003085 struct hci_conn *conn;
Johan Hedberga5c29682011-02-19 12:05:57 -03003086
3087 BT_DBG("%s", hdev->name);
3088
3089 hci_dev_lock(hdev);
3090
Johan Hedberga8b2d5c2012-01-08 23:11:15 +02003091 if (!test_bit(HCI_MGMT, &hdev->dev_flags))
Johan Hedberg7a828902011-04-28 11:28:53 -07003092 goto unlock;
Johan Hedberga5c29682011-02-19 12:05:57 -03003093
Johan Hedberg7a828902011-04-28 11:28:53 -07003094 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
3095 if (!conn)
3096 goto unlock;
3097
3098 loc_mitm = (conn->auth_type & 0x01);
3099 rem_mitm = (conn->remote_auth & 0x01);
3100
3101 /* If we require MITM but the remote device can't provide that
3102 * (it has NoInputNoOutput) then reject the confirmation
3103 * request. The only exception is when we're dedicated bonding
3104 * initiators (connect_cfm_cb set) since then we always have the MITM
3105 * bit set. */
3106 if (!conn->connect_cfm_cb && loc_mitm && conn->remote_cap == 0x03) {
3107 BT_DBG("Rejecting request: remote device can't provide MITM");
3108 hci_send_cmd(hdev, HCI_OP_USER_CONFIRM_NEG_REPLY,
3109 sizeof(ev->bdaddr), &ev->bdaddr);
3110 goto unlock;
3111 }
3112
3113 /* If no side requires MITM protection; auto-accept */
3114 if ((!loc_mitm || conn->remote_cap == 0x03) &&
3115 (!rem_mitm || conn->io_capability == 0x03)) {
Johan Hedberg55bc1a32011-04-28 11:28:56 -07003116
3117 /* If we're not the initiators request authorization to
3118 * proceed from user space (mgmt_user_confirm with
3119 * confirm_hint set to 1). */
Johan Hedberg51a8efd2012-01-16 06:10:31 +02003120 if (!test_bit(HCI_CONN_AUTH_PEND, &conn->flags)) {
Johan Hedberg55bc1a32011-04-28 11:28:56 -07003121 BT_DBG("Confirming auto-accept as acceptor");
3122 confirm_hint = 1;
3123 goto confirm;
3124 }
3125
Johan Hedberg9f616562011-04-28 11:28:54 -07003126 BT_DBG("Auto-accept of user confirmation with %ums delay",
3127 hdev->auto_accept_delay);
3128
3129 if (hdev->auto_accept_delay > 0) {
3130 int delay = msecs_to_jiffies(hdev->auto_accept_delay);
3131 mod_timer(&conn->auto_accept_timer, jiffies + delay);
3132 goto unlock;
3133 }
3134
Johan Hedberg7a828902011-04-28 11:28:53 -07003135 hci_send_cmd(hdev, HCI_OP_USER_CONFIRM_REPLY,
3136 sizeof(ev->bdaddr), &ev->bdaddr);
3137 goto unlock;
3138 }
3139
Johan Hedberg55bc1a32011-04-28 11:28:56 -07003140confirm:
Johan Hedberg272d90d2012-02-09 15:26:12 +02003141 mgmt_user_confirm_request(hdev, &ev->bdaddr, ACL_LINK, 0, ev->passkey,
Johan Hedberg55bc1a32011-04-28 11:28:56 -07003142 confirm_hint);
Johan Hedberg7a828902011-04-28 11:28:53 -07003143
3144unlock:
Johan Hedberga5c29682011-02-19 12:05:57 -03003145 hci_dev_unlock(hdev);
3146}
3147
Brian Gix1143d452011-11-23 08:28:34 -08003148static inline void hci_user_passkey_request_evt(struct hci_dev *hdev,
3149 struct sk_buff *skb)
3150{
3151 struct hci_ev_user_passkey_req *ev = (void *) skb->data;
3152
3153 BT_DBG("%s", hdev->name);
3154
3155 hci_dev_lock(hdev);
3156
Johan Hedberga8b2d5c2012-01-08 23:11:15 +02003157 if (test_bit(HCI_MGMT, &hdev->dev_flags))
Johan Hedberg272d90d2012-02-09 15:26:12 +02003158 mgmt_user_passkey_request(hdev, &ev->bdaddr, ACL_LINK, 0);
Brian Gix1143d452011-11-23 08:28:34 -08003159
3160 hci_dev_unlock(hdev);
3161}
3162
Marcel Holtmann04936842008-07-14 20:13:48 +02003163static inline void hci_simple_pair_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
3164{
3165 struct hci_ev_simple_pair_complete *ev = (void *) skb->data;
3166 struct hci_conn *conn;
3167
3168 BT_DBG("%s", hdev->name);
3169
3170 hci_dev_lock(hdev);
3171
3172 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
Johan Hedberg2a611692011-02-19 12:06:00 -03003173 if (!conn)
3174 goto unlock;
Marcel Holtmann04936842008-07-14 20:13:48 +02003175
Johan Hedberg2a611692011-02-19 12:06:00 -03003176 /* To avoid duplicate auth_failed events to user space we check
3177 * the HCI_CONN_AUTH_PEND flag which will be set if we
3178 * initiated the authentication. A traditional auth_complete
3179 * event gets always produced as initiator and is also mapped to
3180 * the mgmt_auth_failed event */
Johan Hedberg51a8efd2012-01-16 06:10:31 +02003181 if (!test_bit(HCI_CONN_AUTH_PEND, &conn->flags) && ev->status != 0)
Johan Hedbergbab73cb2012-02-09 16:07:29 +02003182 mgmt_auth_failed(hdev, &conn->dst, conn->type, conn->dst_type,
3183 ev->status);
Johan Hedberg2a611692011-02-19 12:06:00 -03003184
3185 hci_conn_put(conn);
3186
3187unlock:
Marcel Holtmann04936842008-07-14 20:13:48 +02003188 hci_dev_unlock(hdev);
3189}
3190
Marcel Holtmann41a96212008-07-14 20:13:48 +02003191static inline void hci_remote_host_features_evt(struct hci_dev *hdev, struct sk_buff *skb)
3192{
3193 struct hci_ev_remote_host_features *ev = (void *) skb->data;
3194 struct inquiry_entry *ie;
3195
3196 BT_DBG("%s", hdev->name);
3197
3198 hci_dev_lock(hdev);
3199
Andrei Emeltchenkocc11b9c2010-11-22 13:21:37 +02003200 ie = hci_inquiry_cache_lookup(hdev, &ev->bdaddr);
3201 if (ie)
Marcel Holtmann41a96212008-07-14 20:13:48 +02003202 ie->data.ssp_mode = (ev->features[0] & 0x01);
3203
3204 hci_dev_unlock(hdev);
3205}
3206
Szymon Janc2763eda2011-03-22 13:12:22 +01003207static inline void hci_remote_oob_data_request_evt(struct hci_dev *hdev,
3208 struct sk_buff *skb)
3209{
3210 struct hci_ev_remote_oob_data_request *ev = (void *) skb->data;
3211 struct oob_data *data;
3212
3213 BT_DBG("%s", hdev->name);
3214
3215 hci_dev_lock(hdev);
3216
Johan Hedberga8b2d5c2012-01-08 23:11:15 +02003217 if (!test_bit(HCI_MGMT, &hdev->dev_flags))
Szymon Jance1ba1f12011-04-06 13:01:59 +02003218 goto unlock;
3219
Szymon Janc2763eda2011-03-22 13:12:22 +01003220 data = hci_find_remote_oob_data(hdev, &ev->bdaddr);
3221 if (data) {
3222 struct hci_cp_remote_oob_data_reply cp;
3223
3224 bacpy(&cp.bdaddr, &ev->bdaddr);
3225 memcpy(cp.hash, data->hash, sizeof(cp.hash));
3226 memcpy(cp.randomizer, data->randomizer, sizeof(cp.randomizer));
3227
3228 hci_send_cmd(hdev, HCI_OP_REMOTE_OOB_DATA_REPLY, sizeof(cp),
3229 &cp);
3230 } else {
3231 struct hci_cp_remote_oob_data_neg_reply cp;
3232
3233 bacpy(&cp.bdaddr, &ev->bdaddr);
3234 hci_send_cmd(hdev, HCI_OP_REMOTE_OOB_DATA_NEG_REPLY, sizeof(cp),
3235 &cp);
3236 }
3237
Szymon Jance1ba1f12011-04-06 13:01:59 +02003238unlock:
Szymon Janc2763eda2011-03-22 13:12:22 +01003239 hci_dev_unlock(hdev);
3240}
3241
Ville Tervofcd89c02011-02-10 22:38:47 -03003242static inline void hci_le_conn_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
3243{
3244 struct hci_ev_le_conn_complete *ev = (void *) skb->data;
3245 struct hci_conn *conn;
3246
3247 BT_DBG("%s status %d", hdev->name, ev->status);
3248
3249 hci_dev_lock(hdev);
3250
3251 conn = hci_conn_hash_lookup_ba(hdev, LE_LINK, &ev->bdaddr);
Ville Tervob62f3282011-02-10 22:38:50 -03003252 if (!conn) {
3253 conn = hci_conn_add(hdev, LE_LINK, &ev->bdaddr);
3254 if (!conn) {
3255 BT_ERR("No memory for new connection");
3256 hci_dev_unlock(hdev);
3257 return;
3258 }
Andre Guedes29b79882011-05-31 14:20:54 -03003259
3260 conn->dst_type = ev->bdaddr_type;
Ville Tervob62f3282011-02-10 22:38:50 -03003261 }
Ville Tervofcd89c02011-02-10 22:38:47 -03003262
3263 if (ev->status) {
Johan Hedberg48264f02011-11-09 13:58:58 +02003264 mgmt_connect_failed(hdev, &ev->bdaddr, conn->type,
3265 conn->dst_type, ev->status);
Ville Tervofcd89c02011-02-10 22:38:47 -03003266 hci_proto_connect_cfm(conn, ev->status);
3267 conn->state = BT_CLOSED;
3268 hci_conn_del(conn);
3269 goto unlock;
3270 }
3271
Johan Hedbergb644ba32012-01-17 21:48:47 +02003272 if (!test_and_set_bit(HCI_CONN_MGMT_CONNECTED, &conn->flags))
3273 mgmt_device_connected(hdev, &ev->bdaddr, conn->type,
3274 conn->dst_type, NULL, 0, 0);
Vinicius Costa Gomes83bc71b2011-05-06 18:41:43 -03003275
Vinicius Costa Gomes7b5c0d52011-06-09 18:50:50 -03003276 conn->sec_level = BT_SECURITY_LOW;
Ville Tervofcd89c02011-02-10 22:38:47 -03003277 conn->handle = __le16_to_cpu(ev->handle);
3278 conn->state = BT_CONNECTED;
3279
3280 hci_conn_hold_device(conn);
3281 hci_conn_add_sysfs(conn);
3282
3283 hci_proto_connect_cfm(conn, ev->status);
3284
3285unlock:
3286 hci_dev_unlock(hdev);
3287}
3288
Andre Guedes9aa04c92011-05-26 16:23:51 -03003289static inline void hci_le_adv_report_evt(struct hci_dev *hdev,
3290 struct sk_buff *skb)
3291{
Andre Guedese95beb42011-09-26 20:48:35 -03003292 u8 num_reports = skb->data[0];
3293 void *ptr = &skb->data[1];
Andre Guedes3c9e9192012-01-10 18:20:50 -03003294 s8 rssi;
Andre Guedes9aa04c92011-05-26 16:23:51 -03003295
3296 hci_dev_lock(hdev);
3297
Andre Guedese95beb42011-09-26 20:48:35 -03003298 while (num_reports--) {
3299 struct hci_ev_le_advertising_info *ev = ptr;
Andre Guedes9aa04c92011-05-26 16:23:51 -03003300
Andre Guedes9aa04c92011-05-26 16:23:51 -03003301 hci_add_adv_entry(hdev, ev);
Andre Guedese95beb42011-09-26 20:48:35 -03003302
Andre Guedes3c9e9192012-01-10 18:20:50 -03003303 rssi = ev->data[ev->length];
3304 mgmt_device_found(hdev, &ev->bdaddr, LE_LINK, ev->bdaddr_type,
3305 NULL, rssi, 0, ev->data, ev->length);
3306
Andre Guedese95beb42011-09-26 20:48:35 -03003307 ptr += sizeof(*ev) + ev->length + 1;
Andre Guedes9aa04c92011-05-26 16:23:51 -03003308 }
3309
3310 hci_dev_unlock(hdev);
3311}
3312
Vinicius Costa Gomesa7a595f2011-06-09 18:50:47 -03003313static inline void hci_le_ltk_request_evt(struct hci_dev *hdev,
3314 struct sk_buff *skb)
3315{
3316 struct hci_ev_le_ltk_req *ev = (void *) skb->data;
3317 struct hci_cp_le_ltk_reply cp;
Vinicius Costa Gomesbea710f2011-07-07 18:59:37 -03003318 struct hci_cp_le_ltk_neg_reply neg;
Vinicius Costa Gomesa7a595f2011-06-09 18:50:47 -03003319 struct hci_conn *conn;
Vinicius Costa Gomesc9839a12012-02-02 21:08:01 -03003320 struct smp_ltk *ltk;
Vinicius Costa Gomesa7a595f2011-06-09 18:50:47 -03003321
3322 BT_DBG("%s handle %d", hdev->name, cpu_to_le16(ev->handle));
3323
3324 hci_dev_lock(hdev);
3325
3326 conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
Vinicius Costa Gomesbea710f2011-07-07 18:59:37 -03003327 if (conn == NULL)
3328 goto not_found;
Vinicius Costa Gomesa7a595f2011-06-09 18:50:47 -03003329
Vinicius Costa Gomesbea710f2011-07-07 18:59:37 -03003330 ltk = hci_find_ltk(hdev, ev->ediv, ev->random);
3331 if (ltk == NULL)
3332 goto not_found;
3333
3334 memcpy(cp.ltk, ltk->val, sizeof(ltk->val));
Vinicius Costa Gomesa7a595f2011-06-09 18:50:47 -03003335 cp.handle = cpu_to_le16(conn->handle);
Vinicius Costa Gomesc9839a12012-02-02 21:08:01 -03003336
3337 if (ltk->authenticated)
3338 conn->sec_level = BT_SECURITY_HIGH;
Vinicius Costa Gomesa7a595f2011-06-09 18:50:47 -03003339
3340 hci_send_cmd(hdev, HCI_OP_LE_LTK_REPLY, sizeof(cp), &cp);
3341
Vinicius Costa Gomesc9839a12012-02-02 21:08:01 -03003342 if (ltk->type & HCI_SMP_STK) {
3343 list_del(&ltk->list);
3344 kfree(ltk);
3345 }
3346
Vinicius Costa Gomesa7a595f2011-06-09 18:50:47 -03003347 hci_dev_unlock(hdev);
Vinicius Costa Gomesbea710f2011-07-07 18:59:37 -03003348
3349 return;
3350
3351not_found:
3352 neg.handle = ev->handle;
3353 hci_send_cmd(hdev, HCI_OP_LE_LTK_NEG_REPLY, sizeof(neg), &neg);
3354 hci_dev_unlock(hdev);
Vinicius Costa Gomesa7a595f2011-06-09 18:50:47 -03003355}
3356
Ville Tervofcd89c02011-02-10 22:38:47 -03003357static inline void hci_le_meta_evt(struct hci_dev *hdev, struct sk_buff *skb)
3358{
3359 struct hci_ev_le_meta *le_ev = (void *) skb->data;
3360
3361 skb_pull(skb, sizeof(*le_ev));
3362
3363 switch (le_ev->subevent) {
3364 case HCI_EV_LE_CONN_COMPLETE:
3365 hci_le_conn_complete_evt(hdev, skb);
3366 break;
3367
Andre Guedes9aa04c92011-05-26 16:23:51 -03003368 case HCI_EV_LE_ADVERTISING_REPORT:
3369 hci_le_adv_report_evt(hdev, skb);
3370 break;
3371
Vinicius Costa Gomesa7a595f2011-06-09 18:50:47 -03003372 case HCI_EV_LE_LTK_REQ:
3373 hci_le_ltk_request_evt(hdev, skb);
3374 break;
3375
Ville Tervofcd89c02011-02-10 22:38:47 -03003376 default:
3377 break;
3378 }
3379}
3380
Linus Torvalds1da177e2005-04-16 15:20:36 -07003381void hci_event_packet(struct hci_dev *hdev, struct sk_buff *skb)
3382{
Marcel Holtmanna9de9242007-10-20 13:33:56 +02003383 struct hci_event_hdr *hdr = (void *) skb->data;
3384 __u8 event = hdr->evt;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003385
3386 skb_pull(skb, HCI_EVENT_HDR_SIZE);
3387
Marcel Holtmanna9de9242007-10-20 13:33:56 +02003388 switch (event) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003389 case HCI_EV_INQUIRY_COMPLETE:
3390 hci_inquiry_complete_evt(hdev, skb);
3391 break;
3392
3393 case HCI_EV_INQUIRY_RESULT:
3394 hci_inquiry_result_evt(hdev, skb);
3395 break;
3396
Marcel Holtmanna9de9242007-10-20 13:33:56 +02003397 case HCI_EV_CONN_COMPLETE:
3398 hci_conn_complete_evt(hdev, skb);
Marcel Holtmann21d9e302005-09-13 01:32:25 +02003399 break;
3400
Linus Torvalds1da177e2005-04-16 15:20:36 -07003401 case HCI_EV_CONN_REQUEST:
3402 hci_conn_request_evt(hdev, skb);
3403 break;
3404
Linus Torvalds1da177e2005-04-16 15:20:36 -07003405 case HCI_EV_DISCONN_COMPLETE:
3406 hci_disconn_complete_evt(hdev, skb);
3407 break;
3408
Linus Torvalds1da177e2005-04-16 15:20:36 -07003409 case HCI_EV_AUTH_COMPLETE:
3410 hci_auth_complete_evt(hdev, skb);
3411 break;
3412
Marcel Holtmanna9de9242007-10-20 13:33:56 +02003413 case HCI_EV_REMOTE_NAME:
3414 hci_remote_name_evt(hdev, skb);
3415 break;
3416
Linus Torvalds1da177e2005-04-16 15:20:36 -07003417 case HCI_EV_ENCRYPT_CHANGE:
3418 hci_encrypt_change_evt(hdev, skb);
3419 break;
3420
Marcel Holtmanna9de9242007-10-20 13:33:56 +02003421 case HCI_EV_CHANGE_LINK_KEY_COMPLETE:
3422 hci_change_link_key_complete_evt(hdev, skb);
3423 break;
3424
3425 case HCI_EV_REMOTE_FEATURES:
3426 hci_remote_features_evt(hdev, skb);
3427 break;
3428
3429 case HCI_EV_REMOTE_VERSION:
3430 hci_remote_version_evt(hdev, skb);
3431 break;
3432
3433 case HCI_EV_QOS_SETUP_COMPLETE:
3434 hci_qos_setup_complete_evt(hdev, skb);
3435 break;
3436
3437 case HCI_EV_CMD_COMPLETE:
3438 hci_cmd_complete_evt(hdev, skb);
3439 break;
3440
3441 case HCI_EV_CMD_STATUS:
3442 hci_cmd_status_evt(hdev, skb);
3443 break;
3444
3445 case HCI_EV_ROLE_CHANGE:
3446 hci_role_change_evt(hdev, skb);
3447 break;
3448
3449 case HCI_EV_NUM_COMP_PKTS:
3450 hci_num_comp_pkts_evt(hdev, skb);
3451 break;
3452
3453 case HCI_EV_MODE_CHANGE:
3454 hci_mode_change_evt(hdev, skb);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003455 break;
3456
3457 case HCI_EV_PIN_CODE_REQ:
3458 hci_pin_code_request_evt(hdev, skb);
3459 break;
3460
3461 case HCI_EV_LINK_KEY_REQ:
3462 hci_link_key_request_evt(hdev, skb);
3463 break;
3464
3465 case HCI_EV_LINK_KEY_NOTIFY:
3466 hci_link_key_notify_evt(hdev, skb);
3467 break;
3468
3469 case HCI_EV_CLOCK_OFFSET:
3470 hci_clock_offset_evt(hdev, skb);
3471 break;
3472
Marcel Holtmanna8746412008-07-14 20:13:46 +02003473 case HCI_EV_PKT_TYPE_CHANGE:
3474 hci_pkt_type_change_evt(hdev, skb);
3475 break;
3476
Marcel Holtmann85a1e932005-08-09 20:28:02 -07003477 case HCI_EV_PSCAN_REP_MODE:
3478 hci_pscan_rep_mode_evt(hdev, skb);
3479 break;
3480
Marcel Holtmanna9de9242007-10-20 13:33:56 +02003481 case HCI_EV_INQUIRY_RESULT_WITH_RSSI:
3482 hci_inquiry_result_with_rssi_evt(hdev, skb);
3483 break;
3484
3485 case HCI_EV_REMOTE_EXT_FEATURES:
3486 hci_remote_ext_features_evt(hdev, skb);
3487 break;
3488
3489 case HCI_EV_SYNC_CONN_COMPLETE:
3490 hci_sync_conn_complete_evt(hdev, skb);
3491 break;
3492
3493 case HCI_EV_SYNC_CONN_CHANGED:
3494 hci_sync_conn_changed_evt(hdev, skb);
3495 break;
3496
Marcel Holtmann04837f62006-07-03 10:02:33 +02003497 case HCI_EV_SNIFF_SUBRATE:
3498 hci_sniff_subrate_evt(hdev, skb);
3499 break;
3500
Marcel Holtmanna9de9242007-10-20 13:33:56 +02003501 case HCI_EV_EXTENDED_INQUIRY_RESULT:
3502 hci_extended_inquiry_result_evt(hdev, skb);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003503 break;
3504
Marcel Holtmann04936842008-07-14 20:13:48 +02003505 case HCI_EV_IO_CAPA_REQUEST:
3506 hci_io_capa_request_evt(hdev, skb);
3507 break;
3508
Johan Hedberg03b555e2011-01-04 15:40:05 +02003509 case HCI_EV_IO_CAPA_REPLY:
3510 hci_io_capa_reply_evt(hdev, skb);
3511 break;
3512
Johan Hedberga5c29682011-02-19 12:05:57 -03003513 case HCI_EV_USER_CONFIRM_REQUEST:
3514 hci_user_confirm_request_evt(hdev, skb);
3515 break;
3516
Brian Gix1143d452011-11-23 08:28:34 -08003517 case HCI_EV_USER_PASSKEY_REQUEST:
3518 hci_user_passkey_request_evt(hdev, skb);
3519 break;
3520
Marcel Holtmann04936842008-07-14 20:13:48 +02003521 case HCI_EV_SIMPLE_PAIR_COMPLETE:
3522 hci_simple_pair_complete_evt(hdev, skb);
3523 break;
3524
Marcel Holtmann41a96212008-07-14 20:13:48 +02003525 case HCI_EV_REMOTE_HOST_FEATURES:
3526 hci_remote_host_features_evt(hdev, skb);
3527 break;
3528
Ville Tervofcd89c02011-02-10 22:38:47 -03003529 case HCI_EV_LE_META:
3530 hci_le_meta_evt(hdev, skb);
3531 break;
3532
Szymon Janc2763eda2011-03-22 13:12:22 +01003533 case HCI_EV_REMOTE_OOB_DATA_REQUEST:
3534 hci_remote_oob_data_request_evt(hdev, skb);
3535 break;
3536
Andrei Emeltchenko25e89e92012-01-04 12:41:58 +02003537 case HCI_EV_NUM_COMP_BLOCKS:
3538 hci_num_comp_blocks_evt(hdev, skb);
3539 break;
3540
Marcel Holtmanna9de9242007-10-20 13:33:56 +02003541 default:
3542 BT_DBG("%s event 0x%x", hdev->name, event);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003543 break;
3544 }
3545
3546 kfree_skb(skb);
3547 hdev->stat.evt_rx++;
3548}
3549
3550/* Generate internal stack event */
3551void hci_si_event(struct hci_dev *hdev, int type, int dlen, void *data)
3552{
3553 struct hci_event_hdr *hdr;
3554 struct hci_ev_stack_internal *ev;
3555 struct sk_buff *skb;
3556
3557 skb = bt_skb_alloc(HCI_EVENT_HDR_SIZE + sizeof(*ev) + dlen, GFP_ATOMIC);
3558 if (!skb)
3559 return;
3560
3561 hdr = (void *) skb_put(skb, HCI_EVENT_HDR_SIZE);
3562 hdr->evt = HCI_EV_STACK_INTERNAL;
3563 hdr->plen = sizeof(*ev) + dlen;
3564
3565 ev = (void *) skb_put(skb, sizeof(*ev) + dlen);
3566 ev->type = type;
3567 memcpy(ev->data, data, dlen);
3568
Marcel Holtmann576c7d82005-08-06 12:36:54 +02003569 bt_cb(skb)->incoming = 1;
Patrick McHardya61bbcf2005-08-14 17:24:31 -07003570 __net_timestamp(skb);
Marcel Holtmann576c7d82005-08-06 12:36:54 +02003571
Marcel Holtmann0d48d932005-08-09 20:30:28 -07003572 bt_cb(skb)->pkt_type = HCI_EVENT_PKT;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003573 skb->dev = (void *) hdev;
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02003574 hci_send_to_sock(hdev, skb, NULL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003575 kfree_skb(skb);
3576}
Andre Guedese6100a22011-06-30 19:20:54 -03003577
Gustavo F. Padovan669bb392011-10-11 15:57:01 -03003578module_param(enable_le, bool, 0644);
Andre Guedese6100a22011-06-30 19:20:54 -03003579MODULE_PARM_DESC(enable_le, "Enable LE support");