blob: 1795c0c9b41176b51782342fd59ff622b4243bf8 [file] [log] [blame]
YOSHIFUJI Hideaki8e87d142007-02-09 23:24:33 +09001/*
Linus Torvalds1da177e2005-04-16 15:20:36 -07002 BlueZ - Bluetooth protocol stack for Linux
Ron Shaffer2d0a0342010-05-28 11:53:46 -04003 Copyright (c) 2000-2001, 2010, Code Aurora Forum. All rights reserved.
Linus Torvalds1da177e2005-04-16 15:20:36 -07004
5 Written 2000,2001 by Maxim Krasnyansky <maxk@qualcomm.com>
6
7 This program is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License version 2 as
9 published by the Free Software Foundation;
10
11 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
12 OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
13 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF THIRD PARTY RIGHTS.
14 IN NO EVENT SHALL THE COPYRIGHT HOLDER(S) AND AUTHOR(S) BE LIABLE FOR ANY
YOSHIFUJI Hideaki8e87d142007-02-09 23:24:33 +090015 CLAIM, OR ANY SPECIAL INDIRECT OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES
16 WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
17 ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
Linus Torvalds1da177e2005-04-16 15:20:36 -070018 OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
19
YOSHIFUJI Hideaki8e87d142007-02-09 23:24:33 +090020 ALL LIABILITY, INCLUDING LIABILITY FOR INFRINGEMENT OF ANY PATENTS,
21 COPYRIGHTS, TRADEMARKS OR OTHER RIGHTS, RELATING TO USE OF THIS
Linus Torvalds1da177e2005-04-16 15:20:36 -070022 SOFTWARE IS DISCLAIMED.
23*/
24
25/* Bluetooth HCI event handling. */
26
Linus Torvalds1da177e2005-04-16 15:20:36 -070027#include <linux/module.h>
28
29#include <linux/types.h>
30#include <linux/errno.h>
31#include <linux/kernel.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070032#include <linux/slab.h>
33#include <linux/poll.h>
34#include <linux/fcntl.h>
35#include <linux/init.h>
36#include <linux/skbuff.h>
37#include <linux/interrupt.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070038#include <net/sock.h>
39
Andrei Emeltchenko70f230202010-12-01 16:58:25 +020040#include <linux/uaccess.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070041#include <asm/unaligned.h>
42
43#include <net/bluetooth/bluetooth.h>
44#include <net/bluetooth/hci_core.h>
45
Linus Torvalds1da177e2005-04-16 15:20:36 -070046/* Handle HCI Event packets */
47
Marcel Holtmanna9de9242007-10-20 13:33:56 +020048static void hci_cc_inquiry_cancel(struct hci_dev *hdev, struct sk_buff *skb)
Linus Torvalds1da177e2005-04-16 15:20:36 -070049{
Marcel Holtmanna9de9242007-10-20 13:33:56 +020050 __u8 status = *((__u8 *) skb->data);
Linus Torvalds1da177e2005-04-16 15:20:36 -070051
Marcel Holtmanna9de9242007-10-20 13:33:56 +020052 BT_DBG("%s status 0x%x", hdev->name, status);
Linus Torvalds1da177e2005-04-16 15:20:36 -070053
Andre Guedese6d465c2011-11-09 17:14:26 -030054 if (status) {
55 hci_dev_lock(hdev);
56 mgmt_stop_discovery_failed(hdev, status);
57 hci_dev_unlock(hdev);
Marcel Holtmanna9de9242007-10-20 13:33:56 +020058 return;
Andre Guedese6d465c2011-11-09 17:14:26 -030059 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070060
Andre Guedes89352e72011-11-04 14:16:53 -030061 clear_bit(HCI_INQUIRY, &hdev->flags);
62
Johan Hedberg56e5cb82011-11-08 20:40:16 +020063 hci_dev_lock(hdev);
Johan Hedbergff9ef572012-01-04 14:23:45 +020064 hci_discovery_set_state(hdev, DISCOVERY_STOPPED);
Johan Hedberg56e5cb82011-11-08 20:40:16 +020065 hci_dev_unlock(hdev);
Marcel Holtmann6bd57412006-11-18 22:14:22 +010066
Johan Hedberg23bb5762010-12-21 23:01:27 +020067 hci_req_complete(hdev, HCI_OP_INQUIRY_CANCEL, status);
Marcel Holtmann6bd57412006-11-18 22:14:22 +010068
Marcel Holtmanna9de9242007-10-20 13:33:56 +020069 hci_conn_check_pending(hdev);
Linus Torvalds1da177e2005-04-16 15:20:36 -070070}
71
Andre Guedes4d934832012-03-21 00:03:35 -030072static void hci_cc_periodic_inq(struct hci_dev *hdev, struct sk_buff *skb)
73{
74 __u8 status = *((__u8 *) skb->data);
75
76 BT_DBG("%s status 0x%x", hdev->name, status);
Andre Guedesae854a72012-03-21 00:03:36 -030077
78 if (status)
79 return;
80
81 set_bit(HCI_PERIODIC_INQ, &hdev->dev_flags);
Andre Guedes4d934832012-03-21 00:03:35 -030082}
83
Marcel Holtmanna9de9242007-10-20 13:33:56 +020084static void hci_cc_exit_periodic_inq(struct hci_dev *hdev, struct sk_buff *skb)
Linus Torvalds1da177e2005-04-16 15:20:36 -070085{
Marcel Holtmanna9de9242007-10-20 13:33:56 +020086 __u8 status = *((__u8 *) skb->data);
87
88 BT_DBG("%s status 0x%x", hdev->name, status);
89
90 if (status)
91 return;
92
Andre Guedesae854a72012-03-21 00:03:36 -030093 clear_bit(HCI_PERIODIC_INQ, &hdev->dev_flags);
94
Marcel Holtmanna9de9242007-10-20 13:33:56 +020095 hci_conn_check_pending(hdev);
96}
97
Gustavo Padovan807deac2012-05-17 00:36:24 -030098static void hci_cc_remote_name_req_cancel(struct hci_dev *hdev,
99 struct sk_buff *skb)
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200100{
101 BT_DBG("%s", hdev->name);
102}
103
104static void hci_cc_role_discovery(struct hci_dev *hdev, struct sk_buff *skb)
105{
106 struct hci_rp_role_discovery *rp = (void *) skb->data;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700107 struct hci_conn *conn;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700108
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200109 BT_DBG("%s status 0x%x", hdev->name, rp->status);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700110
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200111 if (rp->status)
112 return;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700113
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200114 hci_dev_lock(hdev);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700115
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200116 conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(rp->handle));
117 if (conn) {
118 if (rp->role)
119 conn->link_mode &= ~HCI_LM_MASTER;
120 else
121 conn->link_mode |= HCI_LM_MASTER;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700122 }
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200123
124 hci_dev_unlock(hdev);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700125}
126
Marcel Holtmanne4e8e372008-07-14 20:13:47 +0200127static void hci_cc_read_link_policy(struct hci_dev *hdev, struct sk_buff *skb)
128{
129 struct hci_rp_read_link_policy *rp = (void *) skb->data;
130 struct hci_conn *conn;
131
132 BT_DBG("%s status 0x%x", hdev->name, rp->status);
133
134 if (rp->status)
135 return;
136
137 hci_dev_lock(hdev);
138
139 conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(rp->handle));
140 if (conn)
141 conn->link_policy = __le16_to_cpu(rp->policy);
142
143 hci_dev_unlock(hdev);
144}
145
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200146static void hci_cc_write_link_policy(struct hci_dev *hdev, struct sk_buff *skb)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700147{
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200148 struct hci_rp_write_link_policy *rp = (void *) skb->data;
149 struct hci_conn *conn;
150 void *sent;
151
152 BT_DBG("%s status 0x%x", hdev->name, rp->status);
153
154 if (rp->status)
155 return;
156
157 sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_LINK_POLICY);
158 if (!sent)
159 return;
160
161 hci_dev_lock(hdev);
162
163 conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(rp->handle));
Marcel Holtmanne4e8e372008-07-14 20:13:47 +0200164 if (conn)
Harvey Harrison83985312008-05-02 16:25:46 -0700165 conn->link_policy = get_unaligned_le16(sent + 2);
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200166
167 hci_dev_unlock(hdev);
168}
169
Gustavo Padovan807deac2012-05-17 00:36:24 -0300170static void hci_cc_read_def_link_policy(struct hci_dev *hdev,
171 struct sk_buff *skb)
Marcel Holtmanne4e8e372008-07-14 20:13:47 +0200172{
173 struct hci_rp_read_def_link_policy *rp = (void *) skb->data;
174
175 BT_DBG("%s status 0x%x", hdev->name, rp->status);
176
177 if (rp->status)
178 return;
179
180 hdev->link_policy = __le16_to_cpu(rp->policy);
181}
182
Gustavo Padovan807deac2012-05-17 00:36:24 -0300183static void hci_cc_write_def_link_policy(struct hci_dev *hdev,
184 struct sk_buff *skb)
Marcel Holtmanne4e8e372008-07-14 20:13:47 +0200185{
186 __u8 status = *((__u8 *) skb->data);
187 void *sent;
188
189 BT_DBG("%s status 0x%x", hdev->name, status);
190
191 sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_DEF_LINK_POLICY);
192 if (!sent)
193 return;
194
195 if (!status)
196 hdev->link_policy = get_unaligned_le16(sent);
197
Johan Hedberg23bb5762010-12-21 23:01:27 +0200198 hci_req_complete(hdev, HCI_OP_WRITE_DEF_LINK_POLICY, status);
Marcel Holtmanne4e8e372008-07-14 20:13:47 +0200199}
200
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200201static void hci_cc_reset(struct hci_dev *hdev, struct sk_buff *skb)
202{
203 __u8 status = *((__u8 *) skb->data);
204
205 BT_DBG("%s status 0x%x", hdev->name, status);
206
Gustavo F. Padovan10572132011-03-16 15:36:29 -0300207 clear_bit(HCI_RESET, &hdev->flags);
208
Johan Hedberg23bb5762010-12-21 23:01:27 +0200209 hci_req_complete(hdev, HCI_OP_RESET, status);
Andre Guedesd23264a2011-11-25 20:53:38 -0300210
Johan Hedberga297e972012-02-21 17:55:47 +0200211 /* Reset all non-persistent flags */
Andre Guedesae854a72012-03-21 00:03:36 -0300212 hdev->dev_flags &= ~(BIT(HCI_LE_SCAN) | BIT(HCI_PENDING_CLASS) |
213 BIT(HCI_PERIODIC_INQ));
Andre Guedes69775ff2012-02-23 16:50:05 +0200214
215 hdev->discovery.state = DISCOVERY_STOPPED;
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200216}
217
218static void hci_cc_write_local_name(struct hci_dev *hdev, struct sk_buff *skb)
219{
220 __u8 status = *((__u8 *) skb->data);
221 void *sent;
222
223 BT_DBG("%s status 0x%x", hdev->name, status);
224
225 sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_LOCAL_NAME);
226 if (!sent)
227 return;
228
Johan Hedberg56e5cb82011-11-08 20:40:16 +0200229 hci_dev_lock(hdev);
230
Johan Hedbergf51d5b22012-02-22 18:17:32 +0200231 if (test_bit(HCI_MGMT, &hdev->dev_flags))
232 mgmt_set_local_name_complete(hdev, sent, status);
Johan Hedberg28cc7bd2012-02-22 21:06:55 +0200233 else if (!status)
234 memcpy(hdev->dev_name, sent, HCI_MAX_NAME_LENGTH);
Johan Hedbergf51d5b22012-02-22 18:17:32 +0200235
Johan Hedberg56e5cb82011-11-08 20:40:16 +0200236 hci_dev_unlock(hdev);
Johan Hedberg3159d382012-02-24 13:47:56 +0200237
238 hci_req_complete(hdev, HCI_OP_WRITE_LOCAL_NAME, status);
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200239}
240
241static void hci_cc_read_local_name(struct hci_dev *hdev, struct sk_buff *skb)
242{
243 struct hci_rp_read_local_name *rp = (void *) skb->data;
244
245 BT_DBG("%s status 0x%x", hdev->name, rp->status);
246
247 if (rp->status)
248 return;
249
Johan Hedbergdb99b5f2012-02-22 20:14:22 +0200250 if (test_bit(HCI_SETUP, &hdev->dev_flags))
251 memcpy(hdev->dev_name, rp->name, HCI_MAX_NAME_LENGTH);
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200252}
253
254static void hci_cc_write_auth_enable(struct hci_dev *hdev, struct sk_buff *skb)
255{
256 __u8 status = *((__u8 *) skb->data);
257 void *sent;
258
259 BT_DBG("%s status 0x%x", hdev->name, status);
260
261 sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_AUTH_ENABLE);
262 if (!sent)
263 return;
264
265 if (!status) {
266 __u8 param = *((__u8 *) sent);
267
268 if (param == AUTH_ENABLED)
269 set_bit(HCI_AUTH, &hdev->flags);
270 else
271 clear_bit(HCI_AUTH, &hdev->flags);
272 }
273
Johan Hedberg33ef95e2012-02-16 23:56:27 +0200274 if (test_bit(HCI_MGMT, &hdev->dev_flags))
275 mgmt_auth_enable_complete(hdev, status);
276
Johan Hedberg23bb5762010-12-21 23:01:27 +0200277 hci_req_complete(hdev, HCI_OP_WRITE_AUTH_ENABLE, status);
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200278}
279
280static void hci_cc_write_encrypt_mode(struct hci_dev *hdev, struct sk_buff *skb)
281{
282 __u8 status = *((__u8 *) skb->data);
283 void *sent;
284
285 BT_DBG("%s status 0x%x", hdev->name, status);
286
287 sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_ENCRYPT_MODE);
288 if (!sent)
289 return;
290
291 if (!status) {
292 __u8 param = *((__u8 *) sent);
293
294 if (param)
295 set_bit(HCI_ENCRYPT, &hdev->flags);
296 else
297 clear_bit(HCI_ENCRYPT, &hdev->flags);
298 }
299
Johan Hedberg23bb5762010-12-21 23:01:27 +0200300 hci_req_complete(hdev, HCI_OP_WRITE_ENCRYPT_MODE, status);
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200301}
302
303static void hci_cc_write_scan_enable(struct hci_dev *hdev, struct sk_buff *skb)
304{
Johan Hedberg36f7fc72011-11-04 00:17:45 +0200305 __u8 param, status = *((__u8 *) skb->data);
306 int old_pscan, old_iscan;
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200307 void *sent;
308
309 BT_DBG("%s status 0x%x", hdev->name, status);
310
311 sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_SCAN_ENABLE);
312 if (!sent)
313 return;
314
Johan Hedberg36f7fc72011-11-04 00:17:45 +0200315 param = *((__u8 *) sent);
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200316
Johan Hedberg56e5cb82011-11-08 20:40:16 +0200317 hci_dev_lock(hdev);
318
Johan Hedberg2d7cee52011-11-07 22:16:03 +0200319 if (status != 0) {
Johan Hedberg744cf192011-11-08 20:40:14 +0200320 mgmt_write_scan_failed(hdev, param, status);
Johan Hedberg2d7cee52011-11-07 22:16:03 +0200321 hdev->discov_timeout = 0;
322 goto done;
323 }
324
Johan Hedberg36f7fc72011-11-04 00:17:45 +0200325 old_pscan = test_and_clear_bit(HCI_PSCAN, &hdev->flags);
326 old_iscan = test_and_clear_bit(HCI_ISCAN, &hdev->flags);
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200327
Johan Hedberg36f7fc72011-11-04 00:17:45 +0200328 if (param & SCAN_INQUIRY) {
329 set_bit(HCI_ISCAN, &hdev->flags);
330 if (!old_iscan)
Johan Hedberg744cf192011-11-08 20:40:14 +0200331 mgmt_discoverable(hdev, 1);
Johan Hedberg16ab91a2011-11-07 22:16:02 +0200332 if (hdev->discov_timeout > 0) {
333 int to = msecs_to_jiffies(hdev->discov_timeout * 1000);
334 queue_delayed_work(hdev->workqueue, &hdev->discov_off,
Gustavo Padovan807deac2012-05-17 00:36:24 -0300335 to);
Johan Hedberg16ab91a2011-11-07 22:16:02 +0200336 }
Johan Hedberg36f7fc72011-11-04 00:17:45 +0200337 } else if (old_iscan)
Johan Hedberg744cf192011-11-08 20:40:14 +0200338 mgmt_discoverable(hdev, 0);
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200339
Johan Hedberg36f7fc72011-11-04 00:17:45 +0200340 if (param & SCAN_PAGE) {
341 set_bit(HCI_PSCAN, &hdev->flags);
342 if (!old_pscan)
Johan Hedberg744cf192011-11-08 20:40:14 +0200343 mgmt_connectable(hdev, 1);
Johan Hedberg36f7fc72011-11-04 00:17:45 +0200344 } else if (old_pscan)
Johan Hedberg744cf192011-11-08 20:40:14 +0200345 mgmt_connectable(hdev, 0);
Johan Hedberg36f7fc72011-11-04 00:17:45 +0200346
347done:
Johan Hedberg56e5cb82011-11-08 20:40:16 +0200348 hci_dev_unlock(hdev);
Johan Hedberg23bb5762010-12-21 23:01:27 +0200349 hci_req_complete(hdev, HCI_OP_WRITE_SCAN_ENABLE, status);
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200350}
351
352static void hci_cc_read_class_of_dev(struct hci_dev *hdev, struct sk_buff *skb)
353{
354 struct hci_rp_read_class_of_dev *rp = (void *) skb->data;
355
356 BT_DBG("%s status 0x%x", hdev->name, rp->status);
357
358 if (rp->status)
359 return;
360
361 memcpy(hdev->dev_class, rp->dev_class, 3);
362
363 BT_DBG("%s class 0x%.2x%.2x%.2x", hdev->name,
Gustavo Padovan807deac2012-05-17 00:36:24 -0300364 hdev->dev_class[2], hdev->dev_class[1], hdev->dev_class[0]);
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200365}
366
367static void hci_cc_write_class_of_dev(struct hci_dev *hdev, struct sk_buff *skb)
368{
369 __u8 status = *((__u8 *) skb->data);
370 void *sent;
371
372 BT_DBG("%s status 0x%x", hdev->name, status);
373
374 sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_CLASS_OF_DEV);
375 if (!sent)
376 return;
377
Marcel Holtmann7f9a9032012-02-22 18:38:01 +0100378 hci_dev_lock(hdev);
379
380 if (status == 0)
381 memcpy(hdev->dev_class, sent, 3);
382
383 if (test_bit(HCI_MGMT, &hdev->dev_flags))
384 mgmt_set_class_of_dev_complete(hdev, sent, status);
385
386 hci_dev_unlock(hdev);
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200387}
388
389static void hci_cc_read_voice_setting(struct hci_dev *hdev, struct sk_buff *skb)
390{
391 struct hci_rp_read_voice_setting *rp = (void *) skb->data;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700392 __u16 setting;
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200393
394 BT_DBG("%s status 0x%x", hdev->name, rp->status);
395
396 if (rp->status)
397 return;
398
399 setting = __le16_to_cpu(rp->voice_setting);
400
Marcel Holtmannf383f272008-07-14 20:13:47 +0200401 if (hdev->voice_setting == setting)
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200402 return;
403
404 hdev->voice_setting = setting;
405
406 BT_DBG("%s voice setting 0x%04x", hdev->name, setting);
407
Gustavo F. Padovan3c547112011-12-14 22:58:44 -0200408 if (hdev->notify)
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200409 hdev->notify(hdev, HCI_NOTIFY_VOICE_SETTING);
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200410}
411
412static void hci_cc_write_voice_setting(struct hci_dev *hdev, struct sk_buff *skb)
413{
414 __u8 status = *((__u8 *) skb->data);
Marcel Holtmannf383f272008-07-14 20:13:47 +0200415 __u16 setting;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700416 void *sent;
417
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200418 BT_DBG("%s status 0x%x", hdev->name, status);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700419
Marcel Holtmannf383f272008-07-14 20:13:47 +0200420 if (status)
421 return;
422
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200423 sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_VOICE_SETTING);
424 if (!sent)
425 return;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700426
Marcel Holtmannf383f272008-07-14 20:13:47 +0200427 setting = get_unaligned_le16(sent);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700428
Marcel Holtmannf383f272008-07-14 20:13:47 +0200429 if (hdev->voice_setting == setting)
430 return;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700431
Marcel Holtmannf383f272008-07-14 20:13:47 +0200432 hdev->voice_setting = setting;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700433
Marcel Holtmannf383f272008-07-14 20:13:47 +0200434 BT_DBG("%s voice setting 0x%04x", hdev->name, setting);
435
Gustavo F. Padovan3c547112011-12-14 22:58:44 -0200436 if (hdev->notify)
Marcel Holtmannf383f272008-07-14 20:13:47 +0200437 hdev->notify(hdev, HCI_NOTIFY_VOICE_SETTING);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700438}
439
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200440static void hci_cc_host_buffer_size(struct hci_dev *hdev, struct sk_buff *skb)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700441{
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200442 __u8 status = *((__u8 *) skb->data);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700443
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200444 BT_DBG("%s status 0x%x", hdev->name, status);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700445
Johan Hedberg23bb5762010-12-21 23:01:27 +0200446 hci_req_complete(hdev, HCI_OP_HOST_BUFFER_SIZE, status);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700447}
448
Marcel Holtmann333140b2008-07-14 20:13:48 +0200449static void hci_cc_write_ssp_mode(struct hci_dev *hdev, struct sk_buff *skb)
450{
451 __u8 status = *((__u8 *) skb->data);
452 void *sent;
453
454 BT_DBG("%s status 0x%x", hdev->name, status);
455
Marcel Holtmann333140b2008-07-14 20:13:48 +0200456 sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_SSP_MODE);
457 if (!sent)
458 return;
459
Johan Hedberged2c4ee2012-02-17 00:56:28 +0200460 if (test_bit(HCI_MGMT, &hdev->dev_flags))
Johan Hedbergc0ecddc2012-02-22 12:38:31 +0200461 mgmt_ssp_enable_complete(hdev, *((u8 *) sent), status);
462 else if (!status) {
463 if (*((u8 *) sent))
464 set_bit(HCI_SSP_ENABLED, &hdev->dev_flags);
465 else
466 clear_bit(HCI_SSP_ENABLED, &hdev->dev_flags);
467 }
Marcel Holtmann333140b2008-07-14 20:13:48 +0200468}
469
Johan Hedbergd5859e22011-01-25 01:19:58 +0200470static u8 hci_get_inquiry_mode(struct hci_dev *hdev)
471{
472 if (hdev->features[6] & LMP_EXT_INQ)
473 return 2;
474
475 if (hdev->features[3] & LMP_RSSI_INQ)
476 return 1;
477
478 if (hdev->manufacturer == 11 && hdev->hci_rev == 0x00 &&
Gustavo Padovan807deac2012-05-17 00:36:24 -0300479 hdev->lmp_subver == 0x0757)
Johan Hedbergd5859e22011-01-25 01:19:58 +0200480 return 1;
481
482 if (hdev->manufacturer == 15) {
483 if (hdev->hci_rev == 0x03 && hdev->lmp_subver == 0x6963)
484 return 1;
485 if (hdev->hci_rev == 0x09 && hdev->lmp_subver == 0x6963)
486 return 1;
487 if (hdev->hci_rev == 0x00 && hdev->lmp_subver == 0x6965)
488 return 1;
489 }
490
491 if (hdev->manufacturer == 31 && hdev->hci_rev == 0x2005 &&
Gustavo Padovan807deac2012-05-17 00:36:24 -0300492 hdev->lmp_subver == 0x1805)
Johan Hedbergd5859e22011-01-25 01:19:58 +0200493 return 1;
494
495 return 0;
496}
497
498static void hci_setup_inquiry_mode(struct hci_dev *hdev)
499{
500 u8 mode;
501
502 mode = hci_get_inquiry_mode(hdev);
503
504 hci_send_cmd(hdev, HCI_OP_WRITE_INQUIRY_MODE, 1, &mode);
505}
506
507static void hci_setup_event_mask(struct hci_dev *hdev)
508{
509 /* The second byte is 0xff instead of 0x9f (two reserved bits
510 * disabled) since a Broadcom 1.2 dongle doesn't respond to the
511 * command otherwise */
512 u8 events[8] = { 0xff, 0xff, 0xfb, 0xff, 0x00, 0x00, 0x00, 0x00 };
513
Ville Tervo6de6c182011-05-27 11:16:21 +0300514 /* CSR 1.1 dongles does not accept any bitfield so don't try to set
515 * any event mask for pre 1.2 devices */
Andrei Emeltchenko5a13b092011-12-01 14:33:28 +0200516 if (hdev->hci_ver < BLUETOOTH_VER_1_2)
Ville Tervo6de6c182011-05-27 11:16:21 +0300517 return;
518
519 events[4] |= 0x01; /* Flow Specification Complete */
520 events[4] |= 0x02; /* Inquiry Result with RSSI */
521 events[4] |= 0x04; /* Read Remote Extended Features Complete */
522 events[5] |= 0x08; /* Synchronous Connection Complete */
523 events[5] |= 0x10; /* Synchronous Connection Changed */
Johan Hedbergd5859e22011-01-25 01:19:58 +0200524
525 if (hdev->features[3] & LMP_RSSI_INQ)
Johan Hedberga24299e2012-04-26 09:47:46 +0300526 events[4] |= 0x02; /* Inquiry Result with RSSI */
Johan Hedbergd5859e22011-01-25 01:19:58 +0200527
528 if (hdev->features[5] & LMP_SNIFF_SUBR)
529 events[5] |= 0x20; /* Sniff Subrating */
530
531 if (hdev->features[5] & LMP_PAUSE_ENC)
532 events[5] |= 0x80; /* Encryption Key Refresh Complete */
533
534 if (hdev->features[6] & LMP_EXT_INQ)
535 events[5] |= 0x40; /* Extended Inquiry Result */
536
537 if (hdev->features[6] & LMP_NO_FLUSH)
538 events[7] |= 0x01; /* Enhanced Flush Complete */
539
540 if (hdev->features[7] & LMP_LSTO)
541 events[6] |= 0x80; /* Link Supervision Timeout Changed */
542
543 if (hdev->features[6] & LMP_SIMPLE_PAIR) {
544 events[6] |= 0x01; /* IO Capability Request */
545 events[6] |= 0x02; /* IO Capability Response */
546 events[6] |= 0x04; /* User Confirmation Request */
547 events[6] |= 0x08; /* User Passkey Request */
548 events[6] |= 0x10; /* Remote OOB Data Request */
549 events[6] |= 0x20; /* Simple Pairing Complete */
550 events[7] |= 0x04; /* User Passkey Notification */
551 events[7] |= 0x08; /* Keypress Notification */
552 events[7] |= 0x10; /* Remote Host Supported
553 * Features Notification */
554 }
555
556 if (hdev->features[4] & LMP_LE)
557 events[7] |= 0x20; /* LE Meta-Event */
558
559 hci_send_cmd(hdev, HCI_OP_SET_EVENT_MASK, sizeof(events), events);
560}
561
562static void hci_setup(struct hci_dev *hdev)
563{
Andrei Emeltchenkoe61ef4992011-12-19 16:31:27 +0200564 if (hdev->dev_type != HCI_BREDR)
565 return;
566
Johan Hedbergd5859e22011-01-25 01:19:58 +0200567 hci_setup_event_mask(hdev);
568
Andrei Emeltchenkod095c1e2011-12-01 14:33:27 +0200569 if (hdev->hci_ver > BLUETOOTH_VER_1_1)
Johan Hedbergd5859e22011-01-25 01:19:58 +0200570 hci_send_cmd(hdev, HCI_OP_READ_LOCAL_COMMANDS, 0, NULL);
571
Johan Hedberg54d04db2012-02-22 15:47:48 +0200572 if (hdev->features[6] & LMP_SIMPLE_PAIR) {
573 if (test_bit(HCI_SSP_ENABLED, &hdev->dev_flags)) {
574 u8 mode = 0x01;
575 hci_send_cmd(hdev, HCI_OP_WRITE_SSP_MODE,
Gustavo F. Padovan04124682012-03-08 01:25:00 -0300576 sizeof(mode), &mode);
Johan Hedberg54d04db2012-02-22 15:47:48 +0200577 } else {
578 struct hci_cp_write_eir cp;
579
580 memset(hdev->eir, 0, sizeof(hdev->eir));
581 memset(&cp, 0, sizeof(cp));
582
583 hci_send_cmd(hdev, HCI_OP_WRITE_EIR, sizeof(cp), &cp);
584 }
Johan Hedbergd5859e22011-01-25 01:19:58 +0200585 }
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;
Gustavo F. Padovan04124682012-03-08 01:25:00 -0300597 hci_send_cmd(hdev, HCI_OP_READ_LOCAL_EXT_FEATURES, sizeof(cp),
598 &cp);
Andre Guedes971e3a42011-06-30 19:20:52 -0300599 }
Andre Guedese6100a22011-06-30 19:20:54 -0300600
Johan Hedberg47990ea2012-02-22 11:58:37 +0200601 if (test_bit(HCI_LINK_SECURITY, &hdev->dev_flags)) {
602 u8 enable = 1;
Gustavo F. Padovan04124682012-03-08 01:25:00 -0300603 hci_send_cmd(hdev, HCI_OP_WRITE_AUTH_ENABLE, sizeof(enable),
604 &enable);
Johan Hedberg47990ea2012-02-22 11:58:37 +0200605 }
Johan Hedbergd5859e22011-01-25 01:19:58 +0200606}
607
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200608static void hci_cc_read_local_version(struct hci_dev *hdev, struct sk_buff *skb)
609{
610 struct hci_rp_read_local_version *rp = (void *) skb->data;
611
612 BT_DBG("%s status 0x%x", hdev->name, rp->status);
613
614 if (rp->status)
Andrei Emeltchenko28b8df72012-02-24 12:45:44 +0200615 goto done;
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200616
617 hdev->hci_ver = rp->hci_ver;
Marcel Holtmanne4e8e372008-07-14 20:13:47 +0200618 hdev->hci_rev = __le16_to_cpu(rp->hci_rev);
Johan Hedbergd5859e22011-01-25 01:19:58 +0200619 hdev->lmp_ver = rp->lmp_ver;
Marcel Holtmanne4e8e372008-07-14 20:13:47 +0200620 hdev->manufacturer = __le16_to_cpu(rp->manufacturer);
Johan Hedbergd5859e22011-01-25 01:19:58 +0200621 hdev->lmp_subver = __le16_to_cpu(rp->lmp_subver);
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200622
623 BT_DBG("%s manufacturer %d hci ver %d:%d", hdev->name,
Gustavo Padovan807deac2012-05-17 00:36:24 -0300624 hdev->manufacturer, hdev->hci_ver, hdev->hci_rev);
Johan Hedbergd5859e22011-01-25 01:19:58 +0200625
626 if (test_bit(HCI_INIT, &hdev->flags))
627 hci_setup(hdev);
Andrei Emeltchenko28b8df72012-02-24 12:45:44 +0200628
629done:
630 hci_req_complete(hdev, HCI_OP_READ_LOCAL_VERSION, rp->status);
Johan Hedbergd5859e22011-01-25 01:19:58 +0200631}
632
633static void hci_setup_link_policy(struct hci_dev *hdev)
634{
Andrei Emeltchenko035100c2012-03-12 15:59:32 +0200635 struct hci_cp_write_def_link_policy cp;
Johan Hedbergd5859e22011-01-25 01:19:58 +0200636 u16 link_policy = 0;
637
638 if (hdev->features[0] & LMP_RSWITCH)
639 link_policy |= HCI_LP_RSWITCH;
640 if (hdev->features[0] & LMP_HOLD)
641 link_policy |= HCI_LP_HOLD;
642 if (hdev->features[0] & LMP_SNIFF)
643 link_policy |= HCI_LP_SNIFF;
644 if (hdev->features[1] & LMP_PARK)
645 link_policy |= HCI_LP_PARK;
646
Andrei Emeltchenko035100c2012-03-12 15:59:32 +0200647 cp.policy = cpu_to_le16(link_policy);
648 hci_send_cmd(hdev, HCI_OP_WRITE_DEF_LINK_POLICY, sizeof(cp), &cp);
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200649}
650
651static void hci_cc_read_local_commands(struct hci_dev *hdev, struct sk_buff *skb)
652{
653 struct hci_rp_read_local_commands *rp = (void *) skb->data;
654
655 BT_DBG("%s status 0x%x", hdev->name, rp->status);
656
657 if (rp->status)
Johan Hedbergd5859e22011-01-25 01:19:58 +0200658 goto done;
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200659
660 memcpy(hdev->commands, rp->commands, sizeof(hdev->commands));
Johan Hedbergd5859e22011-01-25 01:19:58 +0200661
662 if (test_bit(HCI_INIT, &hdev->flags) && (hdev->commands[5] & 0x10))
663 hci_setup_link_policy(hdev);
664
665done:
666 hci_req_complete(hdev, HCI_OP_READ_LOCAL_COMMANDS, rp->status);
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200667}
668
669static void hci_cc_read_local_features(struct hci_dev *hdev, struct sk_buff *skb)
670{
671 struct hci_rp_read_local_features *rp = (void *) skb->data;
672
673 BT_DBG("%s status 0x%x", hdev->name, rp->status);
674
675 if (rp->status)
676 return;
677
678 memcpy(hdev->features, rp->features, 8);
679
680 /* Adjust default settings according to features
681 * supported by device. */
682
683 if (hdev->features[0] & LMP_3SLOT)
684 hdev->pkt_type |= (HCI_DM3 | HCI_DH3);
685
686 if (hdev->features[0] & LMP_5SLOT)
687 hdev->pkt_type |= (HCI_DM5 | HCI_DH5);
688
689 if (hdev->features[1] & LMP_HV2) {
690 hdev->pkt_type |= (HCI_HV2);
691 hdev->esco_type |= (ESCO_HV2);
692 }
693
694 if (hdev->features[1] & LMP_HV3) {
695 hdev->pkt_type |= (HCI_HV3);
696 hdev->esco_type |= (ESCO_HV3);
697 }
698
699 if (hdev->features[3] & LMP_ESCO)
700 hdev->esco_type |= (ESCO_EV3);
701
702 if (hdev->features[4] & LMP_EV4)
703 hdev->esco_type |= (ESCO_EV4);
704
705 if (hdev->features[4] & LMP_EV5)
706 hdev->esco_type |= (ESCO_EV5);
707
Marcel Holtmannefc76882009-02-06 09:13:37 +0100708 if (hdev->features[5] & LMP_EDR_ESCO_2M)
709 hdev->esco_type |= (ESCO_2EV3);
710
711 if (hdev->features[5] & LMP_EDR_ESCO_3M)
712 hdev->esco_type |= (ESCO_3EV3);
713
714 if (hdev->features[5] & LMP_EDR_3S_ESCO)
715 hdev->esco_type |= (ESCO_2EV5 | ESCO_3EV5);
716
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200717 BT_DBG("%s features 0x%.2x%.2x%.2x%.2x%.2x%.2x%.2x%.2x", hdev->name,
Gustavo Padovan807deac2012-05-17 00:36:24 -0300718 hdev->features[0], hdev->features[1],
719 hdev->features[2], hdev->features[3],
720 hdev->features[4], hdev->features[5],
721 hdev->features[6], hdev->features[7]);
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200722}
723
Johan Hedberg8f984df2012-02-28 01:07:22 +0200724static void hci_set_le_support(struct hci_dev *hdev)
725{
726 struct hci_cp_write_le_host_supported cp;
727
728 memset(&cp, 0, sizeof(cp));
729
Marcel Holtmann9d428202012-05-03 07:12:31 +0200730 if (test_bit(HCI_LE_ENABLED, &hdev->dev_flags)) {
Johan Hedberg8f984df2012-02-28 01:07:22 +0200731 cp.le = 1;
732 cp.simul = !!(hdev->features[6] & LMP_SIMUL_LE_BR);
733 }
734
735 if (cp.le != !!(hdev->host_features[0] & LMP_HOST_LE))
Gustavo F. Padovan04124682012-03-08 01:25:00 -0300736 hci_send_cmd(hdev, HCI_OP_WRITE_LE_HOST_SUPPORTED, sizeof(cp),
737 &cp);
Johan Hedberg8f984df2012-02-28 01:07:22 +0200738}
739
Andre Guedes971e3a42011-06-30 19:20:52 -0300740static void hci_cc_read_local_ext_features(struct hci_dev *hdev,
Gustavo Padovan807deac2012-05-17 00:36:24 -0300741 struct sk_buff *skb)
Andre Guedes971e3a42011-06-30 19:20:52 -0300742{
743 struct hci_rp_read_local_ext_features *rp = (void *) skb->data;
744
745 BT_DBG("%s status 0x%x", hdev->name, rp->status);
746
747 if (rp->status)
Johan Hedberg8f984df2012-02-28 01:07:22 +0200748 goto done;
Andre Guedes971e3a42011-06-30 19:20:52 -0300749
Andre Guedesb5b32b62011-12-30 10:34:04 -0300750 switch (rp->page) {
751 case 0:
752 memcpy(hdev->features, rp->features, 8);
753 break;
754 case 1:
755 memcpy(hdev->host_features, rp->features, 8);
756 break;
757 }
Andre Guedes971e3a42011-06-30 19:20:52 -0300758
Johan Hedberg8f984df2012-02-28 01:07:22 +0200759 if (test_bit(HCI_INIT, &hdev->flags) && hdev->features[4] & LMP_LE)
760 hci_set_le_support(hdev);
761
762done:
Andre Guedes971e3a42011-06-30 19:20:52 -0300763 hci_req_complete(hdev, HCI_OP_READ_LOCAL_EXT_FEATURES, rp->status);
764}
765
Andrei Emeltchenko1e89cff2011-11-24 14:52:02 +0200766static void hci_cc_read_flow_control_mode(struct hci_dev *hdev,
Gustavo Padovan807deac2012-05-17 00:36:24 -0300767 struct sk_buff *skb)
Andrei Emeltchenko1e89cff2011-11-24 14:52:02 +0200768{
769 struct hci_rp_read_flow_control_mode *rp = (void *) skb->data;
770
771 BT_DBG("%s status 0x%x", hdev->name, rp->status);
772
773 if (rp->status)
774 return;
775
776 hdev->flow_ctl_mode = rp->mode;
777
778 hci_req_complete(hdev, HCI_OP_READ_FLOW_CONTROL_MODE, rp->status);
779}
780
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200781static void hci_cc_read_buffer_size(struct hci_dev *hdev, struct sk_buff *skb)
782{
783 struct hci_rp_read_buffer_size *rp = (void *) skb->data;
784
785 BT_DBG("%s status 0x%x", hdev->name, rp->status);
786
787 if (rp->status)
788 return;
789
790 hdev->acl_mtu = __le16_to_cpu(rp->acl_mtu);
791 hdev->sco_mtu = rp->sco_mtu;
792 hdev->acl_pkts = __le16_to_cpu(rp->acl_max_pkt);
793 hdev->sco_pkts = __le16_to_cpu(rp->sco_max_pkt);
794
795 if (test_bit(HCI_QUIRK_FIXUP_BUFFER_SIZE, &hdev->quirks)) {
796 hdev->sco_mtu = 64;
797 hdev->sco_pkts = 8;
798 }
799
800 hdev->acl_cnt = hdev->acl_pkts;
801 hdev->sco_cnt = hdev->sco_pkts;
802
Gustavo Padovan807deac2012-05-17 00:36:24 -0300803 BT_DBG("%s acl mtu %d:%d sco mtu %d:%d", hdev->name, hdev->acl_mtu,
804 hdev->acl_pkts, hdev->sco_mtu, hdev->sco_pkts);
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200805}
806
807static void hci_cc_read_bd_addr(struct hci_dev *hdev, struct sk_buff *skb)
808{
809 struct hci_rp_read_bd_addr *rp = (void *) skb->data;
810
811 BT_DBG("%s status 0x%x", hdev->name, rp->status);
812
813 if (!rp->status)
814 bacpy(&hdev->bdaddr, &rp->bdaddr);
815
Johan Hedberg23bb5762010-12-21 23:01:27 +0200816 hci_req_complete(hdev, HCI_OP_READ_BD_ADDR, rp->status);
817}
818
Andrei Emeltchenko350ee4c2011-12-07 15:56:51 +0200819static void hci_cc_read_data_block_size(struct hci_dev *hdev,
Gustavo Padovan807deac2012-05-17 00:36:24 -0300820 struct sk_buff *skb)
Andrei Emeltchenko350ee4c2011-12-07 15:56:51 +0200821{
822 struct hci_rp_read_data_block_size *rp = (void *) skb->data;
823
824 BT_DBG("%s status 0x%x", hdev->name, rp->status);
825
826 if (rp->status)
827 return;
828
829 hdev->block_mtu = __le16_to_cpu(rp->max_acl_len);
830 hdev->block_len = __le16_to_cpu(rp->block_len);
831 hdev->num_blocks = __le16_to_cpu(rp->num_blocks);
832
833 hdev->block_cnt = hdev->num_blocks;
834
835 BT_DBG("%s blk mtu %d cnt %d len %d", hdev->name, hdev->block_mtu,
Gustavo Padovan807deac2012-05-17 00:36:24 -0300836 hdev->block_cnt, hdev->block_len);
Andrei Emeltchenko350ee4c2011-12-07 15:56:51 +0200837
838 hci_req_complete(hdev, HCI_OP_READ_DATA_BLOCK_SIZE, rp->status);
839}
840
Johan Hedberg23bb5762010-12-21 23:01:27 +0200841static void hci_cc_write_ca_timeout(struct hci_dev *hdev, struct sk_buff *skb)
842{
843 __u8 status = *((__u8 *) skb->data);
844
845 BT_DBG("%s status 0x%x", hdev->name, status);
846
847 hci_req_complete(hdev, HCI_OP_WRITE_CA_TIMEOUT, status);
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200848}
849
Andrei Emeltchenko928abaa2011-10-12 10:53:57 +0300850static void hci_cc_read_local_amp_info(struct hci_dev *hdev,
Gustavo Padovan807deac2012-05-17 00:36:24 -0300851 struct sk_buff *skb)
Andrei Emeltchenko928abaa2011-10-12 10:53:57 +0300852{
853 struct hci_rp_read_local_amp_info *rp = (void *) skb->data;
854
855 BT_DBG("%s status 0x%x", hdev->name, rp->status);
856
857 if (rp->status)
858 return;
859
860 hdev->amp_status = rp->amp_status;
861 hdev->amp_total_bw = __le32_to_cpu(rp->total_bw);
862 hdev->amp_max_bw = __le32_to_cpu(rp->max_bw);
863 hdev->amp_min_latency = __le32_to_cpu(rp->min_latency);
864 hdev->amp_max_pdu = __le32_to_cpu(rp->max_pdu);
865 hdev->amp_type = rp->amp_type;
866 hdev->amp_pal_cap = __le16_to_cpu(rp->pal_cap);
867 hdev->amp_assoc_size = __le16_to_cpu(rp->max_assoc_size);
868 hdev->amp_be_flush_to = __le32_to_cpu(rp->be_flush_to);
869 hdev->amp_max_flush_to = __le32_to_cpu(rp->max_flush_to);
870
871 hci_req_complete(hdev, HCI_OP_READ_LOCAL_AMP_INFO, rp->status);
872}
873
Johan Hedbergb0916ea2011-01-10 13:44:55 +0200874static void hci_cc_delete_stored_link_key(struct hci_dev *hdev,
Gustavo Padovan807deac2012-05-17 00:36:24 -0300875 struct sk_buff *skb)
Johan Hedbergb0916ea2011-01-10 13:44:55 +0200876{
877 __u8 status = *((__u8 *) skb->data);
878
879 BT_DBG("%s status 0x%x", hdev->name, status);
880
881 hci_req_complete(hdev, HCI_OP_DELETE_STORED_LINK_KEY, status);
882}
883
Johan Hedbergd5859e22011-01-25 01:19:58 +0200884static void hci_cc_set_event_mask(struct hci_dev *hdev, struct sk_buff *skb)
885{
886 __u8 status = *((__u8 *) skb->data);
887
888 BT_DBG("%s status 0x%x", hdev->name, status);
889
890 hci_req_complete(hdev, HCI_OP_SET_EVENT_MASK, status);
891}
892
893static void hci_cc_write_inquiry_mode(struct hci_dev *hdev,
Gustavo Padovan807deac2012-05-17 00:36:24 -0300894 struct sk_buff *skb)
Johan Hedbergd5859e22011-01-25 01:19:58 +0200895{
896 __u8 status = *((__u8 *) skb->data);
897
898 BT_DBG("%s status 0x%x", hdev->name, status);
899
900 hci_req_complete(hdev, HCI_OP_WRITE_INQUIRY_MODE, status);
901}
902
903static void hci_cc_read_inq_rsp_tx_power(struct hci_dev *hdev,
Gustavo Padovan807deac2012-05-17 00:36:24 -0300904 struct sk_buff *skb)
Johan Hedbergd5859e22011-01-25 01:19:58 +0200905{
Marcel Holtmann91c4e9b2012-03-11 19:27:21 -0700906 struct hci_rp_read_inq_rsp_tx_power *rp = (void *) skb->data;
Johan Hedbergd5859e22011-01-25 01:19:58 +0200907
Marcel Holtmann91c4e9b2012-03-11 19:27:21 -0700908 BT_DBG("%s status 0x%x", hdev->name, rp->status);
Johan Hedbergd5859e22011-01-25 01:19:58 +0200909
Marcel Holtmann91c4e9b2012-03-11 19:27:21 -0700910 if (!rp->status)
911 hdev->inq_tx_power = rp->tx_power;
912
913 hci_req_complete(hdev, HCI_OP_READ_INQ_RSP_TX_POWER, rp->status);
Johan Hedbergd5859e22011-01-25 01:19:58 +0200914}
915
916static void hci_cc_set_event_flt(struct hci_dev *hdev, struct sk_buff *skb)
917{
918 __u8 status = *((__u8 *) skb->data);
919
920 BT_DBG("%s status 0x%x", hdev->name, status);
921
922 hci_req_complete(hdev, HCI_OP_SET_EVENT_FLT, status);
923}
924
Johan Hedberg980e1a52011-01-22 06:10:07 +0200925static void hci_cc_pin_code_reply(struct hci_dev *hdev, struct sk_buff *skb)
926{
927 struct hci_rp_pin_code_reply *rp = (void *) skb->data;
928 struct hci_cp_pin_code_reply *cp;
929 struct hci_conn *conn;
930
931 BT_DBG("%s status 0x%x", hdev->name, rp->status);
932
Johan Hedberg56e5cb82011-11-08 20:40:16 +0200933 hci_dev_lock(hdev);
934
Johan Hedberga8b2d5c2012-01-08 23:11:15 +0200935 if (test_bit(HCI_MGMT, &hdev->dev_flags))
Johan Hedberg744cf192011-11-08 20:40:14 +0200936 mgmt_pin_code_reply_complete(hdev, &rp->bdaddr, rp->status);
Johan Hedberg980e1a52011-01-22 06:10:07 +0200937
938 if (rp->status != 0)
Johan Hedberg56e5cb82011-11-08 20:40:16 +0200939 goto unlock;
Johan Hedberg980e1a52011-01-22 06:10:07 +0200940
941 cp = hci_sent_cmd_data(hdev, HCI_OP_PIN_CODE_REPLY);
942 if (!cp)
Johan Hedberg56e5cb82011-11-08 20:40:16 +0200943 goto unlock;
Johan Hedberg980e1a52011-01-22 06:10:07 +0200944
945 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &cp->bdaddr);
946 if (conn)
947 conn->pin_length = cp->pin_len;
Johan Hedberg56e5cb82011-11-08 20:40:16 +0200948
949unlock:
950 hci_dev_unlock(hdev);
Johan Hedberg980e1a52011-01-22 06:10:07 +0200951}
952
953static void hci_cc_pin_code_neg_reply(struct hci_dev *hdev, struct sk_buff *skb)
954{
955 struct hci_rp_pin_code_neg_reply *rp = (void *) skb->data;
956
957 BT_DBG("%s status 0x%x", hdev->name, rp->status);
958
Johan Hedberg56e5cb82011-11-08 20:40:16 +0200959 hci_dev_lock(hdev);
960
Johan Hedberga8b2d5c2012-01-08 23:11:15 +0200961 if (test_bit(HCI_MGMT, &hdev->dev_flags))
Johan Hedberg744cf192011-11-08 20:40:14 +0200962 mgmt_pin_code_neg_reply_complete(hdev, &rp->bdaddr,
Gustavo Padovan807deac2012-05-17 00:36:24 -0300963 rp->status);
Johan Hedberg56e5cb82011-11-08 20:40:16 +0200964
965 hci_dev_unlock(hdev);
Johan Hedberg980e1a52011-01-22 06:10:07 +0200966}
Johan Hedberg56e5cb82011-11-08 20:40:16 +0200967
Ville Tervo6ed58ec2011-02-10 22:38:48 -0300968static void hci_cc_le_read_buffer_size(struct hci_dev *hdev,
969 struct sk_buff *skb)
970{
971 struct hci_rp_le_read_buffer_size *rp = (void *) skb->data;
972
973 BT_DBG("%s status 0x%x", hdev->name, rp->status);
974
975 if (rp->status)
976 return;
977
978 hdev->le_mtu = __le16_to_cpu(rp->le_mtu);
979 hdev->le_pkts = rp->le_max_pkt;
980
981 hdev->le_cnt = hdev->le_pkts;
982
983 BT_DBG("%s le mtu %d:%d", hdev->name, hdev->le_mtu, hdev->le_pkts);
984
985 hci_req_complete(hdev, HCI_OP_LE_READ_BUFFER_SIZE, rp->status);
986}
Johan Hedberg980e1a52011-01-22 06:10:07 +0200987
Johan Hedberga5c29682011-02-19 12:05:57 -0300988static void hci_cc_user_confirm_reply(struct hci_dev *hdev, struct sk_buff *skb)
989{
990 struct hci_rp_user_confirm_reply *rp = (void *) skb->data;
991
992 BT_DBG("%s status 0x%x", hdev->name, rp->status);
993
Johan Hedberg56e5cb82011-11-08 20:40:16 +0200994 hci_dev_lock(hdev);
995
Johan Hedberga8b2d5c2012-01-08 23:11:15 +0200996 if (test_bit(HCI_MGMT, &hdev->dev_flags))
Gustavo F. Padovan04124682012-03-08 01:25:00 -0300997 mgmt_user_confirm_reply_complete(hdev, &rp->bdaddr, ACL_LINK, 0,
998 rp->status);
Johan Hedberg56e5cb82011-11-08 20:40:16 +0200999
1000 hci_dev_unlock(hdev);
Johan Hedberga5c29682011-02-19 12:05:57 -03001001}
1002
1003static void hci_cc_user_confirm_neg_reply(struct hci_dev *hdev,
Gustavo Padovan807deac2012-05-17 00:36:24 -03001004 struct sk_buff *skb)
Johan Hedberga5c29682011-02-19 12:05:57 -03001005{
1006 struct hci_rp_user_confirm_reply *rp = (void *) skb->data;
1007
1008 BT_DBG("%s status 0x%x", hdev->name, rp->status);
1009
Johan Hedberg56e5cb82011-11-08 20:40:16 +02001010 hci_dev_lock(hdev);
1011
Johan Hedberga8b2d5c2012-01-08 23:11:15 +02001012 if (test_bit(HCI_MGMT, &hdev->dev_flags))
Johan Hedberg744cf192011-11-08 20:40:14 +02001013 mgmt_user_confirm_neg_reply_complete(hdev, &rp->bdaddr,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001014 ACL_LINK, 0, rp->status);
Johan Hedberg56e5cb82011-11-08 20:40:16 +02001015
1016 hci_dev_unlock(hdev);
Johan Hedberga5c29682011-02-19 12:05:57 -03001017}
1018
Brian Gix1143d452011-11-23 08:28:34 -08001019static void hci_cc_user_passkey_reply(struct hci_dev *hdev, struct sk_buff *skb)
1020{
1021 struct hci_rp_user_confirm_reply *rp = (void *) skb->data;
1022
1023 BT_DBG("%s status 0x%x", hdev->name, rp->status);
1024
1025 hci_dev_lock(hdev);
1026
Johan Hedberga8b2d5c2012-01-08 23:11:15 +02001027 if (test_bit(HCI_MGMT, &hdev->dev_flags))
Johan Hedberg272d90d2012-02-09 15:26:12 +02001028 mgmt_user_passkey_reply_complete(hdev, &rp->bdaddr, ACL_LINK,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001029 0, rp->status);
Brian Gix1143d452011-11-23 08:28:34 -08001030
1031 hci_dev_unlock(hdev);
1032}
1033
1034static void hci_cc_user_passkey_neg_reply(struct hci_dev *hdev,
Gustavo Padovan807deac2012-05-17 00:36:24 -03001035 struct sk_buff *skb)
Brian Gix1143d452011-11-23 08:28:34 -08001036{
1037 struct hci_rp_user_confirm_reply *rp = (void *) skb->data;
1038
1039 BT_DBG("%s status 0x%x", hdev->name, rp->status);
1040
1041 hci_dev_lock(hdev);
1042
Johan Hedberga8b2d5c2012-01-08 23:11:15 +02001043 if (test_bit(HCI_MGMT, &hdev->dev_flags))
Brian Gix1143d452011-11-23 08:28:34 -08001044 mgmt_user_passkey_neg_reply_complete(hdev, &rp->bdaddr,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001045 ACL_LINK, 0, rp->status);
Brian Gix1143d452011-11-23 08:28:34 -08001046
1047 hci_dev_unlock(hdev);
1048}
1049
Szymon Jancc35938b2011-03-22 13:12:21 +01001050static void hci_cc_read_local_oob_data_reply(struct hci_dev *hdev,
Gustavo Padovan807deac2012-05-17 00:36:24 -03001051 struct sk_buff *skb)
Szymon Jancc35938b2011-03-22 13:12:21 +01001052{
1053 struct hci_rp_read_local_oob_data *rp = (void *) skb->data;
1054
1055 BT_DBG("%s status 0x%x", hdev->name, rp->status);
1056
Johan Hedberg56e5cb82011-11-08 20:40:16 +02001057 hci_dev_lock(hdev);
Johan Hedberg744cf192011-11-08 20:40:14 +02001058 mgmt_read_local_oob_data_reply_complete(hdev, rp->hash,
Szymon Jancc35938b2011-03-22 13:12:21 +01001059 rp->randomizer, rp->status);
Johan Hedberg56e5cb82011-11-08 20:40:16 +02001060 hci_dev_unlock(hdev);
Szymon Jancc35938b2011-03-22 13:12:21 +01001061}
1062
Andre Guedes07f7fa52011-12-02 21:13:31 +09001063static void hci_cc_le_set_scan_param(struct hci_dev *hdev, struct sk_buff *skb)
1064{
1065 __u8 status = *((__u8 *) skb->data);
1066
1067 BT_DBG("%s status 0x%x", hdev->name, status);
Andre Guedes7ba8b4b2012-02-03 17:47:59 -03001068
1069 hci_req_complete(hdev, HCI_OP_LE_SET_SCAN_PARAM, status);
Andre Guedes3fd24152012-02-03 17:48:01 -03001070
1071 if (status) {
1072 hci_dev_lock(hdev);
1073 mgmt_start_discovery_failed(hdev, status);
1074 hci_dev_unlock(hdev);
1075 return;
1076 }
Andre Guedes07f7fa52011-12-02 21:13:31 +09001077}
1078
Andre Guedeseb9d91f2011-05-26 16:23:52 -03001079static void hci_cc_le_set_scan_enable(struct hci_dev *hdev,
Gustavo Padovan807deac2012-05-17 00:36:24 -03001080 struct sk_buff *skb)
Andre Guedeseb9d91f2011-05-26 16:23:52 -03001081{
1082 struct hci_cp_le_set_scan_enable *cp;
1083 __u8 status = *((__u8 *) skb->data);
1084
1085 BT_DBG("%s status 0x%x", hdev->name, status);
1086
Andre Guedeseb9d91f2011-05-26 16:23:52 -03001087 cp = hci_sent_cmd_data(hdev, HCI_OP_LE_SET_SCAN_ENABLE);
1088 if (!cp)
1089 return;
1090
Andrei Emeltchenko68a8aea2011-12-19 16:14:18 +02001091 switch (cp->enable) {
1092 case LE_SCANNING_ENABLED:
Andre Guedes7ba8b4b2012-02-03 17:47:59 -03001093 hci_req_complete(hdev, HCI_OP_LE_SET_SCAN_ENABLE, status);
1094
Andre Guedes3fd24152012-02-03 17:48:01 -03001095 if (status) {
1096 hci_dev_lock(hdev);
1097 mgmt_start_discovery_failed(hdev, status);
1098 hci_dev_unlock(hdev);
Andre Guedes7ba8b4b2012-02-03 17:47:59 -03001099 return;
Andre Guedes3fd24152012-02-03 17:48:01 -03001100 }
Andre Guedes7ba8b4b2012-02-03 17:47:59 -03001101
Andre Guedesd23264a2011-11-25 20:53:38 -03001102 set_bit(HCI_LE_SCAN, &hdev->dev_flags);
1103
Andre Guedesa8f13c82011-09-09 18:56:24 -03001104 hci_dev_lock(hdev);
Andre Guedes343f9352012-02-17 20:39:37 -03001105 hci_discovery_set_state(hdev, DISCOVERY_FINDING);
Andre Guedesa8f13c82011-09-09 18:56:24 -03001106 hci_dev_unlock(hdev);
Andrei Emeltchenko68a8aea2011-12-19 16:14:18 +02001107 break;
1108
1109 case LE_SCANNING_DISABLED:
Andre Guedesc9ecc482012-03-15 16:52:08 -03001110 if (status) {
1111 hci_dev_lock(hdev);
1112 mgmt_stop_discovery_failed(hdev, status);
1113 hci_dev_unlock(hdev);
Andre Guedes7ba8b4b2012-02-03 17:47:59 -03001114 return;
Andre Guedesc9ecc482012-03-15 16:52:08 -03001115 }
Andre Guedes7ba8b4b2012-02-03 17:47:59 -03001116
Andre Guedesd23264a2011-11-25 20:53:38 -03001117 clear_bit(HCI_LE_SCAN, &hdev->dev_flags);
1118
Andre Guedesbc3dd332012-03-06 19:37:06 -03001119 if (hdev->discovery.type == DISCOV_TYPE_INTERLEAVED &&
1120 hdev->discovery.state == DISCOVERY_FINDING) {
Andre Guedes5e0452c2012-02-17 20:39:38 -03001121 mgmt_interleaved_discovery(hdev);
1122 } else {
1123 hci_dev_lock(hdev);
1124 hci_discovery_set_state(hdev, DISCOVERY_STOPPED);
1125 hci_dev_unlock(hdev);
1126 }
1127
Andrei Emeltchenko68a8aea2011-12-19 16:14:18 +02001128 break;
1129
1130 default:
1131 BT_ERR("Used reserved LE_Scan_Enable param %d", cp->enable);
1132 break;
Andre Guedes35815082011-05-26 16:23:53 -03001133 }
Andre Guedeseb9d91f2011-05-26 16:23:52 -03001134}
1135
Vinicius Costa Gomesa7a595f2011-06-09 18:50:47 -03001136static void hci_cc_le_ltk_reply(struct hci_dev *hdev, struct sk_buff *skb)
1137{
1138 struct hci_rp_le_ltk_reply *rp = (void *) skb->data;
1139
1140 BT_DBG("%s status 0x%x", hdev->name, rp->status);
1141
1142 if (rp->status)
1143 return;
1144
1145 hci_req_complete(hdev, HCI_OP_LE_LTK_REPLY, rp->status);
1146}
1147
1148static void hci_cc_le_ltk_neg_reply(struct hci_dev *hdev, struct sk_buff *skb)
1149{
1150 struct hci_rp_le_ltk_neg_reply *rp = (void *) skb->data;
1151
1152 BT_DBG("%s status 0x%x", hdev->name, rp->status);
1153
1154 if (rp->status)
1155 return;
1156
1157 hci_req_complete(hdev, HCI_OP_LE_LTK_NEG_REPLY, rp->status);
1158}
1159
Andre Guedesf9b49302011-06-30 19:20:53 -03001160static inline void hci_cc_write_le_host_supported(struct hci_dev *hdev,
Gustavo Padovan807deac2012-05-17 00:36:24 -03001161 struct sk_buff *skb)
Andre Guedesf9b49302011-06-30 19:20:53 -03001162{
Johan Hedberg06199cf2012-02-22 16:37:11 +02001163 struct hci_cp_write_le_host_supported *sent;
Andre Guedesf9b49302011-06-30 19:20:53 -03001164 __u8 status = *((__u8 *) skb->data);
1165
1166 BT_DBG("%s status 0x%x", hdev->name, status);
1167
Johan Hedberg06199cf2012-02-22 16:37:11 +02001168 sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_LE_HOST_SUPPORTED);
Johan Hedberg8f984df2012-02-28 01:07:22 +02001169 if (!sent)
Andre Guedesf9b49302011-06-30 19:20:53 -03001170 return;
1171
Johan Hedberg8f984df2012-02-28 01:07:22 +02001172 if (!status) {
1173 if (sent->le)
1174 hdev->host_features[0] |= LMP_HOST_LE;
1175 else
1176 hdev->host_features[0] &= ~LMP_HOST_LE;
1177 }
1178
1179 if (test_bit(HCI_MGMT, &hdev->dev_flags) &&
Gustavo Padovan807deac2012-05-17 00:36:24 -03001180 !test_bit(HCI_INIT, &hdev->flags))
Johan Hedberg8f984df2012-02-28 01:07:22 +02001181 mgmt_le_enable_complete(hdev, sent->le, status);
1182
1183 hci_req_complete(hdev, HCI_OP_WRITE_LE_HOST_SUPPORTED, status);
Andre Guedesf9b49302011-06-30 19:20:53 -03001184}
1185
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001186static inline void hci_cs_inquiry(struct hci_dev *hdev, __u8 status)
1187{
1188 BT_DBG("%s status 0x%x", hdev->name, status);
1189
1190 if (status) {
Johan Hedberg23bb5762010-12-21 23:01:27 +02001191 hci_req_complete(hdev, HCI_OP_INQUIRY, status);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001192 hci_conn_check_pending(hdev);
Johan Hedberg56e5cb82011-11-08 20:40:16 +02001193 hci_dev_lock(hdev);
Johan Hedberga8b2d5c2012-01-08 23:11:15 +02001194 if (test_bit(HCI_MGMT, &hdev->dev_flags))
Andre Guedes7a135102011-11-09 17:14:25 -03001195 mgmt_start_discovery_failed(hdev, status);
Johan Hedberg56e5cb82011-11-08 20:40:16 +02001196 hci_dev_unlock(hdev);
Johan Hedberg314b2382011-04-27 10:29:57 -04001197 return;
1198 }
1199
Andre Guedes89352e72011-11-04 14:16:53 -03001200 set_bit(HCI_INQUIRY, &hdev->flags);
1201
Johan Hedberg56e5cb82011-11-08 20:40:16 +02001202 hci_dev_lock(hdev);
Andre Guedes343f9352012-02-17 20:39:37 -03001203 hci_discovery_set_state(hdev, DISCOVERY_FINDING);
Johan Hedberg56e5cb82011-11-08 20:40:16 +02001204 hci_dev_unlock(hdev);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001205}
1206
Linus Torvalds1da177e2005-04-16 15:20:36 -07001207static inline void hci_cs_create_conn(struct hci_dev *hdev, __u8 status)
1208{
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001209 struct hci_cp_create_conn *cp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001210 struct hci_conn *conn;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001211
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001212 BT_DBG("%s status 0x%x", hdev->name, status);
1213
1214 cp = hci_sent_cmd_data(hdev, HCI_OP_CREATE_CONN);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001215 if (!cp)
1216 return;
1217
1218 hci_dev_lock(hdev);
1219
1220 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &cp->bdaddr);
1221
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001222 BT_DBG("%s bdaddr %s conn %p", hdev->name, batostr(&cp->bdaddr), conn);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001223
1224 if (status) {
1225 if (conn && conn->state == BT_CONNECT) {
Marcel Holtmann4c67bc72006-10-15 17:30:56 +02001226 if (status != 0x0c || conn->attempt > 2) {
1227 conn->state = BT_CLOSED;
1228 hci_proto_connect_cfm(conn, status);
1229 hci_conn_del(conn);
1230 } else
1231 conn->state = BT_CONNECT2;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001232 }
1233 } else {
1234 if (!conn) {
1235 conn = hci_conn_add(hdev, ACL_LINK, &cp->bdaddr);
1236 if (conn) {
Johan Hedberga0c808b2012-01-16 09:49:58 +02001237 conn->out = true;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001238 conn->link_mode |= HCI_LM_MASTER;
1239 } else
Gustavo F. Padovan893ef972010-07-18 15:13:37 -03001240 BT_ERR("No memory for new connection");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001241 }
1242 }
1243
1244 hci_dev_unlock(hdev);
1245}
1246
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001247static void hci_cs_add_sco(struct hci_dev *hdev, __u8 status)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001248{
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001249 struct hci_cp_add_sco *cp;
1250 struct hci_conn *acl, *sco;
1251 __u16 handle;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001252
Marcel Holtmannb6a0dc82007-10-20 14:55:10 +02001253 BT_DBG("%s status 0x%x", hdev->name, status);
1254
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001255 if (!status)
1256 return;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001257
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001258 cp = hci_sent_cmd_data(hdev, HCI_OP_ADD_SCO);
1259 if (!cp)
1260 return;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001261
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001262 handle = __le16_to_cpu(cp->handle);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001263
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001264 BT_DBG("%s handle %d", hdev->name, handle);
Marcel Holtmann6bd57412006-11-18 22:14:22 +01001265
1266 hci_dev_lock(hdev);
1267
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001268 acl = hci_conn_hash_lookup_handle(hdev, handle);
Andrei Emeltchenko5a08ecc2011-01-11 17:20:20 +02001269 if (acl) {
1270 sco = acl->link;
1271 if (sco) {
1272 sco->state = BT_CLOSED;
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001273
Andrei Emeltchenko5a08ecc2011-01-11 17:20:20 +02001274 hci_proto_connect_cfm(sco, status);
1275 hci_conn_del(sco);
1276 }
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001277 }
Marcel Holtmann6bd57412006-11-18 22:14:22 +01001278
1279 hci_dev_unlock(hdev);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001280}
1281
Marcel Holtmannf8558552008-07-14 20:13:49 +02001282static void hci_cs_auth_requested(struct hci_dev *hdev, __u8 status)
1283{
1284 struct hci_cp_auth_requested *cp;
1285 struct hci_conn *conn;
1286
1287 BT_DBG("%s status 0x%x", hdev->name, status);
1288
1289 if (!status)
1290 return;
1291
1292 cp = hci_sent_cmd_data(hdev, HCI_OP_AUTH_REQUESTED);
1293 if (!cp)
1294 return;
1295
1296 hci_dev_lock(hdev);
1297
1298 conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(cp->handle));
1299 if (conn) {
1300 if (conn->state == BT_CONFIG) {
1301 hci_proto_connect_cfm(conn, status);
1302 hci_conn_put(conn);
1303 }
1304 }
1305
1306 hci_dev_unlock(hdev);
1307}
1308
1309static void hci_cs_set_conn_encrypt(struct hci_dev *hdev, __u8 status)
1310{
1311 struct hci_cp_set_conn_encrypt *cp;
1312 struct hci_conn *conn;
1313
1314 BT_DBG("%s status 0x%x", hdev->name, status);
1315
1316 if (!status)
1317 return;
1318
1319 cp = hci_sent_cmd_data(hdev, HCI_OP_SET_CONN_ENCRYPT);
1320 if (!cp)
1321 return;
1322
1323 hci_dev_lock(hdev);
1324
1325 conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(cp->handle));
1326 if (conn) {
1327 if (conn->state == BT_CONFIG) {
1328 hci_proto_connect_cfm(conn, status);
1329 hci_conn_put(conn);
1330 }
1331 }
1332
1333 hci_dev_unlock(hdev);
1334}
1335
Johan Hedberg127178d2010-11-18 22:22:29 +02001336static int hci_outgoing_auth_needed(struct hci_dev *hdev,
Gustavo Padovan807deac2012-05-17 00:36:24 -03001337 struct hci_conn *conn)
Johan Hedberg392599b2010-11-18 22:22:28 +02001338{
Johan Hedberg392599b2010-11-18 22:22:28 +02001339 if (conn->state != BT_CONFIG || !conn->out)
1340 return 0;
1341
Johan Hedberg765c2a92011-01-19 12:06:52 +05301342 if (conn->pending_sec_level == BT_SECURITY_SDP)
Johan Hedberg392599b2010-11-18 22:22:28 +02001343 return 0;
1344
1345 /* Only request authentication for SSP connections or non-SSP
Vinicius Costa Gomese9bf2bf2011-09-02 14:51:20 -03001346 * devices with sec_level HIGH or if MITM protection is requested */
Gustavo Padovan807deac2012-05-17 00:36:24 -03001347 if (!hci_conn_ssp_enabled(conn) && !(conn->auth_type & 0x01) &&
1348 conn->pending_sec_level != BT_SECURITY_HIGH)
Johan Hedberg392599b2010-11-18 22:22:28 +02001349 return 0;
1350
Johan Hedberg392599b2010-11-18 22:22:28 +02001351 return 1;
1352}
1353
Gustavo F. Padovan00abfe42012-03-01 00:37:10 -03001354static inline int hci_resolve_name(struct hci_dev *hdev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001355 struct inquiry_entry *e)
Johan Hedberg30dc78e2012-01-04 15:44:20 +02001356{
1357 struct hci_cp_remote_name_req cp;
1358
1359 memset(&cp, 0, sizeof(cp));
1360
1361 bacpy(&cp.bdaddr, &e->data.bdaddr);
1362 cp.pscan_rep_mode = e->data.pscan_rep_mode;
1363 cp.pscan_mode = e->data.pscan_mode;
1364 cp.clock_offset = e->data.clock_offset;
1365
1366 return hci_send_cmd(hdev, HCI_OP_REMOTE_NAME_REQ, sizeof(cp), &cp);
1367}
1368
Johan Hedbergb644ba32012-01-17 21:48:47 +02001369static bool hci_resolve_next_name(struct hci_dev *hdev)
Johan Hedberg30dc78e2012-01-04 15:44:20 +02001370{
1371 struct discovery_state *discov = &hdev->discovery;
1372 struct inquiry_entry *e;
1373
Johan Hedbergb644ba32012-01-17 21:48:47 +02001374 if (list_empty(&discov->resolve))
1375 return false;
1376
1377 e = hci_inquiry_cache_lookup_resolve(hdev, BDADDR_ANY, NAME_NEEDED);
1378 if (hci_resolve_name(hdev, e) == 0) {
1379 e->name_state = NAME_PENDING;
1380 return true;
1381 }
1382
1383 return false;
1384}
1385
1386static void hci_check_pending_name(struct hci_dev *hdev, struct hci_conn *conn,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001387 bdaddr_t *bdaddr, u8 *name, u8 name_len)
Johan Hedbergb644ba32012-01-17 21:48:47 +02001388{
1389 struct discovery_state *discov = &hdev->discovery;
1390 struct inquiry_entry *e;
1391
1392 if (conn && !test_and_set_bit(HCI_CONN_MGMT_CONNECTED, &conn->flags))
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001393 mgmt_device_connected(hdev, bdaddr, ACL_LINK, 0x00, 0, name,
1394 name_len, conn->dev_class);
Johan Hedbergb644ba32012-01-17 21:48:47 +02001395
1396 if (discov->state == DISCOVERY_STOPPED)
1397 return;
1398
Johan Hedberg30dc78e2012-01-04 15:44:20 +02001399 if (discov->state == DISCOVERY_STOPPING)
1400 goto discov_complete;
1401
1402 if (discov->state != DISCOVERY_RESOLVING)
1403 return;
1404
1405 e = hci_inquiry_cache_lookup_resolve(hdev, bdaddr, NAME_PENDING);
1406 if (e) {
1407 e->name_state = NAME_KNOWN;
1408 list_del(&e->list);
Johan Hedbergb644ba32012-01-17 21:48:47 +02001409 if (name)
1410 mgmt_remote_name(hdev, bdaddr, ACL_LINK, 0x00,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001411 e->data.rssi, name, name_len);
Johan Hedberg30dc78e2012-01-04 15:44:20 +02001412 }
1413
Johan Hedbergb644ba32012-01-17 21:48:47 +02001414 if (hci_resolve_next_name(hdev))
Johan Hedberg30dc78e2012-01-04 15:44:20 +02001415 return;
Johan Hedberg30dc78e2012-01-04 15:44:20 +02001416
1417discov_complete:
1418 hci_discovery_set_state(hdev, DISCOVERY_STOPPED);
1419}
1420
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001421static void hci_cs_remote_name_req(struct hci_dev *hdev, __u8 status)
1422{
Johan Hedberg127178d2010-11-18 22:22:29 +02001423 struct hci_cp_remote_name_req *cp;
1424 struct hci_conn *conn;
1425
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001426 BT_DBG("%s status 0x%x", hdev->name, status);
Johan Hedberg127178d2010-11-18 22:22:29 +02001427
1428 /* If successful wait for the name req complete event before
1429 * checking for the need to do authentication */
1430 if (!status)
1431 return;
1432
1433 cp = hci_sent_cmd_data(hdev, HCI_OP_REMOTE_NAME_REQ);
1434 if (!cp)
1435 return;
1436
1437 hci_dev_lock(hdev);
1438
1439 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &cp->bdaddr);
Johan Hedbergb644ba32012-01-17 21:48:47 +02001440
1441 if (test_bit(HCI_MGMT, &hdev->dev_flags))
1442 hci_check_pending_name(hdev, conn, &cp->bdaddr, NULL, 0);
1443
Johan Hedberg79c6c702011-04-28 11:28:55 -07001444 if (!conn)
1445 goto unlock;
1446
1447 if (!hci_outgoing_auth_needed(hdev, conn))
1448 goto unlock;
1449
Johan Hedberg51a8efd2012-01-16 06:10:31 +02001450 if (!test_and_set_bit(HCI_CONN_AUTH_PEND, &conn->flags)) {
Johan Hedberg127178d2010-11-18 22:22:29 +02001451 struct hci_cp_auth_requested cp;
1452 cp.handle = __cpu_to_le16(conn->handle);
1453 hci_send_cmd(hdev, HCI_OP_AUTH_REQUESTED, sizeof(cp), &cp);
1454 }
1455
Johan Hedberg79c6c702011-04-28 11:28:55 -07001456unlock:
Johan Hedberg127178d2010-11-18 22:22:29 +02001457 hci_dev_unlock(hdev);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001458}
1459
Marcel Holtmann769be972008-07-14 20:13:49 +02001460static void hci_cs_read_remote_features(struct hci_dev *hdev, __u8 status)
1461{
1462 struct hci_cp_read_remote_features *cp;
1463 struct hci_conn *conn;
1464
1465 BT_DBG("%s status 0x%x", hdev->name, status);
1466
1467 if (!status)
1468 return;
1469
1470 cp = hci_sent_cmd_data(hdev, HCI_OP_READ_REMOTE_FEATURES);
1471 if (!cp)
1472 return;
1473
1474 hci_dev_lock(hdev);
1475
1476 conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(cp->handle));
1477 if (conn) {
1478 if (conn->state == BT_CONFIG) {
Marcel Holtmann769be972008-07-14 20:13:49 +02001479 hci_proto_connect_cfm(conn, status);
1480 hci_conn_put(conn);
1481 }
1482 }
1483
1484 hci_dev_unlock(hdev);
1485}
1486
1487static void hci_cs_read_remote_ext_features(struct hci_dev *hdev, __u8 status)
1488{
1489 struct hci_cp_read_remote_ext_features *cp;
1490 struct hci_conn *conn;
1491
1492 BT_DBG("%s status 0x%x", hdev->name, status);
1493
1494 if (!status)
1495 return;
1496
1497 cp = hci_sent_cmd_data(hdev, HCI_OP_READ_REMOTE_EXT_FEATURES);
1498 if (!cp)
1499 return;
1500
1501 hci_dev_lock(hdev);
1502
1503 conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(cp->handle));
1504 if (conn) {
1505 if (conn->state == BT_CONFIG) {
Marcel Holtmann769be972008-07-14 20:13:49 +02001506 hci_proto_connect_cfm(conn, status);
1507 hci_conn_put(conn);
1508 }
1509 }
1510
1511 hci_dev_unlock(hdev);
1512}
1513
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001514static void hci_cs_setup_sync_conn(struct hci_dev *hdev, __u8 status)
1515{
Marcel Holtmannb6a0dc82007-10-20 14:55:10 +02001516 struct hci_cp_setup_sync_conn *cp;
1517 struct hci_conn *acl, *sco;
1518 __u16 handle;
1519
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001520 BT_DBG("%s status 0x%x", hdev->name, status);
Marcel Holtmannb6a0dc82007-10-20 14:55:10 +02001521
1522 if (!status)
1523 return;
1524
1525 cp = hci_sent_cmd_data(hdev, HCI_OP_SETUP_SYNC_CONN);
1526 if (!cp)
1527 return;
1528
1529 handle = __le16_to_cpu(cp->handle);
1530
1531 BT_DBG("%s handle %d", hdev->name, handle);
1532
1533 hci_dev_lock(hdev);
1534
1535 acl = hci_conn_hash_lookup_handle(hdev, handle);
Andrei Emeltchenko5a08ecc2011-01-11 17:20:20 +02001536 if (acl) {
1537 sco = acl->link;
1538 if (sco) {
1539 sco->state = BT_CLOSED;
Marcel Holtmannb6a0dc82007-10-20 14:55:10 +02001540
Andrei Emeltchenko5a08ecc2011-01-11 17:20:20 +02001541 hci_proto_connect_cfm(sco, status);
1542 hci_conn_del(sco);
1543 }
Marcel Holtmannb6a0dc82007-10-20 14:55:10 +02001544 }
1545
1546 hci_dev_unlock(hdev);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001547}
1548
1549static void hci_cs_sniff_mode(struct hci_dev *hdev, __u8 status)
1550{
1551 struct hci_cp_sniff_mode *cp;
1552 struct hci_conn *conn;
1553
1554 BT_DBG("%s status 0x%x", hdev->name, status);
1555
1556 if (!status)
1557 return;
1558
1559 cp = hci_sent_cmd_data(hdev, HCI_OP_SNIFF_MODE);
1560 if (!cp)
1561 return;
1562
1563 hci_dev_lock(hdev);
1564
1565 conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(cp->handle));
Marcel Holtmanne73439d2010-07-26 10:06:00 -04001566 if (conn) {
Johan Hedberg51a8efd2012-01-16 06:10:31 +02001567 clear_bit(HCI_CONN_MODE_CHANGE_PEND, &conn->flags);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001568
Johan Hedberg51a8efd2012-01-16 06:10:31 +02001569 if (test_and_clear_bit(HCI_CONN_SCO_SETUP_PEND, &conn->flags))
Marcel Holtmanne73439d2010-07-26 10:06:00 -04001570 hci_sco_setup(conn, status);
1571 }
1572
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001573 hci_dev_unlock(hdev);
1574}
1575
1576static void hci_cs_exit_sniff_mode(struct hci_dev *hdev, __u8 status)
1577{
1578 struct hci_cp_exit_sniff_mode *cp;
1579 struct hci_conn *conn;
1580
1581 BT_DBG("%s status 0x%x", hdev->name, status);
1582
1583 if (!status)
1584 return;
1585
1586 cp = hci_sent_cmd_data(hdev, HCI_OP_EXIT_SNIFF_MODE);
1587 if (!cp)
1588 return;
1589
1590 hci_dev_lock(hdev);
1591
1592 conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(cp->handle));
Marcel Holtmanne73439d2010-07-26 10:06:00 -04001593 if (conn) {
Johan Hedberg51a8efd2012-01-16 06:10:31 +02001594 clear_bit(HCI_CONN_MODE_CHANGE_PEND, &conn->flags);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001595
Johan Hedberg51a8efd2012-01-16 06:10:31 +02001596 if (test_and_clear_bit(HCI_CONN_SCO_SETUP_PEND, &conn->flags))
Marcel Holtmanne73439d2010-07-26 10:06:00 -04001597 hci_sco_setup(conn, status);
1598 }
1599
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001600 hci_dev_unlock(hdev);
1601}
1602
Johan Hedberg88c3df12012-02-09 14:27:38 +02001603static void hci_cs_disconnect(struct hci_dev *hdev, u8 status)
1604{
1605 struct hci_cp_disconnect *cp;
1606 struct hci_conn *conn;
1607
1608 if (!status)
1609 return;
1610
1611 cp = hci_sent_cmd_data(hdev, HCI_OP_DISCONNECT);
1612 if (!cp)
1613 return;
1614
1615 hci_dev_lock(hdev);
1616
1617 conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(cp->handle));
1618 if (conn)
1619 mgmt_disconnect_failed(hdev, &conn->dst, conn->type,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001620 conn->dst_type, status);
Johan Hedberg88c3df12012-02-09 14:27:38 +02001621
1622 hci_dev_unlock(hdev);
1623}
1624
Ville Tervofcd89c02011-02-10 22:38:47 -03001625static void hci_cs_le_create_conn(struct hci_dev *hdev, __u8 status)
1626{
1627 struct hci_cp_le_create_conn *cp;
1628 struct hci_conn *conn;
1629
1630 BT_DBG("%s status 0x%x", hdev->name, status);
1631
1632 cp = hci_sent_cmd_data(hdev, HCI_OP_LE_CREATE_CONN);
1633 if (!cp)
1634 return;
1635
1636 hci_dev_lock(hdev);
1637
1638 conn = hci_conn_hash_lookup_ba(hdev, LE_LINK, &cp->peer_addr);
1639
1640 BT_DBG("%s bdaddr %s conn %p", hdev->name, batostr(&cp->peer_addr),
Gustavo Padovan807deac2012-05-17 00:36:24 -03001641 conn);
Ville Tervofcd89c02011-02-10 22:38:47 -03001642
1643 if (status) {
1644 if (conn && conn->state == BT_CONNECT) {
1645 conn->state = BT_CLOSED;
Hemant Gupta328c9242012-04-05 16:51:04 +05301646 mgmt_connect_failed(hdev, &cp->peer_addr, conn->type,
1647 conn->dst_type, status);
Ville Tervofcd89c02011-02-10 22:38:47 -03001648 hci_proto_connect_cfm(conn, status);
1649 hci_conn_del(conn);
1650 }
1651 } else {
1652 if (!conn) {
1653 conn = hci_conn_add(hdev, LE_LINK, &cp->peer_addr);
Andre Guedes29b79882011-05-31 14:20:54 -03001654 if (conn) {
1655 conn->dst_type = cp->peer_addr_type;
Johan Hedberga0c808b2012-01-16 09:49:58 +02001656 conn->out = true;
Andre Guedes29b79882011-05-31 14:20:54 -03001657 } else {
Ville Tervofcd89c02011-02-10 22:38:47 -03001658 BT_ERR("No memory for new connection");
Andre Guedes29b79882011-05-31 14:20:54 -03001659 }
Ville Tervofcd89c02011-02-10 22:38:47 -03001660 }
1661 }
1662
1663 hci_dev_unlock(hdev);
1664}
1665
Vinicius Costa Gomesa7a595f2011-06-09 18:50:47 -03001666static void hci_cs_le_start_enc(struct hci_dev *hdev, u8 status)
1667{
1668 BT_DBG("%s status 0x%x", hdev->name, status);
1669}
1670
Gustavo Padovan807deac2012-05-17 00:36:24 -03001671static inline void hci_inquiry_complete_evt(struct hci_dev *hdev,
1672 struct sk_buff *skb)
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001673{
1674 __u8 status = *((__u8 *) skb->data);
Johan Hedberg30dc78e2012-01-04 15:44:20 +02001675 struct discovery_state *discov = &hdev->discovery;
1676 struct inquiry_entry *e;
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001677
1678 BT_DBG("%s status %d", hdev->name, status);
1679
Johan Hedberg23bb5762010-12-21 23:01:27 +02001680 hci_req_complete(hdev, HCI_OP_INQUIRY, status);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001681
1682 hci_conn_check_pending(hdev);
Andre Guedes89352e72011-11-04 14:16:53 -03001683
1684 if (!test_and_clear_bit(HCI_INQUIRY, &hdev->flags))
1685 return;
1686
Johan Hedberga8b2d5c2012-01-08 23:11:15 +02001687 if (!test_bit(HCI_MGMT, &hdev->dev_flags))
Johan Hedberg30dc78e2012-01-04 15:44:20 +02001688 return;
1689
Johan Hedberg56e5cb82011-11-08 20:40:16 +02001690 hci_dev_lock(hdev);
Johan Hedberg30dc78e2012-01-04 15:44:20 +02001691
Andre Guedes343f9352012-02-17 20:39:37 -03001692 if (discov->state != DISCOVERY_FINDING)
Johan Hedberg30dc78e2012-01-04 15:44:20 +02001693 goto unlock;
1694
1695 if (list_empty(&discov->resolve)) {
1696 hci_discovery_set_state(hdev, DISCOVERY_STOPPED);
1697 goto unlock;
1698 }
1699
1700 e = hci_inquiry_cache_lookup_resolve(hdev, BDADDR_ANY, NAME_NEEDED);
1701 if (e && hci_resolve_name(hdev, e) == 0) {
1702 e->name_state = NAME_PENDING;
1703 hci_discovery_set_state(hdev, DISCOVERY_RESOLVING);
1704 } else {
1705 hci_discovery_set_state(hdev, DISCOVERY_STOPPED);
1706 }
1707
1708unlock:
Johan Hedberg56e5cb82011-11-08 20:40:16 +02001709 hci_dev_unlock(hdev);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001710}
1711
Gustavo Padovan807deac2012-05-17 00:36:24 -03001712static inline void hci_inquiry_result_evt(struct hci_dev *hdev,
1713 struct sk_buff *skb)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001714{
Marcel Holtmann45bb4bf2005-08-09 20:27:49 -07001715 struct inquiry_data data;
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001716 struct inquiry_info *info = (void *) (skb->data + 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001717 int num_rsp = *((__u8 *) skb->data);
1718
1719 BT_DBG("%s num_rsp %d", hdev->name, num_rsp);
1720
Marcel Holtmann45bb4bf2005-08-09 20:27:49 -07001721 if (!num_rsp)
1722 return;
1723
Andre Guedes1519cc12012-03-21 00:03:38 -03001724 if (test_bit(HCI_PERIODIC_INQ, &hdev->dev_flags))
1725 return;
1726
Linus Torvalds1da177e2005-04-16 15:20:36 -07001727 hci_dev_lock(hdev);
Marcel Holtmann45bb4bf2005-08-09 20:27:49 -07001728
Johan Hedberge17acd42011-03-30 23:57:16 +03001729 for (; num_rsp; num_rsp--, info++) {
Johan Hedberg388fc8f2012-02-23 00:38:59 +02001730 bool name_known, ssp;
Johan Hedberg31754052012-01-04 13:39:52 +02001731
Linus Torvalds1da177e2005-04-16 15:20:36 -07001732 bacpy(&data.bdaddr, &info->bdaddr);
1733 data.pscan_rep_mode = info->pscan_rep_mode;
1734 data.pscan_period_mode = info->pscan_period_mode;
1735 data.pscan_mode = info->pscan_mode;
1736 memcpy(data.dev_class, info->dev_class, 3);
1737 data.clock_offset = info->clock_offset;
1738 data.rssi = 0x00;
Marcel Holtmann41a96212008-07-14 20:13:48 +02001739 data.ssp_mode = 0x00;
Johan Hedberg31754052012-01-04 13:39:52 +02001740
Johan Hedberg388fc8f2012-02-23 00:38:59 +02001741 name_known = hci_inquiry_cache_update(hdev, &data, false, &ssp);
Johan Hedberg48264f02011-11-09 13:58:58 +02001742 mgmt_device_found(hdev, &info->bdaddr, ACL_LINK, 0x00,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001743 info->dev_class, 0, !name_known, ssp, NULL,
1744 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001745 }
Marcel Holtmann45bb4bf2005-08-09 20:27:49 -07001746
Linus Torvalds1da177e2005-04-16 15:20:36 -07001747 hci_dev_unlock(hdev);
1748}
1749
Gustavo Padovan807deac2012-05-17 00:36:24 -03001750static inline void hci_conn_complete_evt(struct hci_dev *hdev,
1751 struct sk_buff *skb)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001752{
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001753 struct hci_ev_conn_complete *ev = (void *) skb->data;
1754 struct hci_conn *conn;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001755
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001756 BT_DBG("%s", hdev->name);
Marcel Holtmann45bb4bf2005-08-09 20:27:49 -07001757
Linus Torvalds1da177e2005-04-16 15:20:36 -07001758 hci_dev_lock(hdev);
Marcel Holtmann45bb4bf2005-08-09 20:27:49 -07001759
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001760 conn = hci_conn_hash_lookup_ba(hdev, ev->link_type, &ev->bdaddr);
Marcel Holtmann94992372009-04-19 19:30:03 +02001761 if (!conn) {
1762 if (ev->link_type != SCO_LINK)
1763 goto unlock;
1764
1765 conn = hci_conn_hash_lookup_ba(hdev, ESCO_LINK, &ev->bdaddr);
1766 if (!conn)
1767 goto unlock;
1768
1769 conn->type = SCO_LINK;
1770 }
Marcel Holtmann45bb4bf2005-08-09 20:27:49 -07001771
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001772 if (!ev->status) {
1773 conn->handle = __le16_to_cpu(ev->handle);
Marcel Holtmann769be972008-07-14 20:13:49 +02001774
1775 if (conn->type == ACL_LINK) {
1776 conn->state = BT_CONFIG;
1777 hci_conn_hold(conn);
Marcel Holtmann052b30b2009-04-26 20:01:22 +02001778 conn->disc_timeout = HCI_DISCONN_TIMEOUT;
Marcel Holtmann769be972008-07-14 20:13:49 +02001779 } else
1780 conn->state = BT_CONNECTED;
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001781
Marcel Holtmann9eba32b2009-08-22 14:19:26 -07001782 hci_conn_hold_device(conn);
Marcel Holtmann7d0db0a2008-07-14 20:13:51 +02001783 hci_conn_add_sysfs(conn);
1784
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001785 if (test_bit(HCI_AUTH, &hdev->flags))
1786 conn->link_mode |= HCI_LM_AUTH;
1787
1788 if (test_bit(HCI_ENCRYPT, &hdev->flags))
1789 conn->link_mode |= HCI_LM_ENCRYPT;
1790
1791 /* Get remote features */
1792 if (conn->type == ACL_LINK) {
1793 struct hci_cp_read_remote_features cp;
1794 cp.handle = ev->handle;
Marcel Holtmann769be972008-07-14 20:13:49 +02001795 hci_send_cmd(hdev, HCI_OP_READ_REMOTE_FEATURES,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001796 sizeof(cp), &cp);
Marcel Holtmann45bb4bf2005-08-09 20:27:49 -07001797 }
Marcel Holtmann45bb4bf2005-08-09 20:27:49 -07001798
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001799 /* Set packet type for incoming connection */
Andrei Emeltchenkod095c1e2011-12-01 14:33:27 +02001800 if (!conn->out && hdev->hci_ver < BLUETOOTH_VER_2_0) {
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001801 struct hci_cp_change_conn_ptype cp;
1802 cp.handle = ev->handle;
Marcel Holtmanna8746412008-07-14 20:13:46 +02001803 cp.pkt_type = cpu_to_le16(conn->pkt_type);
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001804 hci_send_cmd(hdev, HCI_OP_CHANGE_CONN_PTYPE, sizeof(cp),
1805 &cp);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001806 }
Johan Hedberg17d5c042011-01-22 06:09:08 +02001807 } else {
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001808 conn->state = BT_CLOSED;
Johan Hedberg17d5c042011-01-22 06:09:08 +02001809 if (conn->type == ACL_LINK)
Johan Hedberg744cf192011-11-08 20:40:14 +02001810 mgmt_connect_failed(hdev, &ev->bdaddr, conn->type,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001811 conn->dst_type, ev->status);
Johan Hedberg17d5c042011-01-22 06:09:08 +02001812 }
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001813
Marcel Holtmanne73439d2010-07-26 10:06:00 -04001814 if (conn->type == ACL_LINK)
1815 hci_sco_setup(conn, ev->status);
Marcel Holtmann45bb4bf2005-08-09 20:27:49 -07001816
Marcel Holtmann769be972008-07-14 20:13:49 +02001817 if (ev->status) {
1818 hci_proto_connect_cfm(conn, ev->status);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001819 hci_conn_del(conn);
Marcel Holtmannc89b6e62009-01-15 21:57:03 +01001820 } else if (ev->link_type != ACL_LINK)
1821 hci_proto_connect_cfm(conn, ev->status);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001822
1823unlock:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001824 hci_dev_unlock(hdev);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001825
1826 hci_conn_check_pending(hdev);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001827}
1828
Gustavo Padovan807deac2012-05-17 00:36:24 -03001829static inline void hci_conn_request_evt(struct hci_dev *hdev,
1830 struct sk_buff *skb)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001831{
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001832 struct hci_ev_conn_request *ev = (void *) skb->data;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001833 int mask = hdev->link_mode;
1834
Gustavo Padovan807deac2012-05-17 00:36:24 -03001835 BT_DBG("%s bdaddr %s type 0x%x", hdev->name, batostr(&ev->bdaddr),
1836 ev->link_type);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001837
1838 mask |= hci_proto_connect_ind(hdev, &ev->bdaddr, ev->link_type);
1839
Szymon Janc138d22e2011-02-17 16:44:23 +01001840 if ((mask & HCI_LM_ACCEPT) &&
Gustavo Padovan807deac2012-05-17 00:36:24 -03001841 !hci_blacklist_lookup(hdev, &ev->bdaddr)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001842 /* Connection accepted */
Marcel Holtmannc7bdd502008-07-14 20:13:47 +02001843 struct inquiry_entry *ie;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001844 struct hci_conn *conn;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001845
1846 hci_dev_lock(hdev);
Marcel Holtmannb6a0dc82007-10-20 14:55:10 +02001847
Andrei Emeltchenkocc11b9c2010-11-22 13:21:37 +02001848 ie = hci_inquiry_cache_lookup(hdev, &ev->bdaddr);
1849 if (ie)
Marcel Holtmannc7bdd502008-07-14 20:13:47 +02001850 memcpy(ie->data.dev_class, ev->dev_class, 3);
1851
Linus Torvalds1da177e2005-04-16 15:20:36 -07001852 conn = hci_conn_hash_lookup_ba(hdev, ev->link_type, &ev->bdaddr);
1853 if (!conn) {
Andrei Emeltchenkocc11b9c2010-11-22 13:21:37 +02001854 conn = hci_conn_add(hdev, ev->link_type, &ev->bdaddr);
1855 if (!conn) {
Gustavo F. Padovan893ef972010-07-18 15:13:37 -03001856 BT_ERR("No memory for new connection");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001857 hci_dev_unlock(hdev);
1858 return;
1859 }
1860 }
Marcel Holtmannb6a0dc82007-10-20 14:55:10 +02001861
Linus Torvalds1da177e2005-04-16 15:20:36 -07001862 memcpy(conn->dev_class, ev->dev_class, 3);
1863 conn->state = BT_CONNECT;
Marcel Holtmannb6a0dc82007-10-20 14:55:10 +02001864
Linus Torvalds1da177e2005-04-16 15:20:36 -07001865 hci_dev_unlock(hdev);
1866
Marcel Holtmannb6a0dc82007-10-20 14:55:10 +02001867 if (ev->link_type == ACL_LINK || !lmp_esco_capable(hdev)) {
1868 struct hci_cp_accept_conn_req cp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001869
Marcel Holtmannb6a0dc82007-10-20 14:55:10 +02001870 bacpy(&cp.bdaddr, &ev->bdaddr);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001871
Marcel Holtmannb6a0dc82007-10-20 14:55:10 +02001872 if (lmp_rswitch_capable(hdev) && (mask & HCI_LM_MASTER))
1873 cp.role = 0x00; /* Become master */
1874 else
1875 cp.role = 0x01; /* Remain slave */
1876
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001877 hci_send_cmd(hdev, HCI_OP_ACCEPT_CONN_REQ, sizeof(cp),
1878 &cp);
Marcel Holtmannb6a0dc82007-10-20 14:55:10 +02001879 } else {
1880 struct hci_cp_accept_sync_conn_req cp;
1881
1882 bacpy(&cp.bdaddr, &ev->bdaddr);
Marcel Holtmanna8746412008-07-14 20:13:46 +02001883 cp.pkt_type = cpu_to_le16(conn->pkt_type);
Marcel Holtmannb6a0dc82007-10-20 14:55:10 +02001884
1885 cp.tx_bandwidth = cpu_to_le32(0x00001f40);
1886 cp.rx_bandwidth = cpu_to_le32(0x00001f40);
1887 cp.max_latency = cpu_to_le16(0xffff);
1888 cp.content_format = cpu_to_le16(hdev->voice_setting);
1889 cp.retrans_effort = 0xff;
1890
1891 hci_send_cmd(hdev, HCI_OP_ACCEPT_SYNC_CONN_REQ,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001892 sizeof(cp), &cp);
Marcel Holtmannb6a0dc82007-10-20 14:55:10 +02001893 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001894 } else {
1895 /* Connection rejected */
1896 struct hci_cp_reject_conn_req cp;
1897
1898 bacpy(&cp.bdaddr, &ev->bdaddr);
Andrei Emeltchenko9f5a0d72011-11-07 14:20:25 +02001899 cp.reason = HCI_ERROR_REJ_BAD_ADDR;
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001900 hci_send_cmd(hdev, HCI_OP_REJECT_CONN_REQ, sizeof(cp), &cp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001901 }
1902}
1903
Gustavo Padovan807deac2012-05-17 00:36:24 -03001904static inline void hci_disconn_complete_evt(struct hci_dev *hdev,
1905 struct sk_buff *skb)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001906{
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001907 struct hci_ev_disconn_complete *ev = (void *) skb->data;
Marcel Holtmann04837f62006-07-03 10:02:33 +02001908 struct hci_conn *conn;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001909
1910 BT_DBG("%s status %d", hdev->name, ev->status);
1911
Linus Torvalds1da177e2005-04-16 15:20:36 -07001912 hci_dev_lock(hdev);
1913
Marcel Holtmann04837f62006-07-03 10:02:33 +02001914 conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
Johan Hedbergf7520542011-01-20 12:34:39 +02001915 if (!conn)
1916 goto unlock;
Marcel Holtmann7d0db0a2008-07-14 20:13:51 +02001917
Johan Hedberg37d9ef72011-11-10 15:54:39 +02001918 if (ev->status == 0)
1919 conn->state = BT_CLOSED;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001920
Johan Hedbergb644ba32012-01-17 21:48:47 +02001921 if (test_and_clear_bit(HCI_CONN_MGMT_CONNECTED, &conn->flags) &&
Gustavo Padovan807deac2012-05-17 00:36:24 -03001922 (conn->type == ACL_LINK || conn->type == LE_LINK)) {
Johan Hedberg37d9ef72011-11-10 15:54:39 +02001923 if (ev->status != 0)
Johan Hedberg88c3df12012-02-09 14:27:38 +02001924 mgmt_disconnect_failed(hdev, &conn->dst, conn->type,
Gustavo Padovan807deac2012-05-17 00:36:24 -03001925 conn->dst_type, ev->status);
Johan Hedberg37d9ef72011-11-10 15:54:39 +02001926 else
Johan Hedbergafc747a2012-01-15 18:11:07 +02001927 mgmt_device_disconnected(hdev, &conn->dst, conn->type,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001928 conn->dst_type);
Johan Hedberg37d9ef72011-11-10 15:54:39 +02001929 }
Johan Hedbergf7520542011-01-20 12:34:39 +02001930
Johan Hedberg37d9ef72011-11-10 15:54:39 +02001931 if (ev->status == 0) {
Vishal Agarwal6ec5bca2012-04-16 14:44:44 +05301932 if (conn->type == ACL_LINK && conn->flush_key)
1933 hci_remove_link_key(hdev, &conn->dst);
Johan Hedberg37d9ef72011-11-10 15:54:39 +02001934 hci_proto_disconn_cfm(conn, ev->reason);
1935 hci_conn_del(conn);
1936 }
Johan Hedbergf7520542011-01-20 12:34:39 +02001937
1938unlock:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001939 hci_dev_unlock(hdev);
1940}
1941
Gustavo Padovan807deac2012-05-17 00:36:24 -03001942static inline void hci_auth_complete_evt(struct hci_dev *hdev,
1943 struct sk_buff *skb)
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001944{
1945 struct hci_ev_auth_complete *ev = (void *) skb->data;
1946 struct hci_conn *conn;
1947
1948 BT_DBG("%s status %d", hdev->name, ev->status);
1949
1950 hci_dev_lock(hdev);
1951
1952 conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
Waldemar Rymarkiewiczd7556e22011-05-31 15:49:26 +02001953 if (!conn)
1954 goto unlock;
1955
1956 if (!ev->status) {
Johan Hedbergaa64a8b2012-01-18 21:33:12 +02001957 if (!hci_conn_ssp_enabled(conn) &&
Gustavo Padovan807deac2012-05-17 00:36:24 -03001958 test_bit(HCI_CONN_REAUTH_PEND, &conn->flags)) {
Waldemar Rymarkiewiczd7556e22011-05-31 15:49:26 +02001959 BT_INFO("re-auth of legacy device is not possible.");
Johan Hedberg2a611692011-02-19 12:06:00 -03001960 } else {
Waldemar Rymarkiewiczd7556e22011-05-31 15:49:26 +02001961 conn->link_mode |= HCI_LM_AUTH;
1962 conn->sec_level = conn->pending_sec_level;
Johan Hedberg2a611692011-02-19 12:06:00 -03001963 }
Waldemar Rymarkiewiczd7556e22011-05-31 15:49:26 +02001964 } else {
Johan Hedbergbab73cb2012-02-09 16:07:29 +02001965 mgmt_auth_failed(hdev, &conn->dst, conn->type, conn->dst_type,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001966 ev->status);
Waldemar Rymarkiewiczd7556e22011-05-31 15:49:26 +02001967 }
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001968
Johan Hedberg51a8efd2012-01-16 06:10:31 +02001969 clear_bit(HCI_CONN_AUTH_PEND, &conn->flags);
1970 clear_bit(HCI_CONN_REAUTH_PEND, &conn->flags);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001971
Waldemar Rymarkiewiczd7556e22011-05-31 15:49:26 +02001972 if (conn->state == BT_CONFIG) {
Johan Hedbergaa64a8b2012-01-18 21:33:12 +02001973 if (!ev->status && hci_conn_ssp_enabled(conn)) {
Waldemar Rymarkiewiczd7556e22011-05-31 15:49:26 +02001974 struct hci_cp_set_conn_encrypt cp;
1975 cp.handle = ev->handle;
1976 cp.encrypt = 0x01;
1977 hci_send_cmd(hdev, HCI_OP_SET_CONN_ENCRYPT, sizeof(cp),
Gustavo Padovan807deac2012-05-17 00:36:24 -03001978 &cp);
Marcel Holtmann052b30b2009-04-26 20:01:22 +02001979 } else {
Waldemar Rymarkiewiczd7556e22011-05-31 15:49:26 +02001980 conn->state = BT_CONNECTED;
1981 hci_proto_connect_cfm(conn, ev->status);
Marcel Holtmann052b30b2009-04-26 20:01:22 +02001982 hci_conn_put(conn);
1983 }
Waldemar Rymarkiewiczd7556e22011-05-31 15:49:26 +02001984 } else {
1985 hci_auth_cfm(conn, ev->status);
Marcel Holtmann052b30b2009-04-26 20:01:22 +02001986
Waldemar Rymarkiewiczd7556e22011-05-31 15:49:26 +02001987 hci_conn_hold(conn);
1988 conn->disc_timeout = HCI_DISCONN_TIMEOUT;
1989 hci_conn_put(conn);
1990 }
1991
Johan Hedberg51a8efd2012-01-16 06:10:31 +02001992 if (test_bit(HCI_CONN_ENCRYPT_PEND, &conn->flags)) {
Waldemar Rymarkiewiczd7556e22011-05-31 15:49:26 +02001993 if (!ev->status) {
1994 struct hci_cp_set_conn_encrypt cp;
1995 cp.handle = ev->handle;
1996 cp.encrypt = 0x01;
1997 hci_send_cmd(hdev, HCI_OP_SET_CONN_ENCRYPT, sizeof(cp),
Gustavo Padovan807deac2012-05-17 00:36:24 -03001998 &cp);
Waldemar Rymarkiewiczd7556e22011-05-31 15:49:26 +02001999 } else {
Johan Hedberg51a8efd2012-01-16 06:10:31 +02002000 clear_bit(HCI_CONN_ENCRYPT_PEND, &conn->flags);
Waldemar Rymarkiewiczd7556e22011-05-31 15:49:26 +02002001 hci_encrypt_cfm(conn, ev->status, 0x00);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002002 }
2003 }
2004
Waldemar Rymarkiewiczd7556e22011-05-31 15:49:26 +02002005unlock:
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002006 hci_dev_unlock(hdev);
2007}
2008
2009static inline void hci_remote_name_evt(struct hci_dev *hdev, struct sk_buff *skb)
2010{
Johan Hedberg127178d2010-11-18 22:22:29 +02002011 struct hci_ev_remote_name *ev = (void *) skb->data;
2012 struct hci_conn *conn;
2013
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002014 BT_DBG("%s", hdev->name);
2015
2016 hci_conn_check_pending(hdev);
Johan Hedberg127178d2010-11-18 22:22:29 +02002017
2018 hci_dev_lock(hdev);
2019
2020 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
Johan Hedbergb644ba32012-01-17 21:48:47 +02002021
2022 if (!test_bit(HCI_MGMT, &hdev->dev_flags))
2023 goto check_auth;
2024
2025 if (ev->status == 0)
2026 hci_check_pending_name(hdev, conn, &ev->bdaddr, ev->name,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002027 strnlen(ev->name, HCI_MAX_NAME_LENGTH));
Johan Hedbergb644ba32012-01-17 21:48:47 +02002028 else
2029 hci_check_pending_name(hdev, conn, &ev->bdaddr, NULL, 0);
2030
2031check_auth:
Johan Hedberg79c6c702011-04-28 11:28:55 -07002032 if (!conn)
2033 goto unlock;
2034
2035 if (!hci_outgoing_auth_needed(hdev, conn))
2036 goto unlock;
2037
Johan Hedberg51a8efd2012-01-16 06:10:31 +02002038 if (!test_and_set_bit(HCI_CONN_AUTH_PEND, &conn->flags)) {
Johan Hedberg127178d2010-11-18 22:22:29 +02002039 struct hci_cp_auth_requested cp;
2040 cp.handle = __cpu_to_le16(conn->handle);
2041 hci_send_cmd(hdev, HCI_OP_AUTH_REQUESTED, sizeof(cp), &cp);
2042 }
2043
Johan Hedberg79c6c702011-04-28 11:28:55 -07002044unlock:
Johan Hedberg127178d2010-11-18 22:22:29 +02002045 hci_dev_unlock(hdev);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002046}
2047
Gustavo Padovan807deac2012-05-17 00:36:24 -03002048static inline void hci_encrypt_change_evt(struct hci_dev *hdev,
2049 struct sk_buff *skb)
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002050{
2051 struct hci_ev_encrypt_change *ev = (void *) skb->data;
2052 struct hci_conn *conn;
2053
2054 BT_DBG("%s status %d", hdev->name, ev->status);
2055
2056 hci_dev_lock(hdev);
2057
2058 conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
2059 if (conn) {
2060 if (!ev->status) {
Marcel Holtmannae293192008-07-14 20:13:45 +02002061 if (ev->encrypt) {
2062 /* Encryption implies authentication */
2063 conn->link_mode |= HCI_LM_AUTH;
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002064 conn->link_mode |= HCI_LM_ENCRYPT;
Vinicius Costa Gomesda85e5e2011-06-09 18:50:53 -03002065 conn->sec_level = conn->pending_sec_level;
Marcel Holtmannae293192008-07-14 20:13:45 +02002066 } else
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002067 conn->link_mode &= ~HCI_LM_ENCRYPT;
2068 }
2069
Johan Hedberg51a8efd2012-01-16 06:10:31 +02002070 clear_bit(HCI_CONN_ENCRYPT_PEND, &conn->flags);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002071
Gustavo Padovana7d77232012-05-13 03:20:07 -03002072 if (ev->status && conn->state == BT_CONNECTED) {
Gustavo Padovand839c812012-05-16 12:17:12 -03002073 hci_acl_disconn(conn, HCI_ERROR_AUTH_FAILURE);
Gustavo Padovana7d77232012-05-13 03:20:07 -03002074 hci_conn_put(conn);
2075 goto unlock;
2076 }
2077
Marcel Holtmannf8558552008-07-14 20:13:49 +02002078 if (conn->state == BT_CONFIG) {
2079 if (!ev->status)
2080 conn->state = BT_CONNECTED;
2081
2082 hci_proto_connect_cfm(conn, ev->status);
2083 hci_conn_put(conn);
2084 } else
2085 hci_encrypt_cfm(conn, ev->status, ev->encrypt);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002086 }
2087
Gustavo Padovana7d77232012-05-13 03:20:07 -03002088unlock:
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002089 hci_dev_unlock(hdev);
2090}
2091
Gustavo Padovan807deac2012-05-17 00:36:24 -03002092static inline void hci_change_link_key_complete_evt(struct hci_dev *hdev,
2093 struct sk_buff *skb)
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002094{
2095 struct hci_ev_change_link_key_complete *ev = (void *) skb->data;
2096 struct hci_conn *conn;
2097
2098 BT_DBG("%s status %d", hdev->name, ev->status);
2099
2100 hci_dev_lock(hdev);
2101
2102 conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
2103 if (conn) {
2104 if (!ev->status)
2105 conn->link_mode |= HCI_LM_SECURE;
2106
Johan Hedberg51a8efd2012-01-16 06:10:31 +02002107 clear_bit(HCI_CONN_AUTH_PEND, &conn->flags);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002108
2109 hci_key_change_cfm(conn, ev->status);
2110 }
2111
2112 hci_dev_unlock(hdev);
2113}
2114
Gustavo Padovan807deac2012-05-17 00:36:24 -03002115static inline void hci_remote_features_evt(struct hci_dev *hdev,
2116 struct sk_buff *skb)
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002117{
2118 struct hci_ev_remote_features *ev = (void *) skb->data;
2119 struct hci_conn *conn;
2120
2121 BT_DBG("%s status %d", hdev->name, ev->status);
2122
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002123 hci_dev_lock(hdev);
2124
2125 conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
Johan Hedbergccd556f2010-11-10 17:11:51 +02002126 if (!conn)
2127 goto unlock;
Marcel Holtmann769be972008-07-14 20:13:49 +02002128
Johan Hedbergccd556f2010-11-10 17:11:51 +02002129 if (!ev->status)
2130 memcpy(conn->features, ev->features, 8);
2131
2132 if (conn->state != BT_CONFIG)
2133 goto unlock;
2134
2135 if (!ev->status && lmp_ssp_capable(hdev) && lmp_ssp_capable(conn)) {
2136 struct hci_cp_read_remote_ext_features cp;
2137 cp.handle = ev->handle;
2138 cp.page = 0x01;
2139 hci_send_cmd(hdev, HCI_OP_READ_REMOTE_EXT_FEATURES,
Gustavo Padovan807deac2012-05-17 00:36:24 -03002140 sizeof(cp), &cp);
Johan Hedberg392599b2010-11-18 22:22:28 +02002141 goto unlock;
2142 }
2143
Johan Hedberg671267b2012-05-12 16:11:50 -03002144 if (!ev->status && !test_bit(HCI_CONN_MGMT_CONNECTED, &conn->flags)) {
Johan Hedberg127178d2010-11-18 22:22:29 +02002145 struct hci_cp_remote_name_req cp;
2146 memset(&cp, 0, sizeof(cp));
2147 bacpy(&cp.bdaddr, &conn->dst);
2148 cp.pscan_rep_mode = 0x02;
2149 hci_send_cmd(hdev, HCI_OP_REMOTE_NAME_REQ, sizeof(cp), &cp);
Johan Hedbergb644ba32012-01-17 21:48:47 +02002150 } else if (!test_and_set_bit(HCI_CONN_MGMT_CONNECTED, &conn->flags))
2151 mgmt_device_connected(hdev, &conn->dst, conn->type,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002152 conn->dst_type, 0, NULL, 0,
2153 conn->dev_class);
Johan Hedberg392599b2010-11-18 22:22:28 +02002154
Johan Hedberg127178d2010-11-18 22:22:29 +02002155 if (!hci_outgoing_auth_needed(hdev, conn)) {
Johan Hedbergccd556f2010-11-10 17:11:51 +02002156 conn->state = BT_CONNECTED;
2157 hci_proto_connect_cfm(conn, ev->status);
2158 hci_conn_put(conn);
Marcel Holtmann769be972008-07-14 20:13:49 +02002159 }
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002160
Johan Hedbergccd556f2010-11-10 17:11:51 +02002161unlock:
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002162 hci_dev_unlock(hdev);
2163}
2164
Gustavo Padovan807deac2012-05-17 00:36:24 -03002165static inline void hci_remote_version_evt(struct hci_dev *hdev,
2166 struct sk_buff *skb)
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002167{
2168 BT_DBG("%s", hdev->name);
2169}
2170
Gustavo Padovan807deac2012-05-17 00:36:24 -03002171static inline void hci_qos_setup_complete_evt(struct hci_dev *hdev,
2172 struct sk_buff *skb)
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002173{
2174 BT_DBG("%s", hdev->name);
2175}
2176
Gustavo Padovan807deac2012-05-17 00:36:24 -03002177static inline void hci_cmd_complete_evt(struct hci_dev *hdev,
2178 struct sk_buff *skb)
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002179{
2180 struct hci_ev_cmd_complete *ev = (void *) skb->data;
2181 __u16 opcode;
2182
2183 skb_pull(skb, sizeof(*ev));
2184
2185 opcode = __le16_to_cpu(ev->opcode);
2186
2187 switch (opcode) {
2188 case HCI_OP_INQUIRY_CANCEL:
2189 hci_cc_inquiry_cancel(hdev, skb);
2190 break;
2191
Andre Guedes4d934832012-03-21 00:03:35 -03002192 case HCI_OP_PERIODIC_INQ:
2193 hci_cc_periodic_inq(hdev, skb);
2194 break;
2195
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002196 case HCI_OP_EXIT_PERIODIC_INQ:
2197 hci_cc_exit_periodic_inq(hdev, skb);
2198 break;
2199
2200 case HCI_OP_REMOTE_NAME_REQ_CANCEL:
2201 hci_cc_remote_name_req_cancel(hdev, skb);
2202 break;
2203
2204 case HCI_OP_ROLE_DISCOVERY:
2205 hci_cc_role_discovery(hdev, skb);
2206 break;
2207
Marcel Holtmanne4e8e372008-07-14 20:13:47 +02002208 case HCI_OP_READ_LINK_POLICY:
2209 hci_cc_read_link_policy(hdev, skb);
2210 break;
2211
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002212 case HCI_OP_WRITE_LINK_POLICY:
2213 hci_cc_write_link_policy(hdev, skb);
2214 break;
2215
Marcel Holtmanne4e8e372008-07-14 20:13:47 +02002216 case HCI_OP_READ_DEF_LINK_POLICY:
2217 hci_cc_read_def_link_policy(hdev, skb);
2218 break;
2219
2220 case HCI_OP_WRITE_DEF_LINK_POLICY:
2221 hci_cc_write_def_link_policy(hdev, skb);
2222 break;
2223
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002224 case HCI_OP_RESET:
2225 hci_cc_reset(hdev, skb);
2226 break;
2227
2228 case HCI_OP_WRITE_LOCAL_NAME:
2229 hci_cc_write_local_name(hdev, skb);
2230 break;
2231
2232 case HCI_OP_READ_LOCAL_NAME:
2233 hci_cc_read_local_name(hdev, skb);
2234 break;
2235
2236 case HCI_OP_WRITE_AUTH_ENABLE:
2237 hci_cc_write_auth_enable(hdev, skb);
2238 break;
2239
2240 case HCI_OP_WRITE_ENCRYPT_MODE:
2241 hci_cc_write_encrypt_mode(hdev, skb);
2242 break;
2243
2244 case HCI_OP_WRITE_SCAN_ENABLE:
2245 hci_cc_write_scan_enable(hdev, skb);
2246 break;
2247
2248 case HCI_OP_READ_CLASS_OF_DEV:
2249 hci_cc_read_class_of_dev(hdev, skb);
2250 break;
2251
2252 case HCI_OP_WRITE_CLASS_OF_DEV:
2253 hci_cc_write_class_of_dev(hdev, skb);
2254 break;
2255
2256 case HCI_OP_READ_VOICE_SETTING:
2257 hci_cc_read_voice_setting(hdev, skb);
2258 break;
2259
2260 case HCI_OP_WRITE_VOICE_SETTING:
2261 hci_cc_write_voice_setting(hdev, skb);
2262 break;
2263
2264 case HCI_OP_HOST_BUFFER_SIZE:
2265 hci_cc_host_buffer_size(hdev, skb);
2266 break;
2267
Marcel Holtmann333140b2008-07-14 20:13:48 +02002268 case HCI_OP_WRITE_SSP_MODE:
2269 hci_cc_write_ssp_mode(hdev, skb);
2270 break;
2271
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002272 case HCI_OP_READ_LOCAL_VERSION:
2273 hci_cc_read_local_version(hdev, skb);
2274 break;
2275
2276 case HCI_OP_READ_LOCAL_COMMANDS:
2277 hci_cc_read_local_commands(hdev, skb);
2278 break;
2279
2280 case HCI_OP_READ_LOCAL_FEATURES:
2281 hci_cc_read_local_features(hdev, skb);
2282 break;
2283
Andre Guedes971e3a42011-06-30 19:20:52 -03002284 case HCI_OP_READ_LOCAL_EXT_FEATURES:
2285 hci_cc_read_local_ext_features(hdev, skb);
2286 break;
2287
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002288 case HCI_OP_READ_BUFFER_SIZE:
2289 hci_cc_read_buffer_size(hdev, skb);
2290 break;
2291
2292 case HCI_OP_READ_BD_ADDR:
2293 hci_cc_read_bd_addr(hdev, skb);
2294 break;
2295
Andrei Emeltchenko350ee4c2011-12-07 15:56:51 +02002296 case HCI_OP_READ_DATA_BLOCK_SIZE:
2297 hci_cc_read_data_block_size(hdev, skb);
2298 break;
2299
Johan Hedberg23bb5762010-12-21 23:01:27 +02002300 case HCI_OP_WRITE_CA_TIMEOUT:
2301 hci_cc_write_ca_timeout(hdev, skb);
2302 break;
2303
Andrei Emeltchenko1e89cff2011-11-24 14:52:02 +02002304 case HCI_OP_READ_FLOW_CONTROL_MODE:
2305 hci_cc_read_flow_control_mode(hdev, skb);
2306 break;
2307
Andrei Emeltchenko928abaa2011-10-12 10:53:57 +03002308 case HCI_OP_READ_LOCAL_AMP_INFO:
2309 hci_cc_read_local_amp_info(hdev, skb);
2310 break;
2311
Johan Hedbergb0916ea2011-01-10 13:44:55 +02002312 case HCI_OP_DELETE_STORED_LINK_KEY:
2313 hci_cc_delete_stored_link_key(hdev, skb);
2314 break;
2315
Johan Hedbergd5859e22011-01-25 01:19:58 +02002316 case HCI_OP_SET_EVENT_MASK:
2317 hci_cc_set_event_mask(hdev, skb);
2318 break;
2319
2320 case HCI_OP_WRITE_INQUIRY_MODE:
2321 hci_cc_write_inquiry_mode(hdev, skb);
2322 break;
2323
2324 case HCI_OP_READ_INQ_RSP_TX_POWER:
2325 hci_cc_read_inq_rsp_tx_power(hdev, skb);
2326 break;
2327
2328 case HCI_OP_SET_EVENT_FLT:
2329 hci_cc_set_event_flt(hdev, skb);
2330 break;
2331
Johan Hedberg980e1a52011-01-22 06:10:07 +02002332 case HCI_OP_PIN_CODE_REPLY:
2333 hci_cc_pin_code_reply(hdev, skb);
2334 break;
2335
2336 case HCI_OP_PIN_CODE_NEG_REPLY:
2337 hci_cc_pin_code_neg_reply(hdev, skb);
2338 break;
2339
Szymon Jancc35938b2011-03-22 13:12:21 +01002340 case HCI_OP_READ_LOCAL_OOB_DATA:
2341 hci_cc_read_local_oob_data_reply(hdev, skb);
2342 break;
2343
Ville Tervo6ed58ec2011-02-10 22:38:48 -03002344 case HCI_OP_LE_READ_BUFFER_SIZE:
2345 hci_cc_le_read_buffer_size(hdev, skb);
2346 break;
2347
Johan Hedberga5c29682011-02-19 12:05:57 -03002348 case HCI_OP_USER_CONFIRM_REPLY:
2349 hci_cc_user_confirm_reply(hdev, skb);
2350 break;
2351
2352 case HCI_OP_USER_CONFIRM_NEG_REPLY:
2353 hci_cc_user_confirm_neg_reply(hdev, skb);
2354 break;
2355
Brian Gix1143d452011-11-23 08:28:34 -08002356 case HCI_OP_USER_PASSKEY_REPLY:
2357 hci_cc_user_passkey_reply(hdev, skb);
2358 break;
2359
2360 case HCI_OP_USER_PASSKEY_NEG_REPLY:
2361 hci_cc_user_passkey_neg_reply(hdev, skb);
Szymon Janc16cde992012-04-13 12:32:42 +02002362 break;
Andre Guedes07f7fa52011-12-02 21:13:31 +09002363
2364 case HCI_OP_LE_SET_SCAN_PARAM:
2365 hci_cc_le_set_scan_param(hdev, skb);
Brian Gix1143d452011-11-23 08:28:34 -08002366 break;
2367
Andre Guedeseb9d91f2011-05-26 16:23:52 -03002368 case HCI_OP_LE_SET_SCAN_ENABLE:
2369 hci_cc_le_set_scan_enable(hdev, skb);
2370 break;
2371
Vinicius Costa Gomesa7a595f2011-06-09 18:50:47 -03002372 case HCI_OP_LE_LTK_REPLY:
2373 hci_cc_le_ltk_reply(hdev, skb);
2374 break;
2375
2376 case HCI_OP_LE_LTK_NEG_REPLY:
2377 hci_cc_le_ltk_neg_reply(hdev, skb);
2378 break;
2379
Andre Guedesf9b49302011-06-30 19:20:53 -03002380 case HCI_OP_WRITE_LE_HOST_SUPPORTED:
2381 hci_cc_write_le_host_supported(hdev, skb);
2382 break;
2383
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002384 default:
2385 BT_DBG("%s opcode 0x%x", hdev->name, opcode);
2386 break;
2387 }
2388
Ville Tervo6bd32322011-02-16 16:32:41 +02002389 if (ev->opcode != HCI_OP_NOP)
2390 del_timer(&hdev->cmd_timer);
2391
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002392 if (ev->ncmd) {
2393 atomic_set(&hdev->cmd_cnt, 1);
2394 if (!skb_queue_empty(&hdev->cmd_q))
Gustavo F. Padovanc347b762011-12-14 23:53:47 -02002395 queue_work(hdev->workqueue, &hdev->cmd_work);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002396 }
2397}
2398
2399static inline void hci_cmd_status_evt(struct hci_dev *hdev, struct sk_buff *skb)
2400{
2401 struct hci_ev_cmd_status *ev = (void *) skb->data;
2402 __u16 opcode;
2403
2404 skb_pull(skb, sizeof(*ev));
2405
2406 opcode = __le16_to_cpu(ev->opcode);
2407
2408 switch (opcode) {
2409 case HCI_OP_INQUIRY:
2410 hci_cs_inquiry(hdev, ev->status);
2411 break;
2412
2413 case HCI_OP_CREATE_CONN:
2414 hci_cs_create_conn(hdev, ev->status);
2415 break;
2416
2417 case HCI_OP_ADD_SCO:
2418 hci_cs_add_sco(hdev, ev->status);
2419 break;
2420
Marcel Holtmannf8558552008-07-14 20:13:49 +02002421 case HCI_OP_AUTH_REQUESTED:
2422 hci_cs_auth_requested(hdev, ev->status);
2423 break;
2424
2425 case HCI_OP_SET_CONN_ENCRYPT:
2426 hci_cs_set_conn_encrypt(hdev, ev->status);
2427 break;
2428
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002429 case HCI_OP_REMOTE_NAME_REQ:
2430 hci_cs_remote_name_req(hdev, ev->status);
2431 break;
2432
Marcel Holtmann769be972008-07-14 20:13:49 +02002433 case HCI_OP_READ_REMOTE_FEATURES:
2434 hci_cs_read_remote_features(hdev, ev->status);
2435 break;
2436
2437 case HCI_OP_READ_REMOTE_EXT_FEATURES:
2438 hci_cs_read_remote_ext_features(hdev, ev->status);
2439 break;
2440
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002441 case HCI_OP_SETUP_SYNC_CONN:
2442 hci_cs_setup_sync_conn(hdev, ev->status);
2443 break;
2444
2445 case HCI_OP_SNIFF_MODE:
2446 hci_cs_sniff_mode(hdev, ev->status);
2447 break;
2448
2449 case HCI_OP_EXIT_SNIFF_MODE:
2450 hci_cs_exit_sniff_mode(hdev, ev->status);
2451 break;
2452
Johan Hedberg8962ee72011-01-20 12:40:27 +02002453 case HCI_OP_DISCONNECT:
Johan Hedberg88c3df12012-02-09 14:27:38 +02002454 hci_cs_disconnect(hdev, ev->status);
Johan Hedberg8962ee72011-01-20 12:40:27 +02002455 break;
2456
Ville Tervofcd89c02011-02-10 22:38:47 -03002457 case HCI_OP_LE_CREATE_CONN:
2458 hci_cs_le_create_conn(hdev, ev->status);
2459 break;
2460
Vinicius Costa Gomesa7a595f2011-06-09 18:50:47 -03002461 case HCI_OP_LE_START_ENC:
2462 hci_cs_le_start_enc(hdev, ev->status);
2463 break;
2464
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002465 default:
2466 BT_DBG("%s opcode 0x%x", hdev->name, opcode);
2467 break;
2468 }
2469
Ville Tervo6bd32322011-02-16 16:32:41 +02002470 if (ev->opcode != HCI_OP_NOP)
2471 del_timer(&hdev->cmd_timer);
2472
Gustavo F. Padovan10572132011-03-16 15:36:29 -03002473 if (ev->ncmd && !test_bit(HCI_RESET, &hdev->flags)) {
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002474 atomic_set(&hdev->cmd_cnt, 1);
2475 if (!skb_queue_empty(&hdev->cmd_q))
Gustavo F. Padovanc347b762011-12-14 23:53:47 -02002476 queue_work(hdev->workqueue, &hdev->cmd_work);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002477 }
2478}
2479
Gustavo Padovan807deac2012-05-17 00:36:24 -03002480static inline void hci_role_change_evt(struct hci_dev *hdev,
2481 struct sk_buff *skb)
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002482{
2483 struct hci_ev_role_change *ev = (void *) skb->data;
2484 struct hci_conn *conn;
2485
2486 BT_DBG("%s status %d", hdev->name, ev->status);
2487
2488 hci_dev_lock(hdev);
2489
2490 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
2491 if (conn) {
2492 if (!ev->status) {
2493 if (ev->role)
2494 conn->link_mode &= ~HCI_LM_MASTER;
2495 else
2496 conn->link_mode |= HCI_LM_MASTER;
2497 }
2498
Johan Hedberg51a8efd2012-01-16 06:10:31 +02002499 clear_bit(HCI_CONN_RSWITCH_PEND, &conn->flags);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002500
2501 hci_role_switch_cfm(conn, ev->status, ev->role);
2502 }
2503
2504 hci_dev_unlock(hdev);
2505}
2506
Gustavo Padovan807deac2012-05-17 00:36:24 -03002507static inline void hci_num_comp_pkts_evt(struct hci_dev *hdev,
2508 struct sk_buff *skb)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002509{
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002510 struct hci_ev_num_comp_pkts *ev = (void *) skb->data;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002511 int i;
2512
Andrei Emeltchenko32ac5b92011-12-19 16:31:29 +02002513 if (hdev->flow_ctl_mode != HCI_FLOW_CTL_MODE_PACKET_BASED) {
2514 BT_ERR("Wrong event for mode %d", hdev->flow_ctl_mode);
2515 return;
2516 }
2517
Andrei Emeltchenkoc5993de2011-12-30 12:07:47 +02002518 if (skb->len < sizeof(*ev) || skb->len < sizeof(*ev) +
Gustavo Padovan807deac2012-05-17 00:36:24 -03002519 ev->num_hndl * sizeof(struct hci_comp_pkts_info)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002520 BT_DBG("%s bad parameters", hdev->name);
2521 return;
2522 }
2523
Andrei Emeltchenkoc5993de2011-12-30 12:07:47 +02002524 BT_DBG("%s num_hndl %d", hdev->name, ev->num_hndl);
2525
Andrei Emeltchenko613a1c02011-12-19 16:31:30 +02002526 for (i = 0; i < ev->num_hndl; i++) {
2527 struct hci_comp_pkts_info *info = &ev->handles[i];
Linus Torvalds1da177e2005-04-16 15:20:36 -07002528 struct hci_conn *conn;
2529 __u16 handle, count;
2530
Andrei Emeltchenko613a1c02011-12-19 16:31:30 +02002531 handle = __le16_to_cpu(info->handle);
2532 count = __le16_to_cpu(info->count);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002533
2534 conn = hci_conn_hash_lookup_handle(hdev, handle);
Andrei Emeltchenkof4280912011-12-07 15:56:52 +02002535 if (!conn)
2536 continue;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002537
Andrei Emeltchenkof4280912011-12-07 15:56:52 +02002538 conn->sent -= count;
2539
2540 switch (conn->type) {
2541 case ACL_LINK:
2542 hdev->acl_cnt += count;
2543 if (hdev->acl_cnt > hdev->acl_pkts)
2544 hdev->acl_cnt = hdev->acl_pkts;
2545 break;
2546
2547 case LE_LINK:
2548 if (hdev->le_pkts) {
2549 hdev->le_cnt += count;
2550 if (hdev->le_cnt > hdev->le_pkts)
2551 hdev->le_cnt = hdev->le_pkts;
2552 } else {
Andrei Emeltchenko70f230202010-12-01 16:58:25 +02002553 hdev->acl_cnt += count;
2554 if (hdev->acl_cnt > hdev->acl_pkts)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002555 hdev->acl_cnt = hdev->acl_pkts;
2556 }
Andrei Emeltchenkof4280912011-12-07 15:56:52 +02002557 break;
2558
2559 case SCO_LINK:
2560 hdev->sco_cnt += count;
2561 if (hdev->sco_cnt > hdev->sco_pkts)
2562 hdev->sco_cnt = hdev->sco_pkts;
2563 break;
2564
2565 default:
2566 BT_ERR("Unknown type %d conn %p", conn->type, conn);
2567 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002568 }
2569 }
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002570
Gustavo F. Padovan3eff45e2011-12-15 00:50:02 -02002571 queue_work(hdev->workqueue, &hdev->tx_work);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002572}
2573
Andrei Emeltchenko25e89e92012-01-04 12:41:58 +02002574static inline void hci_num_comp_blocks_evt(struct hci_dev *hdev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002575 struct sk_buff *skb)
Andrei Emeltchenko25e89e92012-01-04 12:41:58 +02002576{
2577 struct hci_ev_num_comp_blocks *ev = (void *) skb->data;
2578 int i;
2579
2580 if (hdev->flow_ctl_mode != HCI_FLOW_CTL_MODE_BLOCK_BASED) {
2581 BT_ERR("Wrong event for mode %d", hdev->flow_ctl_mode);
2582 return;
2583 }
2584
2585 if (skb->len < sizeof(*ev) || skb->len < sizeof(*ev) +
Gustavo Padovan807deac2012-05-17 00:36:24 -03002586 ev->num_hndl * sizeof(struct hci_comp_blocks_info)) {
Andrei Emeltchenko25e89e92012-01-04 12:41:58 +02002587 BT_DBG("%s bad parameters", hdev->name);
2588 return;
2589 }
2590
2591 BT_DBG("%s num_blocks %d num_hndl %d", hdev->name, ev->num_blocks,
Gustavo Padovan807deac2012-05-17 00:36:24 -03002592 ev->num_hndl);
Andrei Emeltchenko25e89e92012-01-04 12:41:58 +02002593
2594 for (i = 0; i < ev->num_hndl; i++) {
2595 struct hci_comp_blocks_info *info = &ev->handles[i];
2596 struct hci_conn *conn;
2597 __u16 handle, block_count;
2598
2599 handle = __le16_to_cpu(info->handle);
2600 block_count = __le16_to_cpu(info->blocks);
2601
2602 conn = hci_conn_hash_lookup_handle(hdev, handle);
2603 if (!conn)
2604 continue;
2605
2606 conn->sent -= block_count;
2607
2608 switch (conn->type) {
2609 case ACL_LINK:
2610 hdev->block_cnt += block_count;
2611 if (hdev->block_cnt > hdev->num_blocks)
2612 hdev->block_cnt = hdev->num_blocks;
2613 break;
2614
2615 default:
2616 BT_ERR("Unknown type %d conn %p", conn->type, conn);
2617 break;
2618 }
2619 }
2620
2621 queue_work(hdev->workqueue, &hdev->tx_work);
2622}
2623
Gustavo Padovan807deac2012-05-17 00:36:24 -03002624static inline void hci_mode_change_evt(struct hci_dev *hdev,
2625 struct sk_buff *skb)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002626{
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002627 struct hci_ev_mode_change *ev = (void *) skb->data;
Marcel Holtmann04837f62006-07-03 10:02:33 +02002628 struct hci_conn *conn;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002629
2630 BT_DBG("%s status %d", hdev->name, ev->status);
2631
2632 hci_dev_lock(hdev);
2633
Marcel Holtmann04837f62006-07-03 10:02:33 +02002634 conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
2635 if (conn) {
2636 conn->mode = ev->mode;
2637 conn->interval = __le16_to_cpu(ev->interval);
2638
Johan Hedberg51a8efd2012-01-16 06:10:31 +02002639 if (!test_and_clear_bit(HCI_CONN_MODE_CHANGE_PEND, &conn->flags)) {
Marcel Holtmann04837f62006-07-03 10:02:33 +02002640 if (conn->mode == HCI_CM_ACTIVE)
Johan Hedberg58a681e2012-01-16 06:47:28 +02002641 set_bit(HCI_CONN_POWER_SAVE, &conn->flags);
Marcel Holtmann04837f62006-07-03 10:02:33 +02002642 else
Johan Hedberg58a681e2012-01-16 06:47:28 +02002643 clear_bit(HCI_CONN_POWER_SAVE, &conn->flags);
Marcel Holtmann04837f62006-07-03 10:02:33 +02002644 }
Marcel Holtmanne73439d2010-07-26 10:06:00 -04002645
Johan Hedberg51a8efd2012-01-16 06:10:31 +02002646 if (test_and_clear_bit(HCI_CONN_SCO_SETUP_PEND, &conn->flags))
Marcel Holtmanne73439d2010-07-26 10:06:00 -04002647 hci_sco_setup(conn, ev->status);
Marcel Holtmann04837f62006-07-03 10:02:33 +02002648 }
2649
2650 hci_dev_unlock(hdev);
2651}
2652
Gustavo Padovan807deac2012-05-17 00:36:24 -03002653static inline void hci_pin_code_request_evt(struct hci_dev *hdev,
2654 struct sk_buff *skb)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002655{
Marcel Holtmann052b30b2009-04-26 20:01:22 +02002656 struct hci_ev_pin_code_req *ev = (void *) skb->data;
2657 struct hci_conn *conn;
2658
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002659 BT_DBG("%s", hdev->name);
Marcel Holtmann052b30b2009-04-26 20:01:22 +02002660
2661 hci_dev_lock(hdev);
2662
2663 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
Waldemar Rymarkiewiczb6f98042011-09-23 10:01:30 +02002664 if (!conn)
2665 goto unlock;
2666
2667 if (conn->state == BT_CONNECTED) {
Marcel Holtmann052b30b2009-04-26 20:01:22 +02002668 hci_conn_hold(conn);
2669 conn->disc_timeout = HCI_PAIRING_TIMEOUT;
2670 hci_conn_put(conn);
2671 }
2672
Johan Hedberga8b2d5c2012-01-08 23:11:15 +02002673 if (!test_bit(HCI_PAIRABLE, &hdev->dev_flags))
Johan Hedberg03b555e2011-01-04 15:40:05 +02002674 hci_send_cmd(hdev, HCI_OP_PIN_CODE_NEG_REPLY,
Gustavo Padovan807deac2012-05-17 00:36:24 -03002675 sizeof(ev->bdaddr), &ev->bdaddr);
Johan Hedberga8b2d5c2012-01-08 23:11:15 +02002676 else if (test_bit(HCI_MGMT, &hdev->dev_flags)) {
Waldemar Rymarkiewicza770bb52011-04-28 12:07:59 +02002677 u8 secure;
2678
2679 if (conn->pending_sec_level == BT_SECURITY_HIGH)
2680 secure = 1;
2681 else
2682 secure = 0;
2683
Johan Hedberg744cf192011-11-08 20:40:14 +02002684 mgmt_pin_code_request(hdev, &ev->bdaddr, secure);
Waldemar Rymarkiewicza770bb52011-04-28 12:07:59 +02002685 }
Johan Hedberg980e1a52011-01-22 06:10:07 +02002686
Waldemar Rymarkiewiczb6f98042011-09-23 10:01:30 +02002687unlock:
Marcel Holtmann052b30b2009-04-26 20:01:22 +02002688 hci_dev_unlock(hdev);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002689}
2690
Gustavo Padovan807deac2012-05-17 00:36:24 -03002691static inline void hci_link_key_request_evt(struct hci_dev *hdev,
2692 struct sk_buff *skb)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002693{
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002694 struct hci_ev_link_key_req *ev = (void *) skb->data;
2695 struct hci_cp_link_key_reply cp;
2696 struct hci_conn *conn;
2697 struct link_key *key;
2698
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002699 BT_DBG("%s", hdev->name);
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002700
Johan Hedberga8b2d5c2012-01-08 23:11:15 +02002701 if (!test_bit(HCI_LINK_KEYS, &hdev->dev_flags))
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002702 return;
2703
2704 hci_dev_lock(hdev);
2705
2706 key = hci_find_link_key(hdev, &ev->bdaddr);
2707 if (!key) {
2708 BT_DBG("%s link key not found for %s", hdev->name,
Gustavo Padovan807deac2012-05-17 00:36:24 -03002709 batostr(&ev->bdaddr));
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002710 goto not_found;
2711 }
2712
2713 BT_DBG("%s found key type %u for %s", hdev->name, key->type,
Gustavo Padovan807deac2012-05-17 00:36:24 -03002714 batostr(&ev->bdaddr));
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002715
Johan Hedberga8b2d5c2012-01-08 23:11:15 +02002716 if (!test_bit(HCI_DEBUG_KEYS, &hdev->dev_flags) &&
Gustavo Padovan807deac2012-05-17 00:36:24 -03002717 key->type == HCI_LK_DEBUG_COMBINATION) {
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002718 BT_DBG("%s ignoring debug key", hdev->name);
2719 goto not_found;
2720 }
2721
2722 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
Waldemar Rymarkiewicz60b83f52011-04-28 12:07:56 +02002723 if (conn) {
2724 if (key->type == HCI_LK_UNAUTH_COMBINATION &&
Gustavo Padovan807deac2012-05-17 00:36:24 -03002725 conn->auth_type != 0xff && (conn->auth_type & 0x01)) {
Waldemar Rymarkiewicz60b83f52011-04-28 12:07:56 +02002726 BT_DBG("%s ignoring unauthenticated key", hdev->name);
2727 goto not_found;
2728 }
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002729
Waldemar Rymarkiewicz60b83f52011-04-28 12:07:56 +02002730 if (key->type == HCI_LK_COMBINATION && key->pin_len < 16 &&
Gustavo Padovan807deac2012-05-17 00:36:24 -03002731 conn->pending_sec_level == BT_SECURITY_HIGH) {
Waldemar Rymarkiewicz60b83f52011-04-28 12:07:56 +02002732 BT_DBG("%s ignoring key unauthenticated for high \
Gustavo Padovan807deac2012-05-17 00:36:24 -03002733 security", hdev->name);
Waldemar Rymarkiewicz60b83f52011-04-28 12:07:56 +02002734 goto not_found;
2735 }
2736
2737 conn->key_type = key->type;
2738 conn->pin_length = key->pin_len;
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002739 }
2740
2741 bacpy(&cp.bdaddr, &ev->bdaddr);
Andrei Emeltchenko9b3b4462012-05-23 11:31:20 +03002742 memcpy(cp.link_key, key->val, HCI_LINK_KEY_SIZE);
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002743
2744 hci_send_cmd(hdev, HCI_OP_LINK_KEY_REPLY, sizeof(cp), &cp);
2745
2746 hci_dev_unlock(hdev);
2747
2748 return;
2749
2750not_found:
2751 hci_send_cmd(hdev, HCI_OP_LINK_KEY_NEG_REPLY, 6, &ev->bdaddr);
2752 hci_dev_unlock(hdev);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002753}
2754
Gustavo Padovan807deac2012-05-17 00:36:24 -03002755static inline void hci_link_key_notify_evt(struct hci_dev *hdev,
2756 struct sk_buff *skb)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002757{
Marcel Holtmann052b30b2009-04-26 20:01:22 +02002758 struct hci_ev_link_key_notify *ev = (void *) skb->data;
2759 struct hci_conn *conn;
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002760 u8 pin_len = 0;
Marcel Holtmann052b30b2009-04-26 20:01:22 +02002761
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002762 BT_DBG("%s", hdev->name);
Marcel Holtmann052b30b2009-04-26 20:01:22 +02002763
2764 hci_dev_lock(hdev);
2765
2766 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
2767 if (conn) {
2768 hci_conn_hold(conn);
2769 conn->disc_timeout = HCI_DISCONN_TIMEOUT;
Johan Hedberg980e1a52011-01-22 06:10:07 +02002770 pin_len = conn->pin_length;
Waldemar Rymarkiewicz13d39312011-04-28 12:07:55 +02002771
2772 if (ev->key_type != HCI_LK_CHANGED_COMBINATION)
2773 conn->key_type = ev->key_type;
2774
Marcel Holtmann052b30b2009-04-26 20:01:22 +02002775 hci_conn_put(conn);
2776 }
2777
Johan Hedberga8b2d5c2012-01-08 23:11:15 +02002778 if (test_bit(HCI_LINK_KEYS, &hdev->dev_flags))
Johan Hedbergd25e28a2011-04-28 11:28:59 -07002779 hci_add_link_key(hdev, conn, 1, &ev->bdaddr, ev->link_key,
Gustavo Padovan807deac2012-05-17 00:36:24 -03002780 ev->key_type, pin_len);
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002781
Marcel Holtmann052b30b2009-04-26 20:01:22 +02002782 hci_dev_unlock(hdev);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002783}
2784
Gustavo Padovan807deac2012-05-17 00:36:24 -03002785static inline void hci_clock_offset_evt(struct hci_dev *hdev,
2786 struct sk_buff *skb)
Marcel Holtmann04837f62006-07-03 10:02:33 +02002787{
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002788 struct hci_ev_clock_offset *ev = (void *) skb->data;
Marcel Holtmann04837f62006-07-03 10:02:33 +02002789 struct hci_conn *conn;
2790
2791 BT_DBG("%s status %d", hdev->name, ev->status);
2792
2793 hci_dev_lock(hdev);
2794
2795 conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
Linus Torvalds1da177e2005-04-16 15:20:36 -07002796 if (conn && !ev->status) {
2797 struct inquiry_entry *ie;
2798
Andrei Emeltchenkocc11b9c2010-11-22 13:21:37 +02002799 ie = hci_inquiry_cache_lookup(hdev, &conn->dst);
2800 if (ie) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002801 ie->data.clock_offset = ev->clock_offset;
2802 ie->timestamp = jiffies;
2803 }
2804 }
2805
2806 hci_dev_unlock(hdev);
2807}
2808
Gustavo Padovan807deac2012-05-17 00:36:24 -03002809static inline void hci_pkt_type_change_evt(struct hci_dev *hdev,
2810 struct sk_buff *skb)
Marcel Holtmanna8746412008-07-14 20:13:46 +02002811{
2812 struct hci_ev_pkt_type_change *ev = (void *) skb->data;
2813 struct hci_conn *conn;
2814
2815 BT_DBG("%s status %d", hdev->name, ev->status);
2816
2817 hci_dev_lock(hdev);
2818
2819 conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
2820 if (conn && !ev->status)
2821 conn->pkt_type = __le16_to_cpu(ev->pkt_type);
2822
2823 hci_dev_unlock(hdev);
2824}
2825
Gustavo Padovan807deac2012-05-17 00:36:24 -03002826static inline void hci_pscan_rep_mode_evt(struct hci_dev *hdev,
2827 struct sk_buff *skb)
Marcel Holtmann85a1e932005-08-09 20:28:02 -07002828{
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002829 struct hci_ev_pscan_rep_mode *ev = (void *) skb->data;
Marcel Holtmann85a1e932005-08-09 20:28:02 -07002830 struct inquiry_entry *ie;
2831
2832 BT_DBG("%s", hdev->name);
2833
2834 hci_dev_lock(hdev);
2835
Andrei Emeltchenkocc11b9c2010-11-22 13:21:37 +02002836 ie = hci_inquiry_cache_lookup(hdev, &ev->bdaddr);
2837 if (ie) {
Marcel Holtmann85a1e932005-08-09 20:28:02 -07002838 ie->data.pscan_rep_mode = ev->pscan_rep_mode;
2839 ie->timestamp = jiffies;
2840 }
2841
2842 hci_dev_unlock(hdev);
2843}
2844
Gustavo Padovan807deac2012-05-17 00:36:24 -03002845static inline void hci_inquiry_result_with_rssi_evt(struct hci_dev *hdev,
2846 struct sk_buff *skb)
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002847{
2848 struct inquiry_data data;
2849 int num_rsp = *((__u8 *) skb->data);
Johan Hedberg388fc8f2012-02-23 00:38:59 +02002850 bool name_known, ssp;
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002851
2852 BT_DBG("%s num_rsp %d", hdev->name, num_rsp);
2853
2854 if (!num_rsp)
2855 return;
2856
Andre Guedes1519cc12012-03-21 00:03:38 -03002857 if (test_bit(HCI_PERIODIC_INQ, &hdev->dev_flags))
2858 return;
2859
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002860 hci_dev_lock(hdev);
2861
2862 if ((skb->len - 1) / num_rsp != sizeof(struct inquiry_info_with_rssi)) {
Szymon Janc138d22e2011-02-17 16:44:23 +01002863 struct inquiry_info_with_rssi_and_pscan_mode *info;
2864 info = (void *) (skb->data + 1);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002865
Johan Hedberge17acd42011-03-30 23:57:16 +03002866 for (; num_rsp; num_rsp--, info++) {
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002867 bacpy(&data.bdaddr, &info->bdaddr);
2868 data.pscan_rep_mode = info->pscan_rep_mode;
2869 data.pscan_period_mode = info->pscan_period_mode;
2870 data.pscan_mode = info->pscan_mode;
2871 memcpy(data.dev_class, info->dev_class, 3);
2872 data.clock_offset = info->clock_offset;
2873 data.rssi = info->rssi;
Marcel Holtmann41a96212008-07-14 20:13:48 +02002874 data.ssp_mode = 0x00;
Johan Hedberg31754052012-01-04 13:39:52 +02002875
2876 name_known = hci_inquiry_cache_update(hdev, &data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002877 false, &ssp);
Johan Hedberg48264f02011-11-09 13:58:58 +02002878 mgmt_device_found(hdev, &info->bdaddr, ACL_LINK, 0x00,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002879 info->dev_class, info->rssi,
2880 !name_known, ssp, NULL, 0);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002881 }
2882 } else {
2883 struct inquiry_info_with_rssi *info = (void *) (skb->data + 1);
2884
Johan Hedberge17acd42011-03-30 23:57:16 +03002885 for (; num_rsp; num_rsp--, info++) {
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002886 bacpy(&data.bdaddr, &info->bdaddr);
2887 data.pscan_rep_mode = info->pscan_rep_mode;
2888 data.pscan_period_mode = info->pscan_period_mode;
2889 data.pscan_mode = 0x00;
2890 memcpy(data.dev_class, info->dev_class, 3);
2891 data.clock_offset = info->clock_offset;
2892 data.rssi = info->rssi;
Marcel Holtmann41a96212008-07-14 20:13:48 +02002893 data.ssp_mode = 0x00;
Johan Hedberg31754052012-01-04 13:39:52 +02002894 name_known = hci_inquiry_cache_update(hdev, &data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002895 false, &ssp);
Johan Hedberg48264f02011-11-09 13:58:58 +02002896 mgmt_device_found(hdev, &info->bdaddr, ACL_LINK, 0x00,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002897 info->dev_class, info->rssi,
2898 !name_known, ssp, NULL, 0);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002899 }
2900 }
2901
2902 hci_dev_unlock(hdev);
2903}
2904
Gustavo Padovan807deac2012-05-17 00:36:24 -03002905static inline void hci_remote_ext_features_evt(struct hci_dev *hdev,
2906 struct sk_buff *skb)
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002907{
Marcel Holtmann41a96212008-07-14 20:13:48 +02002908 struct hci_ev_remote_ext_features *ev = (void *) skb->data;
2909 struct hci_conn *conn;
2910
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002911 BT_DBG("%s", hdev->name);
Marcel Holtmann41a96212008-07-14 20:13:48 +02002912
Marcel Holtmann41a96212008-07-14 20:13:48 +02002913 hci_dev_lock(hdev);
2914
2915 conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
Johan Hedbergccd556f2010-11-10 17:11:51 +02002916 if (!conn)
2917 goto unlock;
Marcel Holtmann41a96212008-07-14 20:13:48 +02002918
Johan Hedbergccd556f2010-11-10 17:11:51 +02002919 if (!ev->status && ev->page == 0x01) {
2920 struct inquiry_entry *ie;
Marcel Holtmann41a96212008-07-14 20:13:48 +02002921
Andrei Emeltchenkocc11b9c2010-11-22 13:21:37 +02002922 ie = hci_inquiry_cache_lookup(hdev, &conn->dst);
2923 if (ie)
Johan Hedberg02b7cc62012-02-28 02:28:43 +02002924 ie->data.ssp_mode = (ev->features[0] & LMP_HOST_SSP);
Marcel Holtmann769be972008-07-14 20:13:49 +02002925
Johan Hedberg02b7cc62012-02-28 02:28:43 +02002926 if (ev->features[0] & LMP_HOST_SSP)
Johan Hedberg58a681e2012-01-16 06:47:28 +02002927 set_bit(HCI_CONN_SSP_ENABLED, &conn->flags);
Marcel Holtmann41a96212008-07-14 20:13:48 +02002928 }
2929
Johan Hedbergccd556f2010-11-10 17:11:51 +02002930 if (conn->state != BT_CONFIG)
2931 goto unlock;
2932
Johan Hedberg671267b2012-05-12 16:11:50 -03002933 if (!ev->status && !test_bit(HCI_CONN_MGMT_CONNECTED, &conn->flags)) {
Johan Hedberg127178d2010-11-18 22:22:29 +02002934 struct hci_cp_remote_name_req cp;
2935 memset(&cp, 0, sizeof(cp));
2936 bacpy(&cp.bdaddr, &conn->dst);
2937 cp.pscan_rep_mode = 0x02;
2938 hci_send_cmd(hdev, HCI_OP_REMOTE_NAME_REQ, sizeof(cp), &cp);
Johan Hedbergb644ba32012-01-17 21:48:47 +02002939 } else if (!test_and_set_bit(HCI_CONN_MGMT_CONNECTED, &conn->flags))
2940 mgmt_device_connected(hdev, &conn->dst, conn->type,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002941 conn->dst_type, 0, NULL, 0,
2942 conn->dev_class);
Johan Hedberg392599b2010-11-18 22:22:28 +02002943
Johan Hedberg127178d2010-11-18 22:22:29 +02002944 if (!hci_outgoing_auth_needed(hdev, conn)) {
Johan Hedbergccd556f2010-11-10 17:11:51 +02002945 conn->state = BT_CONNECTED;
2946 hci_proto_connect_cfm(conn, ev->status);
2947 hci_conn_put(conn);
2948 }
2949
2950unlock:
Marcel Holtmann41a96212008-07-14 20:13:48 +02002951 hci_dev_unlock(hdev);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002952}
2953
Gustavo Padovan807deac2012-05-17 00:36:24 -03002954static inline void hci_sync_conn_complete_evt(struct hci_dev *hdev,
2955 struct sk_buff *skb)
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002956{
Marcel Holtmannb6a0dc82007-10-20 14:55:10 +02002957 struct hci_ev_sync_conn_complete *ev = (void *) skb->data;
2958 struct hci_conn *conn;
2959
2960 BT_DBG("%s status %d", hdev->name, ev->status);
2961
2962 hci_dev_lock(hdev);
2963
2964 conn = hci_conn_hash_lookup_ba(hdev, ev->link_type, &ev->bdaddr);
Marcel Holtmann9dc0a3a2008-07-14 20:13:46 +02002965 if (!conn) {
2966 if (ev->link_type == ESCO_LINK)
2967 goto unlock;
2968
2969 conn = hci_conn_hash_lookup_ba(hdev, ESCO_LINK, &ev->bdaddr);
2970 if (!conn)
2971 goto unlock;
2972
2973 conn->type = SCO_LINK;
2974 }
Marcel Holtmannb6a0dc82007-10-20 14:55:10 +02002975
Marcel Holtmann732547f2009-04-19 19:14:14 +02002976 switch (ev->status) {
2977 case 0x00:
Marcel Holtmannb6a0dc82007-10-20 14:55:10 +02002978 conn->handle = __le16_to_cpu(ev->handle);
2979 conn->state = BT_CONNECTED;
Marcel Holtmann7d0db0a2008-07-14 20:13:51 +02002980
Marcel Holtmann9eba32b2009-08-22 14:19:26 -07002981 hci_conn_hold_device(conn);
Marcel Holtmann7d0db0a2008-07-14 20:13:51 +02002982 hci_conn_add_sysfs(conn);
Marcel Holtmann732547f2009-04-19 19:14:14 +02002983 break;
2984
Stephen Coe705e5712010-02-16 11:29:44 -05002985 case 0x11: /* Unsupported Feature or Parameter Value */
Marcel Holtmann732547f2009-04-19 19:14:14 +02002986 case 0x1c: /* SCO interval rejected */
Nick Pelly1038a002010-02-03 11:42:26 -08002987 case 0x1a: /* Unsupported Remote Feature */
Marcel Holtmann732547f2009-04-19 19:14:14 +02002988 case 0x1f: /* Unspecified error */
2989 if (conn->out && conn->attempt < 2) {
2990 conn->pkt_type = (hdev->esco_type & SCO_ESCO_MASK) |
2991 (hdev->esco_type & EDR_ESCO_MASK);
2992 hci_setup_sync(conn, conn->link->handle);
2993 goto unlock;
2994 }
2995 /* fall through */
2996
2997 default:
Marcel Holtmannb6a0dc82007-10-20 14:55:10 +02002998 conn->state = BT_CLOSED;
Marcel Holtmann732547f2009-04-19 19:14:14 +02002999 break;
3000 }
Marcel Holtmannb6a0dc82007-10-20 14:55:10 +02003001
3002 hci_proto_connect_cfm(conn, ev->status);
3003 if (ev->status)
3004 hci_conn_del(conn);
3005
3006unlock:
3007 hci_dev_unlock(hdev);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02003008}
3009
Gustavo Padovan807deac2012-05-17 00:36:24 -03003010static inline void hci_sync_conn_changed_evt(struct hci_dev *hdev,
3011 struct sk_buff *skb)
Marcel Holtmanna9de9242007-10-20 13:33:56 +02003012{
3013 BT_DBG("%s", hdev->name);
3014}
3015
Gustavo Padovan807deac2012-05-17 00:36:24 -03003016static inline void hci_sniff_subrate_evt(struct hci_dev *hdev,
3017 struct sk_buff *skb)
Marcel Holtmann04837f62006-07-03 10:02:33 +02003018{
Marcel Holtmanna9de9242007-10-20 13:33:56 +02003019 struct hci_ev_sniff_subrate *ev = (void *) skb->data;
Marcel Holtmann04837f62006-07-03 10:02:33 +02003020
3021 BT_DBG("%s status %d", hdev->name, ev->status);
Marcel Holtmann04837f62006-07-03 10:02:33 +02003022}
3023
Gustavo Padovan807deac2012-05-17 00:36:24 -03003024static inline void hci_extended_inquiry_result_evt(struct hci_dev *hdev,
3025 struct sk_buff *skb)
Marcel Holtmanna9de9242007-10-20 13:33:56 +02003026{
3027 struct inquiry_data data;
3028 struct extended_inquiry_info *info = (void *) (skb->data + 1);
3029 int num_rsp = *((__u8 *) skb->data);
Vishal Agarwal9d939d92012-04-26 19:19:56 +05303030 size_t eir_len;
Marcel Holtmanna9de9242007-10-20 13:33:56 +02003031
3032 BT_DBG("%s num_rsp %d", hdev->name, num_rsp);
3033
3034 if (!num_rsp)
3035 return;
3036
Andre Guedes1519cc12012-03-21 00:03:38 -03003037 if (test_bit(HCI_PERIODIC_INQ, &hdev->dev_flags))
3038 return;
3039
Marcel Holtmanna9de9242007-10-20 13:33:56 +02003040 hci_dev_lock(hdev);
3041
Johan Hedberge17acd42011-03-30 23:57:16 +03003042 for (; num_rsp; num_rsp--, info++) {
Johan Hedberg388fc8f2012-02-23 00:38:59 +02003043 bool name_known, ssp;
Johan Hedberg561aafb2012-01-04 13:31:59 +02003044
Marcel Holtmanna9de9242007-10-20 13:33:56 +02003045 bacpy(&data.bdaddr, &info->bdaddr);
Szymon Janc138d22e2011-02-17 16:44:23 +01003046 data.pscan_rep_mode = info->pscan_rep_mode;
3047 data.pscan_period_mode = info->pscan_period_mode;
3048 data.pscan_mode = 0x00;
Marcel Holtmanna9de9242007-10-20 13:33:56 +02003049 memcpy(data.dev_class, info->dev_class, 3);
Szymon Janc138d22e2011-02-17 16:44:23 +01003050 data.clock_offset = info->clock_offset;
3051 data.rssi = info->rssi;
Marcel Holtmann41a96212008-07-14 20:13:48 +02003052 data.ssp_mode = 0x01;
Johan Hedberg561aafb2012-01-04 13:31:59 +02003053
Johan Hedberga8b2d5c2012-01-08 23:11:15 +02003054 if (test_bit(HCI_MGMT, &hdev->dev_flags))
Johan Hedberg4ddb1932012-01-15 20:04:43 +02003055 name_known = eir_has_data_type(info->data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003056 sizeof(info->data),
3057 EIR_NAME_COMPLETE);
Johan Hedberg561aafb2012-01-04 13:31:59 +02003058 else
3059 name_known = true;
3060
Johan Hedberg388fc8f2012-02-23 00:38:59 +02003061 name_known = hci_inquiry_cache_update(hdev, &data, name_known,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003062 &ssp);
Vishal Agarwal9d939d92012-04-26 19:19:56 +05303063 eir_len = eir_get_length(info->data, sizeof(info->data));
Johan Hedberg48264f02011-11-09 13:58:58 +02003064 mgmt_device_found(hdev, &info->bdaddr, ACL_LINK, 0x00,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003065 info->dev_class, info->rssi, !name_known,
Vishal Agarwal9d939d92012-04-26 19:19:56 +05303066 ssp, info->data, eir_len);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02003067 }
3068
3069 hci_dev_unlock(hdev);
3070}
3071
Johan Hedberg17fa4b92011-01-25 13:28:33 +02003072static inline u8 hci_get_auth_req(struct hci_conn *conn)
3073{
3074 /* If remote requests dedicated bonding follow that lead */
3075 if (conn->remote_auth == 0x02 || conn->remote_auth == 0x03) {
3076 /* If both remote and local IO capabilities allow MITM
3077 * protection then require it, otherwise don't */
3078 if (conn->remote_cap == 0x03 || conn->io_capability == 0x03)
3079 return 0x02;
3080 else
3081 return 0x03;
3082 }
3083
3084 /* If remote requests no-bonding follow that lead */
3085 if (conn->remote_auth == 0x00 || conn->remote_auth == 0x01)
Waldemar Rymarkiewicz58797bf2011-04-28 12:07:58 +02003086 return conn->remote_auth | (conn->auth_type & 0x01);
Johan Hedberg17fa4b92011-01-25 13:28:33 +02003087
3088 return conn->auth_type;
3089}
3090
Gustavo Padovan807deac2012-05-17 00:36:24 -03003091static inline void hci_io_capa_request_evt(struct hci_dev *hdev,
3092 struct sk_buff *skb)
Marcel Holtmann04936842008-07-14 20:13:48 +02003093{
3094 struct hci_ev_io_capa_request *ev = (void *) skb->data;
3095 struct hci_conn *conn;
3096
3097 BT_DBG("%s", hdev->name);
3098
3099 hci_dev_lock(hdev);
3100
3101 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
Johan Hedberg03b555e2011-01-04 15:40:05 +02003102 if (!conn)
3103 goto unlock;
Marcel Holtmann04936842008-07-14 20:13:48 +02003104
Johan Hedberg03b555e2011-01-04 15:40:05 +02003105 hci_conn_hold(conn);
3106
Johan Hedberga8b2d5c2012-01-08 23:11:15 +02003107 if (!test_bit(HCI_MGMT, &hdev->dev_flags))
Johan Hedberg03b555e2011-01-04 15:40:05 +02003108 goto unlock;
3109
Johan Hedberga8b2d5c2012-01-08 23:11:15 +02003110 if (test_bit(HCI_PAIRABLE, &hdev->dev_flags) ||
Gustavo Padovan807deac2012-05-17 00:36:24 -03003111 (conn->remote_auth & ~0x01) == HCI_AT_NO_BONDING) {
Johan Hedberg17fa4b92011-01-25 13:28:33 +02003112 struct hci_cp_io_capability_reply cp;
3113
3114 bacpy(&cp.bdaddr, &ev->bdaddr);
Hemant Gupta7a7f1e72012-01-16 13:34:29 +05303115 /* Change the IO capability from KeyboardDisplay
3116 * to DisplayYesNo as it is not supported by BT spec. */
3117 cp.capability = (conn->io_capability == 0x04) ?
3118 0x01 : conn->io_capability;
Johan Hedberg7cbc9bd2011-04-28 11:29:04 -07003119 conn->auth_type = hci_get_auth_req(conn);
3120 cp.authentication = conn->auth_type;
Johan Hedberg17fa4b92011-01-25 13:28:33 +02003121
Johan Hedberg58a681e2012-01-16 06:47:28 +02003122 if ((conn->out || test_bit(HCI_CONN_REMOTE_OOB, &conn->flags)) &&
Gustavo Padovan807deac2012-05-17 00:36:24 -03003123 hci_find_remote_oob_data(hdev, &conn->dst))
Szymon Jancce85ee12011-03-22 13:12:23 +01003124 cp.oob_data = 0x01;
3125 else
3126 cp.oob_data = 0x00;
3127
Johan Hedberg17fa4b92011-01-25 13:28:33 +02003128 hci_send_cmd(hdev, HCI_OP_IO_CAPABILITY_REPLY,
Gustavo Padovan807deac2012-05-17 00:36:24 -03003129 sizeof(cp), &cp);
Johan Hedberg03b555e2011-01-04 15:40:05 +02003130 } else {
3131 struct hci_cp_io_capability_neg_reply cp;
3132
3133 bacpy(&cp.bdaddr, &ev->bdaddr);
Andrei Emeltchenko9f5a0d72011-11-07 14:20:25 +02003134 cp.reason = HCI_ERROR_PAIRING_NOT_ALLOWED;
Johan Hedberg03b555e2011-01-04 15:40:05 +02003135
3136 hci_send_cmd(hdev, HCI_OP_IO_CAPABILITY_NEG_REPLY,
Gustavo Padovan807deac2012-05-17 00:36:24 -03003137 sizeof(cp), &cp);
Johan Hedberg03b555e2011-01-04 15:40:05 +02003138 }
3139
3140unlock:
3141 hci_dev_unlock(hdev);
3142}
3143
Gustavo Padovan807deac2012-05-17 00:36:24 -03003144static inline void hci_io_capa_reply_evt(struct hci_dev *hdev,
3145 struct sk_buff *skb)
Johan Hedberg03b555e2011-01-04 15:40:05 +02003146{
3147 struct hci_ev_io_capa_reply *ev = (void *) skb->data;
3148 struct hci_conn *conn;
3149
3150 BT_DBG("%s", hdev->name);
3151
3152 hci_dev_lock(hdev);
3153
3154 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
3155 if (!conn)
3156 goto unlock;
3157
Johan Hedberg03b555e2011-01-04 15:40:05 +02003158 conn->remote_cap = ev->capability;
Johan Hedberg03b555e2011-01-04 15:40:05 +02003159 conn->remote_auth = ev->authentication;
Johan Hedberg58a681e2012-01-16 06:47:28 +02003160 if (ev->oob_data)
3161 set_bit(HCI_CONN_REMOTE_OOB, &conn->flags);
Johan Hedberg03b555e2011-01-04 15:40:05 +02003162
3163unlock:
Marcel Holtmann04936842008-07-14 20:13:48 +02003164 hci_dev_unlock(hdev);
3165}
3166
Johan Hedberga5c29682011-02-19 12:05:57 -03003167static inline void hci_user_confirm_request_evt(struct hci_dev *hdev,
Gustavo Padovan807deac2012-05-17 00:36:24 -03003168 struct sk_buff *skb)
Johan Hedberga5c29682011-02-19 12:05:57 -03003169{
3170 struct hci_ev_user_confirm_req *ev = (void *) skb->data;
Johan Hedberg55bc1a32011-04-28 11:28:56 -07003171 int loc_mitm, rem_mitm, confirm_hint = 0;
Johan Hedberg7a828902011-04-28 11:28:53 -07003172 struct hci_conn *conn;
Johan Hedberga5c29682011-02-19 12:05:57 -03003173
3174 BT_DBG("%s", hdev->name);
3175
3176 hci_dev_lock(hdev);
3177
Johan Hedberga8b2d5c2012-01-08 23:11:15 +02003178 if (!test_bit(HCI_MGMT, &hdev->dev_flags))
Johan Hedberg7a828902011-04-28 11:28:53 -07003179 goto unlock;
Johan Hedberga5c29682011-02-19 12:05:57 -03003180
Johan Hedberg7a828902011-04-28 11:28:53 -07003181 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
3182 if (!conn)
3183 goto unlock;
3184
3185 loc_mitm = (conn->auth_type & 0x01);
3186 rem_mitm = (conn->remote_auth & 0x01);
3187
3188 /* If we require MITM but the remote device can't provide that
3189 * (it has NoInputNoOutput) then reject the confirmation
3190 * request. The only exception is when we're dedicated bonding
3191 * initiators (connect_cfm_cb set) since then we always have the MITM
3192 * bit set. */
3193 if (!conn->connect_cfm_cb && loc_mitm && conn->remote_cap == 0x03) {
3194 BT_DBG("Rejecting request: remote device can't provide MITM");
3195 hci_send_cmd(hdev, HCI_OP_USER_CONFIRM_NEG_REPLY,
Gustavo Padovan807deac2012-05-17 00:36:24 -03003196 sizeof(ev->bdaddr), &ev->bdaddr);
Johan Hedberg7a828902011-04-28 11:28:53 -07003197 goto unlock;
3198 }
3199
3200 /* If no side requires MITM protection; auto-accept */
3201 if ((!loc_mitm || conn->remote_cap == 0x03) &&
Gustavo Padovan807deac2012-05-17 00:36:24 -03003202 (!rem_mitm || conn->io_capability == 0x03)) {
Johan Hedberg55bc1a32011-04-28 11:28:56 -07003203
3204 /* If we're not the initiators request authorization to
3205 * proceed from user space (mgmt_user_confirm with
3206 * confirm_hint set to 1). */
Johan Hedberg51a8efd2012-01-16 06:10:31 +02003207 if (!test_bit(HCI_CONN_AUTH_PEND, &conn->flags)) {
Johan Hedberg55bc1a32011-04-28 11:28:56 -07003208 BT_DBG("Confirming auto-accept as acceptor");
3209 confirm_hint = 1;
3210 goto confirm;
3211 }
3212
Johan Hedberg9f616562011-04-28 11:28:54 -07003213 BT_DBG("Auto-accept of user confirmation with %ums delay",
Gustavo Padovan807deac2012-05-17 00:36:24 -03003214 hdev->auto_accept_delay);
Johan Hedberg9f616562011-04-28 11:28:54 -07003215
3216 if (hdev->auto_accept_delay > 0) {
3217 int delay = msecs_to_jiffies(hdev->auto_accept_delay);
3218 mod_timer(&conn->auto_accept_timer, jiffies + delay);
3219 goto unlock;
3220 }
3221
Johan Hedberg7a828902011-04-28 11:28:53 -07003222 hci_send_cmd(hdev, HCI_OP_USER_CONFIRM_REPLY,
Gustavo Padovan807deac2012-05-17 00:36:24 -03003223 sizeof(ev->bdaddr), &ev->bdaddr);
Johan Hedberg7a828902011-04-28 11:28:53 -07003224 goto unlock;
3225 }
3226
Johan Hedberg55bc1a32011-04-28 11:28:56 -07003227confirm:
Johan Hedberg272d90d2012-02-09 15:26:12 +02003228 mgmt_user_confirm_request(hdev, &ev->bdaddr, ACL_LINK, 0, ev->passkey,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003229 confirm_hint);
Johan Hedberg7a828902011-04-28 11:28:53 -07003230
3231unlock:
Johan Hedberga5c29682011-02-19 12:05:57 -03003232 hci_dev_unlock(hdev);
3233}
3234
Brian Gix1143d452011-11-23 08:28:34 -08003235static inline void hci_user_passkey_request_evt(struct hci_dev *hdev,
Gustavo Padovan807deac2012-05-17 00:36:24 -03003236 struct sk_buff *skb)
Brian Gix1143d452011-11-23 08:28:34 -08003237{
3238 struct hci_ev_user_passkey_req *ev = (void *) skb->data;
3239
3240 BT_DBG("%s", hdev->name);
3241
3242 hci_dev_lock(hdev);
3243
Johan Hedberga8b2d5c2012-01-08 23:11:15 +02003244 if (test_bit(HCI_MGMT, &hdev->dev_flags))
Johan Hedberg272d90d2012-02-09 15:26:12 +02003245 mgmt_user_passkey_request(hdev, &ev->bdaddr, ACL_LINK, 0);
Brian Gix1143d452011-11-23 08:28:34 -08003246
3247 hci_dev_unlock(hdev);
3248}
3249
Gustavo Padovan807deac2012-05-17 00:36:24 -03003250static inline void hci_simple_pair_complete_evt(struct hci_dev *hdev,
3251 struct sk_buff *skb)
Marcel Holtmann04936842008-07-14 20:13:48 +02003252{
3253 struct hci_ev_simple_pair_complete *ev = (void *) skb->data;
3254 struct hci_conn *conn;
3255
3256 BT_DBG("%s", hdev->name);
3257
3258 hci_dev_lock(hdev);
3259
3260 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
Johan Hedberg2a611692011-02-19 12:06:00 -03003261 if (!conn)
3262 goto unlock;
Marcel Holtmann04936842008-07-14 20:13:48 +02003263
Johan Hedberg2a611692011-02-19 12:06:00 -03003264 /* To avoid duplicate auth_failed events to user space we check
3265 * the HCI_CONN_AUTH_PEND flag which will be set if we
3266 * initiated the authentication. A traditional auth_complete
3267 * event gets always produced as initiator and is also mapped to
3268 * the mgmt_auth_failed event */
Johan Hedberg51a8efd2012-01-16 06:10:31 +02003269 if (!test_bit(HCI_CONN_AUTH_PEND, &conn->flags) && ev->status != 0)
Johan Hedbergbab73cb2012-02-09 16:07:29 +02003270 mgmt_auth_failed(hdev, &conn->dst, conn->type, conn->dst_type,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003271 ev->status);
Johan Hedberg2a611692011-02-19 12:06:00 -03003272
3273 hci_conn_put(conn);
3274
3275unlock:
Marcel Holtmann04936842008-07-14 20:13:48 +02003276 hci_dev_unlock(hdev);
3277}
3278
Gustavo Padovan807deac2012-05-17 00:36:24 -03003279static inline void hci_remote_host_features_evt(struct hci_dev *hdev,
3280 struct sk_buff *skb)
Marcel Holtmann41a96212008-07-14 20:13:48 +02003281{
3282 struct hci_ev_remote_host_features *ev = (void *) skb->data;
3283 struct inquiry_entry *ie;
3284
3285 BT_DBG("%s", hdev->name);
3286
3287 hci_dev_lock(hdev);
3288
Andrei Emeltchenkocc11b9c2010-11-22 13:21:37 +02003289 ie = hci_inquiry_cache_lookup(hdev, &ev->bdaddr);
3290 if (ie)
Johan Hedberg02b7cc62012-02-28 02:28:43 +02003291 ie->data.ssp_mode = (ev->features[0] & LMP_HOST_SSP);
Marcel Holtmann41a96212008-07-14 20:13:48 +02003292
3293 hci_dev_unlock(hdev);
3294}
3295
Szymon Janc2763eda2011-03-22 13:12:22 +01003296static inline void hci_remote_oob_data_request_evt(struct hci_dev *hdev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003297 struct sk_buff *skb)
Szymon Janc2763eda2011-03-22 13:12:22 +01003298{
3299 struct hci_ev_remote_oob_data_request *ev = (void *) skb->data;
3300 struct oob_data *data;
3301
3302 BT_DBG("%s", hdev->name);
3303
3304 hci_dev_lock(hdev);
3305
Johan Hedberga8b2d5c2012-01-08 23:11:15 +02003306 if (!test_bit(HCI_MGMT, &hdev->dev_flags))
Szymon Jance1ba1f12011-04-06 13:01:59 +02003307 goto unlock;
3308
Szymon Janc2763eda2011-03-22 13:12:22 +01003309 data = hci_find_remote_oob_data(hdev, &ev->bdaddr);
3310 if (data) {
3311 struct hci_cp_remote_oob_data_reply cp;
3312
3313 bacpy(&cp.bdaddr, &ev->bdaddr);
3314 memcpy(cp.hash, data->hash, sizeof(cp.hash));
3315 memcpy(cp.randomizer, data->randomizer, sizeof(cp.randomizer));
3316
3317 hci_send_cmd(hdev, HCI_OP_REMOTE_OOB_DATA_REPLY, sizeof(cp),
Gustavo Padovan807deac2012-05-17 00:36:24 -03003318 &cp);
Szymon Janc2763eda2011-03-22 13:12:22 +01003319 } else {
3320 struct hci_cp_remote_oob_data_neg_reply cp;
3321
3322 bacpy(&cp.bdaddr, &ev->bdaddr);
3323 hci_send_cmd(hdev, HCI_OP_REMOTE_OOB_DATA_NEG_REPLY, sizeof(cp),
Gustavo Padovan807deac2012-05-17 00:36:24 -03003324 &cp);
Szymon Janc2763eda2011-03-22 13:12:22 +01003325 }
3326
Szymon Jance1ba1f12011-04-06 13:01:59 +02003327unlock:
Szymon Janc2763eda2011-03-22 13:12:22 +01003328 hci_dev_unlock(hdev);
3329}
3330
Gustavo Padovan807deac2012-05-17 00:36:24 -03003331static inline void hci_le_conn_complete_evt(struct hci_dev *hdev,
3332 struct sk_buff *skb)
Ville Tervofcd89c02011-02-10 22:38:47 -03003333{
3334 struct hci_ev_le_conn_complete *ev = (void *) skb->data;
3335 struct hci_conn *conn;
3336
3337 BT_DBG("%s status %d", hdev->name, ev->status);
3338
3339 hci_dev_lock(hdev);
3340
3341 conn = hci_conn_hash_lookup_ba(hdev, LE_LINK, &ev->bdaddr);
Ville Tervob62f3282011-02-10 22:38:50 -03003342 if (!conn) {
3343 conn = hci_conn_add(hdev, LE_LINK, &ev->bdaddr);
3344 if (!conn) {
3345 BT_ERR("No memory for new connection");
3346 hci_dev_unlock(hdev);
3347 return;
3348 }
Andre Guedes29b79882011-05-31 14:20:54 -03003349
3350 conn->dst_type = ev->bdaddr_type;
Ville Tervob62f3282011-02-10 22:38:50 -03003351 }
Ville Tervofcd89c02011-02-10 22:38:47 -03003352
3353 if (ev->status) {
Johan Hedberg48264f02011-11-09 13:58:58 +02003354 mgmt_connect_failed(hdev, &ev->bdaddr, conn->type,
Gustavo Padovan807deac2012-05-17 00:36:24 -03003355 conn->dst_type, ev->status);
Ville Tervofcd89c02011-02-10 22:38:47 -03003356 hci_proto_connect_cfm(conn, ev->status);
3357 conn->state = BT_CLOSED;
3358 hci_conn_del(conn);
3359 goto unlock;
3360 }
3361
Johan Hedbergb644ba32012-01-17 21:48:47 +02003362 if (!test_and_set_bit(HCI_CONN_MGMT_CONNECTED, &conn->flags))
3363 mgmt_device_connected(hdev, &ev->bdaddr, conn->type,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003364 conn->dst_type, 0, NULL, 0, NULL);
Vinicius Costa Gomes83bc71b2011-05-06 18:41:43 -03003365
Vinicius Costa Gomes7b5c0d52011-06-09 18:50:50 -03003366 conn->sec_level = BT_SECURITY_LOW;
Ville Tervofcd89c02011-02-10 22:38:47 -03003367 conn->handle = __le16_to_cpu(ev->handle);
3368 conn->state = BT_CONNECTED;
3369
3370 hci_conn_hold_device(conn);
3371 hci_conn_add_sysfs(conn);
3372
3373 hci_proto_connect_cfm(conn, ev->status);
3374
3375unlock:
3376 hci_dev_unlock(hdev);
3377}
3378
Andre Guedes9aa04c92011-05-26 16:23:51 -03003379static inline void hci_le_adv_report_evt(struct hci_dev *hdev,
Gustavo Padovan807deac2012-05-17 00:36:24 -03003380 struct sk_buff *skb)
Andre Guedes9aa04c92011-05-26 16:23:51 -03003381{
Andre Guedese95beb42011-09-26 20:48:35 -03003382 u8 num_reports = skb->data[0];
3383 void *ptr = &skb->data[1];
Andre Guedes3c9e9192012-01-10 18:20:50 -03003384 s8 rssi;
Andre Guedes9aa04c92011-05-26 16:23:51 -03003385
3386 hci_dev_lock(hdev);
3387
Andre Guedese95beb42011-09-26 20:48:35 -03003388 while (num_reports--) {
3389 struct hci_ev_le_advertising_info *ev = ptr;
Andre Guedes9aa04c92011-05-26 16:23:51 -03003390
Andre Guedes3c9e9192012-01-10 18:20:50 -03003391 rssi = ev->data[ev->length];
3392 mgmt_device_found(hdev, &ev->bdaddr, LE_LINK, ev->bdaddr_type,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003393 NULL, rssi, 0, 1, ev->data, ev->length);
Andre Guedes3c9e9192012-01-10 18:20:50 -03003394
Andre Guedese95beb42011-09-26 20:48:35 -03003395 ptr += sizeof(*ev) + ev->length + 1;
Andre Guedes9aa04c92011-05-26 16:23:51 -03003396 }
3397
3398 hci_dev_unlock(hdev);
3399}
3400
Vinicius Costa Gomesa7a595f2011-06-09 18:50:47 -03003401static inline void hci_le_ltk_request_evt(struct hci_dev *hdev,
Gustavo Padovan807deac2012-05-17 00:36:24 -03003402 struct sk_buff *skb)
Vinicius Costa Gomesa7a595f2011-06-09 18:50:47 -03003403{
3404 struct hci_ev_le_ltk_req *ev = (void *) skb->data;
3405 struct hci_cp_le_ltk_reply cp;
Vinicius Costa Gomesbea710f2011-07-07 18:59:37 -03003406 struct hci_cp_le_ltk_neg_reply neg;
Vinicius Costa Gomesa7a595f2011-06-09 18:50:47 -03003407 struct hci_conn *conn;
Vinicius Costa Gomesc9839a12012-02-02 21:08:01 -03003408 struct smp_ltk *ltk;
Vinicius Costa Gomesa7a595f2011-06-09 18:50:47 -03003409
Andrei Emeltchenkoe4666882012-03-09 11:59:15 +02003410 BT_DBG("%s handle %d", hdev->name, __le16_to_cpu(ev->handle));
Vinicius Costa Gomesa7a595f2011-06-09 18:50:47 -03003411
3412 hci_dev_lock(hdev);
3413
3414 conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
Vinicius Costa Gomesbea710f2011-07-07 18:59:37 -03003415 if (conn == NULL)
3416 goto not_found;
Vinicius Costa Gomesa7a595f2011-06-09 18:50:47 -03003417
Vinicius Costa Gomesbea710f2011-07-07 18:59:37 -03003418 ltk = hci_find_ltk(hdev, ev->ediv, ev->random);
3419 if (ltk == NULL)
3420 goto not_found;
3421
3422 memcpy(cp.ltk, ltk->val, sizeof(ltk->val));
Vinicius Costa Gomesa7a595f2011-06-09 18:50:47 -03003423 cp.handle = cpu_to_le16(conn->handle);
Vinicius Costa Gomesc9839a12012-02-02 21:08:01 -03003424
3425 if (ltk->authenticated)
3426 conn->sec_level = BT_SECURITY_HIGH;
Vinicius Costa Gomesa7a595f2011-06-09 18:50:47 -03003427
3428 hci_send_cmd(hdev, HCI_OP_LE_LTK_REPLY, sizeof(cp), &cp);
3429
Vinicius Costa Gomesc9839a12012-02-02 21:08:01 -03003430 if (ltk->type & HCI_SMP_STK) {
3431 list_del(&ltk->list);
3432 kfree(ltk);
3433 }
3434
Vinicius Costa Gomesa7a595f2011-06-09 18:50:47 -03003435 hci_dev_unlock(hdev);
Vinicius Costa Gomesbea710f2011-07-07 18:59:37 -03003436
3437 return;
3438
3439not_found:
3440 neg.handle = ev->handle;
3441 hci_send_cmd(hdev, HCI_OP_LE_LTK_NEG_REPLY, sizeof(neg), &neg);
3442 hci_dev_unlock(hdev);
Vinicius Costa Gomesa7a595f2011-06-09 18:50:47 -03003443}
3444
Ville Tervofcd89c02011-02-10 22:38:47 -03003445static inline void hci_le_meta_evt(struct hci_dev *hdev, struct sk_buff *skb)
3446{
3447 struct hci_ev_le_meta *le_ev = (void *) skb->data;
3448
3449 skb_pull(skb, sizeof(*le_ev));
3450
3451 switch (le_ev->subevent) {
3452 case HCI_EV_LE_CONN_COMPLETE:
3453 hci_le_conn_complete_evt(hdev, skb);
3454 break;
3455
Andre Guedes9aa04c92011-05-26 16:23:51 -03003456 case HCI_EV_LE_ADVERTISING_REPORT:
3457 hci_le_adv_report_evt(hdev, skb);
3458 break;
3459
Vinicius Costa Gomesa7a595f2011-06-09 18:50:47 -03003460 case HCI_EV_LE_LTK_REQ:
3461 hci_le_ltk_request_evt(hdev, skb);
3462 break;
3463
Ville Tervofcd89c02011-02-10 22:38:47 -03003464 default:
3465 break;
3466 }
3467}
3468
Linus Torvalds1da177e2005-04-16 15:20:36 -07003469void hci_event_packet(struct hci_dev *hdev, struct sk_buff *skb)
3470{
Marcel Holtmanna9de9242007-10-20 13:33:56 +02003471 struct hci_event_hdr *hdr = (void *) skb->data;
3472 __u8 event = hdr->evt;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003473
3474 skb_pull(skb, HCI_EVENT_HDR_SIZE);
3475
Marcel Holtmanna9de9242007-10-20 13:33:56 +02003476 switch (event) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003477 case HCI_EV_INQUIRY_COMPLETE:
3478 hci_inquiry_complete_evt(hdev, skb);
3479 break;
3480
3481 case HCI_EV_INQUIRY_RESULT:
3482 hci_inquiry_result_evt(hdev, skb);
3483 break;
3484
Marcel Holtmanna9de9242007-10-20 13:33:56 +02003485 case HCI_EV_CONN_COMPLETE:
3486 hci_conn_complete_evt(hdev, skb);
Marcel Holtmann21d9e302005-09-13 01:32:25 +02003487 break;
3488
Linus Torvalds1da177e2005-04-16 15:20:36 -07003489 case HCI_EV_CONN_REQUEST:
3490 hci_conn_request_evt(hdev, skb);
3491 break;
3492
Linus Torvalds1da177e2005-04-16 15:20:36 -07003493 case HCI_EV_DISCONN_COMPLETE:
3494 hci_disconn_complete_evt(hdev, skb);
3495 break;
3496
Linus Torvalds1da177e2005-04-16 15:20:36 -07003497 case HCI_EV_AUTH_COMPLETE:
3498 hci_auth_complete_evt(hdev, skb);
3499 break;
3500
Marcel Holtmanna9de9242007-10-20 13:33:56 +02003501 case HCI_EV_REMOTE_NAME:
3502 hci_remote_name_evt(hdev, skb);
3503 break;
3504
Linus Torvalds1da177e2005-04-16 15:20:36 -07003505 case HCI_EV_ENCRYPT_CHANGE:
3506 hci_encrypt_change_evt(hdev, skb);
3507 break;
3508
Marcel Holtmanna9de9242007-10-20 13:33:56 +02003509 case HCI_EV_CHANGE_LINK_KEY_COMPLETE:
3510 hci_change_link_key_complete_evt(hdev, skb);
3511 break;
3512
3513 case HCI_EV_REMOTE_FEATURES:
3514 hci_remote_features_evt(hdev, skb);
3515 break;
3516
3517 case HCI_EV_REMOTE_VERSION:
3518 hci_remote_version_evt(hdev, skb);
3519 break;
3520
3521 case HCI_EV_QOS_SETUP_COMPLETE:
3522 hci_qos_setup_complete_evt(hdev, skb);
3523 break;
3524
3525 case HCI_EV_CMD_COMPLETE:
3526 hci_cmd_complete_evt(hdev, skb);
3527 break;
3528
3529 case HCI_EV_CMD_STATUS:
3530 hci_cmd_status_evt(hdev, skb);
3531 break;
3532
3533 case HCI_EV_ROLE_CHANGE:
3534 hci_role_change_evt(hdev, skb);
3535 break;
3536
3537 case HCI_EV_NUM_COMP_PKTS:
3538 hci_num_comp_pkts_evt(hdev, skb);
3539 break;
3540
3541 case HCI_EV_MODE_CHANGE:
3542 hci_mode_change_evt(hdev, skb);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003543 break;
3544
3545 case HCI_EV_PIN_CODE_REQ:
3546 hci_pin_code_request_evt(hdev, skb);
3547 break;
3548
3549 case HCI_EV_LINK_KEY_REQ:
3550 hci_link_key_request_evt(hdev, skb);
3551 break;
3552
3553 case HCI_EV_LINK_KEY_NOTIFY:
3554 hci_link_key_notify_evt(hdev, skb);
3555 break;
3556
3557 case HCI_EV_CLOCK_OFFSET:
3558 hci_clock_offset_evt(hdev, skb);
3559 break;
3560
Marcel Holtmanna8746412008-07-14 20:13:46 +02003561 case HCI_EV_PKT_TYPE_CHANGE:
3562 hci_pkt_type_change_evt(hdev, skb);
3563 break;
3564
Marcel Holtmann85a1e932005-08-09 20:28:02 -07003565 case HCI_EV_PSCAN_REP_MODE:
3566 hci_pscan_rep_mode_evt(hdev, skb);
3567 break;
3568
Marcel Holtmanna9de9242007-10-20 13:33:56 +02003569 case HCI_EV_INQUIRY_RESULT_WITH_RSSI:
3570 hci_inquiry_result_with_rssi_evt(hdev, skb);
3571 break;
3572
3573 case HCI_EV_REMOTE_EXT_FEATURES:
3574 hci_remote_ext_features_evt(hdev, skb);
3575 break;
3576
3577 case HCI_EV_SYNC_CONN_COMPLETE:
3578 hci_sync_conn_complete_evt(hdev, skb);
3579 break;
3580
3581 case HCI_EV_SYNC_CONN_CHANGED:
3582 hci_sync_conn_changed_evt(hdev, skb);
3583 break;
3584
Marcel Holtmann04837f62006-07-03 10:02:33 +02003585 case HCI_EV_SNIFF_SUBRATE:
3586 hci_sniff_subrate_evt(hdev, skb);
3587 break;
3588
Marcel Holtmanna9de9242007-10-20 13:33:56 +02003589 case HCI_EV_EXTENDED_INQUIRY_RESULT:
3590 hci_extended_inquiry_result_evt(hdev, skb);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003591 break;
3592
Marcel Holtmann04936842008-07-14 20:13:48 +02003593 case HCI_EV_IO_CAPA_REQUEST:
3594 hci_io_capa_request_evt(hdev, skb);
3595 break;
3596
Johan Hedberg03b555e2011-01-04 15:40:05 +02003597 case HCI_EV_IO_CAPA_REPLY:
3598 hci_io_capa_reply_evt(hdev, skb);
3599 break;
3600
Johan Hedberga5c29682011-02-19 12:05:57 -03003601 case HCI_EV_USER_CONFIRM_REQUEST:
3602 hci_user_confirm_request_evt(hdev, skb);
3603 break;
3604
Brian Gix1143d452011-11-23 08:28:34 -08003605 case HCI_EV_USER_PASSKEY_REQUEST:
3606 hci_user_passkey_request_evt(hdev, skb);
3607 break;
3608
Marcel Holtmann04936842008-07-14 20:13:48 +02003609 case HCI_EV_SIMPLE_PAIR_COMPLETE:
3610 hci_simple_pair_complete_evt(hdev, skb);
3611 break;
3612
Marcel Holtmann41a96212008-07-14 20:13:48 +02003613 case HCI_EV_REMOTE_HOST_FEATURES:
3614 hci_remote_host_features_evt(hdev, skb);
3615 break;
3616
Ville Tervofcd89c02011-02-10 22:38:47 -03003617 case HCI_EV_LE_META:
3618 hci_le_meta_evt(hdev, skb);
3619 break;
3620
Szymon Janc2763eda2011-03-22 13:12:22 +01003621 case HCI_EV_REMOTE_OOB_DATA_REQUEST:
3622 hci_remote_oob_data_request_evt(hdev, skb);
3623 break;
3624
Andrei Emeltchenko25e89e92012-01-04 12:41:58 +02003625 case HCI_EV_NUM_COMP_BLOCKS:
3626 hci_num_comp_blocks_evt(hdev, skb);
3627 break;
3628
Marcel Holtmanna9de9242007-10-20 13:33:56 +02003629 default:
3630 BT_DBG("%s event 0x%x", hdev->name, event);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003631 break;
3632 }
3633
3634 kfree_skb(skb);
3635 hdev->stat.evt_rx++;
3636}