blob: 87e6f74af6fe7064feb0c005d16bd9849dcc32fa [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
Gustavo Padovan8fc9ced2012-05-23 04:04:21 -0300412static void hci_cc_write_voice_setting(struct hci_dev *hdev,
413 struct sk_buff *skb)
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200414{
415 __u8 status = *((__u8 *) skb->data);
Marcel Holtmannf383f272008-07-14 20:13:47 +0200416 __u16 setting;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700417 void *sent;
418
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200419 BT_DBG("%s status 0x%x", hdev->name, status);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700420
Marcel Holtmannf383f272008-07-14 20:13:47 +0200421 if (status)
422 return;
423
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200424 sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_VOICE_SETTING);
425 if (!sent)
426 return;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700427
Marcel Holtmannf383f272008-07-14 20:13:47 +0200428 setting = get_unaligned_le16(sent);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700429
Marcel Holtmannf383f272008-07-14 20:13:47 +0200430 if (hdev->voice_setting == setting)
431 return;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700432
Marcel Holtmannf383f272008-07-14 20:13:47 +0200433 hdev->voice_setting = setting;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700434
Marcel Holtmannf383f272008-07-14 20:13:47 +0200435 BT_DBG("%s voice setting 0x%04x", hdev->name, setting);
436
Gustavo F. Padovan3c547112011-12-14 22:58:44 -0200437 if (hdev->notify)
Marcel Holtmannf383f272008-07-14 20:13:47 +0200438 hdev->notify(hdev, HCI_NOTIFY_VOICE_SETTING);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700439}
440
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200441static void hci_cc_host_buffer_size(struct hci_dev *hdev, struct sk_buff *skb)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700442{
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200443 __u8 status = *((__u8 *) skb->data);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700444
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200445 BT_DBG("%s status 0x%x", hdev->name, status);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700446
Johan Hedberg23bb5762010-12-21 23:01:27 +0200447 hci_req_complete(hdev, HCI_OP_HOST_BUFFER_SIZE, status);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700448}
449
Marcel Holtmann333140b2008-07-14 20:13:48 +0200450static void hci_cc_write_ssp_mode(struct hci_dev *hdev, struct sk_buff *skb)
451{
452 __u8 status = *((__u8 *) skb->data);
453 void *sent;
454
455 BT_DBG("%s status 0x%x", hdev->name, status);
456
Marcel Holtmann333140b2008-07-14 20:13:48 +0200457 sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_SSP_MODE);
458 if (!sent)
459 return;
460
Johan Hedberged2c4ee2012-02-17 00:56:28 +0200461 if (test_bit(HCI_MGMT, &hdev->dev_flags))
Johan Hedbergc0ecddc2012-02-22 12:38:31 +0200462 mgmt_ssp_enable_complete(hdev, *((u8 *) sent), status);
463 else if (!status) {
464 if (*((u8 *) sent))
465 set_bit(HCI_SSP_ENABLED, &hdev->dev_flags);
466 else
467 clear_bit(HCI_SSP_ENABLED, &hdev->dev_flags);
468 }
Marcel Holtmann333140b2008-07-14 20:13:48 +0200469}
470
Johan Hedbergd5859e22011-01-25 01:19:58 +0200471static u8 hci_get_inquiry_mode(struct hci_dev *hdev)
472{
473 if (hdev->features[6] & LMP_EXT_INQ)
474 return 2;
475
476 if (hdev->features[3] & LMP_RSSI_INQ)
477 return 1;
478
479 if (hdev->manufacturer == 11 && hdev->hci_rev == 0x00 &&
Gustavo Padovan807deac2012-05-17 00:36:24 -0300480 hdev->lmp_subver == 0x0757)
Johan Hedbergd5859e22011-01-25 01:19:58 +0200481 return 1;
482
483 if (hdev->manufacturer == 15) {
484 if (hdev->hci_rev == 0x03 && hdev->lmp_subver == 0x6963)
485 return 1;
486 if (hdev->hci_rev == 0x09 && hdev->lmp_subver == 0x6963)
487 return 1;
488 if (hdev->hci_rev == 0x00 && hdev->lmp_subver == 0x6965)
489 return 1;
490 }
491
492 if (hdev->manufacturer == 31 && hdev->hci_rev == 0x2005 &&
Gustavo Padovan807deac2012-05-17 00:36:24 -0300493 hdev->lmp_subver == 0x1805)
Johan Hedbergd5859e22011-01-25 01:19:58 +0200494 return 1;
495
496 return 0;
497}
498
499static void hci_setup_inquiry_mode(struct hci_dev *hdev)
500{
501 u8 mode;
502
503 mode = hci_get_inquiry_mode(hdev);
504
505 hci_send_cmd(hdev, HCI_OP_WRITE_INQUIRY_MODE, 1, &mode);
506}
507
508static void hci_setup_event_mask(struct hci_dev *hdev)
509{
510 /* The second byte is 0xff instead of 0x9f (two reserved bits
511 * disabled) since a Broadcom 1.2 dongle doesn't respond to the
512 * command otherwise */
513 u8 events[8] = { 0xff, 0xff, 0xfb, 0xff, 0x00, 0x00, 0x00, 0x00 };
514
Ville Tervo6de6c182011-05-27 11:16:21 +0300515 /* CSR 1.1 dongles does not accept any bitfield so don't try to set
516 * any event mask for pre 1.2 devices */
Andrei Emeltchenko5a13b092011-12-01 14:33:28 +0200517 if (hdev->hci_ver < BLUETOOTH_VER_1_2)
Ville Tervo6de6c182011-05-27 11:16:21 +0300518 return;
519
520 events[4] |= 0x01; /* Flow Specification Complete */
521 events[4] |= 0x02; /* Inquiry Result with RSSI */
522 events[4] |= 0x04; /* Read Remote Extended Features Complete */
523 events[5] |= 0x08; /* Synchronous Connection Complete */
524 events[5] |= 0x10; /* Synchronous Connection Changed */
Johan Hedbergd5859e22011-01-25 01:19:58 +0200525
526 if (hdev->features[3] & LMP_RSSI_INQ)
Johan Hedberga24299e2012-04-26 09:47:46 +0300527 events[4] |= 0x02; /* Inquiry Result with RSSI */
Johan Hedbergd5859e22011-01-25 01:19:58 +0200528
529 if (hdev->features[5] & LMP_SNIFF_SUBR)
530 events[5] |= 0x20; /* Sniff Subrating */
531
532 if (hdev->features[5] & LMP_PAUSE_ENC)
533 events[5] |= 0x80; /* Encryption Key Refresh Complete */
534
535 if (hdev->features[6] & LMP_EXT_INQ)
536 events[5] |= 0x40; /* Extended Inquiry Result */
537
538 if (hdev->features[6] & LMP_NO_FLUSH)
539 events[7] |= 0x01; /* Enhanced Flush Complete */
540
541 if (hdev->features[7] & LMP_LSTO)
542 events[6] |= 0x80; /* Link Supervision Timeout Changed */
543
544 if (hdev->features[6] & LMP_SIMPLE_PAIR) {
545 events[6] |= 0x01; /* IO Capability Request */
546 events[6] |= 0x02; /* IO Capability Response */
547 events[6] |= 0x04; /* User Confirmation Request */
548 events[6] |= 0x08; /* User Passkey Request */
549 events[6] |= 0x10; /* Remote OOB Data Request */
550 events[6] |= 0x20; /* Simple Pairing Complete */
551 events[7] |= 0x04; /* User Passkey Notification */
552 events[7] |= 0x08; /* Keypress Notification */
553 events[7] |= 0x10; /* Remote Host Supported
554 * Features Notification */
555 }
556
557 if (hdev->features[4] & LMP_LE)
558 events[7] |= 0x20; /* LE Meta-Event */
559
560 hci_send_cmd(hdev, HCI_OP_SET_EVENT_MASK, sizeof(events), events);
561}
562
563static void hci_setup(struct hci_dev *hdev)
564{
Andrei Emeltchenkoe61ef4992011-12-19 16:31:27 +0200565 if (hdev->dev_type != HCI_BREDR)
566 return;
567
Johan Hedbergd5859e22011-01-25 01:19:58 +0200568 hci_setup_event_mask(hdev);
569
Andrei Emeltchenkod095c1e2011-12-01 14:33:27 +0200570 if (hdev->hci_ver > BLUETOOTH_VER_1_1)
Johan Hedbergd5859e22011-01-25 01:19:58 +0200571 hci_send_cmd(hdev, HCI_OP_READ_LOCAL_COMMANDS, 0, NULL);
572
Johan Hedberg54d04db2012-02-22 15:47:48 +0200573 if (hdev->features[6] & LMP_SIMPLE_PAIR) {
574 if (test_bit(HCI_SSP_ENABLED, &hdev->dev_flags)) {
575 u8 mode = 0x01;
576 hci_send_cmd(hdev, HCI_OP_WRITE_SSP_MODE,
Gustavo F. Padovan04124682012-03-08 01:25:00 -0300577 sizeof(mode), &mode);
Johan Hedberg54d04db2012-02-22 15:47:48 +0200578 } else {
579 struct hci_cp_write_eir cp;
580
581 memset(hdev->eir, 0, sizeof(hdev->eir));
582 memset(&cp, 0, sizeof(cp));
583
584 hci_send_cmd(hdev, HCI_OP_WRITE_EIR, sizeof(cp), &cp);
585 }
Johan Hedbergd5859e22011-01-25 01:19:58 +0200586 }
587
588 if (hdev->features[3] & LMP_RSSI_INQ)
589 hci_setup_inquiry_mode(hdev);
590
591 if (hdev->features[7] & LMP_INQ_TX_PWR)
592 hci_send_cmd(hdev, HCI_OP_READ_INQ_RSP_TX_POWER, 0, NULL);
Andre Guedes971e3a42011-06-30 19:20:52 -0300593
594 if (hdev->features[7] & LMP_EXTFEATURES) {
595 struct hci_cp_read_local_ext_features cp;
596
597 cp.page = 0x01;
Gustavo F. Padovan04124682012-03-08 01:25:00 -0300598 hci_send_cmd(hdev, HCI_OP_READ_LOCAL_EXT_FEATURES, sizeof(cp),
599 &cp);
Andre Guedes971e3a42011-06-30 19:20:52 -0300600 }
Andre Guedese6100a22011-06-30 19:20:54 -0300601
Johan Hedberg47990ea2012-02-22 11:58:37 +0200602 if (test_bit(HCI_LINK_SECURITY, &hdev->dev_flags)) {
603 u8 enable = 1;
Gustavo F. Padovan04124682012-03-08 01:25:00 -0300604 hci_send_cmd(hdev, HCI_OP_WRITE_AUTH_ENABLE, sizeof(enable),
605 &enable);
Johan Hedberg47990ea2012-02-22 11:58:37 +0200606 }
Johan Hedbergd5859e22011-01-25 01:19:58 +0200607}
608
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200609static void hci_cc_read_local_version(struct hci_dev *hdev, struct sk_buff *skb)
610{
611 struct hci_rp_read_local_version *rp = (void *) skb->data;
612
613 BT_DBG("%s status 0x%x", hdev->name, rp->status);
614
615 if (rp->status)
Andrei Emeltchenko28b8df72012-02-24 12:45:44 +0200616 goto done;
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200617
618 hdev->hci_ver = rp->hci_ver;
Marcel Holtmanne4e8e372008-07-14 20:13:47 +0200619 hdev->hci_rev = __le16_to_cpu(rp->hci_rev);
Johan Hedbergd5859e22011-01-25 01:19:58 +0200620 hdev->lmp_ver = rp->lmp_ver;
Marcel Holtmanne4e8e372008-07-14 20:13:47 +0200621 hdev->manufacturer = __le16_to_cpu(rp->manufacturer);
Johan Hedbergd5859e22011-01-25 01:19:58 +0200622 hdev->lmp_subver = __le16_to_cpu(rp->lmp_subver);
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200623
624 BT_DBG("%s manufacturer %d hci ver %d:%d", hdev->name,
Gustavo Padovan807deac2012-05-17 00:36:24 -0300625 hdev->manufacturer, hdev->hci_ver, hdev->hci_rev);
Johan Hedbergd5859e22011-01-25 01:19:58 +0200626
627 if (test_bit(HCI_INIT, &hdev->flags))
628 hci_setup(hdev);
Andrei Emeltchenko28b8df72012-02-24 12:45:44 +0200629
630done:
631 hci_req_complete(hdev, HCI_OP_READ_LOCAL_VERSION, rp->status);
Johan Hedbergd5859e22011-01-25 01:19:58 +0200632}
633
634static void hci_setup_link_policy(struct hci_dev *hdev)
635{
Andrei Emeltchenko035100c2012-03-12 15:59:32 +0200636 struct hci_cp_write_def_link_policy cp;
Johan Hedbergd5859e22011-01-25 01:19:58 +0200637 u16 link_policy = 0;
638
639 if (hdev->features[0] & LMP_RSWITCH)
640 link_policy |= HCI_LP_RSWITCH;
641 if (hdev->features[0] & LMP_HOLD)
642 link_policy |= HCI_LP_HOLD;
643 if (hdev->features[0] & LMP_SNIFF)
644 link_policy |= HCI_LP_SNIFF;
645 if (hdev->features[1] & LMP_PARK)
646 link_policy |= HCI_LP_PARK;
647
Andrei Emeltchenko035100c2012-03-12 15:59:32 +0200648 cp.policy = cpu_to_le16(link_policy);
649 hci_send_cmd(hdev, HCI_OP_WRITE_DEF_LINK_POLICY, sizeof(cp), &cp);
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200650}
651
Gustavo Padovan8fc9ced2012-05-23 04:04:21 -0300652static void hci_cc_read_local_commands(struct hci_dev *hdev,
653 struct sk_buff *skb)
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200654{
655 struct hci_rp_read_local_commands *rp = (void *) skb->data;
656
657 BT_DBG("%s status 0x%x", hdev->name, rp->status);
658
659 if (rp->status)
Johan Hedbergd5859e22011-01-25 01:19:58 +0200660 goto done;
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200661
662 memcpy(hdev->commands, rp->commands, sizeof(hdev->commands));
Johan Hedbergd5859e22011-01-25 01:19:58 +0200663
664 if (test_bit(HCI_INIT, &hdev->flags) && (hdev->commands[5] & 0x10))
665 hci_setup_link_policy(hdev);
666
667done:
668 hci_req_complete(hdev, HCI_OP_READ_LOCAL_COMMANDS, rp->status);
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200669}
670
Gustavo Padovan8fc9ced2012-05-23 04:04:21 -0300671static void hci_cc_read_local_features(struct hci_dev *hdev,
672 struct sk_buff *skb)
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200673{
674 struct hci_rp_read_local_features *rp = (void *) skb->data;
675
676 BT_DBG("%s status 0x%x", hdev->name, rp->status);
677
678 if (rp->status)
679 return;
680
681 memcpy(hdev->features, rp->features, 8);
682
683 /* Adjust default settings according to features
684 * supported by device. */
685
686 if (hdev->features[0] & LMP_3SLOT)
687 hdev->pkt_type |= (HCI_DM3 | HCI_DH3);
688
689 if (hdev->features[0] & LMP_5SLOT)
690 hdev->pkt_type |= (HCI_DM5 | HCI_DH5);
691
692 if (hdev->features[1] & LMP_HV2) {
693 hdev->pkt_type |= (HCI_HV2);
694 hdev->esco_type |= (ESCO_HV2);
695 }
696
697 if (hdev->features[1] & LMP_HV3) {
698 hdev->pkt_type |= (HCI_HV3);
699 hdev->esco_type |= (ESCO_HV3);
700 }
701
702 if (hdev->features[3] & LMP_ESCO)
703 hdev->esco_type |= (ESCO_EV3);
704
705 if (hdev->features[4] & LMP_EV4)
706 hdev->esco_type |= (ESCO_EV4);
707
708 if (hdev->features[4] & LMP_EV5)
709 hdev->esco_type |= (ESCO_EV5);
710
Marcel Holtmannefc76882009-02-06 09:13:37 +0100711 if (hdev->features[5] & LMP_EDR_ESCO_2M)
712 hdev->esco_type |= (ESCO_2EV3);
713
714 if (hdev->features[5] & LMP_EDR_ESCO_3M)
715 hdev->esco_type |= (ESCO_3EV3);
716
717 if (hdev->features[5] & LMP_EDR_3S_ESCO)
718 hdev->esco_type |= (ESCO_2EV5 | ESCO_3EV5);
719
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200720 BT_DBG("%s features 0x%.2x%.2x%.2x%.2x%.2x%.2x%.2x%.2x", hdev->name,
Gustavo Padovan807deac2012-05-17 00:36:24 -0300721 hdev->features[0], hdev->features[1],
722 hdev->features[2], hdev->features[3],
723 hdev->features[4], hdev->features[5],
724 hdev->features[6], hdev->features[7]);
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200725}
726
Johan Hedberg8f984df2012-02-28 01:07:22 +0200727static void hci_set_le_support(struct hci_dev *hdev)
728{
729 struct hci_cp_write_le_host_supported cp;
730
731 memset(&cp, 0, sizeof(cp));
732
Marcel Holtmann9d428202012-05-03 07:12:31 +0200733 if (test_bit(HCI_LE_ENABLED, &hdev->dev_flags)) {
Johan Hedberg8f984df2012-02-28 01:07:22 +0200734 cp.le = 1;
735 cp.simul = !!(hdev->features[6] & LMP_SIMUL_LE_BR);
736 }
737
738 if (cp.le != !!(hdev->host_features[0] & LMP_HOST_LE))
Gustavo F. Padovan04124682012-03-08 01:25:00 -0300739 hci_send_cmd(hdev, HCI_OP_WRITE_LE_HOST_SUPPORTED, sizeof(cp),
740 &cp);
Johan Hedberg8f984df2012-02-28 01:07:22 +0200741}
742
Andre Guedes971e3a42011-06-30 19:20:52 -0300743static void hci_cc_read_local_ext_features(struct hci_dev *hdev,
Gustavo Padovan807deac2012-05-17 00:36:24 -0300744 struct sk_buff *skb)
Andre Guedes971e3a42011-06-30 19:20:52 -0300745{
746 struct hci_rp_read_local_ext_features *rp = (void *) skb->data;
747
748 BT_DBG("%s status 0x%x", hdev->name, rp->status);
749
750 if (rp->status)
Johan Hedberg8f984df2012-02-28 01:07:22 +0200751 goto done;
Andre Guedes971e3a42011-06-30 19:20:52 -0300752
Andre Guedesb5b32b62011-12-30 10:34:04 -0300753 switch (rp->page) {
754 case 0:
755 memcpy(hdev->features, rp->features, 8);
756 break;
757 case 1:
758 memcpy(hdev->host_features, rp->features, 8);
759 break;
760 }
Andre Guedes971e3a42011-06-30 19:20:52 -0300761
Johan Hedberg8f984df2012-02-28 01:07:22 +0200762 if (test_bit(HCI_INIT, &hdev->flags) && hdev->features[4] & LMP_LE)
763 hci_set_le_support(hdev);
764
765done:
Andre Guedes971e3a42011-06-30 19:20:52 -0300766 hci_req_complete(hdev, HCI_OP_READ_LOCAL_EXT_FEATURES, rp->status);
767}
768
Andrei Emeltchenko1e89cff2011-11-24 14:52:02 +0200769static void hci_cc_read_flow_control_mode(struct hci_dev *hdev,
Gustavo Padovan807deac2012-05-17 00:36:24 -0300770 struct sk_buff *skb)
Andrei Emeltchenko1e89cff2011-11-24 14:52:02 +0200771{
772 struct hci_rp_read_flow_control_mode *rp = (void *) skb->data;
773
774 BT_DBG("%s status 0x%x", hdev->name, rp->status);
775
776 if (rp->status)
777 return;
778
779 hdev->flow_ctl_mode = rp->mode;
780
781 hci_req_complete(hdev, HCI_OP_READ_FLOW_CONTROL_MODE, rp->status);
782}
783
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200784static void hci_cc_read_buffer_size(struct hci_dev *hdev, struct sk_buff *skb)
785{
786 struct hci_rp_read_buffer_size *rp = (void *) skb->data;
787
788 BT_DBG("%s status 0x%x", hdev->name, rp->status);
789
790 if (rp->status)
791 return;
792
793 hdev->acl_mtu = __le16_to_cpu(rp->acl_mtu);
794 hdev->sco_mtu = rp->sco_mtu;
795 hdev->acl_pkts = __le16_to_cpu(rp->acl_max_pkt);
796 hdev->sco_pkts = __le16_to_cpu(rp->sco_max_pkt);
797
798 if (test_bit(HCI_QUIRK_FIXUP_BUFFER_SIZE, &hdev->quirks)) {
799 hdev->sco_mtu = 64;
800 hdev->sco_pkts = 8;
801 }
802
803 hdev->acl_cnt = hdev->acl_pkts;
804 hdev->sco_cnt = hdev->sco_pkts;
805
Gustavo Padovan807deac2012-05-17 00:36:24 -0300806 BT_DBG("%s acl mtu %d:%d sco mtu %d:%d", hdev->name, hdev->acl_mtu,
807 hdev->acl_pkts, hdev->sco_mtu, hdev->sco_pkts);
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200808}
809
810static void hci_cc_read_bd_addr(struct hci_dev *hdev, struct sk_buff *skb)
811{
812 struct hci_rp_read_bd_addr *rp = (void *) skb->data;
813
814 BT_DBG("%s status 0x%x", hdev->name, rp->status);
815
816 if (!rp->status)
817 bacpy(&hdev->bdaddr, &rp->bdaddr);
818
Johan Hedberg23bb5762010-12-21 23:01:27 +0200819 hci_req_complete(hdev, HCI_OP_READ_BD_ADDR, rp->status);
820}
821
Andrei Emeltchenko350ee4c2011-12-07 15:56:51 +0200822static void hci_cc_read_data_block_size(struct hci_dev *hdev,
Gustavo Padovan807deac2012-05-17 00:36:24 -0300823 struct sk_buff *skb)
Andrei Emeltchenko350ee4c2011-12-07 15:56:51 +0200824{
825 struct hci_rp_read_data_block_size *rp = (void *) skb->data;
826
827 BT_DBG("%s status 0x%x", hdev->name, rp->status);
828
829 if (rp->status)
830 return;
831
832 hdev->block_mtu = __le16_to_cpu(rp->max_acl_len);
833 hdev->block_len = __le16_to_cpu(rp->block_len);
834 hdev->num_blocks = __le16_to_cpu(rp->num_blocks);
835
836 hdev->block_cnt = hdev->num_blocks;
837
838 BT_DBG("%s blk mtu %d cnt %d len %d", hdev->name, hdev->block_mtu,
Gustavo Padovan807deac2012-05-17 00:36:24 -0300839 hdev->block_cnt, hdev->block_len);
Andrei Emeltchenko350ee4c2011-12-07 15:56:51 +0200840
841 hci_req_complete(hdev, HCI_OP_READ_DATA_BLOCK_SIZE, rp->status);
842}
843
Johan Hedberg23bb5762010-12-21 23:01:27 +0200844static void hci_cc_write_ca_timeout(struct hci_dev *hdev, struct sk_buff *skb)
845{
846 __u8 status = *((__u8 *) skb->data);
847
848 BT_DBG("%s status 0x%x", hdev->name, status);
849
850 hci_req_complete(hdev, HCI_OP_WRITE_CA_TIMEOUT, status);
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200851}
852
Andrei Emeltchenko928abaa2011-10-12 10:53:57 +0300853static void hci_cc_read_local_amp_info(struct hci_dev *hdev,
Gustavo Padovan807deac2012-05-17 00:36:24 -0300854 struct sk_buff *skb)
Andrei Emeltchenko928abaa2011-10-12 10:53:57 +0300855{
856 struct hci_rp_read_local_amp_info *rp = (void *) skb->data;
857
858 BT_DBG("%s status 0x%x", hdev->name, rp->status);
859
860 if (rp->status)
861 return;
862
863 hdev->amp_status = rp->amp_status;
864 hdev->amp_total_bw = __le32_to_cpu(rp->total_bw);
865 hdev->amp_max_bw = __le32_to_cpu(rp->max_bw);
866 hdev->amp_min_latency = __le32_to_cpu(rp->min_latency);
867 hdev->amp_max_pdu = __le32_to_cpu(rp->max_pdu);
868 hdev->amp_type = rp->amp_type;
869 hdev->amp_pal_cap = __le16_to_cpu(rp->pal_cap);
870 hdev->amp_assoc_size = __le16_to_cpu(rp->max_assoc_size);
871 hdev->amp_be_flush_to = __le32_to_cpu(rp->be_flush_to);
872 hdev->amp_max_flush_to = __le32_to_cpu(rp->max_flush_to);
873
874 hci_req_complete(hdev, HCI_OP_READ_LOCAL_AMP_INFO, rp->status);
875}
876
Johan Hedbergb0916ea2011-01-10 13:44:55 +0200877static void hci_cc_delete_stored_link_key(struct hci_dev *hdev,
Gustavo Padovan807deac2012-05-17 00:36:24 -0300878 struct sk_buff *skb)
Johan Hedbergb0916ea2011-01-10 13:44:55 +0200879{
880 __u8 status = *((__u8 *) skb->data);
881
882 BT_DBG("%s status 0x%x", hdev->name, status);
883
884 hci_req_complete(hdev, HCI_OP_DELETE_STORED_LINK_KEY, status);
885}
886
Johan Hedbergd5859e22011-01-25 01:19:58 +0200887static void hci_cc_set_event_mask(struct hci_dev *hdev, struct sk_buff *skb)
888{
889 __u8 status = *((__u8 *) skb->data);
890
891 BT_DBG("%s status 0x%x", hdev->name, status);
892
893 hci_req_complete(hdev, HCI_OP_SET_EVENT_MASK, status);
894}
895
896static void hci_cc_write_inquiry_mode(struct hci_dev *hdev,
Gustavo Padovan807deac2012-05-17 00:36:24 -0300897 struct sk_buff *skb)
Johan Hedbergd5859e22011-01-25 01:19:58 +0200898{
899 __u8 status = *((__u8 *) skb->data);
900
901 BT_DBG("%s status 0x%x", hdev->name, status);
902
903 hci_req_complete(hdev, HCI_OP_WRITE_INQUIRY_MODE, status);
904}
905
906static void hci_cc_read_inq_rsp_tx_power(struct hci_dev *hdev,
Gustavo Padovan807deac2012-05-17 00:36:24 -0300907 struct sk_buff *skb)
Johan Hedbergd5859e22011-01-25 01:19:58 +0200908{
Marcel Holtmann91c4e9b2012-03-11 19:27:21 -0700909 struct hci_rp_read_inq_rsp_tx_power *rp = (void *) skb->data;
Johan Hedbergd5859e22011-01-25 01:19:58 +0200910
Marcel Holtmann91c4e9b2012-03-11 19:27:21 -0700911 BT_DBG("%s status 0x%x", hdev->name, rp->status);
Johan Hedbergd5859e22011-01-25 01:19:58 +0200912
Marcel Holtmann91c4e9b2012-03-11 19:27:21 -0700913 if (!rp->status)
914 hdev->inq_tx_power = rp->tx_power;
915
916 hci_req_complete(hdev, HCI_OP_READ_INQ_RSP_TX_POWER, rp->status);
Johan Hedbergd5859e22011-01-25 01:19:58 +0200917}
918
919static void hci_cc_set_event_flt(struct hci_dev *hdev, struct sk_buff *skb)
920{
921 __u8 status = *((__u8 *) skb->data);
922
923 BT_DBG("%s status 0x%x", hdev->name, status);
924
925 hci_req_complete(hdev, HCI_OP_SET_EVENT_FLT, status);
926}
927
Johan Hedberg980e1a52011-01-22 06:10:07 +0200928static void hci_cc_pin_code_reply(struct hci_dev *hdev, struct sk_buff *skb)
929{
930 struct hci_rp_pin_code_reply *rp = (void *) skb->data;
931 struct hci_cp_pin_code_reply *cp;
932 struct hci_conn *conn;
933
934 BT_DBG("%s status 0x%x", hdev->name, rp->status);
935
Johan Hedberg56e5cb82011-11-08 20:40:16 +0200936 hci_dev_lock(hdev);
937
Johan Hedberga8b2d5c2012-01-08 23:11:15 +0200938 if (test_bit(HCI_MGMT, &hdev->dev_flags))
Johan Hedberg744cf192011-11-08 20:40:14 +0200939 mgmt_pin_code_reply_complete(hdev, &rp->bdaddr, rp->status);
Johan Hedberg980e1a52011-01-22 06:10:07 +0200940
941 if (rp->status != 0)
Johan Hedberg56e5cb82011-11-08 20:40:16 +0200942 goto unlock;
Johan Hedberg980e1a52011-01-22 06:10:07 +0200943
944 cp = hci_sent_cmd_data(hdev, HCI_OP_PIN_CODE_REPLY);
945 if (!cp)
Johan Hedberg56e5cb82011-11-08 20:40:16 +0200946 goto unlock;
Johan Hedberg980e1a52011-01-22 06:10:07 +0200947
948 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &cp->bdaddr);
949 if (conn)
950 conn->pin_length = cp->pin_len;
Johan Hedberg56e5cb82011-11-08 20:40:16 +0200951
952unlock:
953 hci_dev_unlock(hdev);
Johan Hedberg980e1a52011-01-22 06:10:07 +0200954}
955
956static void hci_cc_pin_code_neg_reply(struct hci_dev *hdev, struct sk_buff *skb)
957{
958 struct hci_rp_pin_code_neg_reply *rp = (void *) skb->data;
959
960 BT_DBG("%s status 0x%x", hdev->name, rp->status);
961
Johan Hedberg56e5cb82011-11-08 20:40:16 +0200962 hci_dev_lock(hdev);
963
Johan Hedberga8b2d5c2012-01-08 23:11:15 +0200964 if (test_bit(HCI_MGMT, &hdev->dev_flags))
Johan Hedberg744cf192011-11-08 20:40:14 +0200965 mgmt_pin_code_neg_reply_complete(hdev, &rp->bdaddr,
Gustavo Padovan807deac2012-05-17 00:36:24 -0300966 rp->status);
Johan Hedberg56e5cb82011-11-08 20:40:16 +0200967
968 hci_dev_unlock(hdev);
Johan Hedberg980e1a52011-01-22 06:10:07 +0200969}
Johan Hedberg56e5cb82011-11-08 20:40:16 +0200970
Ville Tervo6ed58ec2011-02-10 22:38:48 -0300971static void hci_cc_le_read_buffer_size(struct hci_dev *hdev,
972 struct sk_buff *skb)
973{
974 struct hci_rp_le_read_buffer_size *rp = (void *) skb->data;
975
976 BT_DBG("%s status 0x%x", hdev->name, rp->status);
977
978 if (rp->status)
979 return;
980
981 hdev->le_mtu = __le16_to_cpu(rp->le_mtu);
982 hdev->le_pkts = rp->le_max_pkt;
983
984 hdev->le_cnt = hdev->le_pkts;
985
986 BT_DBG("%s le mtu %d:%d", hdev->name, hdev->le_mtu, hdev->le_pkts);
987
988 hci_req_complete(hdev, HCI_OP_LE_READ_BUFFER_SIZE, rp->status);
989}
Johan Hedberg980e1a52011-01-22 06:10:07 +0200990
Johan Hedberga5c29682011-02-19 12:05:57 -0300991static void hci_cc_user_confirm_reply(struct hci_dev *hdev, struct sk_buff *skb)
992{
993 struct hci_rp_user_confirm_reply *rp = (void *) skb->data;
994
995 BT_DBG("%s status 0x%x", hdev->name, rp->status);
996
Johan Hedberg56e5cb82011-11-08 20:40:16 +0200997 hci_dev_lock(hdev);
998
Johan Hedberga8b2d5c2012-01-08 23:11:15 +0200999 if (test_bit(HCI_MGMT, &hdev->dev_flags))
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001000 mgmt_user_confirm_reply_complete(hdev, &rp->bdaddr, ACL_LINK, 0,
1001 rp->status);
Johan Hedberg56e5cb82011-11-08 20:40:16 +02001002
1003 hci_dev_unlock(hdev);
Johan Hedberga5c29682011-02-19 12:05:57 -03001004}
1005
1006static void hci_cc_user_confirm_neg_reply(struct hci_dev *hdev,
Gustavo Padovan807deac2012-05-17 00:36:24 -03001007 struct sk_buff *skb)
Johan Hedberga5c29682011-02-19 12:05:57 -03001008{
1009 struct hci_rp_user_confirm_reply *rp = (void *) skb->data;
1010
1011 BT_DBG("%s status 0x%x", hdev->name, rp->status);
1012
Johan Hedberg56e5cb82011-11-08 20:40:16 +02001013 hci_dev_lock(hdev);
1014
Johan Hedberga8b2d5c2012-01-08 23:11:15 +02001015 if (test_bit(HCI_MGMT, &hdev->dev_flags))
Johan Hedberg744cf192011-11-08 20:40:14 +02001016 mgmt_user_confirm_neg_reply_complete(hdev, &rp->bdaddr,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001017 ACL_LINK, 0, rp->status);
Johan Hedberg56e5cb82011-11-08 20:40:16 +02001018
1019 hci_dev_unlock(hdev);
Johan Hedberga5c29682011-02-19 12:05:57 -03001020}
1021
Brian Gix1143d452011-11-23 08:28:34 -08001022static void hci_cc_user_passkey_reply(struct hci_dev *hdev, struct sk_buff *skb)
1023{
1024 struct hci_rp_user_confirm_reply *rp = (void *) skb->data;
1025
1026 BT_DBG("%s status 0x%x", hdev->name, rp->status);
1027
1028 hci_dev_lock(hdev);
1029
Johan Hedberga8b2d5c2012-01-08 23:11:15 +02001030 if (test_bit(HCI_MGMT, &hdev->dev_flags))
Johan Hedberg272d90d2012-02-09 15:26:12 +02001031 mgmt_user_passkey_reply_complete(hdev, &rp->bdaddr, ACL_LINK,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001032 0, rp->status);
Brian Gix1143d452011-11-23 08:28:34 -08001033
1034 hci_dev_unlock(hdev);
1035}
1036
1037static void hci_cc_user_passkey_neg_reply(struct hci_dev *hdev,
Gustavo Padovan807deac2012-05-17 00:36:24 -03001038 struct sk_buff *skb)
Brian Gix1143d452011-11-23 08:28:34 -08001039{
1040 struct hci_rp_user_confirm_reply *rp = (void *) skb->data;
1041
1042 BT_DBG("%s status 0x%x", hdev->name, rp->status);
1043
1044 hci_dev_lock(hdev);
1045
Johan Hedberga8b2d5c2012-01-08 23:11:15 +02001046 if (test_bit(HCI_MGMT, &hdev->dev_flags))
Brian Gix1143d452011-11-23 08:28:34 -08001047 mgmt_user_passkey_neg_reply_complete(hdev, &rp->bdaddr,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001048 ACL_LINK, 0, rp->status);
Brian Gix1143d452011-11-23 08:28:34 -08001049
1050 hci_dev_unlock(hdev);
1051}
1052
Szymon Jancc35938b2011-03-22 13:12:21 +01001053static void hci_cc_read_local_oob_data_reply(struct hci_dev *hdev,
Gustavo Padovan807deac2012-05-17 00:36:24 -03001054 struct sk_buff *skb)
Szymon Jancc35938b2011-03-22 13:12:21 +01001055{
1056 struct hci_rp_read_local_oob_data *rp = (void *) skb->data;
1057
1058 BT_DBG("%s status 0x%x", hdev->name, rp->status);
1059
Johan Hedberg56e5cb82011-11-08 20:40:16 +02001060 hci_dev_lock(hdev);
Johan Hedberg744cf192011-11-08 20:40:14 +02001061 mgmt_read_local_oob_data_reply_complete(hdev, rp->hash,
Szymon Jancc35938b2011-03-22 13:12:21 +01001062 rp->randomizer, rp->status);
Johan Hedberg56e5cb82011-11-08 20:40:16 +02001063 hci_dev_unlock(hdev);
Szymon Jancc35938b2011-03-22 13:12:21 +01001064}
1065
Andre Guedes07f7fa52011-12-02 21:13:31 +09001066static void hci_cc_le_set_scan_param(struct hci_dev *hdev, struct sk_buff *skb)
1067{
1068 __u8 status = *((__u8 *) skb->data);
1069
1070 BT_DBG("%s status 0x%x", hdev->name, status);
Andre Guedes7ba8b4b2012-02-03 17:47:59 -03001071
1072 hci_req_complete(hdev, HCI_OP_LE_SET_SCAN_PARAM, status);
Andre Guedes3fd24152012-02-03 17:48:01 -03001073
1074 if (status) {
1075 hci_dev_lock(hdev);
1076 mgmt_start_discovery_failed(hdev, status);
1077 hci_dev_unlock(hdev);
1078 return;
1079 }
Andre Guedes07f7fa52011-12-02 21:13:31 +09001080}
1081
Andre Guedeseb9d91f2011-05-26 16:23:52 -03001082static void hci_cc_le_set_scan_enable(struct hci_dev *hdev,
Gustavo Padovan807deac2012-05-17 00:36:24 -03001083 struct sk_buff *skb)
Andre Guedeseb9d91f2011-05-26 16:23:52 -03001084{
1085 struct hci_cp_le_set_scan_enable *cp;
1086 __u8 status = *((__u8 *) skb->data);
1087
1088 BT_DBG("%s status 0x%x", hdev->name, status);
1089
Andre Guedeseb9d91f2011-05-26 16:23:52 -03001090 cp = hci_sent_cmd_data(hdev, HCI_OP_LE_SET_SCAN_ENABLE);
1091 if (!cp)
1092 return;
1093
Andrei Emeltchenko68a8aea2011-12-19 16:14:18 +02001094 switch (cp->enable) {
1095 case LE_SCANNING_ENABLED:
Andre Guedes7ba8b4b2012-02-03 17:47:59 -03001096 hci_req_complete(hdev, HCI_OP_LE_SET_SCAN_ENABLE, status);
1097
Andre Guedes3fd24152012-02-03 17:48:01 -03001098 if (status) {
1099 hci_dev_lock(hdev);
1100 mgmt_start_discovery_failed(hdev, status);
1101 hci_dev_unlock(hdev);
Andre Guedes7ba8b4b2012-02-03 17:47:59 -03001102 return;
Andre Guedes3fd24152012-02-03 17:48:01 -03001103 }
Andre Guedes7ba8b4b2012-02-03 17:47:59 -03001104
Andre Guedesd23264a2011-11-25 20:53:38 -03001105 set_bit(HCI_LE_SCAN, &hdev->dev_flags);
1106
Andre Guedesa8f13c82011-09-09 18:56:24 -03001107 hci_dev_lock(hdev);
Andre Guedes343f9352012-02-17 20:39:37 -03001108 hci_discovery_set_state(hdev, DISCOVERY_FINDING);
Andre Guedesa8f13c82011-09-09 18:56:24 -03001109 hci_dev_unlock(hdev);
Andrei Emeltchenko68a8aea2011-12-19 16:14:18 +02001110 break;
1111
1112 case LE_SCANNING_DISABLED:
Andre Guedesc9ecc482012-03-15 16:52:08 -03001113 if (status) {
1114 hci_dev_lock(hdev);
1115 mgmt_stop_discovery_failed(hdev, status);
1116 hci_dev_unlock(hdev);
Andre Guedes7ba8b4b2012-02-03 17:47:59 -03001117 return;
Andre Guedesc9ecc482012-03-15 16:52:08 -03001118 }
Andre Guedes7ba8b4b2012-02-03 17:47:59 -03001119
Andre Guedesd23264a2011-11-25 20:53:38 -03001120 clear_bit(HCI_LE_SCAN, &hdev->dev_flags);
1121
Andre Guedesbc3dd332012-03-06 19:37:06 -03001122 if (hdev->discovery.type == DISCOV_TYPE_INTERLEAVED &&
1123 hdev->discovery.state == DISCOVERY_FINDING) {
Andre Guedes5e0452c2012-02-17 20:39:38 -03001124 mgmt_interleaved_discovery(hdev);
1125 } else {
1126 hci_dev_lock(hdev);
1127 hci_discovery_set_state(hdev, DISCOVERY_STOPPED);
1128 hci_dev_unlock(hdev);
1129 }
1130
Andrei Emeltchenko68a8aea2011-12-19 16:14:18 +02001131 break;
1132
1133 default:
1134 BT_ERR("Used reserved LE_Scan_Enable param %d", cp->enable);
1135 break;
Andre Guedes35815082011-05-26 16:23:53 -03001136 }
Andre Guedeseb9d91f2011-05-26 16:23:52 -03001137}
1138
Vinicius Costa Gomesa7a595f2011-06-09 18:50:47 -03001139static void hci_cc_le_ltk_reply(struct hci_dev *hdev, struct sk_buff *skb)
1140{
1141 struct hci_rp_le_ltk_reply *rp = (void *) skb->data;
1142
1143 BT_DBG("%s status 0x%x", hdev->name, rp->status);
1144
1145 if (rp->status)
1146 return;
1147
1148 hci_req_complete(hdev, HCI_OP_LE_LTK_REPLY, rp->status);
1149}
1150
1151static void hci_cc_le_ltk_neg_reply(struct hci_dev *hdev, struct sk_buff *skb)
1152{
1153 struct hci_rp_le_ltk_neg_reply *rp = (void *) skb->data;
1154
1155 BT_DBG("%s status 0x%x", hdev->name, rp->status);
1156
1157 if (rp->status)
1158 return;
1159
1160 hci_req_complete(hdev, HCI_OP_LE_LTK_NEG_REPLY, rp->status);
1161}
1162
Gustavo Padovan6039aa72012-05-23 04:04:18 -03001163static void hci_cc_write_le_host_supported(struct hci_dev *hdev,
1164 struct sk_buff *skb)
Andre Guedesf9b49302011-06-30 19:20:53 -03001165{
Johan Hedberg06199cf2012-02-22 16:37:11 +02001166 struct hci_cp_write_le_host_supported *sent;
Andre Guedesf9b49302011-06-30 19:20:53 -03001167 __u8 status = *((__u8 *) skb->data);
1168
1169 BT_DBG("%s status 0x%x", hdev->name, status);
1170
Johan Hedberg06199cf2012-02-22 16:37:11 +02001171 sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_LE_HOST_SUPPORTED);
Johan Hedberg8f984df2012-02-28 01:07:22 +02001172 if (!sent)
Andre Guedesf9b49302011-06-30 19:20:53 -03001173 return;
1174
Johan Hedberg8f984df2012-02-28 01:07:22 +02001175 if (!status) {
1176 if (sent->le)
1177 hdev->host_features[0] |= LMP_HOST_LE;
1178 else
1179 hdev->host_features[0] &= ~LMP_HOST_LE;
1180 }
1181
1182 if (test_bit(HCI_MGMT, &hdev->dev_flags) &&
Gustavo Padovan807deac2012-05-17 00:36:24 -03001183 !test_bit(HCI_INIT, &hdev->flags))
Johan Hedberg8f984df2012-02-28 01:07:22 +02001184 mgmt_le_enable_complete(hdev, sent->le, status);
1185
1186 hci_req_complete(hdev, HCI_OP_WRITE_LE_HOST_SUPPORTED, status);
Andre Guedesf9b49302011-06-30 19:20:53 -03001187}
1188
Gustavo Padovan6039aa72012-05-23 04:04:18 -03001189static void hci_cs_inquiry(struct hci_dev *hdev, __u8 status)
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001190{
1191 BT_DBG("%s status 0x%x", hdev->name, status);
1192
1193 if (status) {
Johan Hedberg23bb5762010-12-21 23:01:27 +02001194 hci_req_complete(hdev, HCI_OP_INQUIRY, status);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001195 hci_conn_check_pending(hdev);
Johan Hedberg56e5cb82011-11-08 20:40:16 +02001196 hci_dev_lock(hdev);
Johan Hedberga8b2d5c2012-01-08 23:11:15 +02001197 if (test_bit(HCI_MGMT, &hdev->dev_flags))
Andre Guedes7a135102011-11-09 17:14:25 -03001198 mgmt_start_discovery_failed(hdev, status);
Johan Hedberg56e5cb82011-11-08 20:40:16 +02001199 hci_dev_unlock(hdev);
Johan Hedberg314b2382011-04-27 10:29:57 -04001200 return;
1201 }
1202
Andre Guedes89352e72011-11-04 14:16:53 -03001203 set_bit(HCI_INQUIRY, &hdev->flags);
1204
Johan Hedberg56e5cb82011-11-08 20:40:16 +02001205 hci_dev_lock(hdev);
Andre Guedes343f9352012-02-17 20:39:37 -03001206 hci_discovery_set_state(hdev, DISCOVERY_FINDING);
Johan Hedberg56e5cb82011-11-08 20:40:16 +02001207 hci_dev_unlock(hdev);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001208}
1209
Gustavo Padovan6039aa72012-05-23 04:04:18 -03001210static void hci_cs_create_conn(struct hci_dev *hdev, __u8 status)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001211{
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001212 struct hci_cp_create_conn *cp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001213 struct hci_conn *conn;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001214
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001215 BT_DBG("%s status 0x%x", hdev->name, status);
1216
1217 cp = hci_sent_cmd_data(hdev, HCI_OP_CREATE_CONN);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001218 if (!cp)
1219 return;
1220
1221 hci_dev_lock(hdev);
1222
1223 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &cp->bdaddr);
1224
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001225 BT_DBG("%s bdaddr %s conn %p", hdev->name, batostr(&cp->bdaddr), conn);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001226
1227 if (status) {
1228 if (conn && conn->state == BT_CONNECT) {
Marcel Holtmann4c67bc72006-10-15 17:30:56 +02001229 if (status != 0x0c || conn->attempt > 2) {
1230 conn->state = BT_CLOSED;
1231 hci_proto_connect_cfm(conn, status);
1232 hci_conn_del(conn);
1233 } else
1234 conn->state = BT_CONNECT2;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001235 }
1236 } else {
1237 if (!conn) {
1238 conn = hci_conn_add(hdev, ACL_LINK, &cp->bdaddr);
1239 if (conn) {
Johan Hedberga0c808b2012-01-16 09:49:58 +02001240 conn->out = true;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001241 conn->link_mode |= HCI_LM_MASTER;
1242 } else
Gustavo F. Padovan893ef972010-07-18 15:13:37 -03001243 BT_ERR("No memory for new connection");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001244 }
1245 }
1246
1247 hci_dev_unlock(hdev);
1248}
1249
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001250static void hci_cs_add_sco(struct hci_dev *hdev, __u8 status)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001251{
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001252 struct hci_cp_add_sco *cp;
1253 struct hci_conn *acl, *sco;
1254 __u16 handle;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001255
Marcel Holtmannb6a0dc82007-10-20 14:55:10 +02001256 BT_DBG("%s status 0x%x", hdev->name, status);
1257
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001258 if (!status)
1259 return;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001260
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001261 cp = hci_sent_cmd_data(hdev, HCI_OP_ADD_SCO);
1262 if (!cp)
1263 return;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001264
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001265 handle = __le16_to_cpu(cp->handle);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001266
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001267 BT_DBG("%s handle %d", hdev->name, handle);
Marcel Holtmann6bd57412006-11-18 22:14:22 +01001268
1269 hci_dev_lock(hdev);
1270
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001271 acl = hci_conn_hash_lookup_handle(hdev, handle);
Andrei Emeltchenko5a08ecc2011-01-11 17:20:20 +02001272 if (acl) {
1273 sco = acl->link;
1274 if (sco) {
1275 sco->state = BT_CLOSED;
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001276
Andrei Emeltchenko5a08ecc2011-01-11 17:20:20 +02001277 hci_proto_connect_cfm(sco, status);
1278 hci_conn_del(sco);
1279 }
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001280 }
Marcel Holtmann6bd57412006-11-18 22:14:22 +01001281
1282 hci_dev_unlock(hdev);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001283}
1284
Marcel Holtmannf8558552008-07-14 20:13:49 +02001285static void hci_cs_auth_requested(struct hci_dev *hdev, __u8 status)
1286{
1287 struct hci_cp_auth_requested *cp;
1288 struct hci_conn *conn;
1289
1290 BT_DBG("%s status 0x%x", hdev->name, status);
1291
1292 if (!status)
1293 return;
1294
1295 cp = hci_sent_cmd_data(hdev, HCI_OP_AUTH_REQUESTED);
1296 if (!cp)
1297 return;
1298
1299 hci_dev_lock(hdev);
1300
1301 conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(cp->handle));
1302 if (conn) {
1303 if (conn->state == BT_CONFIG) {
1304 hci_proto_connect_cfm(conn, status);
1305 hci_conn_put(conn);
1306 }
1307 }
1308
1309 hci_dev_unlock(hdev);
1310}
1311
1312static void hci_cs_set_conn_encrypt(struct hci_dev *hdev, __u8 status)
1313{
1314 struct hci_cp_set_conn_encrypt *cp;
1315 struct hci_conn *conn;
1316
1317 BT_DBG("%s status 0x%x", hdev->name, status);
1318
1319 if (!status)
1320 return;
1321
1322 cp = hci_sent_cmd_data(hdev, HCI_OP_SET_CONN_ENCRYPT);
1323 if (!cp)
1324 return;
1325
1326 hci_dev_lock(hdev);
1327
1328 conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(cp->handle));
1329 if (conn) {
1330 if (conn->state == BT_CONFIG) {
1331 hci_proto_connect_cfm(conn, status);
1332 hci_conn_put(conn);
1333 }
1334 }
1335
1336 hci_dev_unlock(hdev);
1337}
1338
Johan Hedberg127178d2010-11-18 22:22:29 +02001339static int hci_outgoing_auth_needed(struct hci_dev *hdev,
Gustavo Padovan807deac2012-05-17 00:36:24 -03001340 struct hci_conn *conn)
Johan Hedberg392599b2010-11-18 22:22:28 +02001341{
Johan Hedberg392599b2010-11-18 22:22:28 +02001342 if (conn->state != BT_CONFIG || !conn->out)
1343 return 0;
1344
Johan Hedberg765c2a92011-01-19 12:06:52 +05301345 if (conn->pending_sec_level == BT_SECURITY_SDP)
Johan Hedberg392599b2010-11-18 22:22:28 +02001346 return 0;
1347
1348 /* Only request authentication for SSP connections or non-SSP
Vinicius Costa Gomese9bf2bf2011-09-02 14:51:20 -03001349 * devices with sec_level HIGH or if MITM protection is requested */
Gustavo Padovan807deac2012-05-17 00:36:24 -03001350 if (!hci_conn_ssp_enabled(conn) && !(conn->auth_type & 0x01) &&
1351 conn->pending_sec_level != BT_SECURITY_HIGH)
Johan Hedberg392599b2010-11-18 22:22:28 +02001352 return 0;
1353
Johan Hedberg392599b2010-11-18 22:22:28 +02001354 return 1;
1355}
1356
Gustavo Padovan6039aa72012-05-23 04:04:18 -03001357static int hci_resolve_name(struct hci_dev *hdev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001358 struct inquiry_entry *e)
Johan Hedberg30dc78e2012-01-04 15:44:20 +02001359{
1360 struct hci_cp_remote_name_req cp;
1361
1362 memset(&cp, 0, sizeof(cp));
1363
1364 bacpy(&cp.bdaddr, &e->data.bdaddr);
1365 cp.pscan_rep_mode = e->data.pscan_rep_mode;
1366 cp.pscan_mode = e->data.pscan_mode;
1367 cp.clock_offset = e->data.clock_offset;
1368
1369 return hci_send_cmd(hdev, HCI_OP_REMOTE_NAME_REQ, sizeof(cp), &cp);
1370}
1371
Johan Hedbergb644ba32012-01-17 21:48:47 +02001372static bool hci_resolve_next_name(struct hci_dev *hdev)
Johan Hedberg30dc78e2012-01-04 15:44:20 +02001373{
1374 struct discovery_state *discov = &hdev->discovery;
1375 struct inquiry_entry *e;
1376
Johan Hedbergb644ba32012-01-17 21:48:47 +02001377 if (list_empty(&discov->resolve))
1378 return false;
1379
1380 e = hci_inquiry_cache_lookup_resolve(hdev, BDADDR_ANY, NAME_NEEDED);
1381 if (hci_resolve_name(hdev, e) == 0) {
1382 e->name_state = NAME_PENDING;
1383 return true;
1384 }
1385
1386 return false;
1387}
1388
1389static void hci_check_pending_name(struct hci_dev *hdev, struct hci_conn *conn,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001390 bdaddr_t *bdaddr, u8 *name, u8 name_len)
Johan Hedbergb644ba32012-01-17 21:48:47 +02001391{
1392 struct discovery_state *discov = &hdev->discovery;
1393 struct inquiry_entry *e;
1394
1395 if (conn && !test_and_set_bit(HCI_CONN_MGMT_CONNECTED, &conn->flags))
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001396 mgmt_device_connected(hdev, bdaddr, ACL_LINK, 0x00, 0, name,
1397 name_len, conn->dev_class);
Johan Hedbergb644ba32012-01-17 21:48:47 +02001398
1399 if (discov->state == DISCOVERY_STOPPED)
1400 return;
1401
Johan Hedberg30dc78e2012-01-04 15:44:20 +02001402 if (discov->state == DISCOVERY_STOPPING)
1403 goto discov_complete;
1404
1405 if (discov->state != DISCOVERY_RESOLVING)
1406 return;
1407
1408 e = hci_inquiry_cache_lookup_resolve(hdev, bdaddr, NAME_PENDING);
1409 if (e) {
1410 e->name_state = NAME_KNOWN;
1411 list_del(&e->list);
Johan Hedbergb644ba32012-01-17 21:48:47 +02001412 if (name)
1413 mgmt_remote_name(hdev, bdaddr, ACL_LINK, 0x00,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001414 e->data.rssi, name, name_len);
Johan Hedberg30dc78e2012-01-04 15:44:20 +02001415 }
1416
Johan Hedbergb644ba32012-01-17 21:48:47 +02001417 if (hci_resolve_next_name(hdev))
Johan Hedberg30dc78e2012-01-04 15:44:20 +02001418 return;
Johan Hedberg30dc78e2012-01-04 15:44:20 +02001419
1420discov_complete:
1421 hci_discovery_set_state(hdev, DISCOVERY_STOPPED);
1422}
1423
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001424static void hci_cs_remote_name_req(struct hci_dev *hdev, __u8 status)
1425{
Johan Hedberg127178d2010-11-18 22:22:29 +02001426 struct hci_cp_remote_name_req *cp;
1427 struct hci_conn *conn;
1428
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001429 BT_DBG("%s status 0x%x", hdev->name, status);
Johan Hedberg127178d2010-11-18 22:22:29 +02001430
1431 /* If successful wait for the name req complete event before
1432 * checking for the need to do authentication */
1433 if (!status)
1434 return;
1435
1436 cp = hci_sent_cmd_data(hdev, HCI_OP_REMOTE_NAME_REQ);
1437 if (!cp)
1438 return;
1439
1440 hci_dev_lock(hdev);
1441
1442 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &cp->bdaddr);
Johan Hedbergb644ba32012-01-17 21:48:47 +02001443
1444 if (test_bit(HCI_MGMT, &hdev->dev_flags))
1445 hci_check_pending_name(hdev, conn, &cp->bdaddr, NULL, 0);
1446
Johan Hedberg79c6c702011-04-28 11:28:55 -07001447 if (!conn)
1448 goto unlock;
1449
1450 if (!hci_outgoing_auth_needed(hdev, conn))
1451 goto unlock;
1452
Johan Hedberg51a8efd2012-01-16 06:10:31 +02001453 if (!test_and_set_bit(HCI_CONN_AUTH_PEND, &conn->flags)) {
Johan Hedberg127178d2010-11-18 22:22:29 +02001454 struct hci_cp_auth_requested cp;
1455 cp.handle = __cpu_to_le16(conn->handle);
1456 hci_send_cmd(hdev, HCI_OP_AUTH_REQUESTED, sizeof(cp), &cp);
1457 }
1458
Johan Hedberg79c6c702011-04-28 11:28:55 -07001459unlock:
Johan Hedberg127178d2010-11-18 22:22:29 +02001460 hci_dev_unlock(hdev);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001461}
1462
Marcel Holtmann769be972008-07-14 20:13:49 +02001463static void hci_cs_read_remote_features(struct hci_dev *hdev, __u8 status)
1464{
1465 struct hci_cp_read_remote_features *cp;
1466 struct hci_conn *conn;
1467
1468 BT_DBG("%s status 0x%x", hdev->name, status);
1469
1470 if (!status)
1471 return;
1472
1473 cp = hci_sent_cmd_data(hdev, HCI_OP_READ_REMOTE_FEATURES);
1474 if (!cp)
1475 return;
1476
1477 hci_dev_lock(hdev);
1478
1479 conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(cp->handle));
1480 if (conn) {
1481 if (conn->state == BT_CONFIG) {
Marcel Holtmann769be972008-07-14 20:13:49 +02001482 hci_proto_connect_cfm(conn, status);
1483 hci_conn_put(conn);
1484 }
1485 }
1486
1487 hci_dev_unlock(hdev);
1488}
1489
1490static void hci_cs_read_remote_ext_features(struct hci_dev *hdev, __u8 status)
1491{
1492 struct hci_cp_read_remote_ext_features *cp;
1493 struct hci_conn *conn;
1494
1495 BT_DBG("%s status 0x%x", hdev->name, status);
1496
1497 if (!status)
1498 return;
1499
1500 cp = hci_sent_cmd_data(hdev, HCI_OP_READ_REMOTE_EXT_FEATURES);
1501 if (!cp)
1502 return;
1503
1504 hci_dev_lock(hdev);
1505
1506 conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(cp->handle));
1507 if (conn) {
1508 if (conn->state == BT_CONFIG) {
Marcel Holtmann769be972008-07-14 20:13:49 +02001509 hci_proto_connect_cfm(conn, status);
1510 hci_conn_put(conn);
1511 }
1512 }
1513
1514 hci_dev_unlock(hdev);
1515}
1516
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001517static void hci_cs_setup_sync_conn(struct hci_dev *hdev, __u8 status)
1518{
Marcel Holtmannb6a0dc82007-10-20 14:55:10 +02001519 struct hci_cp_setup_sync_conn *cp;
1520 struct hci_conn *acl, *sco;
1521 __u16 handle;
1522
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001523 BT_DBG("%s status 0x%x", hdev->name, status);
Marcel Holtmannb6a0dc82007-10-20 14:55:10 +02001524
1525 if (!status)
1526 return;
1527
1528 cp = hci_sent_cmd_data(hdev, HCI_OP_SETUP_SYNC_CONN);
1529 if (!cp)
1530 return;
1531
1532 handle = __le16_to_cpu(cp->handle);
1533
1534 BT_DBG("%s handle %d", hdev->name, handle);
1535
1536 hci_dev_lock(hdev);
1537
1538 acl = hci_conn_hash_lookup_handle(hdev, handle);
Andrei Emeltchenko5a08ecc2011-01-11 17:20:20 +02001539 if (acl) {
1540 sco = acl->link;
1541 if (sco) {
1542 sco->state = BT_CLOSED;
Marcel Holtmannb6a0dc82007-10-20 14:55:10 +02001543
Andrei Emeltchenko5a08ecc2011-01-11 17:20:20 +02001544 hci_proto_connect_cfm(sco, status);
1545 hci_conn_del(sco);
1546 }
Marcel Holtmannb6a0dc82007-10-20 14:55:10 +02001547 }
1548
1549 hci_dev_unlock(hdev);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001550}
1551
1552static void hci_cs_sniff_mode(struct hci_dev *hdev, __u8 status)
1553{
1554 struct hci_cp_sniff_mode *cp;
1555 struct hci_conn *conn;
1556
1557 BT_DBG("%s status 0x%x", hdev->name, status);
1558
1559 if (!status)
1560 return;
1561
1562 cp = hci_sent_cmd_data(hdev, HCI_OP_SNIFF_MODE);
1563 if (!cp)
1564 return;
1565
1566 hci_dev_lock(hdev);
1567
1568 conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(cp->handle));
Marcel Holtmanne73439d2010-07-26 10:06:00 -04001569 if (conn) {
Johan Hedberg51a8efd2012-01-16 06:10:31 +02001570 clear_bit(HCI_CONN_MODE_CHANGE_PEND, &conn->flags);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001571
Johan Hedberg51a8efd2012-01-16 06:10:31 +02001572 if (test_and_clear_bit(HCI_CONN_SCO_SETUP_PEND, &conn->flags))
Marcel Holtmanne73439d2010-07-26 10:06:00 -04001573 hci_sco_setup(conn, status);
1574 }
1575
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001576 hci_dev_unlock(hdev);
1577}
1578
1579static void hci_cs_exit_sniff_mode(struct hci_dev *hdev, __u8 status)
1580{
1581 struct hci_cp_exit_sniff_mode *cp;
1582 struct hci_conn *conn;
1583
1584 BT_DBG("%s status 0x%x", hdev->name, status);
1585
1586 if (!status)
1587 return;
1588
1589 cp = hci_sent_cmd_data(hdev, HCI_OP_EXIT_SNIFF_MODE);
1590 if (!cp)
1591 return;
1592
1593 hci_dev_lock(hdev);
1594
1595 conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(cp->handle));
Marcel Holtmanne73439d2010-07-26 10:06:00 -04001596 if (conn) {
Johan Hedberg51a8efd2012-01-16 06:10:31 +02001597 clear_bit(HCI_CONN_MODE_CHANGE_PEND, &conn->flags);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001598
Johan Hedberg51a8efd2012-01-16 06:10:31 +02001599 if (test_and_clear_bit(HCI_CONN_SCO_SETUP_PEND, &conn->flags))
Marcel Holtmanne73439d2010-07-26 10:06:00 -04001600 hci_sco_setup(conn, status);
1601 }
1602
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001603 hci_dev_unlock(hdev);
1604}
1605
Johan Hedberg88c3df12012-02-09 14:27:38 +02001606static void hci_cs_disconnect(struct hci_dev *hdev, u8 status)
1607{
1608 struct hci_cp_disconnect *cp;
1609 struct hci_conn *conn;
1610
1611 if (!status)
1612 return;
1613
1614 cp = hci_sent_cmd_data(hdev, HCI_OP_DISCONNECT);
1615 if (!cp)
1616 return;
1617
1618 hci_dev_lock(hdev);
1619
1620 conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(cp->handle));
1621 if (conn)
1622 mgmt_disconnect_failed(hdev, &conn->dst, conn->type,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001623 conn->dst_type, status);
Johan Hedberg88c3df12012-02-09 14:27:38 +02001624
1625 hci_dev_unlock(hdev);
1626}
1627
Ville Tervofcd89c02011-02-10 22:38:47 -03001628static void hci_cs_le_create_conn(struct hci_dev *hdev, __u8 status)
1629{
1630 struct hci_cp_le_create_conn *cp;
1631 struct hci_conn *conn;
1632
1633 BT_DBG("%s status 0x%x", hdev->name, status);
1634
1635 cp = hci_sent_cmd_data(hdev, HCI_OP_LE_CREATE_CONN);
1636 if (!cp)
1637 return;
1638
1639 hci_dev_lock(hdev);
1640
1641 conn = hci_conn_hash_lookup_ba(hdev, LE_LINK, &cp->peer_addr);
1642
1643 BT_DBG("%s bdaddr %s conn %p", hdev->name, batostr(&cp->peer_addr),
Gustavo Padovan807deac2012-05-17 00:36:24 -03001644 conn);
Ville Tervofcd89c02011-02-10 22:38:47 -03001645
1646 if (status) {
1647 if (conn && conn->state == BT_CONNECT) {
1648 conn->state = BT_CLOSED;
Hemant Gupta328c9242012-04-05 16:51:04 +05301649 mgmt_connect_failed(hdev, &cp->peer_addr, conn->type,
1650 conn->dst_type, status);
Ville Tervofcd89c02011-02-10 22:38:47 -03001651 hci_proto_connect_cfm(conn, status);
1652 hci_conn_del(conn);
1653 }
1654 } else {
1655 if (!conn) {
1656 conn = hci_conn_add(hdev, LE_LINK, &cp->peer_addr);
Andre Guedes29b79882011-05-31 14:20:54 -03001657 if (conn) {
1658 conn->dst_type = cp->peer_addr_type;
Johan Hedberga0c808b2012-01-16 09:49:58 +02001659 conn->out = true;
Andre Guedes29b79882011-05-31 14:20:54 -03001660 } else {
Ville Tervofcd89c02011-02-10 22:38:47 -03001661 BT_ERR("No memory for new connection");
Andre Guedes29b79882011-05-31 14:20:54 -03001662 }
Ville Tervofcd89c02011-02-10 22:38:47 -03001663 }
1664 }
1665
1666 hci_dev_unlock(hdev);
1667}
1668
Vinicius Costa Gomesa7a595f2011-06-09 18:50:47 -03001669static void hci_cs_le_start_enc(struct hci_dev *hdev, u8 status)
1670{
1671 BT_DBG("%s status 0x%x", hdev->name, status);
1672}
1673
Gustavo Padovan6039aa72012-05-23 04:04:18 -03001674static void hci_inquiry_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001675{
1676 __u8 status = *((__u8 *) skb->data);
Johan Hedberg30dc78e2012-01-04 15:44:20 +02001677 struct discovery_state *discov = &hdev->discovery;
1678 struct inquiry_entry *e;
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001679
1680 BT_DBG("%s status %d", hdev->name, status);
1681
Johan Hedberg23bb5762010-12-21 23:01:27 +02001682 hci_req_complete(hdev, HCI_OP_INQUIRY, status);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001683
1684 hci_conn_check_pending(hdev);
Andre Guedes89352e72011-11-04 14:16:53 -03001685
1686 if (!test_and_clear_bit(HCI_INQUIRY, &hdev->flags))
1687 return;
1688
Johan Hedberga8b2d5c2012-01-08 23:11:15 +02001689 if (!test_bit(HCI_MGMT, &hdev->dev_flags))
Johan Hedberg30dc78e2012-01-04 15:44:20 +02001690 return;
1691
Johan Hedberg56e5cb82011-11-08 20:40:16 +02001692 hci_dev_lock(hdev);
Johan Hedberg30dc78e2012-01-04 15:44:20 +02001693
Andre Guedes343f9352012-02-17 20:39:37 -03001694 if (discov->state != DISCOVERY_FINDING)
Johan Hedberg30dc78e2012-01-04 15:44:20 +02001695 goto unlock;
1696
1697 if (list_empty(&discov->resolve)) {
1698 hci_discovery_set_state(hdev, DISCOVERY_STOPPED);
1699 goto unlock;
1700 }
1701
1702 e = hci_inquiry_cache_lookup_resolve(hdev, BDADDR_ANY, NAME_NEEDED);
1703 if (e && hci_resolve_name(hdev, e) == 0) {
1704 e->name_state = NAME_PENDING;
1705 hci_discovery_set_state(hdev, DISCOVERY_RESOLVING);
1706 } else {
1707 hci_discovery_set_state(hdev, DISCOVERY_STOPPED);
1708 }
1709
1710unlock:
Johan Hedberg56e5cb82011-11-08 20:40:16 +02001711 hci_dev_unlock(hdev);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001712}
1713
Gustavo Padovan6039aa72012-05-23 04:04:18 -03001714static void hci_inquiry_result_evt(struct hci_dev *hdev, struct sk_buff *skb)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001715{
Marcel Holtmann45bb4bf2005-08-09 20:27:49 -07001716 struct inquiry_data data;
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001717 struct inquiry_info *info = (void *) (skb->data + 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001718 int num_rsp = *((__u8 *) skb->data);
1719
1720 BT_DBG("%s num_rsp %d", hdev->name, num_rsp);
1721
Marcel Holtmann45bb4bf2005-08-09 20:27:49 -07001722 if (!num_rsp)
1723 return;
1724
Andre Guedes1519cc12012-03-21 00:03:38 -03001725 if (test_bit(HCI_PERIODIC_INQ, &hdev->dev_flags))
1726 return;
1727
Linus Torvalds1da177e2005-04-16 15:20:36 -07001728 hci_dev_lock(hdev);
Marcel Holtmann45bb4bf2005-08-09 20:27:49 -07001729
Johan Hedberge17acd42011-03-30 23:57:16 +03001730 for (; num_rsp; num_rsp--, info++) {
Johan Hedberg388fc8f2012-02-23 00:38:59 +02001731 bool name_known, ssp;
Johan Hedberg31754052012-01-04 13:39:52 +02001732
Linus Torvalds1da177e2005-04-16 15:20:36 -07001733 bacpy(&data.bdaddr, &info->bdaddr);
1734 data.pscan_rep_mode = info->pscan_rep_mode;
1735 data.pscan_period_mode = info->pscan_period_mode;
1736 data.pscan_mode = info->pscan_mode;
1737 memcpy(data.dev_class, info->dev_class, 3);
1738 data.clock_offset = info->clock_offset;
1739 data.rssi = 0x00;
Marcel Holtmann41a96212008-07-14 20:13:48 +02001740 data.ssp_mode = 0x00;
Johan Hedberg31754052012-01-04 13:39:52 +02001741
Johan Hedberg388fc8f2012-02-23 00:38:59 +02001742 name_known = hci_inquiry_cache_update(hdev, &data, false, &ssp);
Johan Hedberg48264f02011-11-09 13:58:58 +02001743 mgmt_device_found(hdev, &info->bdaddr, ACL_LINK, 0x00,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001744 info->dev_class, 0, !name_known, ssp, NULL,
1745 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001746 }
Marcel Holtmann45bb4bf2005-08-09 20:27:49 -07001747
Linus Torvalds1da177e2005-04-16 15:20:36 -07001748 hci_dev_unlock(hdev);
1749}
1750
Gustavo Padovan6039aa72012-05-23 04:04:18 -03001751static void hci_conn_complete_evt(struct hci_dev *hdev, 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 Padovan6039aa72012-05-23 04:04:18 -03001829static void hci_conn_request_evt(struct hci_dev *hdev, struct sk_buff *skb)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001830{
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001831 struct hci_ev_conn_request *ev = (void *) skb->data;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001832 int mask = hdev->link_mode;
1833
Gustavo Padovan807deac2012-05-17 00:36:24 -03001834 BT_DBG("%s bdaddr %s type 0x%x", hdev->name, batostr(&ev->bdaddr),
1835 ev->link_type);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001836
1837 mask |= hci_proto_connect_ind(hdev, &ev->bdaddr, ev->link_type);
1838
Szymon Janc138d22e2011-02-17 16:44:23 +01001839 if ((mask & HCI_LM_ACCEPT) &&
Gustavo Padovan807deac2012-05-17 00:36:24 -03001840 !hci_blacklist_lookup(hdev, &ev->bdaddr)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001841 /* Connection accepted */
Marcel Holtmannc7bdd502008-07-14 20:13:47 +02001842 struct inquiry_entry *ie;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001843 struct hci_conn *conn;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001844
1845 hci_dev_lock(hdev);
Marcel Holtmannb6a0dc82007-10-20 14:55:10 +02001846
Andrei Emeltchenkocc11b9c2010-11-22 13:21:37 +02001847 ie = hci_inquiry_cache_lookup(hdev, &ev->bdaddr);
1848 if (ie)
Marcel Holtmannc7bdd502008-07-14 20:13:47 +02001849 memcpy(ie->data.dev_class, ev->dev_class, 3);
1850
Gustavo Padovan8fc9ced2012-05-23 04:04:21 -03001851 conn = hci_conn_hash_lookup_ba(hdev, ev->link_type,
1852 &ev->bdaddr);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001853 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 Padovan6039aa72012-05-23 04:04:18 -03001904static void hci_disconn_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001905{
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001906 struct hci_ev_disconn_complete *ev = (void *) skb->data;
Marcel Holtmann04837f62006-07-03 10:02:33 +02001907 struct hci_conn *conn;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001908
1909 BT_DBG("%s status %d", hdev->name, ev->status);
1910
Linus Torvalds1da177e2005-04-16 15:20:36 -07001911 hci_dev_lock(hdev);
1912
Marcel Holtmann04837f62006-07-03 10:02:33 +02001913 conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
Johan Hedbergf7520542011-01-20 12:34:39 +02001914 if (!conn)
1915 goto unlock;
Marcel Holtmann7d0db0a2008-07-14 20:13:51 +02001916
Johan Hedberg37d9ef72011-11-10 15:54:39 +02001917 if (ev->status == 0)
1918 conn->state = BT_CLOSED;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001919
Johan Hedbergb644ba32012-01-17 21:48:47 +02001920 if (test_and_clear_bit(HCI_CONN_MGMT_CONNECTED, &conn->flags) &&
Gustavo Padovan807deac2012-05-17 00:36:24 -03001921 (conn->type == ACL_LINK || conn->type == LE_LINK)) {
Johan Hedberg37d9ef72011-11-10 15:54:39 +02001922 if (ev->status != 0)
Johan Hedberg88c3df12012-02-09 14:27:38 +02001923 mgmt_disconnect_failed(hdev, &conn->dst, conn->type,
Gustavo Padovan807deac2012-05-17 00:36:24 -03001924 conn->dst_type, ev->status);
Johan Hedberg37d9ef72011-11-10 15:54:39 +02001925 else
Johan Hedbergafc747a2012-01-15 18:11:07 +02001926 mgmt_device_disconnected(hdev, &conn->dst, conn->type,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001927 conn->dst_type);
Johan Hedberg37d9ef72011-11-10 15:54:39 +02001928 }
Johan Hedbergf7520542011-01-20 12:34:39 +02001929
Johan Hedberg37d9ef72011-11-10 15:54:39 +02001930 if (ev->status == 0) {
Vishal Agarwal6ec5bca2012-04-16 14:44:44 +05301931 if (conn->type == ACL_LINK && conn->flush_key)
1932 hci_remove_link_key(hdev, &conn->dst);
Johan Hedberg37d9ef72011-11-10 15:54:39 +02001933 hci_proto_disconn_cfm(conn, ev->reason);
1934 hci_conn_del(conn);
1935 }
Johan Hedbergf7520542011-01-20 12:34:39 +02001936
1937unlock:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001938 hci_dev_unlock(hdev);
1939}
1940
Gustavo Padovan6039aa72012-05-23 04:04:18 -03001941static void hci_auth_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001942{
1943 struct hci_ev_auth_complete *ev = (void *) skb->data;
1944 struct hci_conn *conn;
1945
1946 BT_DBG("%s status %d", hdev->name, ev->status);
1947
1948 hci_dev_lock(hdev);
1949
1950 conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
Waldemar Rymarkiewiczd7556e22011-05-31 15:49:26 +02001951 if (!conn)
1952 goto unlock;
1953
1954 if (!ev->status) {
Johan Hedbergaa64a8b2012-01-18 21:33:12 +02001955 if (!hci_conn_ssp_enabled(conn) &&
Gustavo Padovan807deac2012-05-17 00:36:24 -03001956 test_bit(HCI_CONN_REAUTH_PEND, &conn->flags)) {
Waldemar Rymarkiewiczd7556e22011-05-31 15:49:26 +02001957 BT_INFO("re-auth of legacy device is not possible.");
Johan Hedberg2a611692011-02-19 12:06:00 -03001958 } else {
Waldemar Rymarkiewiczd7556e22011-05-31 15:49:26 +02001959 conn->link_mode |= HCI_LM_AUTH;
1960 conn->sec_level = conn->pending_sec_level;
Johan Hedberg2a611692011-02-19 12:06:00 -03001961 }
Waldemar Rymarkiewiczd7556e22011-05-31 15:49:26 +02001962 } else {
Johan Hedbergbab73cb2012-02-09 16:07:29 +02001963 mgmt_auth_failed(hdev, &conn->dst, conn->type, conn->dst_type,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001964 ev->status);
Waldemar Rymarkiewiczd7556e22011-05-31 15:49:26 +02001965 }
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001966
Johan Hedberg51a8efd2012-01-16 06:10:31 +02001967 clear_bit(HCI_CONN_AUTH_PEND, &conn->flags);
1968 clear_bit(HCI_CONN_REAUTH_PEND, &conn->flags);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001969
Waldemar Rymarkiewiczd7556e22011-05-31 15:49:26 +02001970 if (conn->state == BT_CONFIG) {
Johan Hedbergaa64a8b2012-01-18 21:33:12 +02001971 if (!ev->status && hci_conn_ssp_enabled(conn)) {
Waldemar Rymarkiewiczd7556e22011-05-31 15:49:26 +02001972 struct hci_cp_set_conn_encrypt cp;
1973 cp.handle = ev->handle;
1974 cp.encrypt = 0x01;
1975 hci_send_cmd(hdev, HCI_OP_SET_CONN_ENCRYPT, sizeof(cp),
Gustavo Padovan807deac2012-05-17 00:36:24 -03001976 &cp);
Marcel Holtmann052b30b2009-04-26 20:01:22 +02001977 } else {
Waldemar Rymarkiewiczd7556e22011-05-31 15:49:26 +02001978 conn->state = BT_CONNECTED;
1979 hci_proto_connect_cfm(conn, ev->status);
Marcel Holtmann052b30b2009-04-26 20:01:22 +02001980 hci_conn_put(conn);
1981 }
Waldemar Rymarkiewiczd7556e22011-05-31 15:49:26 +02001982 } else {
1983 hci_auth_cfm(conn, ev->status);
Marcel Holtmann052b30b2009-04-26 20:01:22 +02001984
Waldemar Rymarkiewiczd7556e22011-05-31 15:49:26 +02001985 hci_conn_hold(conn);
1986 conn->disc_timeout = HCI_DISCONN_TIMEOUT;
1987 hci_conn_put(conn);
1988 }
1989
Johan Hedberg51a8efd2012-01-16 06:10:31 +02001990 if (test_bit(HCI_CONN_ENCRYPT_PEND, &conn->flags)) {
Waldemar Rymarkiewiczd7556e22011-05-31 15:49:26 +02001991 if (!ev->status) {
1992 struct hci_cp_set_conn_encrypt cp;
1993 cp.handle = ev->handle;
1994 cp.encrypt = 0x01;
1995 hci_send_cmd(hdev, HCI_OP_SET_CONN_ENCRYPT, sizeof(cp),
Gustavo Padovan807deac2012-05-17 00:36:24 -03001996 &cp);
Waldemar Rymarkiewiczd7556e22011-05-31 15:49:26 +02001997 } else {
Johan Hedberg51a8efd2012-01-16 06:10:31 +02001998 clear_bit(HCI_CONN_ENCRYPT_PEND, &conn->flags);
Waldemar Rymarkiewiczd7556e22011-05-31 15:49:26 +02001999 hci_encrypt_cfm(conn, ev->status, 0x00);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002000 }
2001 }
2002
Waldemar Rymarkiewiczd7556e22011-05-31 15:49:26 +02002003unlock:
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002004 hci_dev_unlock(hdev);
2005}
2006
Gustavo Padovan6039aa72012-05-23 04:04:18 -03002007static void hci_remote_name_evt(struct hci_dev *hdev, struct sk_buff *skb)
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002008{
Johan Hedberg127178d2010-11-18 22:22:29 +02002009 struct hci_ev_remote_name *ev = (void *) skb->data;
2010 struct hci_conn *conn;
2011
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002012 BT_DBG("%s", hdev->name);
2013
2014 hci_conn_check_pending(hdev);
Johan Hedberg127178d2010-11-18 22:22:29 +02002015
2016 hci_dev_lock(hdev);
2017
2018 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
Johan Hedbergb644ba32012-01-17 21:48:47 +02002019
2020 if (!test_bit(HCI_MGMT, &hdev->dev_flags))
2021 goto check_auth;
2022
2023 if (ev->status == 0)
2024 hci_check_pending_name(hdev, conn, &ev->bdaddr, ev->name,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002025 strnlen(ev->name, HCI_MAX_NAME_LENGTH));
Johan Hedbergb644ba32012-01-17 21:48:47 +02002026 else
2027 hci_check_pending_name(hdev, conn, &ev->bdaddr, NULL, 0);
2028
2029check_auth:
Johan Hedberg79c6c702011-04-28 11:28:55 -07002030 if (!conn)
2031 goto unlock;
2032
2033 if (!hci_outgoing_auth_needed(hdev, conn))
2034 goto unlock;
2035
Johan Hedberg51a8efd2012-01-16 06:10:31 +02002036 if (!test_and_set_bit(HCI_CONN_AUTH_PEND, &conn->flags)) {
Johan Hedberg127178d2010-11-18 22:22:29 +02002037 struct hci_cp_auth_requested cp;
2038 cp.handle = __cpu_to_le16(conn->handle);
2039 hci_send_cmd(hdev, HCI_OP_AUTH_REQUESTED, sizeof(cp), &cp);
2040 }
2041
Johan Hedberg79c6c702011-04-28 11:28:55 -07002042unlock:
Johan Hedberg127178d2010-11-18 22:22:29 +02002043 hci_dev_unlock(hdev);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002044}
2045
Gustavo Padovan6039aa72012-05-23 04:04:18 -03002046static void hci_encrypt_change_evt(struct hci_dev *hdev, struct sk_buff *skb)
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002047{
2048 struct hci_ev_encrypt_change *ev = (void *) skb->data;
2049 struct hci_conn *conn;
2050
2051 BT_DBG("%s status %d", hdev->name, ev->status);
2052
2053 hci_dev_lock(hdev);
2054
2055 conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
2056 if (conn) {
2057 if (!ev->status) {
Marcel Holtmannae293192008-07-14 20:13:45 +02002058 if (ev->encrypt) {
2059 /* Encryption implies authentication */
2060 conn->link_mode |= HCI_LM_AUTH;
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002061 conn->link_mode |= HCI_LM_ENCRYPT;
Vinicius Costa Gomesda85e5e2011-06-09 18:50:53 -03002062 conn->sec_level = conn->pending_sec_level;
Marcel Holtmannae293192008-07-14 20:13:45 +02002063 } else
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002064 conn->link_mode &= ~HCI_LM_ENCRYPT;
2065 }
2066
Johan Hedberg51a8efd2012-01-16 06:10:31 +02002067 clear_bit(HCI_CONN_ENCRYPT_PEND, &conn->flags);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002068
Gustavo Padovana7d77232012-05-13 03:20:07 -03002069 if (ev->status && conn->state == BT_CONNECTED) {
Gustavo Padovand839c812012-05-16 12:17:12 -03002070 hci_acl_disconn(conn, HCI_ERROR_AUTH_FAILURE);
Gustavo Padovana7d77232012-05-13 03:20:07 -03002071 hci_conn_put(conn);
2072 goto unlock;
2073 }
2074
Marcel Holtmannf8558552008-07-14 20:13:49 +02002075 if (conn->state == BT_CONFIG) {
2076 if (!ev->status)
2077 conn->state = BT_CONNECTED;
2078
2079 hci_proto_connect_cfm(conn, ev->status);
2080 hci_conn_put(conn);
2081 } else
2082 hci_encrypt_cfm(conn, ev->status, ev->encrypt);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002083 }
2084
Gustavo Padovana7d77232012-05-13 03:20:07 -03002085unlock:
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002086 hci_dev_unlock(hdev);
2087}
2088
Gustavo Padovan6039aa72012-05-23 04:04:18 -03002089static void hci_change_link_key_complete_evt(struct hci_dev *hdev,
2090 struct sk_buff *skb)
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002091{
2092 struct hci_ev_change_link_key_complete *ev = (void *) skb->data;
2093 struct hci_conn *conn;
2094
2095 BT_DBG("%s status %d", hdev->name, ev->status);
2096
2097 hci_dev_lock(hdev);
2098
2099 conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
2100 if (conn) {
2101 if (!ev->status)
2102 conn->link_mode |= HCI_LM_SECURE;
2103
Johan Hedberg51a8efd2012-01-16 06:10:31 +02002104 clear_bit(HCI_CONN_AUTH_PEND, &conn->flags);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002105
2106 hci_key_change_cfm(conn, ev->status);
2107 }
2108
2109 hci_dev_unlock(hdev);
2110}
2111
Gustavo Padovan6039aa72012-05-23 04:04:18 -03002112static void hci_remote_features_evt(struct hci_dev *hdev,
2113 struct sk_buff *skb)
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002114{
2115 struct hci_ev_remote_features *ev = (void *) skb->data;
2116 struct hci_conn *conn;
2117
2118 BT_DBG("%s status %d", hdev->name, ev->status);
2119
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002120 hci_dev_lock(hdev);
2121
2122 conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
Johan Hedbergccd556f2010-11-10 17:11:51 +02002123 if (!conn)
2124 goto unlock;
Marcel Holtmann769be972008-07-14 20:13:49 +02002125
Johan Hedbergccd556f2010-11-10 17:11:51 +02002126 if (!ev->status)
2127 memcpy(conn->features, ev->features, 8);
2128
2129 if (conn->state != BT_CONFIG)
2130 goto unlock;
2131
2132 if (!ev->status && lmp_ssp_capable(hdev) && lmp_ssp_capable(conn)) {
2133 struct hci_cp_read_remote_ext_features cp;
2134 cp.handle = ev->handle;
2135 cp.page = 0x01;
2136 hci_send_cmd(hdev, HCI_OP_READ_REMOTE_EXT_FEATURES,
Gustavo Padovan807deac2012-05-17 00:36:24 -03002137 sizeof(cp), &cp);
Johan Hedberg392599b2010-11-18 22:22:28 +02002138 goto unlock;
2139 }
2140
Johan Hedberg671267b2012-05-12 16:11:50 -03002141 if (!ev->status && !test_bit(HCI_CONN_MGMT_CONNECTED, &conn->flags)) {
Johan Hedberg127178d2010-11-18 22:22:29 +02002142 struct hci_cp_remote_name_req cp;
2143 memset(&cp, 0, sizeof(cp));
2144 bacpy(&cp.bdaddr, &conn->dst);
2145 cp.pscan_rep_mode = 0x02;
2146 hci_send_cmd(hdev, HCI_OP_REMOTE_NAME_REQ, sizeof(cp), &cp);
Johan Hedbergb644ba32012-01-17 21:48:47 +02002147 } else if (!test_and_set_bit(HCI_CONN_MGMT_CONNECTED, &conn->flags))
2148 mgmt_device_connected(hdev, &conn->dst, conn->type,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002149 conn->dst_type, 0, NULL, 0,
2150 conn->dev_class);
Johan Hedberg392599b2010-11-18 22:22:28 +02002151
Johan Hedberg127178d2010-11-18 22:22:29 +02002152 if (!hci_outgoing_auth_needed(hdev, conn)) {
Johan Hedbergccd556f2010-11-10 17:11:51 +02002153 conn->state = BT_CONNECTED;
2154 hci_proto_connect_cfm(conn, ev->status);
2155 hci_conn_put(conn);
Marcel Holtmann769be972008-07-14 20:13:49 +02002156 }
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002157
Johan Hedbergccd556f2010-11-10 17:11:51 +02002158unlock:
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002159 hci_dev_unlock(hdev);
2160}
2161
Gustavo Padovan6039aa72012-05-23 04:04:18 -03002162static void hci_remote_version_evt(struct hci_dev *hdev, struct sk_buff *skb)
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002163{
2164 BT_DBG("%s", hdev->name);
2165}
2166
Gustavo Padovan6039aa72012-05-23 04:04:18 -03002167static void hci_qos_setup_complete_evt(struct hci_dev *hdev,
2168 struct sk_buff *skb)
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002169{
2170 BT_DBG("%s", hdev->name);
2171}
2172
Gustavo Padovan6039aa72012-05-23 04:04:18 -03002173static void hci_cmd_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002174{
2175 struct hci_ev_cmd_complete *ev = (void *) skb->data;
2176 __u16 opcode;
2177
2178 skb_pull(skb, sizeof(*ev));
2179
2180 opcode = __le16_to_cpu(ev->opcode);
2181
2182 switch (opcode) {
2183 case HCI_OP_INQUIRY_CANCEL:
2184 hci_cc_inquiry_cancel(hdev, skb);
2185 break;
2186
Andre Guedes4d934832012-03-21 00:03:35 -03002187 case HCI_OP_PERIODIC_INQ:
2188 hci_cc_periodic_inq(hdev, skb);
2189 break;
2190
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002191 case HCI_OP_EXIT_PERIODIC_INQ:
2192 hci_cc_exit_periodic_inq(hdev, skb);
2193 break;
2194
2195 case HCI_OP_REMOTE_NAME_REQ_CANCEL:
2196 hci_cc_remote_name_req_cancel(hdev, skb);
2197 break;
2198
2199 case HCI_OP_ROLE_DISCOVERY:
2200 hci_cc_role_discovery(hdev, skb);
2201 break;
2202
Marcel Holtmanne4e8e372008-07-14 20:13:47 +02002203 case HCI_OP_READ_LINK_POLICY:
2204 hci_cc_read_link_policy(hdev, skb);
2205 break;
2206
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002207 case HCI_OP_WRITE_LINK_POLICY:
2208 hci_cc_write_link_policy(hdev, skb);
2209 break;
2210
Marcel Holtmanne4e8e372008-07-14 20:13:47 +02002211 case HCI_OP_READ_DEF_LINK_POLICY:
2212 hci_cc_read_def_link_policy(hdev, skb);
2213 break;
2214
2215 case HCI_OP_WRITE_DEF_LINK_POLICY:
2216 hci_cc_write_def_link_policy(hdev, skb);
2217 break;
2218
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002219 case HCI_OP_RESET:
2220 hci_cc_reset(hdev, skb);
2221 break;
2222
2223 case HCI_OP_WRITE_LOCAL_NAME:
2224 hci_cc_write_local_name(hdev, skb);
2225 break;
2226
2227 case HCI_OP_READ_LOCAL_NAME:
2228 hci_cc_read_local_name(hdev, skb);
2229 break;
2230
2231 case HCI_OP_WRITE_AUTH_ENABLE:
2232 hci_cc_write_auth_enable(hdev, skb);
2233 break;
2234
2235 case HCI_OP_WRITE_ENCRYPT_MODE:
2236 hci_cc_write_encrypt_mode(hdev, skb);
2237 break;
2238
2239 case HCI_OP_WRITE_SCAN_ENABLE:
2240 hci_cc_write_scan_enable(hdev, skb);
2241 break;
2242
2243 case HCI_OP_READ_CLASS_OF_DEV:
2244 hci_cc_read_class_of_dev(hdev, skb);
2245 break;
2246
2247 case HCI_OP_WRITE_CLASS_OF_DEV:
2248 hci_cc_write_class_of_dev(hdev, skb);
2249 break;
2250
2251 case HCI_OP_READ_VOICE_SETTING:
2252 hci_cc_read_voice_setting(hdev, skb);
2253 break;
2254
2255 case HCI_OP_WRITE_VOICE_SETTING:
2256 hci_cc_write_voice_setting(hdev, skb);
2257 break;
2258
2259 case HCI_OP_HOST_BUFFER_SIZE:
2260 hci_cc_host_buffer_size(hdev, skb);
2261 break;
2262
Marcel Holtmann333140b2008-07-14 20:13:48 +02002263 case HCI_OP_WRITE_SSP_MODE:
2264 hci_cc_write_ssp_mode(hdev, skb);
2265 break;
2266
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002267 case HCI_OP_READ_LOCAL_VERSION:
2268 hci_cc_read_local_version(hdev, skb);
2269 break;
2270
2271 case HCI_OP_READ_LOCAL_COMMANDS:
2272 hci_cc_read_local_commands(hdev, skb);
2273 break;
2274
2275 case HCI_OP_READ_LOCAL_FEATURES:
2276 hci_cc_read_local_features(hdev, skb);
2277 break;
2278
Andre Guedes971e3a42011-06-30 19:20:52 -03002279 case HCI_OP_READ_LOCAL_EXT_FEATURES:
2280 hci_cc_read_local_ext_features(hdev, skb);
2281 break;
2282
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002283 case HCI_OP_READ_BUFFER_SIZE:
2284 hci_cc_read_buffer_size(hdev, skb);
2285 break;
2286
2287 case HCI_OP_READ_BD_ADDR:
2288 hci_cc_read_bd_addr(hdev, skb);
2289 break;
2290
Andrei Emeltchenko350ee4c2011-12-07 15:56:51 +02002291 case HCI_OP_READ_DATA_BLOCK_SIZE:
2292 hci_cc_read_data_block_size(hdev, skb);
2293 break;
2294
Johan Hedberg23bb5762010-12-21 23:01:27 +02002295 case HCI_OP_WRITE_CA_TIMEOUT:
2296 hci_cc_write_ca_timeout(hdev, skb);
2297 break;
2298
Andrei Emeltchenko1e89cff2011-11-24 14:52:02 +02002299 case HCI_OP_READ_FLOW_CONTROL_MODE:
2300 hci_cc_read_flow_control_mode(hdev, skb);
2301 break;
2302
Andrei Emeltchenko928abaa2011-10-12 10:53:57 +03002303 case HCI_OP_READ_LOCAL_AMP_INFO:
2304 hci_cc_read_local_amp_info(hdev, skb);
2305 break;
2306
Johan Hedbergb0916ea2011-01-10 13:44:55 +02002307 case HCI_OP_DELETE_STORED_LINK_KEY:
2308 hci_cc_delete_stored_link_key(hdev, skb);
2309 break;
2310
Johan Hedbergd5859e22011-01-25 01:19:58 +02002311 case HCI_OP_SET_EVENT_MASK:
2312 hci_cc_set_event_mask(hdev, skb);
2313 break;
2314
2315 case HCI_OP_WRITE_INQUIRY_MODE:
2316 hci_cc_write_inquiry_mode(hdev, skb);
2317 break;
2318
2319 case HCI_OP_READ_INQ_RSP_TX_POWER:
2320 hci_cc_read_inq_rsp_tx_power(hdev, skb);
2321 break;
2322
2323 case HCI_OP_SET_EVENT_FLT:
2324 hci_cc_set_event_flt(hdev, skb);
2325 break;
2326
Johan Hedberg980e1a52011-01-22 06:10:07 +02002327 case HCI_OP_PIN_CODE_REPLY:
2328 hci_cc_pin_code_reply(hdev, skb);
2329 break;
2330
2331 case HCI_OP_PIN_CODE_NEG_REPLY:
2332 hci_cc_pin_code_neg_reply(hdev, skb);
2333 break;
2334
Szymon Jancc35938b2011-03-22 13:12:21 +01002335 case HCI_OP_READ_LOCAL_OOB_DATA:
2336 hci_cc_read_local_oob_data_reply(hdev, skb);
2337 break;
2338
Ville Tervo6ed58ec2011-02-10 22:38:48 -03002339 case HCI_OP_LE_READ_BUFFER_SIZE:
2340 hci_cc_le_read_buffer_size(hdev, skb);
2341 break;
2342
Johan Hedberga5c29682011-02-19 12:05:57 -03002343 case HCI_OP_USER_CONFIRM_REPLY:
2344 hci_cc_user_confirm_reply(hdev, skb);
2345 break;
2346
2347 case HCI_OP_USER_CONFIRM_NEG_REPLY:
2348 hci_cc_user_confirm_neg_reply(hdev, skb);
2349 break;
2350
Brian Gix1143d452011-11-23 08:28:34 -08002351 case HCI_OP_USER_PASSKEY_REPLY:
2352 hci_cc_user_passkey_reply(hdev, skb);
2353 break;
2354
2355 case HCI_OP_USER_PASSKEY_NEG_REPLY:
2356 hci_cc_user_passkey_neg_reply(hdev, skb);
Szymon Janc16cde992012-04-13 12:32:42 +02002357 break;
Andre Guedes07f7fa52011-12-02 21:13:31 +09002358
2359 case HCI_OP_LE_SET_SCAN_PARAM:
2360 hci_cc_le_set_scan_param(hdev, skb);
Brian Gix1143d452011-11-23 08:28:34 -08002361 break;
2362
Andre Guedeseb9d91f2011-05-26 16:23:52 -03002363 case HCI_OP_LE_SET_SCAN_ENABLE:
2364 hci_cc_le_set_scan_enable(hdev, skb);
2365 break;
2366
Vinicius Costa Gomesa7a595f2011-06-09 18:50:47 -03002367 case HCI_OP_LE_LTK_REPLY:
2368 hci_cc_le_ltk_reply(hdev, skb);
2369 break;
2370
2371 case HCI_OP_LE_LTK_NEG_REPLY:
2372 hci_cc_le_ltk_neg_reply(hdev, skb);
2373 break;
2374
Andre Guedesf9b49302011-06-30 19:20:53 -03002375 case HCI_OP_WRITE_LE_HOST_SUPPORTED:
2376 hci_cc_write_le_host_supported(hdev, skb);
2377 break;
2378
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002379 default:
2380 BT_DBG("%s opcode 0x%x", hdev->name, opcode);
2381 break;
2382 }
2383
Ville Tervo6bd32322011-02-16 16:32:41 +02002384 if (ev->opcode != HCI_OP_NOP)
2385 del_timer(&hdev->cmd_timer);
2386
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002387 if (ev->ncmd) {
2388 atomic_set(&hdev->cmd_cnt, 1);
2389 if (!skb_queue_empty(&hdev->cmd_q))
Gustavo F. Padovanc347b762011-12-14 23:53:47 -02002390 queue_work(hdev->workqueue, &hdev->cmd_work);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002391 }
2392}
2393
Gustavo Padovan6039aa72012-05-23 04:04:18 -03002394static void hci_cmd_status_evt(struct hci_dev *hdev, struct sk_buff *skb)
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002395{
2396 struct hci_ev_cmd_status *ev = (void *) skb->data;
2397 __u16 opcode;
2398
2399 skb_pull(skb, sizeof(*ev));
2400
2401 opcode = __le16_to_cpu(ev->opcode);
2402
2403 switch (opcode) {
2404 case HCI_OP_INQUIRY:
2405 hci_cs_inquiry(hdev, ev->status);
2406 break;
2407
2408 case HCI_OP_CREATE_CONN:
2409 hci_cs_create_conn(hdev, ev->status);
2410 break;
2411
2412 case HCI_OP_ADD_SCO:
2413 hci_cs_add_sco(hdev, ev->status);
2414 break;
2415
Marcel Holtmannf8558552008-07-14 20:13:49 +02002416 case HCI_OP_AUTH_REQUESTED:
2417 hci_cs_auth_requested(hdev, ev->status);
2418 break;
2419
2420 case HCI_OP_SET_CONN_ENCRYPT:
2421 hci_cs_set_conn_encrypt(hdev, ev->status);
2422 break;
2423
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002424 case HCI_OP_REMOTE_NAME_REQ:
2425 hci_cs_remote_name_req(hdev, ev->status);
2426 break;
2427
Marcel Holtmann769be972008-07-14 20:13:49 +02002428 case HCI_OP_READ_REMOTE_FEATURES:
2429 hci_cs_read_remote_features(hdev, ev->status);
2430 break;
2431
2432 case HCI_OP_READ_REMOTE_EXT_FEATURES:
2433 hci_cs_read_remote_ext_features(hdev, ev->status);
2434 break;
2435
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002436 case HCI_OP_SETUP_SYNC_CONN:
2437 hci_cs_setup_sync_conn(hdev, ev->status);
2438 break;
2439
2440 case HCI_OP_SNIFF_MODE:
2441 hci_cs_sniff_mode(hdev, ev->status);
2442 break;
2443
2444 case HCI_OP_EXIT_SNIFF_MODE:
2445 hci_cs_exit_sniff_mode(hdev, ev->status);
2446 break;
2447
Johan Hedberg8962ee72011-01-20 12:40:27 +02002448 case HCI_OP_DISCONNECT:
Johan Hedberg88c3df12012-02-09 14:27:38 +02002449 hci_cs_disconnect(hdev, ev->status);
Johan Hedberg8962ee72011-01-20 12:40:27 +02002450 break;
2451
Ville Tervofcd89c02011-02-10 22:38:47 -03002452 case HCI_OP_LE_CREATE_CONN:
2453 hci_cs_le_create_conn(hdev, ev->status);
2454 break;
2455
Vinicius Costa Gomesa7a595f2011-06-09 18:50:47 -03002456 case HCI_OP_LE_START_ENC:
2457 hci_cs_le_start_enc(hdev, ev->status);
2458 break;
2459
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002460 default:
2461 BT_DBG("%s opcode 0x%x", hdev->name, opcode);
2462 break;
2463 }
2464
Ville Tervo6bd32322011-02-16 16:32:41 +02002465 if (ev->opcode != HCI_OP_NOP)
2466 del_timer(&hdev->cmd_timer);
2467
Gustavo F. Padovan10572132011-03-16 15:36:29 -03002468 if (ev->ncmd && !test_bit(HCI_RESET, &hdev->flags)) {
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002469 atomic_set(&hdev->cmd_cnt, 1);
2470 if (!skb_queue_empty(&hdev->cmd_q))
Gustavo F. Padovanc347b762011-12-14 23:53:47 -02002471 queue_work(hdev->workqueue, &hdev->cmd_work);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002472 }
2473}
2474
Gustavo Padovan6039aa72012-05-23 04:04:18 -03002475static void hci_role_change_evt(struct hci_dev *hdev, struct sk_buff *skb)
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002476{
2477 struct hci_ev_role_change *ev = (void *) skb->data;
2478 struct hci_conn *conn;
2479
2480 BT_DBG("%s status %d", hdev->name, ev->status);
2481
2482 hci_dev_lock(hdev);
2483
2484 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
2485 if (conn) {
2486 if (!ev->status) {
2487 if (ev->role)
2488 conn->link_mode &= ~HCI_LM_MASTER;
2489 else
2490 conn->link_mode |= HCI_LM_MASTER;
2491 }
2492
Johan Hedberg51a8efd2012-01-16 06:10:31 +02002493 clear_bit(HCI_CONN_RSWITCH_PEND, &conn->flags);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002494
2495 hci_role_switch_cfm(conn, ev->status, ev->role);
2496 }
2497
2498 hci_dev_unlock(hdev);
2499}
2500
Gustavo Padovan6039aa72012-05-23 04:04:18 -03002501static void hci_num_comp_pkts_evt(struct hci_dev *hdev, struct sk_buff *skb)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002502{
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002503 struct hci_ev_num_comp_pkts *ev = (void *) skb->data;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002504 int i;
2505
Andrei Emeltchenko32ac5b92011-12-19 16:31:29 +02002506 if (hdev->flow_ctl_mode != HCI_FLOW_CTL_MODE_PACKET_BASED) {
2507 BT_ERR("Wrong event for mode %d", hdev->flow_ctl_mode);
2508 return;
2509 }
2510
Andrei Emeltchenkoc5993de2011-12-30 12:07:47 +02002511 if (skb->len < sizeof(*ev) || skb->len < sizeof(*ev) +
Gustavo Padovan807deac2012-05-17 00:36:24 -03002512 ev->num_hndl * sizeof(struct hci_comp_pkts_info)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002513 BT_DBG("%s bad parameters", hdev->name);
2514 return;
2515 }
2516
Andrei Emeltchenkoc5993de2011-12-30 12:07:47 +02002517 BT_DBG("%s num_hndl %d", hdev->name, ev->num_hndl);
2518
Andrei Emeltchenko613a1c02011-12-19 16:31:30 +02002519 for (i = 0; i < ev->num_hndl; i++) {
2520 struct hci_comp_pkts_info *info = &ev->handles[i];
Linus Torvalds1da177e2005-04-16 15:20:36 -07002521 struct hci_conn *conn;
2522 __u16 handle, count;
2523
Andrei Emeltchenko613a1c02011-12-19 16:31:30 +02002524 handle = __le16_to_cpu(info->handle);
2525 count = __le16_to_cpu(info->count);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002526
2527 conn = hci_conn_hash_lookup_handle(hdev, handle);
Andrei Emeltchenkof4280912011-12-07 15:56:52 +02002528 if (!conn)
2529 continue;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002530
Andrei Emeltchenkof4280912011-12-07 15:56:52 +02002531 conn->sent -= count;
2532
2533 switch (conn->type) {
2534 case ACL_LINK:
2535 hdev->acl_cnt += count;
2536 if (hdev->acl_cnt > hdev->acl_pkts)
2537 hdev->acl_cnt = hdev->acl_pkts;
2538 break;
2539
2540 case LE_LINK:
2541 if (hdev->le_pkts) {
2542 hdev->le_cnt += count;
2543 if (hdev->le_cnt > hdev->le_pkts)
2544 hdev->le_cnt = hdev->le_pkts;
2545 } else {
Andrei Emeltchenko70f230202010-12-01 16:58:25 +02002546 hdev->acl_cnt += count;
2547 if (hdev->acl_cnt > hdev->acl_pkts)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002548 hdev->acl_cnt = hdev->acl_pkts;
2549 }
Andrei Emeltchenkof4280912011-12-07 15:56:52 +02002550 break;
2551
2552 case SCO_LINK:
2553 hdev->sco_cnt += count;
2554 if (hdev->sco_cnt > hdev->sco_pkts)
2555 hdev->sco_cnt = hdev->sco_pkts;
2556 break;
2557
2558 default:
2559 BT_ERR("Unknown type %d conn %p", conn->type, conn);
2560 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002561 }
2562 }
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002563
Gustavo F. Padovan3eff45e2011-12-15 00:50:02 -02002564 queue_work(hdev->workqueue, &hdev->tx_work);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002565}
2566
Gustavo Padovan6039aa72012-05-23 04:04:18 -03002567static void hci_num_comp_blocks_evt(struct hci_dev *hdev, struct sk_buff *skb)
Andrei Emeltchenko25e89e92012-01-04 12:41:58 +02002568{
2569 struct hci_ev_num_comp_blocks *ev = (void *) skb->data;
2570 int i;
2571
2572 if (hdev->flow_ctl_mode != HCI_FLOW_CTL_MODE_BLOCK_BASED) {
2573 BT_ERR("Wrong event for mode %d", hdev->flow_ctl_mode);
2574 return;
2575 }
2576
2577 if (skb->len < sizeof(*ev) || skb->len < sizeof(*ev) +
Gustavo Padovan807deac2012-05-17 00:36:24 -03002578 ev->num_hndl * sizeof(struct hci_comp_blocks_info)) {
Andrei Emeltchenko25e89e92012-01-04 12:41:58 +02002579 BT_DBG("%s bad parameters", hdev->name);
2580 return;
2581 }
2582
2583 BT_DBG("%s num_blocks %d num_hndl %d", hdev->name, ev->num_blocks,
Gustavo Padovan807deac2012-05-17 00:36:24 -03002584 ev->num_hndl);
Andrei Emeltchenko25e89e92012-01-04 12:41:58 +02002585
2586 for (i = 0; i < ev->num_hndl; i++) {
2587 struct hci_comp_blocks_info *info = &ev->handles[i];
2588 struct hci_conn *conn;
2589 __u16 handle, block_count;
2590
2591 handle = __le16_to_cpu(info->handle);
2592 block_count = __le16_to_cpu(info->blocks);
2593
2594 conn = hci_conn_hash_lookup_handle(hdev, handle);
2595 if (!conn)
2596 continue;
2597
2598 conn->sent -= block_count;
2599
2600 switch (conn->type) {
2601 case ACL_LINK:
2602 hdev->block_cnt += block_count;
2603 if (hdev->block_cnt > hdev->num_blocks)
2604 hdev->block_cnt = hdev->num_blocks;
2605 break;
2606
2607 default:
2608 BT_ERR("Unknown type %d conn %p", conn->type, conn);
2609 break;
2610 }
2611 }
2612
2613 queue_work(hdev->workqueue, &hdev->tx_work);
2614}
2615
Gustavo Padovan6039aa72012-05-23 04:04:18 -03002616static void hci_mode_change_evt(struct hci_dev *hdev, struct sk_buff *skb)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002617{
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002618 struct hci_ev_mode_change *ev = (void *) skb->data;
Marcel Holtmann04837f62006-07-03 10:02:33 +02002619 struct hci_conn *conn;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002620
2621 BT_DBG("%s status %d", hdev->name, ev->status);
2622
2623 hci_dev_lock(hdev);
2624
Marcel Holtmann04837f62006-07-03 10:02:33 +02002625 conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
2626 if (conn) {
2627 conn->mode = ev->mode;
2628 conn->interval = __le16_to_cpu(ev->interval);
2629
Gustavo Padovan8fc9ced2012-05-23 04:04:21 -03002630 if (!test_and_clear_bit(HCI_CONN_MODE_CHANGE_PEND,
2631 &conn->flags)) {
Marcel Holtmann04837f62006-07-03 10:02:33 +02002632 if (conn->mode == HCI_CM_ACTIVE)
Johan Hedberg58a681e2012-01-16 06:47:28 +02002633 set_bit(HCI_CONN_POWER_SAVE, &conn->flags);
Marcel Holtmann04837f62006-07-03 10:02:33 +02002634 else
Johan Hedberg58a681e2012-01-16 06:47:28 +02002635 clear_bit(HCI_CONN_POWER_SAVE, &conn->flags);
Marcel Holtmann04837f62006-07-03 10:02:33 +02002636 }
Marcel Holtmanne73439d2010-07-26 10:06:00 -04002637
Johan Hedberg51a8efd2012-01-16 06:10:31 +02002638 if (test_and_clear_bit(HCI_CONN_SCO_SETUP_PEND, &conn->flags))
Marcel Holtmanne73439d2010-07-26 10:06:00 -04002639 hci_sco_setup(conn, ev->status);
Marcel Holtmann04837f62006-07-03 10:02:33 +02002640 }
2641
2642 hci_dev_unlock(hdev);
2643}
2644
Gustavo Padovan6039aa72012-05-23 04:04:18 -03002645static void hci_pin_code_request_evt(struct hci_dev *hdev, struct sk_buff *skb)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002646{
Marcel Holtmann052b30b2009-04-26 20:01:22 +02002647 struct hci_ev_pin_code_req *ev = (void *) skb->data;
2648 struct hci_conn *conn;
2649
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002650 BT_DBG("%s", hdev->name);
Marcel Holtmann052b30b2009-04-26 20:01:22 +02002651
2652 hci_dev_lock(hdev);
2653
2654 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
Waldemar Rymarkiewiczb6f98042011-09-23 10:01:30 +02002655 if (!conn)
2656 goto unlock;
2657
2658 if (conn->state == BT_CONNECTED) {
Marcel Holtmann052b30b2009-04-26 20:01:22 +02002659 hci_conn_hold(conn);
2660 conn->disc_timeout = HCI_PAIRING_TIMEOUT;
2661 hci_conn_put(conn);
2662 }
2663
Johan Hedberga8b2d5c2012-01-08 23:11:15 +02002664 if (!test_bit(HCI_PAIRABLE, &hdev->dev_flags))
Johan Hedberg03b555e2011-01-04 15:40:05 +02002665 hci_send_cmd(hdev, HCI_OP_PIN_CODE_NEG_REPLY,
Gustavo Padovan807deac2012-05-17 00:36:24 -03002666 sizeof(ev->bdaddr), &ev->bdaddr);
Johan Hedberga8b2d5c2012-01-08 23:11:15 +02002667 else if (test_bit(HCI_MGMT, &hdev->dev_flags)) {
Waldemar Rymarkiewicza770bb52011-04-28 12:07:59 +02002668 u8 secure;
2669
2670 if (conn->pending_sec_level == BT_SECURITY_HIGH)
2671 secure = 1;
2672 else
2673 secure = 0;
2674
Johan Hedberg744cf192011-11-08 20:40:14 +02002675 mgmt_pin_code_request(hdev, &ev->bdaddr, secure);
Waldemar Rymarkiewicza770bb52011-04-28 12:07:59 +02002676 }
Johan Hedberg980e1a52011-01-22 06:10:07 +02002677
Waldemar Rymarkiewiczb6f98042011-09-23 10:01:30 +02002678unlock:
Marcel Holtmann052b30b2009-04-26 20:01:22 +02002679 hci_dev_unlock(hdev);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002680}
2681
Gustavo Padovan6039aa72012-05-23 04:04:18 -03002682static void hci_link_key_request_evt(struct hci_dev *hdev, struct sk_buff *skb)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002683{
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002684 struct hci_ev_link_key_req *ev = (void *) skb->data;
2685 struct hci_cp_link_key_reply cp;
2686 struct hci_conn *conn;
2687 struct link_key *key;
2688
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002689 BT_DBG("%s", hdev->name);
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002690
Johan Hedberga8b2d5c2012-01-08 23:11:15 +02002691 if (!test_bit(HCI_LINK_KEYS, &hdev->dev_flags))
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002692 return;
2693
2694 hci_dev_lock(hdev);
2695
2696 key = hci_find_link_key(hdev, &ev->bdaddr);
2697 if (!key) {
2698 BT_DBG("%s link key not found for %s", hdev->name,
Gustavo Padovan807deac2012-05-17 00:36:24 -03002699 batostr(&ev->bdaddr));
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002700 goto not_found;
2701 }
2702
2703 BT_DBG("%s found key type %u for %s", hdev->name, key->type,
Gustavo Padovan807deac2012-05-17 00:36:24 -03002704 batostr(&ev->bdaddr));
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002705
Johan Hedberga8b2d5c2012-01-08 23:11:15 +02002706 if (!test_bit(HCI_DEBUG_KEYS, &hdev->dev_flags) &&
Gustavo Padovan807deac2012-05-17 00:36:24 -03002707 key->type == HCI_LK_DEBUG_COMBINATION) {
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002708 BT_DBG("%s ignoring debug key", hdev->name);
2709 goto not_found;
2710 }
2711
2712 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
Waldemar Rymarkiewicz60b83f52011-04-28 12:07:56 +02002713 if (conn) {
2714 if (key->type == HCI_LK_UNAUTH_COMBINATION &&
Gustavo Padovan807deac2012-05-17 00:36:24 -03002715 conn->auth_type != 0xff && (conn->auth_type & 0x01)) {
Waldemar Rymarkiewicz60b83f52011-04-28 12:07:56 +02002716 BT_DBG("%s ignoring unauthenticated key", hdev->name);
2717 goto not_found;
2718 }
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002719
Waldemar Rymarkiewicz60b83f52011-04-28 12:07:56 +02002720 if (key->type == HCI_LK_COMBINATION && key->pin_len < 16 &&
Gustavo Padovan807deac2012-05-17 00:36:24 -03002721 conn->pending_sec_level == BT_SECURITY_HIGH) {
Gustavo Padovan8fc9ced2012-05-23 04:04:21 -03002722 BT_DBG("%s ignoring key unauthenticated for high security",
2723 hdev->name);
Waldemar Rymarkiewicz60b83f52011-04-28 12:07:56 +02002724 goto not_found;
2725 }
2726
2727 conn->key_type = key->type;
2728 conn->pin_length = key->pin_len;
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002729 }
2730
2731 bacpy(&cp.bdaddr, &ev->bdaddr);
Andrei Emeltchenko9b3b4462012-05-23 11:31:20 +03002732 memcpy(cp.link_key, key->val, HCI_LINK_KEY_SIZE);
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002733
2734 hci_send_cmd(hdev, HCI_OP_LINK_KEY_REPLY, sizeof(cp), &cp);
2735
2736 hci_dev_unlock(hdev);
2737
2738 return;
2739
2740not_found:
2741 hci_send_cmd(hdev, HCI_OP_LINK_KEY_NEG_REPLY, 6, &ev->bdaddr);
2742 hci_dev_unlock(hdev);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002743}
2744
Gustavo Padovan6039aa72012-05-23 04:04:18 -03002745static void hci_link_key_notify_evt(struct hci_dev *hdev, struct sk_buff *skb)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002746{
Marcel Holtmann052b30b2009-04-26 20:01:22 +02002747 struct hci_ev_link_key_notify *ev = (void *) skb->data;
2748 struct hci_conn *conn;
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002749 u8 pin_len = 0;
Marcel Holtmann052b30b2009-04-26 20:01:22 +02002750
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002751 BT_DBG("%s", hdev->name);
Marcel Holtmann052b30b2009-04-26 20:01:22 +02002752
2753 hci_dev_lock(hdev);
2754
2755 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
2756 if (conn) {
2757 hci_conn_hold(conn);
2758 conn->disc_timeout = HCI_DISCONN_TIMEOUT;
Johan Hedberg980e1a52011-01-22 06:10:07 +02002759 pin_len = conn->pin_length;
Waldemar Rymarkiewicz13d39312011-04-28 12:07:55 +02002760
2761 if (ev->key_type != HCI_LK_CHANGED_COMBINATION)
2762 conn->key_type = ev->key_type;
2763
Marcel Holtmann052b30b2009-04-26 20:01:22 +02002764 hci_conn_put(conn);
2765 }
2766
Johan Hedberga8b2d5c2012-01-08 23:11:15 +02002767 if (test_bit(HCI_LINK_KEYS, &hdev->dev_flags))
Johan Hedbergd25e28a2011-04-28 11:28:59 -07002768 hci_add_link_key(hdev, conn, 1, &ev->bdaddr, ev->link_key,
Gustavo Padovan807deac2012-05-17 00:36:24 -03002769 ev->key_type, pin_len);
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002770
Marcel Holtmann052b30b2009-04-26 20:01:22 +02002771 hci_dev_unlock(hdev);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002772}
2773
Gustavo Padovan6039aa72012-05-23 04:04:18 -03002774static void hci_clock_offset_evt(struct hci_dev *hdev, struct sk_buff *skb)
Marcel Holtmann04837f62006-07-03 10:02:33 +02002775{
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002776 struct hci_ev_clock_offset *ev = (void *) skb->data;
Marcel Holtmann04837f62006-07-03 10:02:33 +02002777 struct hci_conn *conn;
2778
2779 BT_DBG("%s status %d", hdev->name, ev->status);
2780
2781 hci_dev_lock(hdev);
2782
2783 conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
Linus Torvalds1da177e2005-04-16 15:20:36 -07002784 if (conn && !ev->status) {
2785 struct inquiry_entry *ie;
2786
Andrei Emeltchenkocc11b9c2010-11-22 13:21:37 +02002787 ie = hci_inquiry_cache_lookup(hdev, &conn->dst);
2788 if (ie) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002789 ie->data.clock_offset = ev->clock_offset;
2790 ie->timestamp = jiffies;
2791 }
2792 }
2793
2794 hci_dev_unlock(hdev);
2795}
2796
Gustavo Padovan6039aa72012-05-23 04:04:18 -03002797static void hci_pkt_type_change_evt(struct hci_dev *hdev, struct sk_buff *skb)
Marcel Holtmanna8746412008-07-14 20:13:46 +02002798{
2799 struct hci_ev_pkt_type_change *ev = (void *) skb->data;
2800 struct hci_conn *conn;
2801
2802 BT_DBG("%s status %d", hdev->name, ev->status);
2803
2804 hci_dev_lock(hdev);
2805
2806 conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
2807 if (conn && !ev->status)
2808 conn->pkt_type = __le16_to_cpu(ev->pkt_type);
2809
2810 hci_dev_unlock(hdev);
2811}
2812
Gustavo Padovan6039aa72012-05-23 04:04:18 -03002813static void hci_pscan_rep_mode_evt(struct hci_dev *hdev, struct sk_buff *skb)
Marcel Holtmann85a1e932005-08-09 20:28:02 -07002814{
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002815 struct hci_ev_pscan_rep_mode *ev = (void *) skb->data;
Marcel Holtmann85a1e932005-08-09 20:28:02 -07002816 struct inquiry_entry *ie;
2817
2818 BT_DBG("%s", hdev->name);
2819
2820 hci_dev_lock(hdev);
2821
Andrei Emeltchenkocc11b9c2010-11-22 13:21:37 +02002822 ie = hci_inquiry_cache_lookup(hdev, &ev->bdaddr);
2823 if (ie) {
Marcel Holtmann85a1e932005-08-09 20:28:02 -07002824 ie->data.pscan_rep_mode = ev->pscan_rep_mode;
2825 ie->timestamp = jiffies;
2826 }
2827
2828 hci_dev_unlock(hdev);
2829}
2830
Gustavo Padovan6039aa72012-05-23 04:04:18 -03002831static void hci_inquiry_result_with_rssi_evt(struct hci_dev *hdev,
2832 struct sk_buff *skb)
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002833{
2834 struct inquiry_data data;
2835 int num_rsp = *((__u8 *) skb->data);
Johan Hedberg388fc8f2012-02-23 00:38:59 +02002836 bool name_known, ssp;
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002837
2838 BT_DBG("%s num_rsp %d", hdev->name, num_rsp);
2839
2840 if (!num_rsp)
2841 return;
2842
Andre Guedes1519cc12012-03-21 00:03:38 -03002843 if (test_bit(HCI_PERIODIC_INQ, &hdev->dev_flags))
2844 return;
2845
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002846 hci_dev_lock(hdev);
2847
2848 if ((skb->len - 1) / num_rsp != sizeof(struct inquiry_info_with_rssi)) {
Szymon Janc138d22e2011-02-17 16:44:23 +01002849 struct inquiry_info_with_rssi_and_pscan_mode *info;
2850 info = (void *) (skb->data + 1);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002851
Johan Hedberge17acd42011-03-30 23:57:16 +03002852 for (; num_rsp; num_rsp--, info++) {
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002853 bacpy(&data.bdaddr, &info->bdaddr);
2854 data.pscan_rep_mode = info->pscan_rep_mode;
2855 data.pscan_period_mode = info->pscan_period_mode;
2856 data.pscan_mode = info->pscan_mode;
2857 memcpy(data.dev_class, info->dev_class, 3);
2858 data.clock_offset = info->clock_offset;
2859 data.rssi = info->rssi;
Marcel Holtmann41a96212008-07-14 20:13:48 +02002860 data.ssp_mode = 0x00;
Johan Hedberg31754052012-01-04 13:39:52 +02002861
2862 name_known = hci_inquiry_cache_update(hdev, &data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002863 false, &ssp);
Johan Hedberg48264f02011-11-09 13:58:58 +02002864 mgmt_device_found(hdev, &info->bdaddr, ACL_LINK, 0x00,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002865 info->dev_class, info->rssi,
2866 !name_known, ssp, NULL, 0);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002867 }
2868 } else {
2869 struct inquiry_info_with_rssi *info = (void *) (skb->data + 1);
2870
Johan Hedberge17acd42011-03-30 23:57:16 +03002871 for (; num_rsp; num_rsp--, info++) {
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002872 bacpy(&data.bdaddr, &info->bdaddr);
2873 data.pscan_rep_mode = info->pscan_rep_mode;
2874 data.pscan_period_mode = info->pscan_period_mode;
2875 data.pscan_mode = 0x00;
2876 memcpy(data.dev_class, info->dev_class, 3);
2877 data.clock_offset = info->clock_offset;
2878 data.rssi = info->rssi;
Marcel Holtmann41a96212008-07-14 20:13:48 +02002879 data.ssp_mode = 0x00;
Johan Hedberg31754052012-01-04 13:39:52 +02002880 name_known = hci_inquiry_cache_update(hdev, &data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002881 false, &ssp);
Johan Hedberg48264f02011-11-09 13:58:58 +02002882 mgmt_device_found(hdev, &info->bdaddr, ACL_LINK, 0x00,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002883 info->dev_class, info->rssi,
2884 !name_known, ssp, NULL, 0);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002885 }
2886 }
2887
2888 hci_dev_unlock(hdev);
2889}
2890
Gustavo Padovan6039aa72012-05-23 04:04:18 -03002891static void hci_remote_ext_features_evt(struct hci_dev *hdev,
2892 struct sk_buff *skb)
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002893{
Marcel Holtmann41a96212008-07-14 20:13:48 +02002894 struct hci_ev_remote_ext_features *ev = (void *) skb->data;
2895 struct hci_conn *conn;
2896
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002897 BT_DBG("%s", hdev->name);
Marcel Holtmann41a96212008-07-14 20:13:48 +02002898
Marcel Holtmann41a96212008-07-14 20:13:48 +02002899 hci_dev_lock(hdev);
2900
2901 conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
Johan Hedbergccd556f2010-11-10 17:11:51 +02002902 if (!conn)
2903 goto unlock;
Marcel Holtmann41a96212008-07-14 20:13:48 +02002904
Johan Hedbergccd556f2010-11-10 17:11:51 +02002905 if (!ev->status && ev->page == 0x01) {
2906 struct inquiry_entry *ie;
Marcel Holtmann41a96212008-07-14 20:13:48 +02002907
Andrei Emeltchenkocc11b9c2010-11-22 13:21:37 +02002908 ie = hci_inquiry_cache_lookup(hdev, &conn->dst);
2909 if (ie)
Johan Hedberg02b7cc62012-02-28 02:28:43 +02002910 ie->data.ssp_mode = (ev->features[0] & LMP_HOST_SSP);
Marcel Holtmann769be972008-07-14 20:13:49 +02002911
Johan Hedberg02b7cc62012-02-28 02:28:43 +02002912 if (ev->features[0] & LMP_HOST_SSP)
Johan Hedberg58a681e2012-01-16 06:47:28 +02002913 set_bit(HCI_CONN_SSP_ENABLED, &conn->flags);
Marcel Holtmann41a96212008-07-14 20:13:48 +02002914 }
2915
Johan Hedbergccd556f2010-11-10 17:11:51 +02002916 if (conn->state != BT_CONFIG)
2917 goto unlock;
2918
Johan Hedberg671267b2012-05-12 16:11:50 -03002919 if (!ev->status && !test_bit(HCI_CONN_MGMT_CONNECTED, &conn->flags)) {
Johan Hedberg127178d2010-11-18 22:22:29 +02002920 struct hci_cp_remote_name_req cp;
2921 memset(&cp, 0, sizeof(cp));
2922 bacpy(&cp.bdaddr, &conn->dst);
2923 cp.pscan_rep_mode = 0x02;
2924 hci_send_cmd(hdev, HCI_OP_REMOTE_NAME_REQ, sizeof(cp), &cp);
Johan Hedbergb644ba32012-01-17 21:48:47 +02002925 } else if (!test_and_set_bit(HCI_CONN_MGMT_CONNECTED, &conn->flags))
2926 mgmt_device_connected(hdev, &conn->dst, conn->type,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002927 conn->dst_type, 0, NULL, 0,
2928 conn->dev_class);
Johan Hedberg392599b2010-11-18 22:22:28 +02002929
Johan Hedberg127178d2010-11-18 22:22:29 +02002930 if (!hci_outgoing_auth_needed(hdev, conn)) {
Johan Hedbergccd556f2010-11-10 17:11:51 +02002931 conn->state = BT_CONNECTED;
2932 hci_proto_connect_cfm(conn, ev->status);
2933 hci_conn_put(conn);
2934 }
2935
2936unlock:
Marcel Holtmann41a96212008-07-14 20:13:48 +02002937 hci_dev_unlock(hdev);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002938}
2939
Gustavo Padovan6039aa72012-05-23 04:04:18 -03002940static void hci_sync_conn_complete_evt(struct hci_dev *hdev,
2941 struct sk_buff *skb)
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002942{
Marcel Holtmannb6a0dc82007-10-20 14:55:10 +02002943 struct hci_ev_sync_conn_complete *ev = (void *) skb->data;
2944 struct hci_conn *conn;
2945
2946 BT_DBG("%s status %d", hdev->name, ev->status);
2947
2948 hci_dev_lock(hdev);
2949
2950 conn = hci_conn_hash_lookup_ba(hdev, ev->link_type, &ev->bdaddr);
Marcel Holtmann9dc0a3a2008-07-14 20:13:46 +02002951 if (!conn) {
2952 if (ev->link_type == ESCO_LINK)
2953 goto unlock;
2954
2955 conn = hci_conn_hash_lookup_ba(hdev, ESCO_LINK, &ev->bdaddr);
2956 if (!conn)
2957 goto unlock;
2958
2959 conn->type = SCO_LINK;
2960 }
Marcel Holtmannb6a0dc82007-10-20 14:55:10 +02002961
Marcel Holtmann732547f2009-04-19 19:14:14 +02002962 switch (ev->status) {
2963 case 0x00:
Marcel Holtmannb6a0dc82007-10-20 14:55:10 +02002964 conn->handle = __le16_to_cpu(ev->handle);
2965 conn->state = BT_CONNECTED;
Marcel Holtmann7d0db0a2008-07-14 20:13:51 +02002966
Marcel Holtmann9eba32b2009-08-22 14:19:26 -07002967 hci_conn_hold_device(conn);
Marcel Holtmann7d0db0a2008-07-14 20:13:51 +02002968 hci_conn_add_sysfs(conn);
Marcel Holtmann732547f2009-04-19 19:14:14 +02002969 break;
2970
Stephen Coe705e5712010-02-16 11:29:44 -05002971 case 0x11: /* Unsupported Feature or Parameter Value */
Marcel Holtmann732547f2009-04-19 19:14:14 +02002972 case 0x1c: /* SCO interval rejected */
Nick Pelly1038a002010-02-03 11:42:26 -08002973 case 0x1a: /* Unsupported Remote Feature */
Marcel Holtmann732547f2009-04-19 19:14:14 +02002974 case 0x1f: /* Unspecified error */
2975 if (conn->out && conn->attempt < 2) {
2976 conn->pkt_type = (hdev->esco_type & SCO_ESCO_MASK) |
2977 (hdev->esco_type & EDR_ESCO_MASK);
2978 hci_setup_sync(conn, conn->link->handle);
2979 goto unlock;
2980 }
2981 /* fall through */
2982
2983 default:
Marcel Holtmannb6a0dc82007-10-20 14:55:10 +02002984 conn->state = BT_CLOSED;
Marcel Holtmann732547f2009-04-19 19:14:14 +02002985 break;
2986 }
Marcel Holtmannb6a0dc82007-10-20 14:55:10 +02002987
2988 hci_proto_connect_cfm(conn, ev->status);
2989 if (ev->status)
2990 hci_conn_del(conn);
2991
2992unlock:
2993 hci_dev_unlock(hdev);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002994}
2995
Gustavo Padovan6039aa72012-05-23 04:04:18 -03002996static void hci_sync_conn_changed_evt(struct hci_dev *hdev, struct sk_buff *skb)
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002997{
2998 BT_DBG("%s", hdev->name);
2999}
3000
Gustavo Padovan6039aa72012-05-23 04:04:18 -03003001static void hci_sniff_subrate_evt(struct hci_dev *hdev, struct sk_buff *skb)
Marcel Holtmann04837f62006-07-03 10:02:33 +02003002{
Marcel Holtmanna9de9242007-10-20 13:33:56 +02003003 struct hci_ev_sniff_subrate *ev = (void *) skb->data;
Marcel Holtmann04837f62006-07-03 10:02:33 +02003004
3005 BT_DBG("%s status %d", hdev->name, ev->status);
Marcel Holtmann04837f62006-07-03 10:02:33 +02003006}
3007
Gustavo Padovan6039aa72012-05-23 04:04:18 -03003008static void hci_extended_inquiry_result_evt(struct hci_dev *hdev,
3009 struct sk_buff *skb)
Marcel Holtmanna9de9242007-10-20 13:33:56 +02003010{
3011 struct inquiry_data data;
3012 struct extended_inquiry_info *info = (void *) (skb->data + 1);
3013 int num_rsp = *((__u8 *) skb->data);
Vishal Agarwal9d939d92012-04-26 19:19:56 +05303014 size_t eir_len;
Marcel Holtmanna9de9242007-10-20 13:33:56 +02003015
3016 BT_DBG("%s num_rsp %d", hdev->name, num_rsp);
3017
3018 if (!num_rsp)
3019 return;
3020
Andre Guedes1519cc12012-03-21 00:03:38 -03003021 if (test_bit(HCI_PERIODIC_INQ, &hdev->dev_flags))
3022 return;
3023
Marcel Holtmanna9de9242007-10-20 13:33:56 +02003024 hci_dev_lock(hdev);
3025
Johan Hedberge17acd42011-03-30 23:57:16 +03003026 for (; num_rsp; num_rsp--, info++) {
Johan Hedberg388fc8f2012-02-23 00:38:59 +02003027 bool name_known, ssp;
Johan Hedberg561aafb2012-01-04 13:31:59 +02003028
Marcel Holtmanna9de9242007-10-20 13:33:56 +02003029 bacpy(&data.bdaddr, &info->bdaddr);
Szymon Janc138d22e2011-02-17 16:44:23 +01003030 data.pscan_rep_mode = info->pscan_rep_mode;
3031 data.pscan_period_mode = info->pscan_period_mode;
3032 data.pscan_mode = 0x00;
Marcel Holtmanna9de9242007-10-20 13:33:56 +02003033 memcpy(data.dev_class, info->dev_class, 3);
Szymon Janc138d22e2011-02-17 16:44:23 +01003034 data.clock_offset = info->clock_offset;
3035 data.rssi = info->rssi;
Marcel Holtmann41a96212008-07-14 20:13:48 +02003036 data.ssp_mode = 0x01;
Johan Hedberg561aafb2012-01-04 13:31:59 +02003037
Johan Hedberga8b2d5c2012-01-08 23:11:15 +02003038 if (test_bit(HCI_MGMT, &hdev->dev_flags))
Johan Hedberg4ddb1932012-01-15 20:04:43 +02003039 name_known = eir_has_data_type(info->data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003040 sizeof(info->data),
3041 EIR_NAME_COMPLETE);
Johan Hedberg561aafb2012-01-04 13:31:59 +02003042 else
3043 name_known = true;
3044
Johan Hedberg388fc8f2012-02-23 00:38:59 +02003045 name_known = hci_inquiry_cache_update(hdev, &data, name_known,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003046 &ssp);
Vishal Agarwal9d939d92012-04-26 19:19:56 +05303047 eir_len = eir_get_length(info->data, sizeof(info->data));
Johan Hedberg48264f02011-11-09 13:58:58 +02003048 mgmt_device_found(hdev, &info->bdaddr, ACL_LINK, 0x00,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003049 info->dev_class, info->rssi, !name_known,
Vishal Agarwal9d939d92012-04-26 19:19:56 +05303050 ssp, info->data, eir_len);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02003051 }
3052
3053 hci_dev_unlock(hdev);
3054}
3055
Gustavo Padovan6039aa72012-05-23 04:04:18 -03003056static u8 hci_get_auth_req(struct hci_conn *conn)
Johan Hedberg17fa4b92011-01-25 13:28:33 +02003057{
3058 /* If remote requests dedicated bonding follow that lead */
3059 if (conn->remote_auth == 0x02 || conn->remote_auth == 0x03) {
3060 /* If both remote and local IO capabilities allow MITM
3061 * protection then require it, otherwise don't */
3062 if (conn->remote_cap == 0x03 || conn->io_capability == 0x03)
3063 return 0x02;
3064 else
3065 return 0x03;
3066 }
3067
3068 /* If remote requests no-bonding follow that lead */
3069 if (conn->remote_auth == 0x00 || conn->remote_auth == 0x01)
Waldemar Rymarkiewicz58797bf2011-04-28 12:07:58 +02003070 return conn->remote_auth | (conn->auth_type & 0x01);
Johan Hedberg17fa4b92011-01-25 13:28:33 +02003071
3072 return conn->auth_type;
3073}
3074
Gustavo Padovan6039aa72012-05-23 04:04:18 -03003075static void hci_io_capa_request_evt(struct hci_dev *hdev, struct sk_buff *skb)
Marcel Holtmann04936842008-07-14 20:13:48 +02003076{
3077 struct hci_ev_io_capa_request *ev = (void *) skb->data;
3078 struct hci_conn *conn;
3079
3080 BT_DBG("%s", hdev->name);
3081
3082 hci_dev_lock(hdev);
3083
3084 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
Johan Hedberg03b555e2011-01-04 15:40:05 +02003085 if (!conn)
3086 goto unlock;
Marcel Holtmann04936842008-07-14 20:13:48 +02003087
Johan Hedberg03b555e2011-01-04 15:40:05 +02003088 hci_conn_hold(conn);
3089
Johan Hedberga8b2d5c2012-01-08 23:11:15 +02003090 if (!test_bit(HCI_MGMT, &hdev->dev_flags))
Johan Hedberg03b555e2011-01-04 15:40:05 +02003091 goto unlock;
3092
Johan Hedberga8b2d5c2012-01-08 23:11:15 +02003093 if (test_bit(HCI_PAIRABLE, &hdev->dev_flags) ||
Gustavo Padovan807deac2012-05-17 00:36:24 -03003094 (conn->remote_auth & ~0x01) == HCI_AT_NO_BONDING) {
Johan Hedberg17fa4b92011-01-25 13:28:33 +02003095 struct hci_cp_io_capability_reply cp;
3096
3097 bacpy(&cp.bdaddr, &ev->bdaddr);
Hemant Gupta7a7f1e72012-01-16 13:34:29 +05303098 /* Change the IO capability from KeyboardDisplay
3099 * to DisplayYesNo as it is not supported by BT spec. */
3100 cp.capability = (conn->io_capability == 0x04) ?
3101 0x01 : conn->io_capability;
Johan Hedberg7cbc9bd2011-04-28 11:29:04 -07003102 conn->auth_type = hci_get_auth_req(conn);
3103 cp.authentication = conn->auth_type;
Johan Hedberg17fa4b92011-01-25 13:28:33 +02003104
Gustavo Padovan8fc9ced2012-05-23 04:04:21 -03003105 if (hci_find_remote_oob_data(hdev, &conn->dst) &&
3106 (conn->out || test_bit(HCI_CONN_REMOTE_OOB, &conn->flags)))
Szymon Jancce85ee12011-03-22 13:12:23 +01003107 cp.oob_data = 0x01;
3108 else
3109 cp.oob_data = 0x00;
3110
Johan Hedberg17fa4b92011-01-25 13:28:33 +02003111 hci_send_cmd(hdev, HCI_OP_IO_CAPABILITY_REPLY,
Gustavo Padovan807deac2012-05-17 00:36:24 -03003112 sizeof(cp), &cp);
Johan Hedberg03b555e2011-01-04 15:40:05 +02003113 } else {
3114 struct hci_cp_io_capability_neg_reply cp;
3115
3116 bacpy(&cp.bdaddr, &ev->bdaddr);
Andrei Emeltchenko9f5a0d72011-11-07 14:20:25 +02003117 cp.reason = HCI_ERROR_PAIRING_NOT_ALLOWED;
Johan Hedberg03b555e2011-01-04 15:40:05 +02003118
3119 hci_send_cmd(hdev, HCI_OP_IO_CAPABILITY_NEG_REPLY,
Gustavo Padovan807deac2012-05-17 00:36:24 -03003120 sizeof(cp), &cp);
Johan Hedberg03b555e2011-01-04 15:40:05 +02003121 }
3122
3123unlock:
3124 hci_dev_unlock(hdev);
3125}
3126
Gustavo Padovan6039aa72012-05-23 04:04:18 -03003127static void hci_io_capa_reply_evt(struct hci_dev *hdev, struct sk_buff *skb)
Johan Hedberg03b555e2011-01-04 15:40:05 +02003128{
3129 struct hci_ev_io_capa_reply *ev = (void *) skb->data;
3130 struct hci_conn *conn;
3131
3132 BT_DBG("%s", hdev->name);
3133
3134 hci_dev_lock(hdev);
3135
3136 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
3137 if (!conn)
3138 goto unlock;
3139
Johan Hedberg03b555e2011-01-04 15:40:05 +02003140 conn->remote_cap = ev->capability;
Johan Hedberg03b555e2011-01-04 15:40:05 +02003141 conn->remote_auth = ev->authentication;
Johan Hedberg58a681e2012-01-16 06:47:28 +02003142 if (ev->oob_data)
3143 set_bit(HCI_CONN_REMOTE_OOB, &conn->flags);
Johan Hedberg03b555e2011-01-04 15:40:05 +02003144
3145unlock:
Marcel Holtmann04936842008-07-14 20:13:48 +02003146 hci_dev_unlock(hdev);
3147}
3148
Gustavo Padovan6039aa72012-05-23 04:04:18 -03003149static void hci_user_confirm_request_evt(struct hci_dev *hdev,
3150 struct sk_buff *skb)
Johan Hedberga5c29682011-02-19 12:05:57 -03003151{
3152 struct hci_ev_user_confirm_req *ev = (void *) skb->data;
Johan Hedberg55bc1a32011-04-28 11:28:56 -07003153 int loc_mitm, rem_mitm, confirm_hint = 0;
Johan Hedberg7a828902011-04-28 11:28:53 -07003154 struct hci_conn *conn;
Johan Hedberga5c29682011-02-19 12:05:57 -03003155
3156 BT_DBG("%s", hdev->name);
3157
3158 hci_dev_lock(hdev);
3159
Johan Hedberga8b2d5c2012-01-08 23:11:15 +02003160 if (!test_bit(HCI_MGMT, &hdev->dev_flags))
Johan Hedberg7a828902011-04-28 11:28:53 -07003161 goto unlock;
Johan Hedberga5c29682011-02-19 12:05:57 -03003162
Johan Hedberg7a828902011-04-28 11:28:53 -07003163 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
3164 if (!conn)
3165 goto unlock;
3166
3167 loc_mitm = (conn->auth_type & 0x01);
3168 rem_mitm = (conn->remote_auth & 0x01);
3169
3170 /* If we require MITM but the remote device can't provide that
3171 * (it has NoInputNoOutput) then reject the confirmation
3172 * request. The only exception is when we're dedicated bonding
3173 * initiators (connect_cfm_cb set) since then we always have the MITM
3174 * bit set. */
3175 if (!conn->connect_cfm_cb && loc_mitm && conn->remote_cap == 0x03) {
3176 BT_DBG("Rejecting request: remote device can't provide MITM");
3177 hci_send_cmd(hdev, HCI_OP_USER_CONFIRM_NEG_REPLY,
Gustavo Padovan807deac2012-05-17 00:36:24 -03003178 sizeof(ev->bdaddr), &ev->bdaddr);
Johan Hedberg7a828902011-04-28 11:28:53 -07003179 goto unlock;
3180 }
3181
3182 /* If no side requires MITM protection; auto-accept */
3183 if ((!loc_mitm || conn->remote_cap == 0x03) &&
Gustavo Padovan807deac2012-05-17 00:36:24 -03003184 (!rem_mitm || conn->io_capability == 0x03)) {
Johan Hedberg55bc1a32011-04-28 11:28:56 -07003185
3186 /* If we're not the initiators request authorization to
3187 * proceed from user space (mgmt_user_confirm with
3188 * confirm_hint set to 1). */
Johan Hedberg51a8efd2012-01-16 06:10:31 +02003189 if (!test_bit(HCI_CONN_AUTH_PEND, &conn->flags)) {
Johan Hedberg55bc1a32011-04-28 11:28:56 -07003190 BT_DBG("Confirming auto-accept as acceptor");
3191 confirm_hint = 1;
3192 goto confirm;
3193 }
3194
Johan Hedberg9f616562011-04-28 11:28:54 -07003195 BT_DBG("Auto-accept of user confirmation with %ums delay",
Gustavo Padovan807deac2012-05-17 00:36:24 -03003196 hdev->auto_accept_delay);
Johan Hedberg9f616562011-04-28 11:28:54 -07003197
3198 if (hdev->auto_accept_delay > 0) {
3199 int delay = msecs_to_jiffies(hdev->auto_accept_delay);
3200 mod_timer(&conn->auto_accept_timer, jiffies + delay);
3201 goto unlock;
3202 }
3203
Johan Hedberg7a828902011-04-28 11:28:53 -07003204 hci_send_cmd(hdev, HCI_OP_USER_CONFIRM_REPLY,
Gustavo Padovan807deac2012-05-17 00:36:24 -03003205 sizeof(ev->bdaddr), &ev->bdaddr);
Johan Hedberg7a828902011-04-28 11:28:53 -07003206 goto unlock;
3207 }
3208
Johan Hedberg55bc1a32011-04-28 11:28:56 -07003209confirm:
Johan Hedberg272d90d2012-02-09 15:26:12 +02003210 mgmt_user_confirm_request(hdev, &ev->bdaddr, ACL_LINK, 0, ev->passkey,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003211 confirm_hint);
Johan Hedberg7a828902011-04-28 11:28:53 -07003212
3213unlock:
Johan Hedberga5c29682011-02-19 12:05:57 -03003214 hci_dev_unlock(hdev);
3215}
3216
Gustavo Padovan6039aa72012-05-23 04:04:18 -03003217static void hci_user_passkey_request_evt(struct hci_dev *hdev,
3218 struct sk_buff *skb)
Brian Gix1143d452011-11-23 08:28:34 -08003219{
3220 struct hci_ev_user_passkey_req *ev = (void *) skb->data;
3221
3222 BT_DBG("%s", hdev->name);
3223
3224 hci_dev_lock(hdev);
3225
Johan Hedberga8b2d5c2012-01-08 23:11:15 +02003226 if (test_bit(HCI_MGMT, &hdev->dev_flags))
Johan Hedberg272d90d2012-02-09 15:26:12 +02003227 mgmt_user_passkey_request(hdev, &ev->bdaddr, ACL_LINK, 0);
Brian Gix1143d452011-11-23 08:28:34 -08003228
3229 hci_dev_unlock(hdev);
3230}
3231
Gustavo Padovan6039aa72012-05-23 04:04:18 -03003232static void hci_simple_pair_complete_evt(struct hci_dev *hdev,
3233 struct sk_buff *skb)
Marcel Holtmann04936842008-07-14 20:13:48 +02003234{
3235 struct hci_ev_simple_pair_complete *ev = (void *) skb->data;
3236 struct hci_conn *conn;
3237
3238 BT_DBG("%s", hdev->name);
3239
3240 hci_dev_lock(hdev);
3241
3242 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
Johan Hedberg2a611692011-02-19 12:06:00 -03003243 if (!conn)
3244 goto unlock;
Marcel Holtmann04936842008-07-14 20:13:48 +02003245
Johan Hedberg2a611692011-02-19 12:06:00 -03003246 /* To avoid duplicate auth_failed events to user space we check
3247 * the HCI_CONN_AUTH_PEND flag which will be set if we
3248 * initiated the authentication. A traditional auth_complete
3249 * event gets always produced as initiator and is also mapped to
3250 * the mgmt_auth_failed event */
Johan Hedberg51a8efd2012-01-16 06:10:31 +02003251 if (!test_bit(HCI_CONN_AUTH_PEND, &conn->flags) && ev->status != 0)
Johan Hedbergbab73cb2012-02-09 16:07:29 +02003252 mgmt_auth_failed(hdev, &conn->dst, conn->type, conn->dst_type,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003253 ev->status);
Johan Hedberg2a611692011-02-19 12:06:00 -03003254
3255 hci_conn_put(conn);
3256
3257unlock:
Marcel Holtmann04936842008-07-14 20:13:48 +02003258 hci_dev_unlock(hdev);
3259}
3260
Gustavo Padovan6039aa72012-05-23 04:04:18 -03003261static void hci_remote_host_features_evt(struct hci_dev *hdev,
3262 struct sk_buff *skb)
Marcel Holtmann41a96212008-07-14 20:13:48 +02003263{
3264 struct hci_ev_remote_host_features *ev = (void *) skb->data;
3265 struct inquiry_entry *ie;
3266
3267 BT_DBG("%s", hdev->name);
3268
3269 hci_dev_lock(hdev);
3270
Andrei Emeltchenkocc11b9c2010-11-22 13:21:37 +02003271 ie = hci_inquiry_cache_lookup(hdev, &ev->bdaddr);
3272 if (ie)
Johan Hedberg02b7cc62012-02-28 02:28:43 +02003273 ie->data.ssp_mode = (ev->features[0] & LMP_HOST_SSP);
Marcel Holtmann41a96212008-07-14 20:13:48 +02003274
3275 hci_dev_unlock(hdev);
3276}
3277
Gustavo Padovan6039aa72012-05-23 04:04:18 -03003278static void hci_remote_oob_data_request_evt(struct hci_dev *hdev,
3279 struct sk_buff *skb)
Szymon Janc2763eda2011-03-22 13:12:22 +01003280{
3281 struct hci_ev_remote_oob_data_request *ev = (void *) skb->data;
3282 struct oob_data *data;
3283
3284 BT_DBG("%s", hdev->name);
3285
3286 hci_dev_lock(hdev);
3287
Johan Hedberga8b2d5c2012-01-08 23:11:15 +02003288 if (!test_bit(HCI_MGMT, &hdev->dev_flags))
Szymon Jance1ba1f12011-04-06 13:01:59 +02003289 goto unlock;
3290
Szymon Janc2763eda2011-03-22 13:12:22 +01003291 data = hci_find_remote_oob_data(hdev, &ev->bdaddr);
3292 if (data) {
3293 struct hci_cp_remote_oob_data_reply cp;
3294
3295 bacpy(&cp.bdaddr, &ev->bdaddr);
3296 memcpy(cp.hash, data->hash, sizeof(cp.hash));
3297 memcpy(cp.randomizer, data->randomizer, sizeof(cp.randomizer));
3298
3299 hci_send_cmd(hdev, HCI_OP_REMOTE_OOB_DATA_REPLY, sizeof(cp),
Gustavo Padovan807deac2012-05-17 00:36:24 -03003300 &cp);
Szymon Janc2763eda2011-03-22 13:12:22 +01003301 } else {
3302 struct hci_cp_remote_oob_data_neg_reply cp;
3303
3304 bacpy(&cp.bdaddr, &ev->bdaddr);
3305 hci_send_cmd(hdev, HCI_OP_REMOTE_OOB_DATA_NEG_REPLY, sizeof(cp),
Gustavo Padovan807deac2012-05-17 00:36:24 -03003306 &cp);
Szymon Janc2763eda2011-03-22 13:12:22 +01003307 }
3308
Szymon Jance1ba1f12011-04-06 13:01:59 +02003309unlock:
Szymon Janc2763eda2011-03-22 13:12:22 +01003310 hci_dev_unlock(hdev);
3311}
3312
Gustavo Padovan6039aa72012-05-23 04:04:18 -03003313static void hci_le_conn_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
Ville Tervofcd89c02011-02-10 22:38:47 -03003314{
3315 struct hci_ev_le_conn_complete *ev = (void *) skb->data;
3316 struct hci_conn *conn;
3317
3318 BT_DBG("%s status %d", hdev->name, ev->status);
3319
3320 hci_dev_lock(hdev);
3321
3322 conn = hci_conn_hash_lookup_ba(hdev, LE_LINK, &ev->bdaddr);
Ville Tervob62f3282011-02-10 22:38:50 -03003323 if (!conn) {
3324 conn = hci_conn_add(hdev, LE_LINK, &ev->bdaddr);
3325 if (!conn) {
3326 BT_ERR("No memory for new connection");
3327 hci_dev_unlock(hdev);
3328 return;
3329 }
Andre Guedes29b79882011-05-31 14:20:54 -03003330
3331 conn->dst_type = ev->bdaddr_type;
Ville Tervob62f3282011-02-10 22:38:50 -03003332 }
Ville Tervofcd89c02011-02-10 22:38:47 -03003333
3334 if (ev->status) {
Johan Hedberg48264f02011-11-09 13:58:58 +02003335 mgmt_connect_failed(hdev, &ev->bdaddr, conn->type,
Gustavo Padovan807deac2012-05-17 00:36:24 -03003336 conn->dst_type, ev->status);
Ville Tervofcd89c02011-02-10 22:38:47 -03003337 hci_proto_connect_cfm(conn, ev->status);
3338 conn->state = BT_CLOSED;
3339 hci_conn_del(conn);
3340 goto unlock;
3341 }
3342
Johan Hedbergb644ba32012-01-17 21:48:47 +02003343 if (!test_and_set_bit(HCI_CONN_MGMT_CONNECTED, &conn->flags))
3344 mgmt_device_connected(hdev, &ev->bdaddr, conn->type,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003345 conn->dst_type, 0, NULL, 0, NULL);
Vinicius Costa Gomes83bc71b2011-05-06 18:41:43 -03003346
Vinicius Costa Gomes7b5c0d52011-06-09 18:50:50 -03003347 conn->sec_level = BT_SECURITY_LOW;
Ville Tervofcd89c02011-02-10 22:38:47 -03003348 conn->handle = __le16_to_cpu(ev->handle);
3349 conn->state = BT_CONNECTED;
3350
3351 hci_conn_hold_device(conn);
3352 hci_conn_add_sysfs(conn);
3353
3354 hci_proto_connect_cfm(conn, ev->status);
3355
3356unlock:
3357 hci_dev_unlock(hdev);
3358}
3359
Gustavo Padovan6039aa72012-05-23 04:04:18 -03003360static void hci_le_adv_report_evt(struct hci_dev *hdev, struct sk_buff *skb)
Andre Guedes9aa04c92011-05-26 16:23:51 -03003361{
Andre Guedese95beb42011-09-26 20:48:35 -03003362 u8 num_reports = skb->data[0];
3363 void *ptr = &skb->data[1];
Andre Guedes3c9e9192012-01-10 18:20:50 -03003364 s8 rssi;
Andre Guedes9aa04c92011-05-26 16:23:51 -03003365
3366 hci_dev_lock(hdev);
3367
Andre Guedese95beb42011-09-26 20:48:35 -03003368 while (num_reports--) {
3369 struct hci_ev_le_advertising_info *ev = ptr;
Andre Guedes9aa04c92011-05-26 16:23:51 -03003370
Andre Guedes3c9e9192012-01-10 18:20:50 -03003371 rssi = ev->data[ev->length];
3372 mgmt_device_found(hdev, &ev->bdaddr, LE_LINK, ev->bdaddr_type,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003373 NULL, rssi, 0, 1, ev->data, ev->length);
Andre Guedes3c9e9192012-01-10 18:20:50 -03003374
Andre Guedese95beb42011-09-26 20:48:35 -03003375 ptr += sizeof(*ev) + ev->length + 1;
Andre Guedes9aa04c92011-05-26 16:23:51 -03003376 }
3377
3378 hci_dev_unlock(hdev);
3379}
3380
Gustavo Padovan6039aa72012-05-23 04:04:18 -03003381static void hci_le_ltk_request_evt(struct hci_dev *hdev, struct sk_buff *skb)
Vinicius Costa Gomesa7a595f2011-06-09 18:50:47 -03003382{
3383 struct hci_ev_le_ltk_req *ev = (void *) skb->data;
3384 struct hci_cp_le_ltk_reply cp;
Vinicius Costa Gomesbea710f2011-07-07 18:59:37 -03003385 struct hci_cp_le_ltk_neg_reply neg;
Vinicius Costa Gomesa7a595f2011-06-09 18:50:47 -03003386 struct hci_conn *conn;
Vinicius Costa Gomesc9839a12012-02-02 21:08:01 -03003387 struct smp_ltk *ltk;
Vinicius Costa Gomesa7a595f2011-06-09 18:50:47 -03003388
Andrei Emeltchenkoe4666882012-03-09 11:59:15 +02003389 BT_DBG("%s handle %d", hdev->name, __le16_to_cpu(ev->handle));
Vinicius Costa Gomesa7a595f2011-06-09 18:50:47 -03003390
3391 hci_dev_lock(hdev);
3392
3393 conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
Vinicius Costa Gomesbea710f2011-07-07 18:59:37 -03003394 if (conn == NULL)
3395 goto not_found;
Vinicius Costa Gomesa7a595f2011-06-09 18:50:47 -03003396
Vinicius Costa Gomesbea710f2011-07-07 18:59:37 -03003397 ltk = hci_find_ltk(hdev, ev->ediv, ev->random);
3398 if (ltk == NULL)
3399 goto not_found;
3400
3401 memcpy(cp.ltk, ltk->val, sizeof(ltk->val));
Vinicius Costa Gomesa7a595f2011-06-09 18:50:47 -03003402 cp.handle = cpu_to_le16(conn->handle);
Vinicius Costa Gomesc9839a12012-02-02 21:08:01 -03003403
3404 if (ltk->authenticated)
3405 conn->sec_level = BT_SECURITY_HIGH;
Vinicius Costa Gomesa7a595f2011-06-09 18:50:47 -03003406
3407 hci_send_cmd(hdev, HCI_OP_LE_LTK_REPLY, sizeof(cp), &cp);
3408
Vinicius Costa Gomesc9839a12012-02-02 21:08:01 -03003409 if (ltk->type & HCI_SMP_STK) {
3410 list_del(&ltk->list);
3411 kfree(ltk);
3412 }
3413
Vinicius Costa Gomesa7a595f2011-06-09 18:50:47 -03003414 hci_dev_unlock(hdev);
Vinicius Costa Gomesbea710f2011-07-07 18:59:37 -03003415
3416 return;
3417
3418not_found:
3419 neg.handle = ev->handle;
3420 hci_send_cmd(hdev, HCI_OP_LE_LTK_NEG_REPLY, sizeof(neg), &neg);
3421 hci_dev_unlock(hdev);
Vinicius Costa Gomesa7a595f2011-06-09 18:50:47 -03003422}
3423
Gustavo Padovan6039aa72012-05-23 04:04:18 -03003424static void hci_le_meta_evt(struct hci_dev *hdev, struct sk_buff *skb)
Ville Tervofcd89c02011-02-10 22:38:47 -03003425{
3426 struct hci_ev_le_meta *le_ev = (void *) skb->data;
3427
3428 skb_pull(skb, sizeof(*le_ev));
3429
3430 switch (le_ev->subevent) {
3431 case HCI_EV_LE_CONN_COMPLETE:
3432 hci_le_conn_complete_evt(hdev, skb);
3433 break;
3434
Andre Guedes9aa04c92011-05-26 16:23:51 -03003435 case HCI_EV_LE_ADVERTISING_REPORT:
3436 hci_le_adv_report_evt(hdev, skb);
3437 break;
3438
Vinicius Costa Gomesa7a595f2011-06-09 18:50:47 -03003439 case HCI_EV_LE_LTK_REQ:
3440 hci_le_ltk_request_evt(hdev, skb);
3441 break;
3442
Ville Tervofcd89c02011-02-10 22:38:47 -03003443 default:
3444 break;
3445 }
3446}
3447
Linus Torvalds1da177e2005-04-16 15:20:36 -07003448void hci_event_packet(struct hci_dev *hdev, struct sk_buff *skb)
3449{
Marcel Holtmanna9de9242007-10-20 13:33:56 +02003450 struct hci_event_hdr *hdr = (void *) skb->data;
3451 __u8 event = hdr->evt;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003452
3453 skb_pull(skb, HCI_EVENT_HDR_SIZE);
3454
Marcel Holtmanna9de9242007-10-20 13:33:56 +02003455 switch (event) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003456 case HCI_EV_INQUIRY_COMPLETE:
3457 hci_inquiry_complete_evt(hdev, skb);
3458 break;
3459
3460 case HCI_EV_INQUIRY_RESULT:
3461 hci_inquiry_result_evt(hdev, skb);
3462 break;
3463
Marcel Holtmanna9de9242007-10-20 13:33:56 +02003464 case HCI_EV_CONN_COMPLETE:
3465 hci_conn_complete_evt(hdev, skb);
Marcel Holtmann21d9e302005-09-13 01:32:25 +02003466 break;
3467
Linus Torvalds1da177e2005-04-16 15:20:36 -07003468 case HCI_EV_CONN_REQUEST:
3469 hci_conn_request_evt(hdev, skb);
3470 break;
3471
Linus Torvalds1da177e2005-04-16 15:20:36 -07003472 case HCI_EV_DISCONN_COMPLETE:
3473 hci_disconn_complete_evt(hdev, skb);
3474 break;
3475
Linus Torvalds1da177e2005-04-16 15:20:36 -07003476 case HCI_EV_AUTH_COMPLETE:
3477 hci_auth_complete_evt(hdev, skb);
3478 break;
3479
Marcel Holtmanna9de9242007-10-20 13:33:56 +02003480 case HCI_EV_REMOTE_NAME:
3481 hci_remote_name_evt(hdev, skb);
3482 break;
3483
Linus Torvalds1da177e2005-04-16 15:20:36 -07003484 case HCI_EV_ENCRYPT_CHANGE:
3485 hci_encrypt_change_evt(hdev, skb);
3486 break;
3487
Marcel Holtmanna9de9242007-10-20 13:33:56 +02003488 case HCI_EV_CHANGE_LINK_KEY_COMPLETE:
3489 hci_change_link_key_complete_evt(hdev, skb);
3490 break;
3491
3492 case HCI_EV_REMOTE_FEATURES:
3493 hci_remote_features_evt(hdev, skb);
3494 break;
3495
3496 case HCI_EV_REMOTE_VERSION:
3497 hci_remote_version_evt(hdev, skb);
3498 break;
3499
3500 case HCI_EV_QOS_SETUP_COMPLETE:
3501 hci_qos_setup_complete_evt(hdev, skb);
3502 break;
3503
3504 case HCI_EV_CMD_COMPLETE:
3505 hci_cmd_complete_evt(hdev, skb);
3506 break;
3507
3508 case HCI_EV_CMD_STATUS:
3509 hci_cmd_status_evt(hdev, skb);
3510 break;
3511
3512 case HCI_EV_ROLE_CHANGE:
3513 hci_role_change_evt(hdev, skb);
3514 break;
3515
3516 case HCI_EV_NUM_COMP_PKTS:
3517 hci_num_comp_pkts_evt(hdev, skb);
3518 break;
3519
3520 case HCI_EV_MODE_CHANGE:
3521 hci_mode_change_evt(hdev, skb);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003522 break;
3523
3524 case HCI_EV_PIN_CODE_REQ:
3525 hci_pin_code_request_evt(hdev, skb);
3526 break;
3527
3528 case HCI_EV_LINK_KEY_REQ:
3529 hci_link_key_request_evt(hdev, skb);
3530 break;
3531
3532 case HCI_EV_LINK_KEY_NOTIFY:
3533 hci_link_key_notify_evt(hdev, skb);
3534 break;
3535
3536 case HCI_EV_CLOCK_OFFSET:
3537 hci_clock_offset_evt(hdev, skb);
3538 break;
3539
Marcel Holtmanna8746412008-07-14 20:13:46 +02003540 case HCI_EV_PKT_TYPE_CHANGE:
3541 hci_pkt_type_change_evt(hdev, skb);
3542 break;
3543
Marcel Holtmann85a1e932005-08-09 20:28:02 -07003544 case HCI_EV_PSCAN_REP_MODE:
3545 hci_pscan_rep_mode_evt(hdev, skb);
3546 break;
3547
Marcel Holtmanna9de9242007-10-20 13:33:56 +02003548 case HCI_EV_INQUIRY_RESULT_WITH_RSSI:
3549 hci_inquiry_result_with_rssi_evt(hdev, skb);
3550 break;
3551
3552 case HCI_EV_REMOTE_EXT_FEATURES:
3553 hci_remote_ext_features_evt(hdev, skb);
3554 break;
3555
3556 case HCI_EV_SYNC_CONN_COMPLETE:
3557 hci_sync_conn_complete_evt(hdev, skb);
3558 break;
3559
3560 case HCI_EV_SYNC_CONN_CHANGED:
3561 hci_sync_conn_changed_evt(hdev, skb);
3562 break;
3563
Marcel Holtmann04837f62006-07-03 10:02:33 +02003564 case HCI_EV_SNIFF_SUBRATE:
3565 hci_sniff_subrate_evt(hdev, skb);
3566 break;
3567
Marcel Holtmanna9de9242007-10-20 13:33:56 +02003568 case HCI_EV_EXTENDED_INQUIRY_RESULT:
3569 hci_extended_inquiry_result_evt(hdev, skb);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003570 break;
3571
Marcel Holtmann04936842008-07-14 20:13:48 +02003572 case HCI_EV_IO_CAPA_REQUEST:
3573 hci_io_capa_request_evt(hdev, skb);
3574 break;
3575
Johan Hedberg03b555e2011-01-04 15:40:05 +02003576 case HCI_EV_IO_CAPA_REPLY:
3577 hci_io_capa_reply_evt(hdev, skb);
3578 break;
3579
Johan Hedberga5c29682011-02-19 12:05:57 -03003580 case HCI_EV_USER_CONFIRM_REQUEST:
3581 hci_user_confirm_request_evt(hdev, skb);
3582 break;
3583
Brian Gix1143d452011-11-23 08:28:34 -08003584 case HCI_EV_USER_PASSKEY_REQUEST:
3585 hci_user_passkey_request_evt(hdev, skb);
3586 break;
3587
Marcel Holtmann04936842008-07-14 20:13:48 +02003588 case HCI_EV_SIMPLE_PAIR_COMPLETE:
3589 hci_simple_pair_complete_evt(hdev, skb);
3590 break;
3591
Marcel Holtmann41a96212008-07-14 20:13:48 +02003592 case HCI_EV_REMOTE_HOST_FEATURES:
3593 hci_remote_host_features_evt(hdev, skb);
3594 break;
3595
Ville Tervofcd89c02011-02-10 22:38:47 -03003596 case HCI_EV_LE_META:
3597 hci_le_meta_evt(hdev, skb);
3598 break;
3599
Szymon Janc2763eda2011-03-22 13:12:22 +01003600 case HCI_EV_REMOTE_OOB_DATA_REQUEST:
3601 hci_remote_oob_data_request_evt(hdev, skb);
3602 break;
3603
Andrei Emeltchenko25e89e92012-01-04 12:41:58 +02003604 case HCI_EV_NUM_COMP_BLOCKS:
3605 hci_num_comp_blocks_evt(hdev, skb);
3606 break;
3607
Marcel Holtmanna9de9242007-10-20 13:33:56 +02003608 default:
3609 BT_DBG("%s event 0x%x", hdev->name, event);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003610 break;
3611 }
3612
3613 kfree_skb(skb);
3614 hdev->stat.evt_rx++;
3615}