blob: d11b87bc1d1ada465c2c6e00b4d1b3745855cc84 [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 <asm/unaligned.h>
28
29#include <net/bluetooth/bluetooth.h>
30#include <net/bluetooth/hci_core.h>
Mikel Astizf0d6a0e2012-08-09 09:52:30 +020031#include <net/bluetooth/mgmt.h>
Andrei Emeltchenko8e2a0d92012-09-27 17:26:08 +030032#include <net/bluetooth/a2mp.h>
Andrei Emeltchenko903e4542012-09-27 17:26:09 +030033#include <net/bluetooth/amp.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070034
Linus Torvalds1da177e2005-04-16 15:20:36 -070035/* Handle HCI Event packets */
36
Marcel Holtmanna9de9242007-10-20 13:33:56 +020037static void hci_cc_inquiry_cancel(struct hci_dev *hdev, struct sk_buff *skb)
Linus Torvalds1da177e2005-04-16 15:20:36 -070038{
Marcel Holtmanna9de9242007-10-20 13:33:56 +020039 __u8 status = *((__u8 *) skb->data);
Linus Torvalds1da177e2005-04-16 15:20:36 -070040
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +030041 BT_DBG("%s status 0x%2.2x", hdev->name, status);
Linus Torvalds1da177e2005-04-16 15:20:36 -070042
Andre Guedese6d465c2011-11-09 17:14:26 -030043 if (status) {
44 hci_dev_lock(hdev);
45 mgmt_stop_discovery_failed(hdev, status);
46 hci_dev_unlock(hdev);
Marcel Holtmanna9de9242007-10-20 13:33:56 +020047 return;
Andre Guedese6d465c2011-11-09 17:14:26 -030048 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070049
Andre Guedes89352e72011-11-04 14:16:53 -030050 clear_bit(HCI_INQUIRY, &hdev->flags);
51
Johan Hedberg56e5cb82011-11-08 20:40:16 +020052 hci_dev_lock(hdev);
Johan Hedbergff9ef572012-01-04 14:23:45 +020053 hci_discovery_set_state(hdev, DISCOVERY_STOPPED);
Johan Hedberg56e5cb82011-11-08 20:40:16 +020054 hci_dev_unlock(hdev);
Marcel Holtmann6bd57412006-11-18 22:14:22 +010055
Johan Hedberg9238f362013-03-05 20:37:48 +020056 hci_req_cmd_complete(hdev, HCI_OP_INQUIRY, status);
Marcel Holtmann6bd57412006-11-18 22:14:22 +010057
Marcel Holtmanna9de9242007-10-20 13:33:56 +020058 hci_conn_check_pending(hdev);
Linus Torvalds1da177e2005-04-16 15:20:36 -070059}
60
Andre Guedes4d934832012-03-21 00:03:35 -030061static void hci_cc_periodic_inq(struct hci_dev *hdev, struct sk_buff *skb)
62{
63 __u8 status = *((__u8 *) skb->data);
64
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +030065 BT_DBG("%s status 0x%2.2x", hdev->name, status);
Andre Guedesae854a72012-03-21 00:03:36 -030066
67 if (status)
68 return;
69
70 set_bit(HCI_PERIODIC_INQ, &hdev->dev_flags);
Andre Guedes4d934832012-03-21 00:03:35 -030071}
72
Marcel Holtmanna9de9242007-10-20 13:33:56 +020073static void hci_cc_exit_periodic_inq(struct hci_dev *hdev, struct sk_buff *skb)
Linus Torvalds1da177e2005-04-16 15:20:36 -070074{
Marcel Holtmanna9de9242007-10-20 13:33:56 +020075 __u8 status = *((__u8 *) skb->data);
76
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +030077 BT_DBG("%s status 0x%2.2x", hdev->name, status);
Marcel Holtmanna9de9242007-10-20 13:33:56 +020078
79 if (status)
80 return;
81
Andre Guedesae854a72012-03-21 00:03:36 -030082 clear_bit(HCI_PERIODIC_INQ, &hdev->dev_flags);
83
Marcel Holtmanna9de9242007-10-20 13:33:56 +020084 hci_conn_check_pending(hdev);
85}
86
Gustavo Padovan807deac2012-05-17 00:36:24 -030087static void hci_cc_remote_name_req_cancel(struct hci_dev *hdev,
88 struct sk_buff *skb)
Marcel Holtmanna9de9242007-10-20 13:33:56 +020089{
90 BT_DBG("%s", hdev->name);
91}
92
93static void hci_cc_role_discovery(struct hci_dev *hdev, struct sk_buff *skb)
94{
95 struct hci_rp_role_discovery *rp = (void *) skb->data;
Linus Torvalds1da177e2005-04-16 15:20:36 -070096 struct hci_conn *conn;
Linus Torvalds1da177e2005-04-16 15:20:36 -070097
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +030098 BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
Linus Torvalds1da177e2005-04-16 15:20:36 -070099
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200100 if (rp->status)
101 return;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700102
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200103 hci_dev_lock(hdev);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700104
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200105 conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(rp->handle));
106 if (conn) {
107 if (rp->role)
108 conn->link_mode &= ~HCI_LM_MASTER;
109 else
110 conn->link_mode |= HCI_LM_MASTER;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700111 }
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200112
113 hci_dev_unlock(hdev);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700114}
115
Marcel Holtmanne4e8e372008-07-14 20:13:47 +0200116static void hci_cc_read_link_policy(struct hci_dev *hdev, struct sk_buff *skb)
117{
118 struct hci_rp_read_link_policy *rp = (void *) skb->data;
119 struct hci_conn *conn;
120
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +0300121 BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
Marcel Holtmanne4e8e372008-07-14 20:13:47 +0200122
123 if (rp->status)
124 return;
125
126 hci_dev_lock(hdev);
127
128 conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(rp->handle));
129 if (conn)
130 conn->link_policy = __le16_to_cpu(rp->policy);
131
132 hci_dev_unlock(hdev);
133}
134
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200135static void hci_cc_write_link_policy(struct hci_dev *hdev, struct sk_buff *skb)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700136{
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200137 struct hci_rp_write_link_policy *rp = (void *) skb->data;
138 struct hci_conn *conn;
139 void *sent;
140
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +0300141 BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200142
143 if (rp->status)
144 return;
145
146 sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_LINK_POLICY);
147 if (!sent)
148 return;
149
150 hci_dev_lock(hdev);
151
152 conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(rp->handle));
Marcel Holtmanne4e8e372008-07-14 20:13:47 +0200153 if (conn)
Harvey Harrison83985312008-05-02 16:25:46 -0700154 conn->link_policy = get_unaligned_le16(sent + 2);
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200155
156 hci_dev_unlock(hdev);
157}
158
Gustavo Padovan807deac2012-05-17 00:36:24 -0300159static void hci_cc_read_def_link_policy(struct hci_dev *hdev,
160 struct sk_buff *skb)
Marcel Holtmanne4e8e372008-07-14 20:13:47 +0200161{
162 struct hci_rp_read_def_link_policy *rp = (void *) skb->data;
163
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +0300164 BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
Marcel Holtmanne4e8e372008-07-14 20:13:47 +0200165
166 if (rp->status)
167 return;
168
169 hdev->link_policy = __le16_to_cpu(rp->policy);
170}
171
Gustavo Padovan807deac2012-05-17 00:36:24 -0300172static void hci_cc_write_def_link_policy(struct hci_dev *hdev,
173 struct sk_buff *skb)
Marcel Holtmanne4e8e372008-07-14 20:13:47 +0200174{
175 __u8 status = *((__u8 *) skb->data);
176 void *sent;
177
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +0300178 BT_DBG("%s status 0x%2.2x", hdev->name, status);
Marcel Holtmanne4e8e372008-07-14 20:13:47 +0200179
180 sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_DEF_LINK_POLICY);
181 if (!sent)
182 return;
183
184 if (!status)
185 hdev->link_policy = get_unaligned_le16(sent);
Marcel Holtmanne4e8e372008-07-14 20:13:47 +0200186}
187
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200188static void hci_cc_reset(struct hci_dev *hdev, struct sk_buff *skb)
189{
190 __u8 status = *((__u8 *) skb->data);
191
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +0300192 BT_DBG("%s status 0x%2.2x", hdev->name, status);
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200193
Gustavo F. Padovan10572132011-03-16 15:36:29 -0300194 clear_bit(HCI_RESET, &hdev->flags);
195
Johan Hedberga297e972012-02-21 17:55:47 +0200196 /* Reset all non-persistent flags */
Andre Guedesae854a72012-03-21 00:03:36 -0300197 hdev->dev_flags &= ~(BIT(HCI_LE_SCAN) | BIT(HCI_PENDING_CLASS) |
198 BIT(HCI_PERIODIC_INQ));
Andre Guedes69775ff2012-02-23 16:50:05 +0200199
200 hdev->discovery.state = DISCOVERY_STOPPED;
Johan Hedbergbbaf4442012-11-08 01:22:59 +0100201 hdev->inq_tx_power = HCI_TX_POWER_INVALID;
202 hdev->adv_tx_power = HCI_TX_POWER_INVALID;
Johan Hedberg3f0f5242012-11-08 01:23:00 +0100203
204 memset(hdev->adv_data, 0, sizeof(hdev->adv_data));
205 hdev->adv_data_len = 0;
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200206}
207
208static void hci_cc_write_local_name(struct hci_dev *hdev, struct sk_buff *skb)
209{
210 __u8 status = *((__u8 *) skb->data);
211 void *sent;
212
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +0300213 BT_DBG("%s status 0x%2.2x", hdev->name, status);
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200214
215 sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_LOCAL_NAME);
216 if (!sent)
217 return;
218
Johan Hedberg56e5cb82011-11-08 20:40:16 +0200219 hci_dev_lock(hdev);
220
Johan Hedbergf51d5b22012-02-22 18:17:32 +0200221 if (test_bit(HCI_MGMT, &hdev->dev_flags))
222 mgmt_set_local_name_complete(hdev, sent, status);
Johan Hedberg28cc7bd2012-02-22 21:06:55 +0200223 else if (!status)
224 memcpy(hdev->dev_name, sent, HCI_MAX_NAME_LENGTH);
Johan Hedbergf51d5b22012-02-22 18:17:32 +0200225
Johan Hedberg56e5cb82011-11-08 20:40:16 +0200226 hci_dev_unlock(hdev);
Johan Hedberg3159d382012-02-24 13:47:56 +0200227
Johan Hedberg3f0f5242012-11-08 01:23:00 +0100228 if (!status && !test_bit(HCI_INIT, &hdev->flags))
229 hci_update_ad(hdev);
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200230}
231
232static void hci_cc_read_local_name(struct hci_dev *hdev, struct sk_buff *skb)
233{
234 struct hci_rp_read_local_name *rp = (void *) skb->data;
235
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +0300236 BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200237
238 if (rp->status)
239 return;
240
Johan Hedbergdb99b5f2012-02-22 20:14:22 +0200241 if (test_bit(HCI_SETUP, &hdev->dev_flags))
242 memcpy(hdev->dev_name, rp->name, HCI_MAX_NAME_LENGTH);
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200243}
244
245static void hci_cc_write_auth_enable(struct hci_dev *hdev, struct sk_buff *skb)
246{
247 __u8 status = *((__u8 *) skb->data);
248 void *sent;
249
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +0300250 BT_DBG("%s status 0x%2.2x", hdev->name, status);
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200251
252 sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_AUTH_ENABLE);
253 if (!sent)
254 return;
255
256 if (!status) {
257 __u8 param = *((__u8 *) sent);
258
259 if (param == AUTH_ENABLED)
260 set_bit(HCI_AUTH, &hdev->flags);
261 else
262 clear_bit(HCI_AUTH, &hdev->flags);
263 }
264
Johan Hedberg33ef95e2012-02-16 23:56:27 +0200265 if (test_bit(HCI_MGMT, &hdev->dev_flags))
266 mgmt_auth_enable_complete(hdev, status);
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200267}
268
269static void hci_cc_write_encrypt_mode(struct hci_dev *hdev, struct sk_buff *skb)
270{
271 __u8 status = *((__u8 *) skb->data);
272 void *sent;
273
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +0300274 BT_DBG("%s status 0x%2.2x", hdev->name, status);
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200275
276 sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_ENCRYPT_MODE);
277 if (!sent)
278 return;
279
280 if (!status) {
281 __u8 param = *((__u8 *) sent);
282
283 if (param)
284 set_bit(HCI_ENCRYPT, &hdev->flags);
285 else
286 clear_bit(HCI_ENCRYPT, &hdev->flags);
287 }
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200288}
289
290static void hci_cc_write_scan_enable(struct hci_dev *hdev, struct sk_buff *skb)
291{
Johan Hedberg36f7fc72011-11-04 00:17:45 +0200292 __u8 param, status = *((__u8 *) skb->data);
293 int old_pscan, old_iscan;
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200294 void *sent;
295
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +0300296 BT_DBG("%s status 0x%2.2x", hdev->name, status);
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200297
298 sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_SCAN_ENABLE);
299 if (!sent)
300 return;
301
Johan Hedberg36f7fc72011-11-04 00:17:45 +0200302 param = *((__u8 *) sent);
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200303
Johan Hedberg56e5cb82011-11-08 20:40:16 +0200304 hci_dev_lock(hdev);
305
Mikel Astizfa1bd912012-08-09 09:52:29 +0200306 if (status) {
Johan Hedberg744cf192011-11-08 20:40:14 +0200307 mgmt_write_scan_failed(hdev, param, status);
Johan Hedberg2d7cee52011-11-07 22:16:03 +0200308 hdev->discov_timeout = 0;
309 goto done;
310 }
311
Johan Hedberg36f7fc72011-11-04 00:17:45 +0200312 old_pscan = test_and_clear_bit(HCI_PSCAN, &hdev->flags);
313 old_iscan = test_and_clear_bit(HCI_ISCAN, &hdev->flags);
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200314
Johan Hedberg36f7fc72011-11-04 00:17:45 +0200315 if (param & SCAN_INQUIRY) {
316 set_bit(HCI_ISCAN, &hdev->flags);
317 if (!old_iscan)
Johan Hedberg744cf192011-11-08 20:40:14 +0200318 mgmt_discoverable(hdev, 1);
Johan Hedberg16ab91a2011-11-07 22:16:02 +0200319 if (hdev->discov_timeout > 0) {
320 int to = msecs_to_jiffies(hdev->discov_timeout * 1000);
321 queue_delayed_work(hdev->workqueue, &hdev->discov_off,
Gustavo Padovan807deac2012-05-17 00:36:24 -0300322 to);
Johan Hedberg16ab91a2011-11-07 22:16:02 +0200323 }
Johan Hedberg36f7fc72011-11-04 00:17:45 +0200324 } else if (old_iscan)
Johan Hedberg744cf192011-11-08 20:40:14 +0200325 mgmt_discoverable(hdev, 0);
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200326
Johan Hedberg36f7fc72011-11-04 00:17:45 +0200327 if (param & SCAN_PAGE) {
328 set_bit(HCI_PSCAN, &hdev->flags);
329 if (!old_pscan)
Johan Hedberg744cf192011-11-08 20:40:14 +0200330 mgmt_connectable(hdev, 1);
Johan Hedberg36f7fc72011-11-04 00:17:45 +0200331 } else if (old_pscan)
Johan Hedberg744cf192011-11-08 20:40:14 +0200332 mgmt_connectable(hdev, 0);
Johan Hedberg36f7fc72011-11-04 00:17:45 +0200333
334done:
Johan Hedberg56e5cb82011-11-08 20:40:16 +0200335 hci_dev_unlock(hdev);
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200336}
337
338static void hci_cc_read_class_of_dev(struct hci_dev *hdev, struct sk_buff *skb)
339{
340 struct hci_rp_read_class_of_dev *rp = (void *) skb->data;
341
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +0300342 BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200343
344 if (rp->status)
345 return;
346
347 memcpy(hdev->dev_class, rp->dev_class, 3);
348
349 BT_DBG("%s class 0x%.2x%.2x%.2x", hdev->name,
Gustavo Padovan807deac2012-05-17 00:36:24 -0300350 hdev->dev_class[2], hdev->dev_class[1], hdev->dev_class[0]);
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200351}
352
353static void hci_cc_write_class_of_dev(struct hci_dev *hdev, struct sk_buff *skb)
354{
355 __u8 status = *((__u8 *) skb->data);
356 void *sent;
357
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +0300358 BT_DBG("%s status 0x%2.2x", hdev->name, status);
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200359
360 sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_CLASS_OF_DEV);
361 if (!sent)
362 return;
363
Marcel Holtmann7f9a9032012-02-22 18:38:01 +0100364 hci_dev_lock(hdev);
365
366 if (status == 0)
367 memcpy(hdev->dev_class, sent, 3);
368
369 if (test_bit(HCI_MGMT, &hdev->dev_flags))
370 mgmt_set_class_of_dev_complete(hdev, sent, status);
371
372 hci_dev_unlock(hdev);
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200373}
374
375static void hci_cc_read_voice_setting(struct hci_dev *hdev, struct sk_buff *skb)
376{
377 struct hci_rp_read_voice_setting *rp = (void *) skb->data;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700378 __u16 setting;
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200379
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +0300380 BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200381
382 if (rp->status)
383 return;
384
385 setting = __le16_to_cpu(rp->voice_setting);
386
Marcel Holtmannf383f272008-07-14 20:13:47 +0200387 if (hdev->voice_setting == setting)
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200388 return;
389
390 hdev->voice_setting = setting;
391
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +0300392 BT_DBG("%s voice setting 0x%4.4x", hdev->name, setting);
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200393
Gustavo F. Padovan3c547112011-12-14 22:58:44 -0200394 if (hdev->notify)
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200395 hdev->notify(hdev, HCI_NOTIFY_VOICE_SETTING);
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200396}
397
Gustavo Padovan8fc9ced2012-05-23 04:04:21 -0300398static void hci_cc_write_voice_setting(struct hci_dev *hdev,
399 struct sk_buff *skb)
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200400{
401 __u8 status = *((__u8 *) skb->data);
Marcel Holtmannf383f272008-07-14 20:13:47 +0200402 __u16 setting;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700403 void *sent;
404
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +0300405 BT_DBG("%s status 0x%2.2x", hdev->name, status);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700406
Marcel Holtmannf383f272008-07-14 20:13:47 +0200407 if (status)
408 return;
409
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200410 sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_VOICE_SETTING);
411 if (!sent)
412 return;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700413
Marcel Holtmannf383f272008-07-14 20:13:47 +0200414 setting = get_unaligned_le16(sent);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700415
Marcel Holtmannf383f272008-07-14 20:13:47 +0200416 if (hdev->voice_setting == setting)
417 return;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700418
Marcel Holtmannf383f272008-07-14 20:13:47 +0200419 hdev->voice_setting = setting;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700420
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +0300421 BT_DBG("%s voice setting 0x%4.4x", hdev->name, setting);
Marcel Holtmannf383f272008-07-14 20:13:47 +0200422
Gustavo F. Padovan3c547112011-12-14 22:58:44 -0200423 if (hdev->notify)
Marcel Holtmannf383f272008-07-14 20:13:47 +0200424 hdev->notify(hdev, HCI_NOTIFY_VOICE_SETTING);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700425}
426
Marcel Holtmann333140b2008-07-14 20:13:48 +0200427static void hci_cc_write_ssp_mode(struct hci_dev *hdev, struct sk_buff *skb)
428{
429 __u8 status = *((__u8 *) skb->data);
Johan Hedberg5ed8eb22012-10-25 00:09:51 +0300430 struct hci_cp_write_ssp_mode *sent;
Marcel Holtmann333140b2008-07-14 20:13:48 +0200431
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +0300432 BT_DBG("%s status 0x%2.2x", hdev->name, status);
Marcel Holtmann333140b2008-07-14 20:13:48 +0200433
Marcel Holtmann333140b2008-07-14 20:13:48 +0200434 sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_SSP_MODE);
435 if (!sent)
436 return;
437
Johan Hedberg5ed8eb22012-10-25 00:09:51 +0300438 if (!status) {
439 if (sent->mode)
440 hdev->host_features[0] |= LMP_HOST_SSP;
441 else
442 hdev->host_features[0] &= ~LMP_HOST_SSP;
443 }
444
Johan Hedberged2c4ee2012-02-17 00:56:28 +0200445 if (test_bit(HCI_MGMT, &hdev->dev_flags))
Johan Hedberg5ed8eb22012-10-25 00:09:51 +0300446 mgmt_ssp_enable_complete(hdev, sent->mode, status);
Johan Hedbergc0ecddc2012-02-22 12:38:31 +0200447 else if (!status) {
Johan Hedberg5ed8eb22012-10-25 00:09:51 +0300448 if (sent->mode)
Johan Hedbergc0ecddc2012-02-22 12:38:31 +0200449 set_bit(HCI_SSP_ENABLED, &hdev->dev_flags);
450 else
451 clear_bit(HCI_SSP_ENABLED, &hdev->dev_flags);
452 }
Marcel Holtmann333140b2008-07-14 20:13:48 +0200453}
454
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200455static void hci_cc_read_local_version(struct hci_dev *hdev, struct sk_buff *skb)
456{
457 struct hci_rp_read_local_version *rp = (void *) skb->data;
458
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +0300459 BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200460
461 if (rp->status)
Johan Hedberg42c6b122013-03-05 20:37:49 +0200462 return;
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200463
464 hdev->hci_ver = rp->hci_ver;
Marcel Holtmanne4e8e372008-07-14 20:13:47 +0200465 hdev->hci_rev = __le16_to_cpu(rp->hci_rev);
Johan Hedbergd5859e22011-01-25 01:19:58 +0200466 hdev->lmp_ver = rp->lmp_ver;
Marcel Holtmanne4e8e372008-07-14 20:13:47 +0200467 hdev->manufacturer = __le16_to_cpu(rp->manufacturer);
Johan Hedbergd5859e22011-01-25 01:19:58 +0200468 hdev->lmp_subver = __le16_to_cpu(rp->lmp_subver);
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200469
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +0300470 BT_DBG("%s manufacturer 0x%4.4x hci ver %d:%d", hdev->name,
Gustavo Padovan807deac2012-05-17 00:36:24 -0300471 hdev->manufacturer, hdev->hci_ver, hdev->hci_rev);
Johan Hedbergd5859e22011-01-25 01:19:58 +0200472}
473
Gustavo Padovan8fc9ced2012-05-23 04:04:21 -0300474static void hci_cc_read_local_commands(struct hci_dev *hdev,
475 struct sk_buff *skb)
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200476{
477 struct hci_rp_read_local_commands *rp = (void *) skb->data;
478
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +0300479 BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200480
Johan Hedberg2177bab2013-03-05 20:37:43 +0200481 if (!rp->status)
482 memcpy(hdev->commands, rp->commands, sizeof(hdev->commands));
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200483}
484
Gustavo Padovan8fc9ced2012-05-23 04:04:21 -0300485static void hci_cc_read_local_features(struct hci_dev *hdev,
486 struct sk_buff *skb)
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200487{
488 struct hci_rp_read_local_features *rp = (void *) skb->data;
489
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +0300490 BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200491
492 if (rp->status)
493 return;
494
495 memcpy(hdev->features, rp->features, 8);
496
497 /* Adjust default settings according to features
498 * supported by device. */
499
500 if (hdev->features[0] & LMP_3SLOT)
501 hdev->pkt_type |= (HCI_DM3 | HCI_DH3);
502
503 if (hdev->features[0] & LMP_5SLOT)
504 hdev->pkt_type |= (HCI_DM5 | HCI_DH5);
505
506 if (hdev->features[1] & LMP_HV2) {
507 hdev->pkt_type |= (HCI_HV2);
508 hdev->esco_type |= (ESCO_HV2);
509 }
510
511 if (hdev->features[1] & LMP_HV3) {
512 hdev->pkt_type |= (HCI_HV3);
513 hdev->esco_type |= (ESCO_HV3);
514 }
515
Andre Guedes45db810f2012-07-24 15:03:49 -0300516 if (lmp_esco_capable(hdev))
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200517 hdev->esco_type |= (ESCO_EV3);
518
519 if (hdev->features[4] & LMP_EV4)
520 hdev->esco_type |= (ESCO_EV4);
521
522 if (hdev->features[4] & LMP_EV5)
523 hdev->esco_type |= (ESCO_EV5);
524
Marcel Holtmannefc76882009-02-06 09:13:37 +0100525 if (hdev->features[5] & LMP_EDR_ESCO_2M)
526 hdev->esco_type |= (ESCO_2EV3);
527
528 if (hdev->features[5] & LMP_EDR_ESCO_3M)
529 hdev->esco_type |= (ESCO_3EV3);
530
531 if (hdev->features[5] & LMP_EDR_3S_ESCO)
532 hdev->esco_type |= (ESCO_2EV5 | ESCO_3EV5);
533
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200534 BT_DBG("%s features 0x%.2x%.2x%.2x%.2x%.2x%.2x%.2x%.2x", hdev->name,
Gustavo Padovan807deac2012-05-17 00:36:24 -0300535 hdev->features[0], hdev->features[1],
536 hdev->features[2], hdev->features[3],
537 hdev->features[4], hdev->features[5],
538 hdev->features[6], hdev->features[7]);
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200539}
540
Andre Guedes971e3a42011-06-30 19:20:52 -0300541static void hci_cc_read_local_ext_features(struct hci_dev *hdev,
Gustavo Padovan807deac2012-05-17 00:36:24 -0300542 struct sk_buff *skb)
Andre Guedes971e3a42011-06-30 19:20:52 -0300543{
544 struct hci_rp_read_local_ext_features *rp = (void *) skb->data;
545
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +0300546 BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
Andre Guedes971e3a42011-06-30 19:20:52 -0300547
548 if (rp->status)
Johan Hedberg42c6b122013-03-05 20:37:49 +0200549 return;
Andre Guedes971e3a42011-06-30 19:20:52 -0300550
Andre Guedesb5b32b62011-12-30 10:34:04 -0300551 switch (rp->page) {
552 case 0:
553 memcpy(hdev->features, rp->features, 8);
554 break;
555 case 1:
556 memcpy(hdev->host_features, rp->features, 8);
557 break;
558 }
Andre Guedes971e3a42011-06-30 19:20:52 -0300559}
560
Andrei Emeltchenko1e89cff2011-11-24 14:52:02 +0200561static void hci_cc_read_flow_control_mode(struct hci_dev *hdev,
Gustavo Padovan807deac2012-05-17 00:36:24 -0300562 struct sk_buff *skb)
Andrei Emeltchenko1e89cff2011-11-24 14:52:02 +0200563{
564 struct hci_rp_read_flow_control_mode *rp = (void *) skb->data;
565
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +0300566 BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
Andrei Emeltchenko1e89cff2011-11-24 14:52:02 +0200567
Johan Hedberg42c6b122013-03-05 20:37:49 +0200568 if (!rp->status)
569 hdev->flow_ctl_mode = rp->mode;
Andrei Emeltchenko1e89cff2011-11-24 14:52:02 +0200570}
571
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200572static void hci_cc_read_buffer_size(struct hci_dev *hdev, struct sk_buff *skb)
573{
574 struct hci_rp_read_buffer_size *rp = (void *) skb->data;
575
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +0300576 BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200577
578 if (rp->status)
579 return;
580
581 hdev->acl_mtu = __le16_to_cpu(rp->acl_mtu);
582 hdev->sco_mtu = rp->sco_mtu;
583 hdev->acl_pkts = __le16_to_cpu(rp->acl_max_pkt);
584 hdev->sco_pkts = __le16_to_cpu(rp->sco_max_pkt);
585
586 if (test_bit(HCI_QUIRK_FIXUP_BUFFER_SIZE, &hdev->quirks)) {
587 hdev->sco_mtu = 64;
588 hdev->sco_pkts = 8;
589 }
590
591 hdev->acl_cnt = hdev->acl_pkts;
592 hdev->sco_cnt = hdev->sco_pkts;
593
Gustavo Padovan807deac2012-05-17 00:36:24 -0300594 BT_DBG("%s acl mtu %d:%d sco mtu %d:%d", hdev->name, hdev->acl_mtu,
595 hdev->acl_pkts, hdev->sco_mtu, hdev->sco_pkts);
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200596}
597
598static void hci_cc_read_bd_addr(struct hci_dev *hdev, struct sk_buff *skb)
599{
600 struct hci_rp_read_bd_addr *rp = (void *) skb->data;
601
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +0300602 BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200603
604 if (!rp->status)
605 bacpy(&hdev->bdaddr, &rp->bdaddr);
Johan Hedberg23bb5762010-12-21 23:01:27 +0200606}
607
Andrei Emeltchenko350ee4c2011-12-07 15:56:51 +0200608static void hci_cc_read_data_block_size(struct hci_dev *hdev,
Gustavo Padovan807deac2012-05-17 00:36:24 -0300609 struct sk_buff *skb)
Andrei Emeltchenko350ee4c2011-12-07 15:56:51 +0200610{
611 struct hci_rp_read_data_block_size *rp = (void *) skb->data;
612
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +0300613 BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
Andrei Emeltchenko350ee4c2011-12-07 15:56:51 +0200614
615 if (rp->status)
616 return;
617
618 hdev->block_mtu = __le16_to_cpu(rp->max_acl_len);
619 hdev->block_len = __le16_to_cpu(rp->block_len);
620 hdev->num_blocks = __le16_to_cpu(rp->num_blocks);
621
622 hdev->block_cnt = hdev->num_blocks;
623
624 BT_DBG("%s blk mtu %d cnt %d len %d", hdev->name, hdev->block_mtu,
Gustavo Padovan807deac2012-05-17 00:36:24 -0300625 hdev->block_cnt, hdev->block_len);
Andrei Emeltchenko350ee4c2011-12-07 15:56:51 +0200626}
627
Andrei Emeltchenko928abaa2011-10-12 10:53:57 +0300628static void hci_cc_read_local_amp_info(struct hci_dev *hdev,
Gustavo Padovan807deac2012-05-17 00:36:24 -0300629 struct sk_buff *skb)
Andrei Emeltchenko928abaa2011-10-12 10:53:57 +0300630{
631 struct hci_rp_read_local_amp_info *rp = (void *) skb->data;
632
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +0300633 BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
Andrei Emeltchenko928abaa2011-10-12 10:53:57 +0300634
635 if (rp->status)
Andrei Emeltchenko8e2a0d92012-09-27 17:26:08 +0300636 goto a2mp_rsp;
Andrei Emeltchenko928abaa2011-10-12 10:53:57 +0300637
638 hdev->amp_status = rp->amp_status;
639 hdev->amp_total_bw = __le32_to_cpu(rp->total_bw);
640 hdev->amp_max_bw = __le32_to_cpu(rp->max_bw);
641 hdev->amp_min_latency = __le32_to_cpu(rp->min_latency);
642 hdev->amp_max_pdu = __le32_to_cpu(rp->max_pdu);
643 hdev->amp_type = rp->amp_type;
644 hdev->amp_pal_cap = __le16_to_cpu(rp->pal_cap);
645 hdev->amp_assoc_size = __le16_to_cpu(rp->max_assoc_size);
646 hdev->amp_be_flush_to = __le32_to_cpu(rp->be_flush_to);
647 hdev->amp_max_flush_to = __le32_to_cpu(rp->max_flush_to);
648
Andrei Emeltchenko8e2a0d92012-09-27 17:26:08 +0300649a2mp_rsp:
650 a2mp_send_getinfo_rsp(hdev);
Andrei Emeltchenko928abaa2011-10-12 10:53:57 +0300651}
652
Andrei Emeltchenko903e4542012-09-27 17:26:09 +0300653static void hci_cc_read_local_amp_assoc(struct hci_dev *hdev,
654 struct sk_buff *skb)
655{
656 struct hci_rp_read_local_amp_assoc *rp = (void *) skb->data;
657 struct amp_assoc *assoc = &hdev->loc_assoc;
658 size_t rem_len, frag_len;
659
660 BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
661
662 if (rp->status)
663 goto a2mp_rsp;
664
665 frag_len = skb->len - sizeof(*rp);
666 rem_len = __le16_to_cpu(rp->rem_len);
667
668 if (rem_len > frag_len) {
Andrei Emeltchenko2e430be32012-09-28 14:44:23 +0300669 BT_DBG("frag_len %zu rem_len %zu", frag_len, rem_len);
Andrei Emeltchenko903e4542012-09-27 17:26:09 +0300670
671 memcpy(assoc->data + assoc->offset, rp->frag, frag_len);
672 assoc->offset += frag_len;
673
674 /* Read other fragments */
675 amp_read_loc_assoc_frag(hdev, rp->phy_handle);
676
677 return;
678 }
679
680 memcpy(assoc->data + assoc->offset, rp->frag, rem_len);
681 assoc->len = assoc->offset + rem_len;
682 assoc->offset = 0;
683
684a2mp_rsp:
685 /* Send A2MP Rsp when all fragments are received */
686 a2mp_send_getampassoc_rsp(hdev, rp->status);
Andrei Emeltchenko9495b2e2012-09-27 17:26:22 +0300687 a2mp_send_create_phy_link_req(hdev, rp->status);
Andrei Emeltchenko903e4542012-09-27 17:26:09 +0300688}
689
Johan Hedbergd5859e22011-01-25 01:19:58 +0200690static void hci_cc_read_inq_rsp_tx_power(struct hci_dev *hdev,
Gustavo Padovan807deac2012-05-17 00:36:24 -0300691 struct sk_buff *skb)
Johan Hedbergd5859e22011-01-25 01:19:58 +0200692{
Marcel Holtmann91c4e9b2012-03-11 19:27:21 -0700693 struct hci_rp_read_inq_rsp_tx_power *rp = (void *) skb->data;
Johan Hedbergd5859e22011-01-25 01:19:58 +0200694
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +0300695 BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
Johan Hedbergd5859e22011-01-25 01:19:58 +0200696
Marcel Holtmann91c4e9b2012-03-11 19:27:21 -0700697 if (!rp->status)
698 hdev->inq_tx_power = rp->tx_power;
Johan Hedbergd5859e22011-01-25 01:19:58 +0200699}
700
Johan Hedberg980e1a52011-01-22 06:10:07 +0200701static void hci_cc_pin_code_reply(struct hci_dev *hdev, struct sk_buff *skb)
702{
703 struct hci_rp_pin_code_reply *rp = (void *) skb->data;
704 struct hci_cp_pin_code_reply *cp;
705 struct hci_conn *conn;
706
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +0300707 BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
Johan Hedberg980e1a52011-01-22 06:10:07 +0200708
Johan Hedberg56e5cb82011-11-08 20:40:16 +0200709 hci_dev_lock(hdev);
710
Johan Hedberga8b2d5c2012-01-08 23:11:15 +0200711 if (test_bit(HCI_MGMT, &hdev->dev_flags))
Johan Hedberg744cf192011-11-08 20:40:14 +0200712 mgmt_pin_code_reply_complete(hdev, &rp->bdaddr, rp->status);
Johan Hedberg980e1a52011-01-22 06:10:07 +0200713
Mikel Astizfa1bd912012-08-09 09:52:29 +0200714 if (rp->status)
Johan Hedberg56e5cb82011-11-08 20:40:16 +0200715 goto unlock;
Johan Hedberg980e1a52011-01-22 06:10:07 +0200716
717 cp = hci_sent_cmd_data(hdev, HCI_OP_PIN_CODE_REPLY);
718 if (!cp)
Johan Hedberg56e5cb82011-11-08 20:40:16 +0200719 goto unlock;
Johan Hedberg980e1a52011-01-22 06:10:07 +0200720
721 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &cp->bdaddr);
722 if (conn)
723 conn->pin_length = cp->pin_len;
Johan Hedberg56e5cb82011-11-08 20:40:16 +0200724
725unlock:
726 hci_dev_unlock(hdev);
Johan Hedberg980e1a52011-01-22 06:10:07 +0200727}
728
729static void hci_cc_pin_code_neg_reply(struct hci_dev *hdev, struct sk_buff *skb)
730{
731 struct hci_rp_pin_code_neg_reply *rp = (void *) skb->data;
732
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +0300733 BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
Johan Hedberg980e1a52011-01-22 06:10:07 +0200734
Johan Hedberg56e5cb82011-11-08 20:40:16 +0200735 hci_dev_lock(hdev);
736
Johan Hedberga8b2d5c2012-01-08 23:11:15 +0200737 if (test_bit(HCI_MGMT, &hdev->dev_flags))
Johan Hedberg744cf192011-11-08 20:40:14 +0200738 mgmt_pin_code_neg_reply_complete(hdev, &rp->bdaddr,
Gustavo Padovan807deac2012-05-17 00:36:24 -0300739 rp->status);
Johan Hedberg56e5cb82011-11-08 20:40:16 +0200740
741 hci_dev_unlock(hdev);
Johan Hedberg980e1a52011-01-22 06:10:07 +0200742}
Johan Hedberg56e5cb82011-11-08 20:40:16 +0200743
Ville Tervo6ed58ec2011-02-10 22:38:48 -0300744static void hci_cc_le_read_buffer_size(struct hci_dev *hdev,
745 struct sk_buff *skb)
746{
747 struct hci_rp_le_read_buffer_size *rp = (void *) skb->data;
748
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +0300749 BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
Ville Tervo6ed58ec2011-02-10 22:38:48 -0300750
751 if (rp->status)
752 return;
753
754 hdev->le_mtu = __le16_to_cpu(rp->le_mtu);
755 hdev->le_pkts = rp->le_max_pkt;
756
757 hdev->le_cnt = hdev->le_pkts;
758
759 BT_DBG("%s le mtu %d:%d", hdev->name, hdev->le_mtu, hdev->le_pkts);
Ville Tervo6ed58ec2011-02-10 22:38:48 -0300760}
Johan Hedberg980e1a52011-01-22 06:10:07 +0200761
Johan Hedberg60e77322013-01-22 14:01:59 +0200762static void hci_cc_le_read_local_features(struct hci_dev *hdev,
763 struct sk_buff *skb)
764{
765 struct hci_rp_le_read_local_features *rp = (void *) skb->data;
766
767 BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
768
769 if (!rp->status)
770 memcpy(hdev->le_features, rp->features, 8);
Johan Hedberg60e77322013-01-22 14:01:59 +0200771}
772
Johan Hedberg8fa19092012-10-19 20:57:49 +0300773static void hci_cc_le_read_adv_tx_power(struct hci_dev *hdev,
774 struct sk_buff *skb)
775{
776 struct hci_rp_le_read_adv_tx_power *rp = (void *) skb->data;
777
778 BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
779
Johan Hedberg3f0f5242012-11-08 01:23:00 +0100780 if (!rp->status) {
Johan Hedberg8fa19092012-10-19 20:57:49 +0300781 hdev->adv_tx_power = rp->tx_power;
Johan Hedberg3f0f5242012-11-08 01:23:00 +0100782 if (!test_bit(HCI_INIT, &hdev->flags))
783 hci_update_ad(hdev);
784 }
Johan Hedberg8fa19092012-10-19 20:57:49 +0300785}
786
Johan Hedberga5c29682011-02-19 12:05:57 -0300787static void hci_cc_user_confirm_reply(struct hci_dev *hdev, struct sk_buff *skb)
788{
789 struct hci_rp_user_confirm_reply *rp = (void *) skb->data;
790
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +0300791 BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
Johan Hedberga5c29682011-02-19 12:05:57 -0300792
Johan Hedberg56e5cb82011-11-08 20:40:16 +0200793 hci_dev_lock(hdev);
794
Johan Hedberga8b2d5c2012-01-08 23:11:15 +0200795 if (test_bit(HCI_MGMT, &hdev->dev_flags))
Gustavo F. Padovan04124682012-03-08 01:25:00 -0300796 mgmt_user_confirm_reply_complete(hdev, &rp->bdaddr, ACL_LINK, 0,
797 rp->status);
Johan Hedberg56e5cb82011-11-08 20:40:16 +0200798
799 hci_dev_unlock(hdev);
Johan Hedberga5c29682011-02-19 12:05:57 -0300800}
801
802static void hci_cc_user_confirm_neg_reply(struct hci_dev *hdev,
Gustavo Padovan807deac2012-05-17 00:36:24 -0300803 struct sk_buff *skb)
Johan Hedberga5c29682011-02-19 12:05:57 -0300804{
805 struct hci_rp_user_confirm_reply *rp = (void *) skb->data;
806
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +0300807 BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
Johan Hedberga5c29682011-02-19 12:05:57 -0300808
Johan Hedberg56e5cb82011-11-08 20:40:16 +0200809 hci_dev_lock(hdev);
810
Johan Hedberga8b2d5c2012-01-08 23:11:15 +0200811 if (test_bit(HCI_MGMT, &hdev->dev_flags))
Johan Hedberg744cf192011-11-08 20:40:14 +0200812 mgmt_user_confirm_neg_reply_complete(hdev, &rp->bdaddr,
Gustavo F. Padovan04124682012-03-08 01:25:00 -0300813 ACL_LINK, 0, rp->status);
Johan Hedberg56e5cb82011-11-08 20:40:16 +0200814
815 hci_dev_unlock(hdev);
Johan Hedberga5c29682011-02-19 12:05:57 -0300816}
817
Brian Gix1143d452011-11-23 08:28:34 -0800818static void hci_cc_user_passkey_reply(struct hci_dev *hdev, struct sk_buff *skb)
819{
820 struct hci_rp_user_confirm_reply *rp = (void *) skb->data;
821
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +0300822 BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
Brian Gix1143d452011-11-23 08:28:34 -0800823
824 hci_dev_lock(hdev);
825
Johan Hedberga8b2d5c2012-01-08 23:11:15 +0200826 if (test_bit(HCI_MGMT, &hdev->dev_flags))
Johan Hedberg272d90d2012-02-09 15:26:12 +0200827 mgmt_user_passkey_reply_complete(hdev, &rp->bdaddr, ACL_LINK,
Gustavo F. Padovan04124682012-03-08 01:25:00 -0300828 0, rp->status);
Brian Gix1143d452011-11-23 08:28:34 -0800829
830 hci_dev_unlock(hdev);
831}
832
833static void hci_cc_user_passkey_neg_reply(struct hci_dev *hdev,
Gustavo Padovan807deac2012-05-17 00:36:24 -0300834 struct sk_buff *skb)
Brian Gix1143d452011-11-23 08:28:34 -0800835{
836 struct hci_rp_user_confirm_reply *rp = (void *) skb->data;
837
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +0300838 BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
Brian Gix1143d452011-11-23 08:28:34 -0800839
840 hci_dev_lock(hdev);
841
Johan Hedberga8b2d5c2012-01-08 23:11:15 +0200842 if (test_bit(HCI_MGMT, &hdev->dev_flags))
Brian Gix1143d452011-11-23 08:28:34 -0800843 mgmt_user_passkey_neg_reply_complete(hdev, &rp->bdaddr,
Gustavo F. Padovan04124682012-03-08 01:25:00 -0300844 ACL_LINK, 0, rp->status);
Brian Gix1143d452011-11-23 08:28:34 -0800845
846 hci_dev_unlock(hdev);
847}
848
Szymon Jancc35938b2011-03-22 13:12:21 +0100849static void hci_cc_read_local_oob_data_reply(struct hci_dev *hdev,
Gustavo Padovan807deac2012-05-17 00:36:24 -0300850 struct sk_buff *skb)
Szymon Jancc35938b2011-03-22 13:12:21 +0100851{
852 struct hci_rp_read_local_oob_data *rp = (void *) skb->data;
853
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +0300854 BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
Szymon Jancc35938b2011-03-22 13:12:21 +0100855
Johan Hedberg56e5cb82011-11-08 20:40:16 +0200856 hci_dev_lock(hdev);
Johan Hedberg744cf192011-11-08 20:40:14 +0200857 mgmt_read_local_oob_data_reply_complete(hdev, rp->hash,
Szymon Jancc35938b2011-03-22 13:12:21 +0100858 rp->randomizer, rp->status);
Johan Hedberg56e5cb82011-11-08 20:40:16 +0200859 hci_dev_unlock(hdev);
Szymon Jancc35938b2011-03-22 13:12:21 +0100860}
861
Johan Hedbergc1d5dc42012-11-08 01:23:01 +0100862static void hci_cc_le_set_adv_enable(struct hci_dev *hdev, struct sk_buff *skb)
863{
864 __u8 *sent, status = *((__u8 *) skb->data);
865
866 BT_DBG("%s status 0x%2.2x", hdev->name, status);
867
868 sent = hci_sent_cmd_data(hdev, HCI_OP_LE_SET_ADV_ENABLE);
869 if (!sent)
870 return;
871
872 hci_dev_lock(hdev);
873
874 if (!status) {
875 if (*sent)
876 set_bit(HCI_LE_PERIPHERAL, &hdev->dev_flags);
877 else
878 clear_bit(HCI_LE_PERIPHERAL, &hdev->dev_flags);
879 }
880
881 hci_dev_unlock(hdev);
882
883 if (!test_bit(HCI_INIT, &hdev->flags))
884 hci_update_ad(hdev);
Johan Hedbergc1d5dc42012-11-08 01:23:01 +0100885}
886
Andre Guedes07f7fa52011-12-02 21:13:31 +0900887static void hci_cc_le_set_scan_param(struct hci_dev *hdev, struct sk_buff *skb)
888{
889 __u8 status = *((__u8 *) skb->data);
890
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +0300891 BT_DBG("%s status 0x%2.2x", hdev->name, status);
Andre Guedes7ba8b4b2012-02-03 17:47:59 -0300892
Andre Guedes3fd24152012-02-03 17:48:01 -0300893 if (status) {
894 hci_dev_lock(hdev);
895 mgmt_start_discovery_failed(hdev, status);
896 hci_dev_unlock(hdev);
897 return;
898 }
Andre Guedes07f7fa52011-12-02 21:13:31 +0900899}
900
Andre Guedeseb9d91f2011-05-26 16:23:52 -0300901static void hci_cc_le_set_scan_enable(struct hci_dev *hdev,
Gustavo Padovan807deac2012-05-17 00:36:24 -0300902 struct sk_buff *skb)
Andre Guedeseb9d91f2011-05-26 16:23:52 -0300903{
904 struct hci_cp_le_set_scan_enable *cp;
905 __u8 status = *((__u8 *) skb->data);
906
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +0300907 BT_DBG("%s status 0x%2.2x", hdev->name, status);
Andre Guedeseb9d91f2011-05-26 16:23:52 -0300908
Andre Guedeseb9d91f2011-05-26 16:23:52 -0300909 cp = hci_sent_cmd_data(hdev, HCI_OP_LE_SET_SCAN_ENABLE);
910 if (!cp)
911 return;
912
Andrei Emeltchenko68a8aea2011-12-19 16:14:18 +0200913 switch (cp->enable) {
914 case LE_SCANNING_ENABLED:
Andre Guedes3fd24152012-02-03 17:48:01 -0300915 if (status) {
916 hci_dev_lock(hdev);
917 mgmt_start_discovery_failed(hdev, status);
918 hci_dev_unlock(hdev);
Andre Guedes7ba8b4b2012-02-03 17:47:59 -0300919 return;
Andre Guedes3fd24152012-02-03 17:48:01 -0300920 }
Andre Guedes7ba8b4b2012-02-03 17:47:59 -0300921
Andre Guedesd23264a2011-11-25 20:53:38 -0300922 set_bit(HCI_LE_SCAN, &hdev->dev_flags);
923
Andre Guedesa8f13c82011-09-09 18:56:24 -0300924 hci_dev_lock(hdev);
Andre Guedes343f9352012-02-17 20:39:37 -0300925 hci_discovery_set_state(hdev, DISCOVERY_FINDING);
Andre Guedesa8f13c82011-09-09 18:56:24 -0300926 hci_dev_unlock(hdev);
Andrei Emeltchenko68a8aea2011-12-19 16:14:18 +0200927 break;
928
929 case LE_SCANNING_DISABLED:
Andre Guedesc9ecc482012-03-15 16:52:08 -0300930 if (status) {
931 hci_dev_lock(hdev);
932 mgmt_stop_discovery_failed(hdev, status);
933 hci_dev_unlock(hdev);
Andre Guedes7ba8b4b2012-02-03 17:47:59 -0300934 return;
Andre Guedesc9ecc482012-03-15 16:52:08 -0300935 }
Andre Guedes7ba8b4b2012-02-03 17:47:59 -0300936
Andre Guedesd23264a2011-11-25 20:53:38 -0300937 clear_bit(HCI_LE_SCAN, &hdev->dev_flags);
938
Andre Guedesbc3dd332012-03-06 19:37:06 -0300939 if (hdev->discovery.type == DISCOV_TYPE_INTERLEAVED &&
940 hdev->discovery.state == DISCOVERY_FINDING) {
Andre Guedes5e0452c2012-02-17 20:39:38 -0300941 mgmt_interleaved_discovery(hdev);
942 } else {
943 hci_dev_lock(hdev);
944 hci_discovery_set_state(hdev, DISCOVERY_STOPPED);
945 hci_dev_unlock(hdev);
946 }
947
Andrei Emeltchenko68a8aea2011-12-19 16:14:18 +0200948 break;
949
950 default:
951 BT_ERR("Used reserved LE_Scan_Enable param %d", cp->enable);
952 break;
Andre Guedes35815082011-05-26 16:23:53 -0300953 }
Andre Guedeseb9d91f2011-05-26 16:23:52 -0300954}
955
Johan Hedbergcf1d0812013-01-22 14:02:00 +0200956static void hci_cc_le_read_white_list_size(struct hci_dev *hdev,
957 struct sk_buff *skb)
958{
959 struct hci_rp_le_read_white_list_size *rp = (void *) skb->data;
960
961 BT_DBG("%s status 0x%2.2x size %u", hdev->name, rp->status, rp->size);
962
963 if (!rp->status)
964 hdev->le_white_list_size = rp->size;
Johan Hedbergcf1d0812013-01-22 14:02:00 +0200965}
966
Johan Hedberg9b008c02013-01-22 14:02:01 +0200967static void hci_cc_le_read_supported_states(struct hci_dev *hdev,
968 struct sk_buff *skb)
969{
970 struct hci_rp_le_read_supported_states *rp = (void *) skb->data;
971
972 BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
973
974 if (!rp->status)
975 memcpy(hdev->le_states, rp->le_states, 8);
Johan Hedberg9b008c02013-01-22 14:02:01 +0200976}
977
Gustavo Padovan6039aa72012-05-23 04:04:18 -0300978static void hci_cc_write_le_host_supported(struct hci_dev *hdev,
979 struct sk_buff *skb)
Andre Guedesf9b49302011-06-30 19:20:53 -0300980{
Johan Hedberg06199cf2012-02-22 16:37:11 +0200981 struct hci_cp_write_le_host_supported *sent;
Andre Guedesf9b49302011-06-30 19:20:53 -0300982 __u8 status = *((__u8 *) skb->data);
983
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +0300984 BT_DBG("%s status 0x%2.2x", hdev->name, status);
Andre Guedesf9b49302011-06-30 19:20:53 -0300985
Johan Hedberg06199cf2012-02-22 16:37:11 +0200986 sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_LE_HOST_SUPPORTED);
Johan Hedberg8f984df2012-02-28 01:07:22 +0200987 if (!sent)
Andre Guedesf9b49302011-06-30 19:20:53 -0300988 return;
989
Johan Hedberg8f984df2012-02-28 01:07:22 +0200990 if (!status) {
991 if (sent->le)
992 hdev->host_features[0] |= LMP_HOST_LE;
993 else
994 hdev->host_features[0] &= ~LMP_HOST_LE;
Johan Hedberg53b2caa2012-10-24 21:11:59 +0300995
996 if (sent->simul)
997 hdev->host_features[0] |= LMP_HOST_LE_BREDR;
998 else
999 hdev->host_features[0] &= ~LMP_HOST_LE_BREDR;
Johan Hedberg8f984df2012-02-28 01:07:22 +02001000 }
1001
1002 if (test_bit(HCI_MGMT, &hdev->dev_flags) &&
Gustavo Padovan807deac2012-05-17 00:36:24 -03001003 !test_bit(HCI_INIT, &hdev->flags))
Johan Hedberg8f984df2012-02-28 01:07:22 +02001004 mgmt_le_enable_complete(hdev, sent->le, status);
Andre Guedesf9b49302011-06-30 19:20:53 -03001005}
1006
Andrei Emeltchenko93c284e2012-09-27 17:26:20 +03001007static void hci_cc_write_remote_amp_assoc(struct hci_dev *hdev,
1008 struct sk_buff *skb)
1009{
1010 struct hci_rp_write_remote_amp_assoc *rp = (void *) skb->data;
1011
1012 BT_DBG("%s status 0x%2.2x phy_handle 0x%2.2x",
1013 hdev->name, rp->status, rp->phy_handle);
1014
1015 if (rp->status)
1016 return;
1017
1018 amp_write_rem_assoc_continue(hdev, rp->phy_handle);
1019}
1020
Gustavo Padovan6039aa72012-05-23 04:04:18 -03001021static void hci_cs_inquiry(struct hci_dev *hdev, __u8 status)
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001022{
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +03001023 BT_DBG("%s status 0x%2.2x", hdev->name, status);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001024
1025 if (status) {
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001026 hci_conn_check_pending(hdev);
Johan Hedberg56e5cb82011-11-08 20:40:16 +02001027 hci_dev_lock(hdev);
Johan Hedberga8b2d5c2012-01-08 23:11:15 +02001028 if (test_bit(HCI_MGMT, &hdev->dev_flags))
Andre Guedes7a135102011-11-09 17:14:25 -03001029 mgmt_start_discovery_failed(hdev, status);
Johan Hedberg56e5cb82011-11-08 20:40:16 +02001030 hci_dev_unlock(hdev);
Johan Hedberg314b2382011-04-27 10:29:57 -04001031 return;
1032 }
1033
Andre Guedes89352e72011-11-04 14:16:53 -03001034 set_bit(HCI_INQUIRY, &hdev->flags);
1035
Johan Hedberg56e5cb82011-11-08 20:40:16 +02001036 hci_dev_lock(hdev);
Andre Guedes343f9352012-02-17 20:39:37 -03001037 hci_discovery_set_state(hdev, DISCOVERY_FINDING);
Johan Hedberg56e5cb82011-11-08 20:40:16 +02001038 hci_dev_unlock(hdev);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001039}
1040
Gustavo Padovan6039aa72012-05-23 04:04:18 -03001041static void hci_cs_create_conn(struct hci_dev *hdev, __u8 status)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001042{
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001043 struct hci_cp_create_conn *cp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001044 struct hci_conn *conn;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001045
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +03001046 BT_DBG("%s status 0x%2.2x", hdev->name, status);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001047
1048 cp = hci_sent_cmd_data(hdev, HCI_OP_CREATE_CONN);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001049 if (!cp)
1050 return;
1051
1052 hci_dev_lock(hdev);
1053
1054 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &cp->bdaddr);
1055
Andrei Emeltchenko6ed93dc2012-09-25 12:49:43 +03001056 BT_DBG("%s bdaddr %pMR hcon %p", hdev->name, &cp->bdaddr, conn);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001057
1058 if (status) {
1059 if (conn && conn->state == BT_CONNECT) {
Marcel Holtmann4c67bc72006-10-15 17:30:56 +02001060 if (status != 0x0c || conn->attempt > 2) {
1061 conn->state = BT_CLOSED;
1062 hci_proto_connect_cfm(conn, status);
1063 hci_conn_del(conn);
1064 } else
1065 conn->state = BT_CONNECT2;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001066 }
1067 } else {
1068 if (!conn) {
1069 conn = hci_conn_add(hdev, ACL_LINK, &cp->bdaddr);
1070 if (conn) {
Johan Hedberga0c808b2012-01-16 09:49:58 +02001071 conn->out = true;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001072 conn->link_mode |= HCI_LM_MASTER;
1073 } else
Gustavo F. Padovan893ef972010-07-18 15:13:37 -03001074 BT_ERR("No memory for new connection");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001075 }
1076 }
1077
1078 hci_dev_unlock(hdev);
1079}
1080
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001081static void hci_cs_add_sco(struct hci_dev *hdev, __u8 status)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001082{
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001083 struct hci_cp_add_sco *cp;
1084 struct hci_conn *acl, *sco;
1085 __u16 handle;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001086
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +03001087 BT_DBG("%s status 0x%2.2x", hdev->name, status);
Marcel Holtmannb6a0dc82007-10-20 14:55:10 +02001088
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001089 if (!status)
1090 return;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001091
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001092 cp = hci_sent_cmd_data(hdev, HCI_OP_ADD_SCO);
1093 if (!cp)
1094 return;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001095
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001096 handle = __le16_to_cpu(cp->handle);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001097
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +03001098 BT_DBG("%s handle 0x%4.4x", hdev->name, handle);
Marcel Holtmann6bd57412006-11-18 22:14:22 +01001099
1100 hci_dev_lock(hdev);
1101
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001102 acl = hci_conn_hash_lookup_handle(hdev, handle);
Andrei Emeltchenko5a08ecc2011-01-11 17:20:20 +02001103 if (acl) {
1104 sco = acl->link;
1105 if (sco) {
1106 sco->state = BT_CLOSED;
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001107
Andrei Emeltchenko5a08ecc2011-01-11 17:20:20 +02001108 hci_proto_connect_cfm(sco, status);
1109 hci_conn_del(sco);
1110 }
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001111 }
Marcel Holtmann6bd57412006-11-18 22:14:22 +01001112
1113 hci_dev_unlock(hdev);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001114}
1115
Marcel Holtmannf8558552008-07-14 20:13:49 +02001116static void hci_cs_auth_requested(struct hci_dev *hdev, __u8 status)
1117{
1118 struct hci_cp_auth_requested *cp;
1119 struct hci_conn *conn;
1120
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +03001121 BT_DBG("%s status 0x%2.2x", hdev->name, status);
Marcel Holtmannf8558552008-07-14 20:13:49 +02001122
1123 if (!status)
1124 return;
1125
1126 cp = hci_sent_cmd_data(hdev, HCI_OP_AUTH_REQUESTED);
1127 if (!cp)
1128 return;
1129
1130 hci_dev_lock(hdev);
1131
1132 conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(cp->handle));
1133 if (conn) {
1134 if (conn->state == BT_CONFIG) {
1135 hci_proto_connect_cfm(conn, status);
1136 hci_conn_put(conn);
1137 }
1138 }
1139
1140 hci_dev_unlock(hdev);
1141}
1142
1143static void hci_cs_set_conn_encrypt(struct hci_dev *hdev, __u8 status)
1144{
1145 struct hci_cp_set_conn_encrypt *cp;
1146 struct hci_conn *conn;
1147
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +03001148 BT_DBG("%s status 0x%2.2x", hdev->name, status);
Marcel Holtmannf8558552008-07-14 20:13:49 +02001149
1150 if (!status)
1151 return;
1152
1153 cp = hci_sent_cmd_data(hdev, HCI_OP_SET_CONN_ENCRYPT);
1154 if (!cp)
1155 return;
1156
1157 hci_dev_lock(hdev);
1158
1159 conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(cp->handle));
1160 if (conn) {
1161 if (conn->state == BT_CONFIG) {
1162 hci_proto_connect_cfm(conn, status);
1163 hci_conn_put(conn);
1164 }
1165 }
1166
1167 hci_dev_unlock(hdev);
1168}
1169
Johan Hedberg127178d2010-11-18 22:22:29 +02001170static int hci_outgoing_auth_needed(struct hci_dev *hdev,
Gustavo Padovan807deac2012-05-17 00:36:24 -03001171 struct hci_conn *conn)
Johan Hedberg392599b2010-11-18 22:22:28 +02001172{
Johan Hedberg392599b2010-11-18 22:22:28 +02001173 if (conn->state != BT_CONFIG || !conn->out)
1174 return 0;
1175
Johan Hedberg765c2a92011-01-19 12:06:52 +05301176 if (conn->pending_sec_level == BT_SECURITY_SDP)
Johan Hedberg392599b2010-11-18 22:22:28 +02001177 return 0;
1178
1179 /* Only request authentication for SSP connections or non-SSP
Vinicius Costa Gomese9bf2bf2011-09-02 14:51:20 -03001180 * devices with sec_level HIGH or if MITM protection is requested */
Gustavo Padovan807deac2012-05-17 00:36:24 -03001181 if (!hci_conn_ssp_enabled(conn) && !(conn->auth_type & 0x01) &&
1182 conn->pending_sec_level != BT_SECURITY_HIGH)
Johan Hedberg392599b2010-11-18 22:22:28 +02001183 return 0;
1184
Johan Hedberg392599b2010-11-18 22:22:28 +02001185 return 1;
1186}
1187
Gustavo Padovan6039aa72012-05-23 04:04:18 -03001188static int hci_resolve_name(struct hci_dev *hdev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001189 struct inquiry_entry *e)
Johan Hedberg30dc78e2012-01-04 15:44:20 +02001190{
1191 struct hci_cp_remote_name_req cp;
1192
1193 memset(&cp, 0, sizeof(cp));
1194
1195 bacpy(&cp.bdaddr, &e->data.bdaddr);
1196 cp.pscan_rep_mode = e->data.pscan_rep_mode;
1197 cp.pscan_mode = e->data.pscan_mode;
1198 cp.clock_offset = e->data.clock_offset;
1199
1200 return hci_send_cmd(hdev, HCI_OP_REMOTE_NAME_REQ, sizeof(cp), &cp);
1201}
1202
Johan Hedbergb644ba32012-01-17 21:48:47 +02001203static bool hci_resolve_next_name(struct hci_dev *hdev)
Johan Hedberg30dc78e2012-01-04 15:44:20 +02001204{
1205 struct discovery_state *discov = &hdev->discovery;
1206 struct inquiry_entry *e;
1207
Johan Hedbergb644ba32012-01-17 21:48:47 +02001208 if (list_empty(&discov->resolve))
1209 return false;
1210
1211 e = hci_inquiry_cache_lookup_resolve(hdev, BDADDR_ANY, NAME_NEEDED);
Ram Malovanyc8100892012-07-19 10:26:09 +03001212 if (!e)
1213 return false;
1214
Johan Hedbergb644ba32012-01-17 21:48:47 +02001215 if (hci_resolve_name(hdev, e) == 0) {
1216 e->name_state = NAME_PENDING;
1217 return true;
1218 }
1219
1220 return false;
1221}
1222
1223static void hci_check_pending_name(struct hci_dev *hdev, struct hci_conn *conn,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001224 bdaddr_t *bdaddr, u8 *name, u8 name_len)
Johan Hedbergb644ba32012-01-17 21:48:47 +02001225{
1226 struct discovery_state *discov = &hdev->discovery;
1227 struct inquiry_entry *e;
1228
1229 if (conn && !test_and_set_bit(HCI_CONN_MGMT_CONNECTED, &conn->flags))
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001230 mgmt_device_connected(hdev, bdaddr, ACL_LINK, 0x00, 0, name,
1231 name_len, conn->dev_class);
Johan Hedbergb644ba32012-01-17 21:48:47 +02001232
1233 if (discov->state == DISCOVERY_STOPPED)
1234 return;
1235
Johan Hedberg30dc78e2012-01-04 15:44:20 +02001236 if (discov->state == DISCOVERY_STOPPING)
1237 goto discov_complete;
1238
1239 if (discov->state != DISCOVERY_RESOLVING)
1240 return;
1241
1242 e = hci_inquiry_cache_lookup_resolve(hdev, bdaddr, NAME_PENDING);
Ram Malovany7cc83802012-07-19 10:26:10 +03001243 /* If the device was not found in a list of found devices names of which
1244 * are pending. there is no need to continue resolving a next name as it
1245 * will be done upon receiving another Remote Name Request Complete
1246 * Event */
1247 if (!e)
1248 return;
1249
1250 list_del(&e->list);
1251 if (name) {
Johan Hedberg30dc78e2012-01-04 15:44:20 +02001252 e->name_state = NAME_KNOWN;
Ram Malovany7cc83802012-07-19 10:26:10 +03001253 mgmt_remote_name(hdev, bdaddr, ACL_LINK, 0x00,
1254 e->data.rssi, name, name_len);
Ram Malovanyc3e7c0d2012-07-19 10:26:11 +03001255 } else {
1256 e->name_state = NAME_NOT_KNOWN;
Johan Hedberg30dc78e2012-01-04 15:44:20 +02001257 }
1258
Johan Hedbergb644ba32012-01-17 21:48:47 +02001259 if (hci_resolve_next_name(hdev))
Johan Hedberg30dc78e2012-01-04 15:44:20 +02001260 return;
Johan Hedberg30dc78e2012-01-04 15:44:20 +02001261
1262discov_complete:
1263 hci_discovery_set_state(hdev, DISCOVERY_STOPPED);
1264}
1265
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001266static void hci_cs_remote_name_req(struct hci_dev *hdev, __u8 status)
1267{
Johan Hedberg127178d2010-11-18 22:22:29 +02001268 struct hci_cp_remote_name_req *cp;
1269 struct hci_conn *conn;
1270
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +03001271 BT_DBG("%s status 0x%2.2x", hdev->name, status);
Johan Hedberg127178d2010-11-18 22:22:29 +02001272
1273 /* If successful wait for the name req complete event before
1274 * checking for the need to do authentication */
1275 if (!status)
1276 return;
1277
1278 cp = hci_sent_cmd_data(hdev, HCI_OP_REMOTE_NAME_REQ);
1279 if (!cp)
1280 return;
1281
1282 hci_dev_lock(hdev);
1283
1284 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &cp->bdaddr);
Johan Hedbergb644ba32012-01-17 21:48:47 +02001285
1286 if (test_bit(HCI_MGMT, &hdev->dev_flags))
1287 hci_check_pending_name(hdev, conn, &cp->bdaddr, NULL, 0);
1288
Johan Hedberg79c6c702011-04-28 11:28:55 -07001289 if (!conn)
1290 goto unlock;
1291
1292 if (!hci_outgoing_auth_needed(hdev, conn))
1293 goto unlock;
1294
Johan Hedberg51a8efd2012-01-16 06:10:31 +02001295 if (!test_and_set_bit(HCI_CONN_AUTH_PEND, &conn->flags)) {
Johan Hedberg127178d2010-11-18 22:22:29 +02001296 struct hci_cp_auth_requested cp;
1297 cp.handle = __cpu_to_le16(conn->handle);
1298 hci_send_cmd(hdev, HCI_OP_AUTH_REQUESTED, sizeof(cp), &cp);
1299 }
1300
Johan Hedberg79c6c702011-04-28 11:28:55 -07001301unlock:
Johan Hedberg127178d2010-11-18 22:22:29 +02001302 hci_dev_unlock(hdev);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001303}
1304
Marcel Holtmann769be972008-07-14 20:13:49 +02001305static void hci_cs_read_remote_features(struct hci_dev *hdev, __u8 status)
1306{
1307 struct hci_cp_read_remote_features *cp;
1308 struct hci_conn *conn;
1309
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +03001310 BT_DBG("%s status 0x%2.2x", hdev->name, status);
Marcel Holtmann769be972008-07-14 20:13:49 +02001311
1312 if (!status)
1313 return;
1314
1315 cp = hci_sent_cmd_data(hdev, HCI_OP_READ_REMOTE_FEATURES);
1316 if (!cp)
1317 return;
1318
1319 hci_dev_lock(hdev);
1320
1321 conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(cp->handle));
1322 if (conn) {
1323 if (conn->state == BT_CONFIG) {
Marcel Holtmann769be972008-07-14 20:13:49 +02001324 hci_proto_connect_cfm(conn, status);
1325 hci_conn_put(conn);
1326 }
1327 }
1328
1329 hci_dev_unlock(hdev);
1330}
1331
1332static void hci_cs_read_remote_ext_features(struct hci_dev *hdev, __u8 status)
1333{
1334 struct hci_cp_read_remote_ext_features *cp;
1335 struct hci_conn *conn;
1336
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +03001337 BT_DBG("%s status 0x%2.2x", hdev->name, status);
Marcel Holtmann769be972008-07-14 20:13:49 +02001338
1339 if (!status)
1340 return;
1341
1342 cp = hci_sent_cmd_data(hdev, HCI_OP_READ_REMOTE_EXT_FEATURES);
1343 if (!cp)
1344 return;
1345
1346 hci_dev_lock(hdev);
1347
1348 conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(cp->handle));
1349 if (conn) {
1350 if (conn->state == BT_CONFIG) {
Marcel Holtmann769be972008-07-14 20:13:49 +02001351 hci_proto_connect_cfm(conn, status);
1352 hci_conn_put(conn);
1353 }
1354 }
1355
1356 hci_dev_unlock(hdev);
1357}
1358
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001359static void hci_cs_setup_sync_conn(struct hci_dev *hdev, __u8 status)
1360{
Marcel Holtmannb6a0dc82007-10-20 14:55:10 +02001361 struct hci_cp_setup_sync_conn *cp;
1362 struct hci_conn *acl, *sco;
1363 __u16 handle;
1364
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +03001365 BT_DBG("%s status 0x%2.2x", hdev->name, status);
Marcel Holtmannb6a0dc82007-10-20 14:55:10 +02001366
1367 if (!status)
1368 return;
1369
1370 cp = hci_sent_cmd_data(hdev, HCI_OP_SETUP_SYNC_CONN);
1371 if (!cp)
1372 return;
1373
1374 handle = __le16_to_cpu(cp->handle);
1375
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +03001376 BT_DBG("%s handle 0x%4.4x", hdev->name, handle);
Marcel Holtmannb6a0dc82007-10-20 14:55:10 +02001377
1378 hci_dev_lock(hdev);
1379
1380 acl = hci_conn_hash_lookup_handle(hdev, handle);
Andrei Emeltchenko5a08ecc2011-01-11 17:20:20 +02001381 if (acl) {
1382 sco = acl->link;
1383 if (sco) {
1384 sco->state = BT_CLOSED;
Marcel Holtmannb6a0dc82007-10-20 14:55:10 +02001385
Andrei Emeltchenko5a08ecc2011-01-11 17:20:20 +02001386 hci_proto_connect_cfm(sco, status);
1387 hci_conn_del(sco);
1388 }
Marcel Holtmannb6a0dc82007-10-20 14:55:10 +02001389 }
1390
1391 hci_dev_unlock(hdev);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001392}
1393
1394static void hci_cs_sniff_mode(struct hci_dev *hdev, __u8 status)
1395{
1396 struct hci_cp_sniff_mode *cp;
1397 struct hci_conn *conn;
1398
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +03001399 BT_DBG("%s status 0x%2.2x", hdev->name, status);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001400
1401 if (!status)
1402 return;
1403
1404 cp = hci_sent_cmd_data(hdev, HCI_OP_SNIFF_MODE);
1405 if (!cp)
1406 return;
1407
1408 hci_dev_lock(hdev);
1409
1410 conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(cp->handle));
Marcel Holtmanne73439d2010-07-26 10:06:00 -04001411 if (conn) {
Johan Hedberg51a8efd2012-01-16 06:10:31 +02001412 clear_bit(HCI_CONN_MODE_CHANGE_PEND, &conn->flags);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001413
Johan Hedberg51a8efd2012-01-16 06:10:31 +02001414 if (test_and_clear_bit(HCI_CONN_SCO_SETUP_PEND, &conn->flags))
Marcel Holtmanne73439d2010-07-26 10:06:00 -04001415 hci_sco_setup(conn, status);
1416 }
1417
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001418 hci_dev_unlock(hdev);
1419}
1420
1421static void hci_cs_exit_sniff_mode(struct hci_dev *hdev, __u8 status)
1422{
1423 struct hci_cp_exit_sniff_mode *cp;
1424 struct hci_conn *conn;
1425
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +03001426 BT_DBG("%s status 0x%2.2x", hdev->name, status);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001427
1428 if (!status)
1429 return;
1430
1431 cp = hci_sent_cmd_data(hdev, HCI_OP_EXIT_SNIFF_MODE);
1432 if (!cp)
1433 return;
1434
1435 hci_dev_lock(hdev);
1436
1437 conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(cp->handle));
Marcel Holtmanne73439d2010-07-26 10:06:00 -04001438 if (conn) {
Johan Hedberg51a8efd2012-01-16 06:10:31 +02001439 clear_bit(HCI_CONN_MODE_CHANGE_PEND, &conn->flags);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001440
Johan Hedberg51a8efd2012-01-16 06:10:31 +02001441 if (test_and_clear_bit(HCI_CONN_SCO_SETUP_PEND, &conn->flags))
Marcel Holtmanne73439d2010-07-26 10:06:00 -04001442 hci_sco_setup(conn, status);
1443 }
1444
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001445 hci_dev_unlock(hdev);
1446}
1447
Johan Hedberg88c3df12012-02-09 14:27:38 +02001448static void hci_cs_disconnect(struct hci_dev *hdev, u8 status)
1449{
1450 struct hci_cp_disconnect *cp;
1451 struct hci_conn *conn;
1452
1453 if (!status)
1454 return;
1455
1456 cp = hci_sent_cmd_data(hdev, HCI_OP_DISCONNECT);
1457 if (!cp)
1458 return;
1459
1460 hci_dev_lock(hdev);
1461
1462 conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(cp->handle));
1463 if (conn)
1464 mgmt_disconnect_failed(hdev, &conn->dst, conn->type,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001465 conn->dst_type, status);
Johan Hedberg88c3df12012-02-09 14:27:38 +02001466
1467 hci_dev_unlock(hdev);
1468}
1469
Ville Tervofcd89c02011-02-10 22:38:47 -03001470static void hci_cs_le_create_conn(struct hci_dev *hdev, __u8 status)
1471{
Ville Tervofcd89c02011-02-10 22:38:47 -03001472 struct hci_conn *conn;
1473
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +03001474 BT_DBG("%s status 0x%2.2x", hdev->name, status);
Ville Tervofcd89c02011-02-10 22:38:47 -03001475
Ville Tervofcd89c02011-02-10 22:38:47 -03001476 if (status) {
Andre Guedesf00a06a2012-07-27 15:10:13 -03001477 hci_dev_lock(hdev);
Ville Tervofcd89c02011-02-10 22:38:47 -03001478
Andre Guedes0c95ab72012-07-27 15:10:14 -03001479 conn = hci_conn_hash_lookup_state(hdev, LE_LINK, BT_CONNECT);
Andre Guedesf00a06a2012-07-27 15:10:13 -03001480 if (!conn) {
1481 hci_dev_unlock(hdev);
1482 return;
1483 }
1484
Andrei Emeltchenko6ed93dc2012-09-25 12:49:43 +03001485 BT_DBG("%s bdaddr %pMR conn %p", hdev->name, &conn->dst, conn);
Andre Guedesf00a06a2012-07-27 15:10:13 -03001486
1487 conn->state = BT_CLOSED;
Andre Guedes0c95ab72012-07-27 15:10:14 -03001488 mgmt_connect_failed(hdev, &conn->dst, conn->type,
Andre Guedesf00a06a2012-07-27 15:10:13 -03001489 conn->dst_type, status);
1490 hci_proto_connect_cfm(conn, status);
1491 hci_conn_del(conn);
1492
1493 hci_dev_unlock(hdev);
1494 }
Ville Tervofcd89c02011-02-10 22:38:47 -03001495}
1496
Andrei Emeltchenkoa02226d2012-09-27 17:26:19 +03001497static void hci_cs_create_phylink(struct hci_dev *hdev, u8 status)
1498{
Andrei Emeltchenko93c284e2012-09-27 17:26:20 +03001499 struct hci_cp_create_phy_link *cp;
1500
Andrei Emeltchenkoa02226d2012-09-27 17:26:19 +03001501 BT_DBG("%s status 0x%2.2x", hdev->name, status);
Andrei Emeltchenko93c284e2012-09-27 17:26:20 +03001502
Andrei Emeltchenko93c284e2012-09-27 17:26:20 +03001503 cp = hci_sent_cmd_data(hdev, HCI_OP_CREATE_PHY_LINK);
1504 if (!cp)
1505 return;
1506
Andrei Emeltchenkoe58917b2012-10-31 15:46:33 +02001507 hci_dev_lock(hdev);
1508
1509 if (status) {
1510 struct hci_conn *hcon;
1511
1512 hcon = hci_conn_hash_lookup_handle(hdev, cp->phy_handle);
1513 if (hcon)
1514 hci_conn_del(hcon);
1515 } else {
1516 amp_write_remote_assoc(hdev, cp->phy_handle);
1517 }
1518
1519 hci_dev_unlock(hdev);
Andrei Emeltchenkoa02226d2012-09-27 17:26:19 +03001520}
1521
Andrei Emeltchenko0b26ab92012-09-27 17:26:24 +03001522static void hci_cs_accept_phylink(struct hci_dev *hdev, u8 status)
1523{
1524 struct hci_cp_accept_phy_link *cp;
1525
1526 BT_DBG("%s status 0x%2.2x", hdev->name, status);
1527
1528 if (status)
1529 return;
1530
1531 cp = hci_sent_cmd_data(hdev, HCI_OP_ACCEPT_PHY_LINK);
1532 if (!cp)
1533 return;
1534
1535 amp_write_remote_assoc(hdev, cp->phy_handle);
1536}
1537
Gustavo Padovan6039aa72012-05-23 04:04:18 -03001538static void hci_inquiry_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001539{
1540 __u8 status = *((__u8 *) skb->data);
Johan Hedberg30dc78e2012-01-04 15:44:20 +02001541 struct discovery_state *discov = &hdev->discovery;
1542 struct inquiry_entry *e;
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001543
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +03001544 BT_DBG("%s status 0x%2.2x", hdev->name, status);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001545
Johan Hedberg9238f362013-03-05 20:37:48 +02001546 hci_req_cmd_complete(hdev, HCI_OP_INQUIRY, status);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001547
1548 hci_conn_check_pending(hdev);
Andre Guedes89352e72011-11-04 14:16:53 -03001549
1550 if (!test_and_clear_bit(HCI_INQUIRY, &hdev->flags))
1551 return;
1552
Johan Hedberga8b2d5c2012-01-08 23:11:15 +02001553 if (!test_bit(HCI_MGMT, &hdev->dev_flags))
Johan Hedberg30dc78e2012-01-04 15:44:20 +02001554 return;
1555
Johan Hedberg56e5cb82011-11-08 20:40:16 +02001556 hci_dev_lock(hdev);
Johan Hedberg30dc78e2012-01-04 15:44:20 +02001557
Andre Guedes343f9352012-02-17 20:39:37 -03001558 if (discov->state != DISCOVERY_FINDING)
Johan Hedberg30dc78e2012-01-04 15:44:20 +02001559 goto unlock;
1560
1561 if (list_empty(&discov->resolve)) {
1562 hci_discovery_set_state(hdev, DISCOVERY_STOPPED);
1563 goto unlock;
1564 }
1565
1566 e = hci_inquiry_cache_lookup_resolve(hdev, BDADDR_ANY, NAME_NEEDED);
1567 if (e && hci_resolve_name(hdev, e) == 0) {
1568 e->name_state = NAME_PENDING;
1569 hci_discovery_set_state(hdev, DISCOVERY_RESOLVING);
1570 } else {
1571 hci_discovery_set_state(hdev, DISCOVERY_STOPPED);
1572 }
1573
1574unlock:
Johan Hedberg56e5cb82011-11-08 20:40:16 +02001575 hci_dev_unlock(hdev);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001576}
1577
Gustavo Padovan6039aa72012-05-23 04:04:18 -03001578static void hci_inquiry_result_evt(struct hci_dev *hdev, struct sk_buff *skb)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001579{
Marcel Holtmann45bb4bf2005-08-09 20:27:49 -07001580 struct inquiry_data data;
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001581 struct inquiry_info *info = (void *) (skb->data + 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001582 int num_rsp = *((__u8 *) skb->data);
1583
1584 BT_DBG("%s num_rsp %d", hdev->name, num_rsp);
1585
Marcel Holtmann45bb4bf2005-08-09 20:27:49 -07001586 if (!num_rsp)
1587 return;
1588
Andre Guedes1519cc12012-03-21 00:03:38 -03001589 if (test_bit(HCI_PERIODIC_INQ, &hdev->dev_flags))
1590 return;
1591
Linus Torvalds1da177e2005-04-16 15:20:36 -07001592 hci_dev_lock(hdev);
Marcel Holtmann45bb4bf2005-08-09 20:27:49 -07001593
Johan Hedberge17acd42011-03-30 23:57:16 +03001594 for (; num_rsp; num_rsp--, info++) {
Johan Hedberg388fc8f2012-02-23 00:38:59 +02001595 bool name_known, ssp;
Johan Hedberg31754052012-01-04 13:39:52 +02001596
Linus Torvalds1da177e2005-04-16 15:20:36 -07001597 bacpy(&data.bdaddr, &info->bdaddr);
1598 data.pscan_rep_mode = info->pscan_rep_mode;
1599 data.pscan_period_mode = info->pscan_period_mode;
1600 data.pscan_mode = info->pscan_mode;
1601 memcpy(data.dev_class, info->dev_class, 3);
1602 data.clock_offset = info->clock_offset;
1603 data.rssi = 0x00;
Marcel Holtmann41a96212008-07-14 20:13:48 +02001604 data.ssp_mode = 0x00;
Johan Hedberg31754052012-01-04 13:39:52 +02001605
Johan Hedberg388fc8f2012-02-23 00:38:59 +02001606 name_known = hci_inquiry_cache_update(hdev, &data, false, &ssp);
Johan Hedberg48264f02011-11-09 13:58:58 +02001607 mgmt_device_found(hdev, &info->bdaddr, ACL_LINK, 0x00,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001608 info->dev_class, 0, !name_known, ssp, NULL,
1609 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001610 }
Marcel Holtmann45bb4bf2005-08-09 20:27:49 -07001611
Linus Torvalds1da177e2005-04-16 15:20:36 -07001612 hci_dev_unlock(hdev);
1613}
1614
Gustavo Padovan6039aa72012-05-23 04:04:18 -03001615static void hci_conn_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001616{
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001617 struct hci_ev_conn_complete *ev = (void *) skb->data;
1618 struct hci_conn *conn;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001619
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001620 BT_DBG("%s", hdev->name);
Marcel Holtmann45bb4bf2005-08-09 20:27:49 -07001621
Linus Torvalds1da177e2005-04-16 15:20:36 -07001622 hci_dev_lock(hdev);
Marcel Holtmann45bb4bf2005-08-09 20:27:49 -07001623
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001624 conn = hci_conn_hash_lookup_ba(hdev, ev->link_type, &ev->bdaddr);
Marcel Holtmann94992372009-04-19 19:30:03 +02001625 if (!conn) {
1626 if (ev->link_type != SCO_LINK)
1627 goto unlock;
1628
1629 conn = hci_conn_hash_lookup_ba(hdev, ESCO_LINK, &ev->bdaddr);
1630 if (!conn)
1631 goto unlock;
1632
1633 conn->type = SCO_LINK;
1634 }
Marcel Holtmann45bb4bf2005-08-09 20:27:49 -07001635
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001636 if (!ev->status) {
1637 conn->handle = __le16_to_cpu(ev->handle);
Marcel Holtmann769be972008-07-14 20:13:49 +02001638
1639 if (conn->type == ACL_LINK) {
1640 conn->state = BT_CONFIG;
1641 hci_conn_hold(conn);
Szymon Janca9ea3ed2012-07-19 14:46:08 +02001642
1643 if (!conn->out && !hci_conn_ssp_enabled(conn) &&
1644 !hci_find_link_key(hdev, &ev->bdaddr))
1645 conn->disc_timeout = HCI_PAIRING_TIMEOUT;
1646 else
1647 conn->disc_timeout = HCI_DISCONN_TIMEOUT;
Marcel Holtmann769be972008-07-14 20:13:49 +02001648 } else
1649 conn->state = BT_CONNECTED;
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001650
Marcel Holtmann9eba32b2009-08-22 14:19:26 -07001651 hci_conn_hold_device(conn);
Marcel Holtmann7d0db0a2008-07-14 20:13:51 +02001652 hci_conn_add_sysfs(conn);
1653
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001654 if (test_bit(HCI_AUTH, &hdev->flags))
1655 conn->link_mode |= HCI_LM_AUTH;
1656
1657 if (test_bit(HCI_ENCRYPT, &hdev->flags))
1658 conn->link_mode |= HCI_LM_ENCRYPT;
1659
1660 /* Get remote features */
1661 if (conn->type == ACL_LINK) {
1662 struct hci_cp_read_remote_features cp;
1663 cp.handle = ev->handle;
Marcel Holtmann769be972008-07-14 20:13:49 +02001664 hci_send_cmd(hdev, HCI_OP_READ_REMOTE_FEATURES,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001665 sizeof(cp), &cp);
Marcel Holtmann45bb4bf2005-08-09 20:27:49 -07001666 }
Marcel Holtmann45bb4bf2005-08-09 20:27:49 -07001667
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001668 /* Set packet type for incoming connection */
Andrei Emeltchenkod095c1e2011-12-01 14:33:27 +02001669 if (!conn->out && hdev->hci_ver < BLUETOOTH_VER_2_0) {
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001670 struct hci_cp_change_conn_ptype cp;
1671 cp.handle = ev->handle;
Marcel Holtmanna8746412008-07-14 20:13:46 +02001672 cp.pkt_type = cpu_to_le16(conn->pkt_type);
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001673 hci_send_cmd(hdev, HCI_OP_CHANGE_CONN_PTYPE, sizeof(cp),
1674 &cp);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001675 }
Johan Hedberg17d5c042011-01-22 06:09:08 +02001676 } else {
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001677 conn->state = BT_CLOSED;
Johan Hedberg17d5c042011-01-22 06:09:08 +02001678 if (conn->type == ACL_LINK)
Johan Hedberg744cf192011-11-08 20:40:14 +02001679 mgmt_connect_failed(hdev, &ev->bdaddr, conn->type,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001680 conn->dst_type, ev->status);
Johan Hedberg17d5c042011-01-22 06:09:08 +02001681 }
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001682
Marcel Holtmanne73439d2010-07-26 10:06:00 -04001683 if (conn->type == ACL_LINK)
1684 hci_sco_setup(conn, ev->status);
Marcel Holtmann45bb4bf2005-08-09 20:27:49 -07001685
Marcel Holtmann769be972008-07-14 20:13:49 +02001686 if (ev->status) {
1687 hci_proto_connect_cfm(conn, ev->status);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001688 hci_conn_del(conn);
Marcel Holtmannc89b6e62009-01-15 21:57:03 +01001689 } else if (ev->link_type != ACL_LINK)
1690 hci_proto_connect_cfm(conn, ev->status);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001691
1692unlock:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001693 hci_dev_unlock(hdev);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001694
1695 hci_conn_check_pending(hdev);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001696}
1697
Frédéric Dalleau20714bfe2012-11-21 10:51:12 +01001698void hci_conn_accept(struct hci_conn *conn, int mask)
1699{
1700 struct hci_dev *hdev = conn->hdev;
1701
1702 BT_DBG("conn %p", conn);
1703
1704 conn->state = BT_CONFIG;
1705
1706 if (!lmp_esco_capable(hdev)) {
1707 struct hci_cp_accept_conn_req cp;
1708
1709 bacpy(&cp.bdaddr, &conn->dst);
1710
1711 if (lmp_rswitch_capable(hdev) && (mask & HCI_LM_MASTER))
1712 cp.role = 0x00; /* Become master */
1713 else
1714 cp.role = 0x01; /* Remain slave */
1715
1716 hci_send_cmd(hdev, HCI_OP_ACCEPT_CONN_REQ, sizeof(cp), &cp);
1717 } else /* lmp_esco_capable(hdev)) */ {
1718 struct hci_cp_accept_sync_conn_req cp;
1719
1720 bacpy(&cp.bdaddr, &conn->dst);
1721 cp.pkt_type = cpu_to_le16(conn->pkt_type);
1722
1723 cp.tx_bandwidth = __constant_cpu_to_le32(0x00001f40);
1724 cp.rx_bandwidth = __constant_cpu_to_le32(0x00001f40);
1725 cp.max_latency = __constant_cpu_to_le16(0xffff);
1726 cp.content_format = cpu_to_le16(hdev->voice_setting);
1727 cp.retrans_effort = 0xff;
1728
1729 hci_send_cmd(hdev, HCI_OP_ACCEPT_SYNC_CONN_REQ,
1730 sizeof(cp), &cp);
1731 }
1732}
1733
Gustavo Padovan6039aa72012-05-23 04:04:18 -03001734static void hci_conn_request_evt(struct hci_dev *hdev, struct sk_buff *skb)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001735{
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001736 struct hci_ev_conn_request *ev = (void *) skb->data;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001737 int mask = hdev->link_mode;
Frédéric Dalleau20714bfe2012-11-21 10:51:12 +01001738 __u8 flags = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001739
Andrei Emeltchenko6ed93dc2012-09-25 12:49:43 +03001740 BT_DBG("%s bdaddr %pMR type 0x%x", hdev->name, &ev->bdaddr,
Gustavo Padovan807deac2012-05-17 00:36:24 -03001741 ev->link_type);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001742
Frédéric Dalleau20714bfe2012-11-21 10:51:12 +01001743 mask |= hci_proto_connect_ind(hdev, &ev->bdaddr, ev->link_type,
1744 &flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001745
Szymon Janc138d22e2011-02-17 16:44:23 +01001746 if ((mask & HCI_LM_ACCEPT) &&
Gustavo Padovan807deac2012-05-17 00:36:24 -03001747 !hci_blacklist_lookup(hdev, &ev->bdaddr)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001748 /* Connection accepted */
Marcel Holtmannc7bdd502008-07-14 20:13:47 +02001749 struct inquiry_entry *ie;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001750 struct hci_conn *conn;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001751
1752 hci_dev_lock(hdev);
Marcel Holtmannb6a0dc82007-10-20 14:55:10 +02001753
Andrei Emeltchenkocc11b9c2010-11-22 13:21:37 +02001754 ie = hci_inquiry_cache_lookup(hdev, &ev->bdaddr);
1755 if (ie)
Marcel Holtmannc7bdd502008-07-14 20:13:47 +02001756 memcpy(ie->data.dev_class, ev->dev_class, 3);
1757
Gustavo Padovan8fc9ced2012-05-23 04:04:21 -03001758 conn = hci_conn_hash_lookup_ba(hdev, ev->link_type,
1759 &ev->bdaddr);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001760 if (!conn) {
Andrei Emeltchenkocc11b9c2010-11-22 13:21:37 +02001761 conn = hci_conn_add(hdev, ev->link_type, &ev->bdaddr);
1762 if (!conn) {
Gustavo F. Padovan893ef972010-07-18 15:13:37 -03001763 BT_ERR("No memory for new connection");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001764 hci_dev_unlock(hdev);
1765 return;
1766 }
1767 }
Marcel Holtmannb6a0dc82007-10-20 14:55:10 +02001768
Linus Torvalds1da177e2005-04-16 15:20:36 -07001769 memcpy(conn->dev_class, ev->dev_class, 3);
Marcel Holtmannb6a0dc82007-10-20 14:55:10 +02001770
Linus Torvalds1da177e2005-04-16 15:20:36 -07001771 hci_dev_unlock(hdev);
1772
Frédéric Dalleau20714bfe2012-11-21 10:51:12 +01001773 if (ev->link_type == ACL_LINK ||
1774 (!(flags & HCI_PROTO_DEFER) && !lmp_esco_capable(hdev))) {
Marcel Holtmannb6a0dc82007-10-20 14:55:10 +02001775 struct hci_cp_accept_conn_req cp;
Frédéric Dalleau20714bfe2012-11-21 10:51:12 +01001776 conn->state = BT_CONNECT;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001777
Marcel Holtmannb6a0dc82007-10-20 14:55:10 +02001778 bacpy(&cp.bdaddr, &ev->bdaddr);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001779
Marcel Holtmannb6a0dc82007-10-20 14:55:10 +02001780 if (lmp_rswitch_capable(hdev) && (mask & HCI_LM_MASTER))
1781 cp.role = 0x00; /* Become master */
1782 else
1783 cp.role = 0x01; /* Remain slave */
1784
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001785 hci_send_cmd(hdev, HCI_OP_ACCEPT_CONN_REQ, sizeof(cp),
1786 &cp);
Frédéric Dalleau20714bfe2012-11-21 10:51:12 +01001787 } else if (!(flags & HCI_PROTO_DEFER)) {
Marcel Holtmannb6a0dc82007-10-20 14:55:10 +02001788 struct hci_cp_accept_sync_conn_req cp;
Frédéric Dalleau20714bfe2012-11-21 10:51:12 +01001789 conn->state = BT_CONNECT;
Marcel Holtmannb6a0dc82007-10-20 14:55:10 +02001790
1791 bacpy(&cp.bdaddr, &ev->bdaddr);
Marcel Holtmanna8746412008-07-14 20:13:46 +02001792 cp.pkt_type = cpu_to_le16(conn->pkt_type);
Marcel Holtmannb6a0dc82007-10-20 14:55:10 +02001793
Andrei Emeltchenko82781e62012-05-25 11:38:27 +03001794 cp.tx_bandwidth = __constant_cpu_to_le32(0x00001f40);
1795 cp.rx_bandwidth = __constant_cpu_to_le32(0x00001f40);
1796 cp.max_latency = __constant_cpu_to_le16(0xffff);
Marcel Holtmannb6a0dc82007-10-20 14:55:10 +02001797 cp.content_format = cpu_to_le16(hdev->voice_setting);
1798 cp.retrans_effort = 0xff;
1799
1800 hci_send_cmd(hdev, HCI_OP_ACCEPT_SYNC_CONN_REQ,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001801 sizeof(cp), &cp);
Frédéric Dalleau20714bfe2012-11-21 10:51:12 +01001802 } else {
1803 conn->state = BT_CONNECT2;
1804 hci_proto_connect_cfm(conn, 0);
1805 hci_conn_put(conn);
Marcel Holtmannb6a0dc82007-10-20 14:55:10 +02001806 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001807 } else {
1808 /* Connection rejected */
1809 struct hci_cp_reject_conn_req cp;
1810
1811 bacpy(&cp.bdaddr, &ev->bdaddr);
Andrei Emeltchenko9f5a0d72011-11-07 14:20:25 +02001812 cp.reason = HCI_ERROR_REJ_BAD_ADDR;
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001813 hci_send_cmd(hdev, HCI_OP_REJECT_CONN_REQ, sizeof(cp), &cp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001814 }
1815}
1816
Mikel Astizf0d6a0e2012-08-09 09:52:30 +02001817static u8 hci_to_mgmt_reason(u8 err)
1818{
1819 switch (err) {
1820 case HCI_ERROR_CONNECTION_TIMEOUT:
1821 return MGMT_DEV_DISCONN_TIMEOUT;
1822 case HCI_ERROR_REMOTE_USER_TERM:
1823 case HCI_ERROR_REMOTE_LOW_RESOURCES:
1824 case HCI_ERROR_REMOTE_POWER_OFF:
1825 return MGMT_DEV_DISCONN_REMOTE;
1826 case HCI_ERROR_LOCAL_HOST_TERM:
1827 return MGMT_DEV_DISCONN_LOCAL_HOST;
1828 default:
1829 return MGMT_DEV_DISCONN_UNKNOWN;
1830 }
1831}
1832
Gustavo Padovan6039aa72012-05-23 04:04:18 -03001833static void hci_disconn_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001834{
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001835 struct hci_ev_disconn_complete *ev = (void *) skb->data;
Marcel Holtmann04837f62006-07-03 10:02:33 +02001836 struct hci_conn *conn;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001837
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +03001838 BT_DBG("%s status 0x%2.2x", hdev->name, ev->status);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001839
Linus Torvalds1da177e2005-04-16 15:20:36 -07001840 hci_dev_lock(hdev);
1841
Marcel Holtmann04837f62006-07-03 10:02:33 +02001842 conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
Johan Hedbergf7520542011-01-20 12:34:39 +02001843 if (!conn)
1844 goto unlock;
Marcel Holtmann7d0db0a2008-07-14 20:13:51 +02001845
Johan Hedberg37d9ef72011-11-10 15:54:39 +02001846 if (ev->status == 0)
1847 conn->state = BT_CLOSED;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001848
Johan Hedbergb644ba32012-01-17 21:48:47 +02001849 if (test_and_clear_bit(HCI_CONN_MGMT_CONNECTED, &conn->flags) &&
Gustavo Padovan807deac2012-05-17 00:36:24 -03001850 (conn->type == ACL_LINK || conn->type == LE_LINK)) {
Mikel Astizf0d6a0e2012-08-09 09:52:30 +02001851 if (ev->status) {
Johan Hedberg88c3df12012-02-09 14:27:38 +02001852 mgmt_disconnect_failed(hdev, &conn->dst, conn->type,
Gustavo Padovan807deac2012-05-17 00:36:24 -03001853 conn->dst_type, ev->status);
Mikel Astizf0d6a0e2012-08-09 09:52:30 +02001854 } else {
1855 u8 reason = hci_to_mgmt_reason(ev->reason);
1856
Johan Hedbergafc747a2012-01-15 18:11:07 +02001857 mgmt_device_disconnected(hdev, &conn->dst, conn->type,
Mikel Astizf0d6a0e2012-08-09 09:52:30 +02001858 conn->dst_type, reason);
1859 }
Johan Hedberg37d9ef72011-11-10 15:54:39 +02001860 }
Johan Hedbergf7520542011-01-20 12:34:39 +02001861
Johan Hedberg37d9ef72011-11-10 15:54:39 +02001862 if (ev->status == 0) {
Vishal Agarwal6ec5bca2012-04-16 14:44:44 +05301863 if (conn->type == ACL_LINK && conn->flush_key)
1864 hci_remove_link_key(hdev, &conn->dst);
Johan Hedberg37d9ef72011-11-10 15:54:39 +02001865 hci_proto_disconn_cfm(conn, ev->reason);
1866 hci_conn_del(conn);
1867 }
Johan Hedbergf7520542011-01-20 12:34:39 +02001868
1869unlock:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001870 hci_dev_unlock(hdev);
1871}
1872
Gustavo Padovan6039aa72012-05-23 04:04:18 -03001873static void hci_auth_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001874{
1875 struct hci_ev_auth_complete *ev = (void *) skb->data;
1876 struct hci_conn *conn;
1877
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +03001878 BT_DBG("%s status 0x%2.2x", hdev->name, ev->status);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001879
1880 hci_dev_lock(hdev);
1881
1882 conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
Waldemar Rymarkiewiczd7556e22011-05-31 15:49:26 +02001883 if (!conn)
1884 goto unlock;
1885
1886 if (!ev->status) {
Johan Hedbergaa64a8b2012-01-18 21:33:12 +02001887 if (!hci_conn_ssp_enabled(conn) &&
Gustavo Padovan807deac2012-05-17 00:36:24 -03001888 test_bit(HCI_CONN_REAUTH_PEND, &conn->flags)) {
Waldemar Rymarkiewiczd7556e22011-05-31 15:49:26 +02001889 BT_INFO("re-auth of legacy device is not possible.");
Johan Hedberg2a611692011-02-19 12:06:00 -03001890 } else {
Waldemar Rymarkiewiczd7556e22011-05-31 15:49:26 +02001891 conn->link_mode |= HCI_LM_AUTH;
1892 conn->sec_level = conn->pending_sec_level;
Johan Hedberg2a611692011-02-19 12:06:00 -03001893 }
Waldemar Rymarkiewiczd7556e22011-05-31 15:49:26 +02001894 } else {
Johan Hedbergbab73cb2012-02-09 16:07:29 +02001895 mgmt_auth_failed(hdev, &conn->dst, conn->type, conn->dst_type,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001896 ev->status);
Waldemar Rymarkiewiczd7556e22011-05-31 15:49:26 +02001897 }
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001898
Johan Hedberg51a8efd2012-01-16 06:10:31 +02001899 clear_bit(HCI_CONN_AUTH_PEND, &conn->flags);
1900 clear_bit(HCI_CONN_REAUTH_PEND, &conn->flags);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001901
Waldemar Rymarkiewiczd7556e22011-05-31 15:49:26 +02001902 if (conn->state == BT_CONFIG) {
Johan Hedbergaa64a8b2012-01-18 21:33:12 +02001903 if (!ev->status && hci_conn_ssp_enabled(conn)) {
Waldemar Rymarkiewiczd7556e22011-05-31 15:49:26 +02001904 struct hci_cp_set_conn_encrypt cp;
1905 cp.handle = ev->handle;
1906 cp.encrypt = 0x01;
1907 hci_send_cmd(hdev, HCI_OP_SET_CONN_ENCRYPT, sizeof(cp),
Gustavo Padovan807deac2012-05-17 00:36:24 -03001908 &cp);
Marcel Holtmann052b30b2009-04-26 20:01:22 +02001909 } else {
Waldemar Rymarkiewiczd7556e22011-05-31 15:49:26 +02001910 conn->state = BT_CONNECTED;
1911 hci_proto_connect_cfm(conn, ev->status);
Marcel Holtmann052b30b2009-04-26 20:01:22 +02001912 hci_conn_put(conn);
1913 }
Waldemar Rymarkiewiczd7556e22011-05-31 15:49:26 +02001914 } else {
1915 hci_auth_cfm(conn, ev->status);
Marcel Holtmann052b30b2009-04-26 20:01:22 +02001916
Waldemar Rymarkiewiczd7556e22011-05-31 15:49:26 +02001917 hci_conn_hold(conn);
1918 conn->disc_timeout = HCI_DISCONN_TIMEOUT;
1919 hci_conn_put(conn);
1920 }
1921
Johan Hedberg51a8efd2012-01-16 06:10:31 +02001922 if (test_bit(HCI_CONN_ENCRYPT_PEND, &conn->flags)) {
Waldemar Rymarkiewiczd7556e22011-05-31 15:49:26 +02001923 if (!ev->status) {
1924 struct hci_cp_set_conn_encrypt cp;
1925 cp.handle = ev->handle;
1926 cp.encrypt = 0x01;
1927 hci_send_cmd(hdev, HCI_OP_SET_CONN_ENCRYPT, sizeof(cp),
Gustavo Padovan807deac2012-05-17 00:36:24 -03001928 &cp);
Waldemar Rymarkiewiczd7556e22011-05-31 15:49:26 +02001929 } else {
Johan Hedberg51a8efd2012-01-16 06:10:31 +02001930 clear_bit(HCI_CONN_ENCRYPT_PEND, &conn->flags);
Waldemar Rymarkiewiczd7556e22011-05-31 15:49:26 +02001931 hci_encrypt_cfm(conn, ev->status, 0x00);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001932 }
1933 }
1934
Waldemar Rymarkiewiczd7556e22011-05-31 15:49:26 +02001935unlock:
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001936 hci_dev_unlock(hdev);
1937}
1938
Gustavo Padovan6039aa72012-05-23 04:04:18 -03001939static void hci_remote_name_evt(struct hci_dev *hdev, struct sk_buff *skb)
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001940{
Johan Hedberg127178d2010-11-18 22:22:29 +02001941 struct hci_ev_remote_name *ev = (void *) skb->data;
1942 struct hci_conn *conn;
1943
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001944 BT_DBG("%s", hdev->name);
1945
1946 hci_conn_check_pending(hdev);
Johan Hedberg127178d2010-11-18 22:22:29 +02001947
1948 hci_dev_lock(hdev);
1949
1950 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
Johan Hedbergb644ba32012-01-17 21:48:47 +02001951
1952 if (!test_bit(HCI_MGMT, &hdev->dev_flags))
1953 goto check_auth;
1954
1955 if (ev->status == 0)
1956 hci_check_pending_name(hdev, conn, &ev->bdaddr, ev->name,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001957 strnlen(ev->name, HCI_MAX_NAME_LENGTH));
Johan Hedbergb644ba32012-01-17 21:48:47 +02001958 else
1959 hci_check_pending_name(hdev, conn, &ev->bdaddr, NULL, 0);
1960
1961check_auth:
Johan Hedberg79c6c702011-04-28 11:28:55 -07001962 if (!conn)
1963 goto unlock;
1964
1965 if (!hci_outgoing_auth_needed(hdev, conn))
1966 goto unlock;
1967
Johan Hedberg51a8efd2012-01-16 06:10:31 +02001968 if (!test_and_set_bit(HCI_CONN_AUTH_PEND, &conn->flags)) {
Johan Hedberg127178d2010-11-18 22:22:29 +02001969 struct hci_cp_auth_requested cp;
1970 cp.handle = __cpu_to_le16(conn->handle);
1971 hci_send_cmd(hdev, HCI_OP_AUTH_REQUESTED, sizeof(cp), &cp);
1972 }
1973
Johan Hedberg79c6c702011-04-28 11:28:55 -07001974unlock:
Johan Hedberg127178d2010-11-18 22:22:29 +02001975 hci_dev_unlock(hdev);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001976}
1977
Gustavo Padovan6039aa72012-05-23 04:04:18 -03001978static void hci_encrypt_change_evt(struct hci_dev *hdev, struct sk_buff *skb)
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001979{
1980 struct hci_ev_encrypt_change *ev = (void *) skb->data;
1981 struct hci_conn *conn;
1982
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +03001983 BT_DBG("%s status 0x%2.2x", hdev->name, ev->status);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001984
1985 hci_dev_lock(hdev);
1986
1987 conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
1988 if (conn) {
1989 if (!ev->status) {
Marcel Holtmannae293192008-07-14 20:13:45 +02001990 if (ev->encrypt) {
1991 /* Encryption implies authentication */
1992 conn->link_mode |= HCI_LM_AUTH;
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001993 conn->link_mode |= HCI_LM_ENCRYPT;
Vinicius Costa Gomesda85e5e2011-06-09 18:50:53 -03001994 conn->sec_level = conn->pending_sec_level;
Marcel Holtmannae293192008-07-14 20:13:45 +02001995 } else
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001996 conn->link_mode &= ~HCI_LM_ENCRYPT;
1997 }
1998
Johan Hedberg51a8efd2012-01-16 06:10:31 +02001999 clear_bit(HCI_CONN_ENCRYPT_PEND, &conn->flags);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002000
Gustavo Padovana7d77232012-05-13 03:20:07 -03002001 if (ev->status && conn->state == BT_CONNECTED) {
Andre Guedesbed71742013-01-30 11:50:56 -03002002 hci_disconnect(conn, HCI_ERROR_AUTH_FAILURE);
Gustavo Padovana7d77232012-05-13 03:20:07 -03002003 hci_conn_put(conn);
2004 goto unlock;
2005 }
2006
Marcel Holtmannf8558552008-07-14 20:13:49 +02002007 if (conn->state == BT_CONFIG) {
2008 if (!ev->status)
2009 conn->state = BT_CONNECTED;
2010
2011 hci_proto_connect_cfm(conn, ev->status);
2012 hci_conn_put(conn);
2013 } else
2014 hci_encrypt_cfm(conn, ev->status, ev->encrypt);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002015 }
2016
Gustavo Padovana7d77232012-05-13 03:20:07 -03002017unlock:
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002018 hci_dev_unlock(hdev);
2019}
2020
Gustavo Padovan6039aa72012-05-23 04:04:18 -03002021static void hci_change_link_key_complete_evt(struct hci_dev *hdev,
2022 struct sk_buff *skb)
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002023{
2024 struct hci_ev_change_link_key_complete *ev = (void *) skb->data;
2025 struct hci_conn *conn;
2026
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +03002027 BT_DBG("%s status 0x%2.2x", hdev->name, ev->status);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002028
2029 hci_dev_lock(hdev);
2030
2031 conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
2032 if (conn) {
2033 if (!ev->status)
2034 conn->link_mode |= HCI_LM_SECURE;
2035
Johan Hedberg51a8efd2012-01-16 06:10:31 +02002036 clear_bit(HCI_CONN_AUTH_PEND, &conn->flags);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002037
2038 hci_key_change_cfm(conn, ev->status);
2039 }
2040
2041 hci_dev_unlock(hdev);
2042}
2043
Gustavo Padovan6039aa72012-05-23 04:04:18 -03002044static void hci_remote_features_evt(struct hci_dev *hdev,
2045 struct sk_buff *skb)
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002046{
2047 struct hci_ev_remote_features *ev = (void *) skb->data;
2048 struct hci_conn *conn;
2049
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +03002050 BT_DBG("%s status 0x%2.2x", hdev->name, ev->status);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002051
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002052 hci_dev_lock(hdev);
2053
2054 conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
Johan Hedbergccd556f2010-11-10 17:11:51 +02002055 if (!conn)
2056 goto unlock;
Marcel Holtmann769be972008-07-14 20:13:49 +02002057
Johan Hedbergccd556f2010-11-10 17:11:51 +02002058 if (!ev->status)
2059 memcpy(conn->features, ev->features, 8);
2060
2061 if (conn->state != BT_CONFIG)
2062 goto unlock;
2063
2064 if (!ev->status && lmp_ssp_capable(hdev) && lmp_ssp_capable(conn)) {
2065 struct hci_cp_read_remote_ext_features cp;
2066 cp.handle = ev->handle;
2067 cp.page = 0x01;
2068 hci_send_cmd(hdev, HCI_OP_READ_REMOTE_EXT_FEATURES,
Gustavo Padovan807deac2012-05-17 00:36:24 -03002069 sizeof(cp), &cp);
Johan Hedberg392599b2010-11-18 22:22:28 +02002070 goto unlock;
2071 }
2072
Johan Hedberg671267b2012-05-12 16:11:50 -03002073 if (!ev->status && !test_bit(HCI_CONN_MGMT_CONNECTED, &conn->flags)) {
Johan Hedberg127178d2010-11-18 22:22:29 +02002074 struct hci_cp_remote_name_req cp;
2075 memset(&cp, 0, sizeof(cp));
2076 bacpy(&cp.bdaddr, &conn->dst);
2077 cp.pscan_rep_mode = 0x02;
2078 hci_send_cmd(hdev, HCI_OP_REMOTE_NAME_REQ, sizeof(cp), &cp);
Johan Hedbergb644ba32012-01-17 21:48:47 +02002079 } else if (!test_and_set_bit(HCI_CONN_MGMT_CONNECTED, &conn->flags))
2080 mgmt_device_connected(hdev, &conn->dst, conn->type,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002081 conn->dst_type, 0, NULL, 0,
2082 conn->dev_class);
Johan Hedberg392599b2010-11-18 22:22:28 +02002083
Johan Hedberg127178d2010-11-18 22:22:29 +02002084 if (!hci_outgoing_auth_needed(hdev, conn)) {
Johan Hedbergccd556f2010-11-10 17:11:51 +02002085 conn->state = BT_CONNECTED;
2086 hci_proto_connect_cfm(conn, ev->status);
2087 hci_conn_put(conn);
Marcel Holtmann769be972008-07-14 20:13:49 +02002088 }
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002089
Johan Hedbergccd556f2010-11-10 17:11:51 +02002090unlock:
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002091 hci_dev_unlock(hdev);
2092}
2093
Gustavo Padovan6039aa72012-05-23 04:04:18 -03002094static void hci_cmd_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002095{
2096 struct hci_ev_cmd_complete *ev = (void *) skb->data;
Johan Hedberg9238f362013-03-05 20:37:48 +02002097 u8 status = skb->data[sizeof(*ev)];
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002098 __u16 opcode;
2099
2100 skb_pull(skb, sizeof(*ev));
2101
2102 opcode = __le16_to_cpu(ev->opcode);
2103
2104 switch (opcode) {
2105 case HCI_OP_INQUIRY_CANCEL:
2106 hci_cc_inquiry_cancel(hdev, skb);
2107 break;
2108
Andre Guedes4d934832012-03-21 00:03:35 -03002109 case HCI_OP_PERIODIC_INQ:
2110 hci_cc_periodic_inq(hdev, skb);
2111 break;
2112
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002113 case HCI_OP_EXIT_PERIODIC_INQ:
2114 hci_cc_exit_periodic_inq(hdev, skb);
2115 break;
2116
2117 case HCI_OP_REMOTE_NAME_REQ_CANCEL:
2118 hci_cc_remote_name_req_cancel(hdev, skb);
2119 break;
2120
2121 case HCI_OP_ROLE_DISCOVERY:
2122 hci_cc_role_discovery(hdev, skb);
2123 break;
2124
Marcel Holtmanne4e8e372008-07-14 20:13:47 +02002125 case HCI_OP_READ_LINK_POLICY:
2126 hci_cc_read_link_policy(hdev, skb);
2127 break;
2128
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002129 case HCI_OP_WRITE_LINK_POLICY:
2130 hci_cc_write_link_policy(hdev, skb);
2131 break;
2132
Marcel Holtmanne4e8e372008-07-14 20:13:47 +02002133 case HCI_OP_READ_DEF_LINK_POLICY:
2134 hci_cc_read_def_link_policy(hdev, skb);
2135 break;
2136
2137 case HCI_OP_WRITE_DEF_LINK_POLICY:
2138 hci_cc_write_def_link_policy(hdev, skb);
2139 break;
2140
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002141 case HCI_OP_RESET:
2142 hci_cc_reset(hdev, skb);
2143 break;
2144
2145 case HCI_OP_WRITE_LOCAL_NAME:
2146 hci_cc_write_local_name(hdev, skb);
2147 break;
2148
2149 case HCI_OP_READ_LOCAL_NAME:
2150 hci_cc_read_local_name(hdev, skb);
2151 break;
2152
2153 case HCI_OP_WRITE_AUTH_ENABLE:
2154 hci_cc_write_auth_enable(hdev, skb);
2155 break;
2156
2157 case HCI_OP_WRITE_ENCRYPT_MODE:
2158 hci_cc_write_encrypt_mode(hdev, skb);
2159 break;
2160
2161 case HCI_OP_WRITE_SCAN_ENABLE:
2162 hci_cc_write_scan_enable(hdev, skb);
2163 break;
2164
2165 case HCI_OP_READ_CLASS_OF_DEV:
2166 hci_cc_read_class_of_dev(hdev, skb);
2167 break;
2168
2169 case HCI_OP_WRITE_CLASS_OF_DEV:
2170 hci_cc_write_class_of_dev(hdev, skb);
2171 break;
2172
2173 case HCI_OP_READ_VOICE_SETTING:
2174 hci_cc_read_voice_setting(hdev, skb);
2175 break;
2176
2177 case HCI_OP_WRITE_VOICE_SETTING:
2178 hci_cc_write_voice_setting(hdev, skb);
2179 break;
2180
Marcel Holtmann333140b2008-07-14 20:13:48 +02002181 case HCI_OP_WRITE_SSP_MODE:
2182 hci_cc_write_ssp_mode(hdev, skb);
2183 break;
2184
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002185 case HCI_OP_READ_LOCAL_VERSION:
2186 hci_cc_read_local_version(hdev, skb);
2187 break;
2188
2189 case HCI_OP_READ_LOCAL_COMMANDS:
2190 hci_cc_read_local_commands(hdev, skb);
2191 break;
2192
2193 case HCI_OP_READ_LOCAL_FEATURES:
2194 hci_cc_read_local_features(hdev, skb);
2195 break;
2196
Andre Guedes971e3a42011-06-30 19:20:52 -03002197 case HCI_OP_READ_LOCAL_EXT_FEATURES:
2198 hci_cc_read_local_ext_features(hdev, skb);
2199 break;
2200
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002201 case HCI_OP_READ_BUFFER_SIZE:
2202 hci_cc_read_buffer_size(hdev, skb);
2203 break;
2204
2205 case HCI_OP_READ_BD_ADDR:
2206 hci_cc_read_bd_addr(hdev, skb);
2207 break;
2208
Andrei Emeltchenko350ee4c2011-12-07 15:56:51 +02002209 case HCI_OP_READ_DATA_BLOCK_SIZE:
2210 hci_cc_read_data_block_size(hdev, skb);
2211 break;
2212
Andrei Emeltchenko1e89cff2011-11-24 14:52:02 +02002213 case HCI_OP_READ_FLOW_CONTROL_MODE:
2214 hci_cc_read_flow_control_mode(hdev, skb);
2215 break;
2216
Andrei Emeltchenko928abaa2011-10-12 10:53:57 +03002217 case HCI_OP_READ_LOCAL_AMP_INFO:
2218 hci_cc_read_local_amp_info(hdev, skb);
2219 break;
2220
Andrei Emeltchenko903e4542012-09-27 17:26:09 +03002221 case HCI_OP_READ_LOCAL_AMP_ASSOC:
2222 hci_cc_read_local_amp_assoc(hdev, skb);
2223 break;
2224
Johan Hedbergd5859e22011-01-25 01:19:58 +02002225 case HCI_OP_READ_INQ_RSP_TX_POWER:
2226 hci_cc_read_inq_rsp_tx_power(hdev, skb);
2227 break;
2228
Johan Hedberg980e1a52011-01-22 06:10:07 +02002229 case HCI_OP_PIN_CODE_REPLY:
2230 hci_cc_pin_code_reply(hdev, skb);
2231 break;
2232
2233 case HCI_OP_PIN_CODE_NEG_REPLY:
2234 hci_cc_pin_code_neg_reply(hdev, skb);
2235 break;
2236
Szymon Jancc35938b2011-03-22 13:12:21 +01002237 case HCI_OP_READ_LOCAL_OOB_DATA:
2238 hci_cc_read_local_oob_data_reply(hdev, skb);
2239 break;
2240
Ville Tervo6ed58ec2011-02-10 22:38:48 -03002241 case HCI_OP_LE_READ_BUFFER_SIZE:
2242 hci_cc_le_read_buffer_size(hdev, skb);
2243 break;
2244
Johan Hedberg60e77322013-01-22 14:01:59 +02002245 case HCI_OP_LE_READ_LOCAL_FEATURES:
2246 hci_cc_le_read_local_features(hdev, skb);
2247 break;
2248
Johan Hedberg8fa19092012-10-19 20:57:49 +03002249 case HCI_OP_LE_READ_ADV_TX_POWER:
2250 hci_cc_le_read_adv_tx_power(hdev, skb);
2251 break;
2252
Johan Hedberga5c29682011-02-19 12:05:57 -03002253 case HCI_OP_USER_CONFIRM_REPLY:
2254 hci_cc_user_confirm_reply(hdev, skb);
2255 break;
2256
2257 case HCI_OP_USER_CONFIRM_NEG_REPLY:
2258 hci_cc_user_confirm_neg_reply(hdev, skb);
2259 break;
2260
Brian Gix1143d452011-11-23 08:28:34 -08002261 case HCI_OP_USER_PASSKEY_REPLY:
2262 hci_cc_user_passkey_reply(hdev, skb);
2263 break;
2264
2265 case HCI_OP_USER_PASSKEY_NEG_REPLY:
2266 hci_cc_user_passkey_neg_reply(hdev, skb);
Szymon Janc16cde992012-04-13 12:32:42 +02002267 break;
Andre Guedes07f7fa52011-12-02 21:13:31 +09002268
2269 case HCI_OP_LE_SET_SCAN_PARAM:
2270 hci_cc_le_set_scan_param(hdev, skb);
Brian Gix1143d452011-11-23 08:28:34 -08002271 break;
2272
Johan Hedbergc1d5dc42012-11-08 01:23:01 +01002273 case HCI_OP_LE_SET_ADV_ENABLE:
2274 hci_cc_le_set_adv_enable(hdev, skb);
2275 break;
2276
Andre Guedeseb9d91f2011-05-26 16:23:52 -03002277 case HCI_OP_LE_SET_SCAN_ENABLE:
2278 hci_cc_le_set_scan_enable(hdev, skb);
2279 break;
2280
Johan Hedbergcf1d0812013-01-22 14:02:00 +02002281 case HCI_OP_LE_READ_WHITE_LIST_SIZE:
2282 hci_cc_le_read_white_list_size(hdev, skb);
2283 break;
2284
Johan Hedberg9b008c02013-01-22 14:02:01 +02002285 case HCI_OP_LE_READ_SUPPORTED_STATES:
2286 hci_cc_le_read_supported_states(hdev, skb);
2287 break;
2288
Andre Guedesf9b49302011-06-30 19:20:53 -03002289 case HCI_OP_WRITE_LE_HOST_SUPPORTED:
2290 hci_cc_write_le_host_supported(hdev, skb);
2291 break;
2292
Andrei Emeltchenko93c284e2012-09-27 17:26:20 +03002293 case HCI_OP_WRITE_REMOTE_AMP_ASSOC:
2294 hci_cc_write_remote_amp_assoc(hdev, skb);
2295 break;
2296
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002297 default:
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +03002298 BT_DBG("%s opcode 0x%4.4x", hdev->name, opcode);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002299 break;
2300 }
2301
Johan Hedbergad82cdd2013-03-09 09:53:50 +02002302 if (opcode != HCI_OP_NOP)
Ville Tervo6bd32322011-02-16 16:32:41 +02002303 del_timer(&hdev->cmd_timer);
2304
Johan Hedbergad82cdd2013-03-09 09:53:50 +02002305 hci_req_cmd_complete(hdev, opcode, status);
Johan Hedberg9238f362013-03-05 20:37:48 +02002306
Szymon Jancdbccd792012-12-11 08:51:19 +01002307 if (ev->ncmd && !test_bit(HCI_RESET, &hdev->flags)) {
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002308 atomic_set(&hdev->cmd_cnt, 1);
2309 if (!skb_queue_empty(&hdev->cmd_q))
Gustavo F. Padovanc347b762011-12-14 23:53:47 -02002310 queue_work(hdev->workqueue, &hdev->cmd_work);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002311 }
2312}
2313
Gustavo Padovan6039aa72012-05-23 04:04:18 -03002314static void hci_cmd_status_evt(struct hci_dev *hdev, struct sk_buff *skb)
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002315{
2316 struct hci_ev_cmd_status *ev = (void *) skb->data;
2317 __u16 opcode;
2318
2319 skb_pull(skb, sizeof(*ev));
2320
2321 opcode = __le16_to_cpu(ev->opcode);
2322
2323 switch (opcode) {
2324 case HCI_OP_INQUIRY:
2325 hci_cs_inquiry(hdev, ev->status);
2326 break;
2327
2328 case HCI_OP_CREATE_CONN:
2329 hci_cs_create_conn(hdev, ev->status);
2330 break;
2331
2332 case HCI_OP_ADD_SCO:
2333 hci_cs_add_sco(hdev, ev->status);
2334 break;
2335
Marcel Holtmannf8558552008-07-14 20:13:49 +02002336 case HCI_OP_AUTH_REQUESTED:
2337 hci_cs_auth_requested(hdev, ev->status);
2338 break;
2339
2340 case HCI_OP_SET_CONN_ENCRYPT:
2341 hci_cs_set_conn_encrypt(hdev, ev->status);
2342 break;
2343
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002344 case HCI_OP_REMOTE_NAME_REQ:
2345 hci_cs_remote_name_req(hdev, ev->status);
2346 break;
2347
Marcel Holtmann769be972008-07-14 20:13:49 +02002348 case HCI_OP_READ_REMOTE_FEATURES:
2349 hci_cs_read_remote_features(hdev, ev->status);
2350 break;
2351
2352 case HCI_OP_READ_REMOTE_EXT_FEATURES:
2353 hci_cs_read_remote_ext_features(hdev, ev->status);
2354 break;
2355
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002356 case HCI_OP_SETUP_SYNC_CONN:
2357 hci_cs_setup_sync_conn(hdev, ev->status);
2358 break;
2359
2360 case HCI_OP_SNIFF_MODE:
2361 hci_cs_sniff_mode(hdev, ev->status);
2362 break;
2363
2364 case HCI_OP_EXIT_SNIFF_MODE:
2365 hci_cs_exit_sniff_mode(hdev, ev->status);
2366 break;
2367
Johan Hedberg8962ee72011-01-20 12:40:27 +02002368 case HCI_OP_DISCONNECT:
Johan Hedberg88c3df12012-02-09 14:27:38 +02002369 hci_cs_disconnect(hdev, ev->status);
Johan Hedberg8962ee72011-01-20 12:40:27 +02002370 break;
2371
Ville Tervofcd89c02011-02-10 22:38:47 -03002372 case HCI_OP_LE_CREATE_CONN:
2373 hci_cs_le_create_conn(hdev, ev->status);
2374 break;
2375
Andrei Emeltchenkoa02226d2012-09-27 17:26:19 +03002376 case HCI_OP_CREATE_PHY_LINK:
2377 hci_cs_create_phylink(hdev, ev->status);
2378 break;
2379
Andrei Emeltchenko0b26ab92012-09-27 17:26:24 +03002380 case HCI_OP_ACCEPT_PHY_LINK:
2381 hci_cs_accept_phylink(hdev, ev->status);
2382 break;
2383
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002384 default:
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +03002385 BT_DBG("%s opcode 0x%4.4x", hdev->name, opcode);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002386 break;
2387 }
2388
Johan Hedbergad82cdd2013-03-09 09:53:50 +02002389 if (opcode != HCI_OP_NOP)
Ville Tervo6bd32322011-02-16 16:32:41 +02002390 del_timer(&hdev->cmd_timer);
2391
Johan Hedbergad82cdd2013-03-09 09:53:50 +02002392 hci_req_cmd_status(hdev, opcode, ev->status);
Johan Hedberg9238f362013-03-05 20:37:48 +02002393
Gustavo F. Padovan10572132011-03-16 15:36:29 -03002394 if (ev->ncmd && !test_bit(HCI_RESET, &hdev->flags)) {
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002395 atomic_set(&hdev->cmd_cnt, 1);
2396 if (!skb_queue_empty(&hdev->cmd_q))
Gustavo F. Padovanc347b762011-12-14 23:53:47 -02002397 queue_work(hdev->workqueue, &hdev->cmd_work);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002398 }
2399}
2400
Gustavo Padovan6039aa72012-05-23 04:04:18 -03002401static void hci_role_change_evt(struct hci_dev *hdev, struct sk_buff *skb)
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002402{
2403 struct hci_ev_role_change *ev = (void *) skb->data;
2404 struct hci_conn *conn;
2405
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +03002406 BT_DBG("%s status 0x%2.2x", hdev->name, ev->status);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002407
2408 hci_dev_lock(hdev);
2409
2410 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
2411 if (conn) {
2412 if (!ev->status) {
2413 if (ev->role)
2414 conn->link_mode &= ~HCI_LM_MASTER;
2415 else
2416 conn->link_mode |= HCI_LM_MASTER;
2417 }
2418
Johan Hedberg51a8efd2012-01-16 06:10:31 +02002419 clear_bit(HCI_CONN_RSWITCH_PEND, &conn->flags);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002420
2421 hci_role_switch_cfm(conn, ev->status, ev->role);
2422 }
2423
2424 hci_dev_unlock(hdev);
2425}
2426
Gustavo Padovan6039aa72012-05-23 04:04:18 -03002427static void hci_num_comp_pkts_evt(struct hci_dev *hdev, struct sk_buff *skb)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002428{
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002429 struct hci_ev_num_comp_pkts *ev = (void *) skb->data;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002430 int i;
2431
Andrei Emeltchenko32ac5b92011-12-19 16:31:29 +02002432 if (hdev->flow_ctl_mode != HCI_FLOW_CTL_MODE_PACKET_BASED) {
2433 BT_ERR("Wrong event for mode %d", hdev->flow_ctl_mode);
2434 return;
2435 }
2436
Andrei Emeltchenkoc5993de2011-12-30 12:07:47 +02002437 if (skb->len < sizeof(*ev) || skb->len < sizeof(*ev) +
Gustavo Padovan807deac2012-05-17 00:36:24 -03002438 ev->num_hndl * sizeof(struct hci_comp_pkts_info)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002439 BT_DBG("%s bad parameters", hdev->name);
2440 return;
2441 }
2442
Andrei Emeltchenkoc5993de2011-12-30 12:07:47 +02002443 BT_DBG("%s num_hndl %d", hdev->name, ev->num_hndl);
2444
Andrei Emeltchenko613a1c02011-12-19 16:31:30 +02002445 for (i = 0; i < ev->num_hndl; i++) {
2446 struct hci_comp_pkts_info *info = &ev->handles[i];
Linus Torvalds1da177e2005-04-16 15:20:36 -07002447 struct hci_conn *conn;
2448 __u16 handle, count;
2449
Andrei Emeltchenko613a1c02011-12-19 16:31:30 +02002450 handle = __le16_to_cpu(info->handle);
2451 count = __le16_to_cpu(info->count);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002452
2453 conn = hci_conn_hash_lookup_handle(hdev, handle);
Andrei Emeltchenkof4280912011-12-07 15:56:52 +02002454 if (!conn)
2455 continue;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002456
Andrei Emeltchenkof4280912011-12-07 15:56:52 +02002457 conn->sent -= count;
2458
2459 switch (conn->type) {
2460 case ACL_LINK:
2461 hdev->acl_cnt += count;
2462 if (hdev->acl_cnt > hdev->acl_pkts)
2463 hdev->acl_cnt = hdev->acl_pkts;
2464 break;
2465
2466 case LE_LINK:
2467 if (hdev->le_pkts) {
2468 hdev->le_cnt += count;
2469 if (hdev->le_cnt > hdev->le_pkts)
2470 hdev->le_cnt = hdev->le_pkts;
2471 } else {
Andrei Emeltchenko70f230202010-12-01 16:58:25 +02002472 hdev->acl_cnt += count;
2473 if (hdev->acl_cnt > hdev->acl_pkts)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002474 hdev->acl_cnt = hdev->acl_pkts;
2475 }
Andrei Emeltchenkof4280912011-12-07 15:56:52 +02002476 break;
2477
2478 case SCO_LINK:
2479 hdev->sco_cnt += count;
2480 if (hdev->sco_cnt > hdev->sco_pkts)
2481 hdev->sco_cnt = hdev->sco_pkts;
2482 break;
2483
2484 default:
2485 BT_ERR("Unknown type %d conn %p", conn->type, conn);
2486 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002487 }
2488 }
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002489
Gustavo F. Padovan3eff45e2011-12-15 00:50:02 -02002490 queue_work(hdev->workqueue, &hdev->tx_work);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002491}
2492
Andrei Emeltchenko76ef7cf2012-10-10 17:38:29 +03002493static struct hci_conn *__hci_conn_lookup_handle(struct hci_dev *hdev,
2494 __u16 handle)
2495{
2496 struct hci_chan *chan;
2497
2498 switch (hdev->dev_type) {
2499 case HCI_BREDR:
2500 return hci_conn_hash_lookup_handle(hdev, handle);
2501 case HCI_AMP:
2502 chan = hci_chan_lookup_handle(hdev, handle);
2503 if (chan)
2504 return chan->conn;
2505 break;
2506 default:
2507 BT_ERR("%s unknown dev_type %d", hdev->name, hdev->dev_type);
2508 break;
2509 }
2510
2511 return NULL;
2512}
2513
Gustavo Padovan6039aa72012-05-23 04:04:18 -03002514static void hci_num_comp_blocks_evt(struct hci_dev *hdev, struct sk_buff *skb)
Andrei Emeltchenko25e89e92012-01-04 12:41:58 +02002515{
2516 struct hci_ev_num_comp_blocks *ev = (void *) skb->data;
2517 int i;
2518
2519 if (hdev->flow_ctl_mode != HCI_FLOW_CTL_MODE_BLOCK_BASED) {
2520 BT_ERR("Wrong event for mode %d", hdev->flow_ctl_mode);
2521 return;
2522 }
2523
2524 if (skb->len < sizeof(*ev) || skb->len < sizeof(*ev) +
Gustavo Padovan807deac2012-05-17 00:36:24 -03002525 ev->num_hndl * sizeof(struct hci_comp_blocks_info)) {
Andrei Emeltchenko25e89e92012-01-04 12:41:58 +02002526 BT_DBG("%s bad parameters", hdev->name);
2527 return;
2528 }
2529
2530 BT_DBG("%s num_blocks %d num_hndl %d", hdev->name, ev->num_blocks,
Gustavo Padovan807deac2012-05-17 00:36:24 -03002531 ev->num_hndl);
Andrei Emeltchenko25e89e92012-01-04 12:41:58 +02002532
2533 for (i = 0; i < ev->num_hndl; i++) {
2534 struct hci_comp_blocks_info *info = &ev->handles[i];
Andrei Emeltchenko76ef7cf2012-10-10 17:38:29 +03002535 struct hci_conn *conn = NULL;
Andrei Emeltchenko25e89e92012-01-04 12:41:58 +02002536 __u16 handle, block_count;
2537
2538 handle = __le16_to_cpu(info->handle);
2539 block_count = __le16_to_cpu(info->blocks);
2540
Andrei Emeltchenko76ef7cf2012-10-10 17:38:29 +03002541 conn = __hci_conn_lookup_handle(hdev, handle);
Andrei Emeltchenko25e89e92012-01-04 12:41:58 +02002542 if (!conn)
2543 continue;
2544
2545 conn->sent -= block_count;
2546
2547 switch (conn->type) {
2548 case ACL_LINK:
Andrei Emeltchenkobd1eb662012-10-10 17:38:30 +03002549 case AMP_LINK:
Andrei Emeltchenko25e89e92012-01-04 12:41:58 +02002550 hdev->block_cnt += block_count;
2551 if (hdev->block_cnt > hdev->num_blocks)
2552 hdev->block_cnt = hdev->num_blocks;
2553 break;
2554
2555 default:
2556 BT_ERR("Unknown type %d conn %p", conn->type, conn);
2557 break;
2558 }
2559 }
2560
2561 queue_work(hdev->workqueue, &hdev->tx_work);
2562}
2563
Gustavo Padovan6039aa72012-05-23 04:04:18 -03002564static void hci_mode_change_evt(struct hci_dev *hdev, struct sk_buff *skb)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002565{
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002566 struct hci_ev_mode_change *ev = (void *) skb->data;
Marcel Holtmann04837f62006-07-03 10:02:33 +02002567 struct hci_conn *conn;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002568
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +03002569 BT_DBG("%s status 0x%2.2x", hdev->name, ev->status);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002570
2571 hci_dev_lock(hdev);
2572
Marcel Holtmann04837f62006-07-03 10:02:33 +02002573 conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
2574 if (conn) {
2575 conn->mode = ev->mode;
2576 conn->interval = __le16_to_cpu(ev->interval);
2577
Gustavo Padovan8fc9ced2012-05-23 04:04:21 -03002578 if (!test_and_clear_bit(HCI_CONN_MODE_CHANGE_PEND,
2579 &conn->flags)) {
Marcel Holtmann04837f62006-07-03 10:02:33 +02002580 if (conn->mode == HCI_CM_ACTIVE)
Johan Hedberg58a681e2012-01-16 06:47:28 +02002581 set_bit(HCI_CONN_POWER_SAVE, &conn->flags);
Marcel Holtmann04837f62006-07-03 10:02:33 +02002582 else
Johan Hedberg58a681e2012-01-16 06:47:28 +02002583 clear_bit(HCI_CONN_POWER_SAVE, &conn->flags);
Marcel Holtmann04837f62006-07-03 10:02:33 +02002584 }
Marcel Holtmanne73439d2010-07-26 10:06:00 -04002585
Johan Hedberg51a8efd2012-01-16 06:10:31 +02002586 if (test_and_clear_bit(HCI_CONN_SCO_SETUP_PEND, &conn->flags))
Marcel Holtmanne73439d2010-07-26 10:06:00 -04002587 hci_sco_setup(conn, ev->status);
Marcel Holtmann04837f62006-07-03 10:02:33 +02002588 }
2589
2590 hci_dev_unlock(hdev);
2591}
2592
Gustavo Padovan6039aa72012-05-23 04:04:18 -03002593static void hci_pin_code_request_evt(struct hci_dev *hdev, struct sk_buff *skb)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002594{
Marcel Holtmann052b30b2009-04-26 20:01:22 +02002595 struct hci_ev_pin_code_req *ev = (void *) skb->data;
2596 struct hci_conn *conn;
2597
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002598 BT_DBG("%s", hdev->name);
Marcel Holtmann052b30b2009-04-26 20:01:22 +02002599
2600 hci_dev_lock(hdev);
2601
2602 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
Waldemar Rymarkiewiczb6f98042011-09-23 10:01:30 +02002603 if (!conn)
2604 goto unlock;
2605
2606 if (conn->state == BT_CONNECTED) {
Marcel Holtmann052b30b2009-04-26 20:01:22 +02002607 hci_conn_hold(conn);
2608 conn->disc_timeout = HCI_PAIRING_TIMEOUT;
2609 hci_conn_put(conn);
2610 }
2611
Johan Hedberga8b2d5c2012-01-08 23:11:15 +02002612 if (!test_bit(HCI_PAIRABLE, &hdev->dev_flags))
Johan Hedberg03b555e2011-01-04 15:40:05 +02002613 hci_send_cmd(hdev, HCI_OP_PIN_CODE_NEG_REPLY,
Gustavo Padovan807deac2012-05-17 00:36:24 -03002614 sizeof(ev->bdaddr), &ev->bdaddr);
Johan Hedberga8b2d5c2012-01-08 23:11:15 +02002615 else if (test_bit(HCI_MGMT, &hdev->dev_flags)) {
Waldemar Rymarkiewicza770bb52011-04-28 12:07:59 +02002616 u8 secure;
2617
2618 if (conn->pending_sec_level == BT_SECURITY_HIGH)
2619 secure = 1;
2620 else
2621 secure = 0;
2622
Johan Hedberg744cf192011-11-08 20:40:14 +02002623 mgmt_pin_code_request(hdev, &ev->bdaddr, secure);
Waldemar Rymarkiewicza770bb52011-04-28 12:07:59 +02002624 }
Johan Hedberg980e1a52011-01-22 06:10:07 +02002625
Waldemar Rymarkiewiczb6f98042011-09-23 10:01:30 +02002626unlock:
Marcel Holtmann052b30b2009-04-26 20:01:22 +02002627 hci_dev_unlock(hdev);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002628}
2629
Gustavo Padovan6039aa72012-05-23 04:04:18 -03002630static void hci_link_key_request_evt(struct hci_dev *hdev, struct sk_buff *skb)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002631{
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002632 struct hci_ev_link_key_req *ev = (void *) skb->data;
2633 struct hci_cp_link_key_reply cp;
2634 struct hci_conn *conn;
2635 struct link_key *key;
2636
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002637 BT_DBG("%s", hdev->name);
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002638
Johan Hedberga8b2d5c2012-01-08 23:11:15 +02002639 if (!test_bit(HCI_LINK_KEYS, &hdev->dev_flags))
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002640 return;
2641
2642 hci_dev_lock(hdev);
2643
2644 key = hci_find_link_key(hdev, &ev->bdaddr);
2645 if (!key) {
Andrei Emeltchenko6ed93dc2012-09-25 12:49:43 +03002646 BT_DBG("%s link key not found for %pMR", hdev->name,
2647 &ev->bdaddr);
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002648 goto not_found;
2649 }
2650
Andrei Emeltchenko6ed93dc2012-09-25 12:49:43 +03002651 BT_DBG("%s found key type %u for %pMR", hdev->name, key->type,
2652 &ev->bdaddr);
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002653
Johan Hedberga8b2d5c2012-01-08 23:11:15 +02002654 if (!test_bit(HCI_DEBUG_KEYS, &hdev->dev_flags) &&
Gustavo Padovan807deac2012-05-17 00:36:24 -03002655 key->type == HCI_LK_DEBUG_COMBINATION) {
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002656 BT_DBG("%s ignoring debug key", hdev->name);
2657 goto not_found;
2658 }
2659
2660 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
Waldemar Rymarkiewicz60b83f52011-04-28 12:07:56 +02002661 if (conn) {
2662 if (key->type == HCI_LK_UNAUTH_COMBINATION &&
Gustavo Padovan807deac2012-05-17 00:36:24 -03002663 conn->auth_type != 0xff && (conn->auth_type & 0x01)) {
Waldemar Rymarkiewicz60b83f52011-04-28 12:07:56 +02002664 BT_DBG("%s ignoring unauthenticated key", hdev->name);
2665 goto not_found;
2666 }
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002667
Waldemar Rymarkiewicz60b83f52011-04-28 12:07:56 +02002668 if (key->type == HCI_LK_COMBINATION && key->pin_len < 16 &&
Gustavo Padovan807deac2012-05-17 00:36:24 -03002669 conn->pending_sec_level == BT_SECURITY_HIGH) {
Gustavo Padovan8fc9ced2012-05-23 04:04:21 -03002670 BT_DBG("%s ignoring key unauthenticated for high security",
2671 hdev->name);
Waldemar Rymarkiewicz60b83f52011-04-28 12:07:56 +02002672 goto not_found;
2673 }
2674
2675 conn->key_type = key->type;
2676 conn->pin_length = key->pin_len;
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002677 }
2678
2679 bacpy(&cp.bdaddr, &ev->bdaddr);
Andrei Emeltchenko9b3b4462012-05-23 11:31:20 +03002680 memcpy(cp.link_key, key->val, HCI_LINK_KEY_SIZE);
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002681
2682 hci_send_cmd(hdev, HCI_OP_LINK_KEY_REPLY, sizeof(cp), &cp);
2683
2684 hci_dev_unlock(hdev);
2685
2686 return;
2687
2688not_found:
2689 hci_send_cmd(hdev, HCI_OP_LINK_KEY_NEG_REPLY, 6, &ev->bdaddr);
2690 hci_dev_unlock(hdev);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002691}
2692
Gustavo Padovan6039aa72012-05-23 04:04:18 -03002693static void hci_link_key_notify_evt(struct hci_dev *hdev, struct sk_buff *skb)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002694{
Marcel Holtmann052b30b2009-04-26 20:01:22 +02002695 struct hci_ev_link_key_notify *ev = (void *) skb->data;
2696 struct hci_conn *conn;
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002697 u8 pin_len = 0;
Marcel Holtmann052b30b2009-04-26 20:01:22 +02002698
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002699 BT_DBG("%s", hdev->name);
Marcel Holtmann052b30b2009-04-26 20:01:22 +02002700
2701 hci_dev_lock(hdev);
2702
2703 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
2704 if (conn) {
2705 hci_conn_hold(conn);
2706 conn->disc_timeout = HCI_DISCONN_TIMEOUT;
Johan Hedberg980e1a52011-01-22 06:10:07 +02002707 pin_len = conn->pin_length;
Waldemar Rymarkiewicz13d39312011-04-28 12:07:55 +02002708
2709 if (ev->key_type != HCI_LK_CHANGED_COMBINATION)
2710 conn->key_type = ev->key_type;
2711
Marcel Holtmann052b30b2009-04-26 20:01:22 +02002712 hci_conn_put(conn);
2713 }
2714
Johan Hedberga8b2d5c2012-01-08 23:11:15 +02002715 if (test_bit(HCI_LINK_KEYS, &hdev->dev_flags))
Johan Hedbergd25e28a2011-04-28 11:28:59 -07002716 hci_add_link_key(hdev, conn, 1, &ev->bdaddr, ev->link_key,
Gustavo Padovan807deac2012-05-17 00:36:24 -03002717 ev->key_type, pin_len);
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002718
Marcel Holtmann052b30b2009-04-26 20:01:22 +02002719 hci_dev_unlock(hdev);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002720}
2721
Gustavo Padovan6039aa72012-05-23 04:04:18 -03002722static void hci_clock_offset_evt(struct hci_dev *hdev, struct sk_buff *skb)
Marcel Holtmann04837f62006-07-03 10:02:33 +02002723{
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002724 struct hci_ev_clock_offset *ev = (void *) skb->data;
Marcel Holtmann04837f62006-07-03 10:02:33 +02002725 struct hci_conn *conn;
2726
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +03002727 BT_DBG("%s status 0x%2.2x", hdev->name, ev->status);
Marcel Holtmann04837f62006-07-03 10:02:33 +02002728
2729 hci_dev_lock(hdev);
2730
2731 conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
Linus Torvalds1da177e2005-04-16 15:20:36 -07002732 if (conn && !ev->status) {
2733 struct inquiry_entry *ie;
2734
Andrei Emeltchenkocc11b9c2010-11-22 13:21:37 +02002735 ie = hci_inquiry_cache_lookup(hdev, &conn->dst);
2736 if (ie) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002737 ie->data.clock_offset = ev->clock_offset;
2738 ie->timestamp = jiffies;
2739 }
2740 }
2741
2742 hci_dev_unlock(hdev);
2743}
2744
Gustavo Padovan6039aa72012-05-23 04:04:18 -03002745static void hci_pkt_type_change_evt(struct hci_dev *hdev, struct sk_buff *skb)
Marcel Holtmanna8746412008-07-14 20:13:46 +02002746{
2747 struct hci_ev_pkt_type_change *ev = (void *) skb->data;
2748 struct hci_conn *conn;
2749
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +03002750 BT_DBG("%s status 0x%2.2x", hdev->name, ev->status);
Marcel Holtmanna8746412008-07-14 20:13:46 +02002751
2752 hci_dev_lock(hdev);
2753
2754 conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
2755 if (conn && !ev->status)
2756 conn->pkt_type = __le16_to_cpu(ev->pkt_type);
2757
2758 hci_dev_unlock(hdev);
2759}
2760
Gustavo Padovan6039aa72012-05-23 04:04:18 -03002761static void hci_pscan_rep_mode_evt(struct hci_dev *hdev, struct sk_buff *skb)
Marcel Holtmann85a1e932005-08-09 20:28:02 -07002762{
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002763 struct hci_ev_pscan_rep_mode *ev = (void *) skb->data;
Marcel Holtmann85a1e932005-08-09 20:28:02 -07002764 struct inquiry_entry *ie;
2765
2766 BT_DBG("%s", hdev->name);
2767
2768 hci_dev_lock(hdev);
2769
Andrei Emeltchenkocc11b9c2010-11-22 13:21:37 +02002770 ie = hci_inquiry_cache_lookup(hdev, &ev->bdaddr);
2771 if (ie) {
Marcel Holtmann85a1e932005-08-09 20:28:02 -07002772 ie->data.pscan_rep_mode = ev->pscan_rep_mode;
2773 ie->timestamp = jiffies;
2774 }
2775
2776 hci_dev_unlock(hdev);
2777}
2778
Gustavo Padovan6039aa72012-05-23 04:04:18 -03002779static void hci_inquiry_result_with_rssi_evt(struct hci_dev *hdev,
2780 struct sk_buff *skb)
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002781{
2782 struct inquiry_data data;
2783 int num_rsp = *((__u8 *) skb->data);
Johan Hedberg388fc8f2012-02-23 00:38:59 +02002784 bool name_known, ssp;
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002785
2786 BT_DBG("%s num_rsp %d", hdev->name, num_rsp);
2787
2788 if (!num_rsp)
2789 return;
2790
Andre Guedes1519cc12012-03-21 00:03:38 -03002791 if (test_bit(HCI_PERIODIC_INQ, &hdev->dev_flags))
2792 return;
2793
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002794 hci_dev_lock(hdev);
2795
2796 if ((skb->len - 1) / num_rsp != sizeof(struct inquiry_info_with_rssi)) {
Szymon Janc138d22e2011-02-17 16:44:23 +01002797 struct inquiry_info_with_rssi_and_pscan_mode *info;
2798 info = (void *) (skb->data + 1);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002799
Johan Hedberge17acd42011-03-30 23:57:16 +03002800 for (; num_rsp; num_rsp--, info++) {
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002801 bacpy(&data.bdaddr, &info->bdaddr);
2802 data.pscan_rep_mode = info->pscan_rep_mode;
2803 data.pscan_period_mode = info->pscan_period_mode;
2804 data.pscan_mode = info->pscan_mode;
2805 memcpy(data.dev_class, info->dev_class, 3);
2806 data.clock_offset = info->clock_offset;
2807 data.rssi = info->rssi;
Marcel Holtmann41a96212008-07-14 20:13:48 +02002808 data.ssp_mode = 0x00;
Johan Hedberg31754052012-01-04 13:39:52 +02002809
2810 name_known = hci_inquiry_cache_update(hdev, &data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002811 false, &ssp);
Johan Hedberg48264f02011-11-09 13:58:58 +02002812 mgmt_device_found(hdev, &info->bdaddr, ACL_LINK, 0x00,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002813 info->dev_class, info->rssi,
2814 !name_known, ssp, NULL, 0);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002815 }
2816 } else {
2817 struct inquiry_info_with_rssi *info = (void *) (skb->data + 1);
2818
Johan Hedberge17acd42011-03-30 23:57:16 +03002819 for (; num_rsp; num_rsp--, info++) {
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002820 bacpy(&data.bdaddr, &info->bdaddr);
2821 data.pscan_rep_mode = info->pscan_rep_mode;
2822 data.pscan_period_mode = info->pscan_period_mode;
2823 data.pscan_mode = 0x00;
2824 memcpy(data.dev_class, info->dev_class, 3);
2825 data.clock_offset = info->clock_offset;
2826 data.rssi = info->rssi;
Marcel Holtmann41a96212008-07-14 20:13:48 +02002827 data.ssp_mode = 0x00;
Johan Hedberg31754052012-01-04 13:39:52 +02002828 name_known = hci_inquiry_cache_update(hdev, &data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002829 false, &ssp);
Johan Hedberg48264f02011-11-09 13:58:58 +02002830 mgmt_device_found(hdev, &info->bdaddr, ACL_LINK, 0x00,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002831 info->dev_class, info->rssi,
2832 !name_known, ssp, NULL, 0);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002833 }
2834 }
2835
2836 hci_dev_unlock(hdev);
2837}
2838
Gustavo Padovan6039aa72012-05-23 04:04:18 -03002839static void hci_remote_ext_features_evt(struct hci_dev *hdev,
2840 struct sk_buff *skb)
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002841{
Marcel Holtmann41a96212008-07-14 20:13:48 +02002842 struct hci_ev_remote_ext_features *ev = (void *) skb->data;
2843 struct hci_conn *conn;
2844
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002845 BT_DBG("%s", hdev->name);
Marcel Holtmann41a96212008-07-14 20:13:48 +02002846
Marcel Holtmann41a96212008-07-14 20:13:48 +02002847 hci_dev_lock(hdev);
2848
2849 conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
Johan Hedbergccd556f2010-11-10 17:11:51 +02002850 if (!conn)
2851 goto unlock;
Marcel Holtmann41a96212008-07-14 20:13:48 +02002852
Johan Hedbergccd556f2010-11-10 17:11:51 +02002853 if (!ev->status && ev->page == 0x01) {
2854 struct inquiry_entry *ie;
Marcel Holtmann41a96212008-07-14 20:13:48 +02002855
Andrei Emeltchenkocc11b9c2010-11-22 13:21:37 +02002856 ie = hci_inquiry_cache_lookup(hdev, &conn->dst);
2857 if (ie)
Johan Hedberg02b7cc62012-02-28 02:28:43 +02002858 ie->data.ssp_mode = (ev->features[0] & LMP_HOST_SSP);
Marcel Holtmann769be972008-07-14 20:13:49 +02002859
Johan Hedberg02b7cc62012-02-28 02:28:43 +02002860 if (ev->features[0] & LMP_HOST_SSP)
Johan Hedberg58a681e2012-01-16 06:47:28 +02002861 set_bit(HCI_CONN_SSP_ENABLED, &conn->flags);
Marcel Holtmann41a96212008-07-14 20:13:48 +02002862 }
2863
Johan Hedbergccd556f2010-11-10 17:11:51 +02002864 if (conn->state != BT_CONFIG)
2865 goto unlock;
2866
Johan Hedberg671267b2012-05-12 16:11:50 -03002867 if (!ev->status && !test_bit(HCI_CONN_MGMT_CONNECTED, &conn->flags)) {
Johan Hedberg127178d2010-11-18 22:22:29 +02002868 struct hci_cp_remote_name_req cp;
2869 memset(&cp, 0, sizeof(cp));
2870 bacpy(&cp.bdaddr, &conn->dst);
2871 cp.pscan_rep_mode = 0x02;
2872 hci_send_cmd(hdev, HCI_OP_REMOTE_NAME_REQ, sizeof(cp), &cp);
Johan Hedbergb644ba32012-01-17 21:48:47 +02002873 } else if (!test_and_set_bit(HCI_CONN_MGMT_CONNECTED, &conn->flags))
2874 mgmt_device_connected(hdev, &conn->dst, conn->type,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002875 conn->dst_type, 0, NULL, 0,
2876 conn->dev_class);
Johan Hedberg392599b2010-11-18 22:22:28 +02002877
Johan Hedberg127178d2010-11-18 22:22:29 +02002878 if (!hci_outgoing_auth_needed(hdev, conn)) {
Johan Hedbergccd556f2010-11-10 17:11:51 +02002879 conn->state = BT_CONNECTED;
2880 hci_proto_connect_cfm(conn, ev->status);
2881 hci_conn_put(conn);
2882 }
2883
2884unlock:
Marcel Holtmann41a96212008-07-14 20:13:48 +02002885 hci_dev_unlock(hdev);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002886}
2887
Gustavo Padovan6039aa72012-05-23 04:04:18 -03002888static void hci_sync_conn_complete_evt(struct hci_dev *hdev,
2889 struct sk_buff *skb)
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002890{
Marcel Holtmannb6a0dc82007-10-20 14:55:10 +02002891 struct hci_ev_sync_conn_complete *ev = (void *) skb->data;
2892 struct hci_conn *conn;
2893
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +03002894 BT_DBG("%s status 0x%2.2x", hdev->name, ev->status);
Marcel Holtmannb6a0dc82007-10-20 14:55:10 +02002895
2896 hci_dev_lock(hdev);
2897
2898 conn = hci_conn_hash_lookup_ba(hdev, ev->link_type, &ev->bdaddr);
Marcel Holtmann9dc0a3a2008-07-14 20:13:46 +02002899 if (!conn) {
2900 if (ev->link_type == ESCO_LINK)
2901 goto unlock;
2902
2903 conn = hci_conn_hash_lookup_ba(hdev, ESCO_LINK, &ev->bdaddr);
2904 if (!conn)
2905 goto unlock;
2906
2907 conn->type = SCO_LINK;
2908 }
Marcel Holtmannb6a0dc82007-10-20 14:55:10 +02002909
Marcel Holtmann732547f2009-04-19 19:14:14 +02002910 switch (ev->status) {
2911 case 0x00:
Marcel Holtmannb6a0dc82007-10-20 14:55:10 +02002912 conn->handle = __le16_to_cpu(ev->handle);
2913 conn->state = BT_CONNECTED;
Marcel Holtmann7d0db0a2008-07-14 20:13:51 +02002914
Marcel Holtmann9eba32b2009-08-22 14:19:26 -07002915 hci_conn_hold_device(conn);
Marcel Holtmann7d0db0a2008-07-14 20:13:51 +02002916 hci_conn_add_sysfs(conn);
Marcel Holtmann732547f2009-04-19 19:14:14 +02002917 break;
2918
Stephen Coe705e5712010-02-16 11:29:44 -05002919 case 0x11: /* Unsupported Feature or Parameter Value */
Marcel Holtmann732547f2009-04-19 19:14:14 +02002920 case 0x1c: /* SCO interval rejected */
Nick Pelly1038a002010-02-03 11:42:26 -08002921 case 0x1a: /* Unsupported Remote Feature */
Marcel Holtmann732547f2009-04-19 19:14:14 +02002922 case 0x1f: /* Unspecified error */
2923 if (conn->out && conn->attempt < 2) {
2924 conn->pkt_type = (hdev->esco_type & SCO_ESCO_MASK) |
2925 (hdev->esco_type & EDR_ESCO_MASK);
2926 hci_setup_sync(conn, conn->link->handle);
2927 goto unlock;
2928 }
2929 /* fall through */
2930
2931 default:
Marcel Holtmannb6a0dc82007-10-20 14:55:10 +02002932 conn->state = BT_CLOSED;
Marcel Holtmann732547f2009-04-19 19:14:14 +02002933 break;
2934 }
Marcel Holtmannb6a0dc82007-10-20 14:55:10 +02002935
2936 hci_proto_connect_cfm(conn, ev->status);
2937 if (ev->status)
2938 hci_conn_del(conn);
2939
2940unlock:
2941 hci_dev_unlock(hdev);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002942}
2943
Gustavo Padovan6039aa72012-05-23 04:04:18 -03002944static void hci_extended_inquiry_result_evt(struct hci_dev *hdev,
2945 struct sk_buff *skb)
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002946{
2947 struct inquiry_data data;
2948 struct extended_inquiry_info *info = (void *) (skb->data + 1);
2949 int num_rsp = *((__u8 *) skb->data);
Vishal Agarwal9d939d92012-04-26 19:19:56 +05302950 size_t eir_len;
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002951
2952 BT_DBG("%s num_rsp %d", hdev->name, num_rsp);
2953
2954 if (!num_rsp)
2955 return;
2956
Andre Guedes1519cc12012-03-21 00:03:38 -03002957 if (test_bit(HCI_PERIODIC_INQ, &hdev->dev_flags))
2958 return;
2959
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002960 hci_dev_lock(hdev);
2961
Johan Hedberge17acd42011-03-30 23:57:16 +03002962 for (; num_rsp; num_rsp--, info++) {
Johan Hedberg388fc8f2012-02-23 00:38:59 +02002963 bool name_known, ssp;
Johan Hedberg561aafb2012-01-04 13:31:59 +02002964
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002965 bacpy(&data.bdaddr, &info->bdaddr);
Szymon Janc138d22e2011-02-17 16:44:23 +01002966 data.pscan_rep_mode = info->pscan_rep_mode;
2967 data.pscan_period_mode = info->pscan_period_mode;
2968 data.pscan_mode = 0x00;
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002969 memcpy(data.dev_class, info->dev_class, 3);
Szymon Janc138d22e2011-02-17 16:44:23 +01002970 data.clock_offset = info->clock_offset;
2971 data.rssi = info->rssi;
Marcel Holtmann41a96212008-07-14 20:13:48 +02002972 data.ssp_mode = 0x01;
Johan Hedberg561aafb2012-01-04 13:31:59 +02002973
Johan Hedberga8b2d5c2012-01-08 23:11:15 +02002974 if (test_bit(HCI_MGMT, &hdev->dev_flags))
Johan Hedberg4ddb1932012-01-15 20:04:43 +02002975 name_known = eir_has_data_type(info->data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002976 sizeof(info->data),
2977 EIR_NAME_COMPLETE);
Johan Hedberg561aafb2012-01-04 13:31:59 +02002978 else
2979 name_known = true;
2980
Johan Hedberg388fc8f2012-02-23 00:38:59 +02002981 name_known = hci_inquiry_cache_update(hdev, &data, name_known,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002982 &ssp);
Vishal Agarwal9d939d92012-04-26 19:19:56 +05302983 eir_len = eir_get_length(info->data, sizeof(info->data));
Johan Hedberg48264f02011-11-09 13:58:58 +02002984 mgmt_device_found(hdev, &info->bdaddr, ACL_LINK, 0x00,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002985 info->dev_class, info->rssi, !name_known,
Vishal Agarwal9d939d92012-04-26 19:19:56 +05302986 ssp, info->data, eir_len);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002987 }
2988
2989 hci_dev_unlock(hdev);
2990}
2991
Johan Hedberg1c2e0042012-06-08 23:31:13 +08002992static void hci_key_refresh_complete_evt(struct hci_dev *hdev,
2993 struct sk_buff *skb)
2994{
2995 struct hci_ev_key_refresh_complete *ev = (void *) skb->data;
2996 struct hci_conn *conn;
2997
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +03002998 BT_DBG("%s status 0x%2.2x handle 0x%4.4x", hdev->name, ev->status,
Johan Hedberg1c2e0042012-06-08 23:31:13 +08002999 __le16_to_cpu(ev->handle));
3000
3001 hci_dev_lock(hdev);
3002
3003 conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
3004 if (!conn)
3005 goto unlock;
3006
3007 if (!ev->status)
3008 conn->sec_level = conn->pending_sec_level;
3009
3010 clear_bit(HCI_CONN_ENCRYPT_PEND, &conn->flags);
3011
3012 if (ev->status && conn->state == BT_CONNECTED) {
Andre Guedesbed71742013-01-30 11:50:56 -03003013 hci_disconnect(conn, HCI_ERROR_AUTH_FAILURE);
Johan Hedberg1c2e0042012-06-08 23:31:13 +08003014 hci_conn_put(conn);
3015 goto unlock;
3016 }
3017
3018 if (conn->state == BT_CONFIG) {
3019 if (!ev->status)
3020 conn->state = BT_CONNECTED;
3021
3022 hci_proto_connect_cfm(conn, ev->status);
3023 hci_conn_put(conn);
3024 } else {
3025 hci_auth_cfm(conn, ev->status);
3026
3027 hci_conn_hold(conn);
3028 conn->disc_timeout = HCI_DISCONN_TIMEOUT;
3029 hci_conn_put(conn);
3030 }
3031
3032unlock:
3033 hci_dev_unlock(hdev);
3034}
3035
Gustavo Padovan6039aa72012-05-23 04:04:18 -03003036static u8 hci_get_auth_req(struct hci_conn *conn)
Johan Hedberg17fa4b92011-01-25 13:28:33 +02003037{
3038 /* If remote requests dedicated bonding follow that lead */
3039 if (conn->remote_auth == 0x02 || conn->remote_auth == 0x03) {
3040 /* If both remote and local IO capabilities allow MITM
3041 * protection then require it, otherwise don't */
3042 if (conn->remote_cap == 0x03 || conn->io_capability == 0x03)
3043 return 0x02;
3044 else
3045 return 0x03;
3046 }
3047
3048 /* If remote requests no-bonding follow that lead */
3049 if (conn->remote_auth == 0x00 || conn->remote_auth == 0x01)
Waldemar Rymarkiewicz58797bf2011-04-28 12:07:58 +02003050 return conn->remote_auth | (conn->auth_type & 0x01);
Johan Hedberg17fa4b92011-01-25 13:28:33 +02003051
3052 return conn->auth_type;
3053}
3054
Gustavo Padovan6039aa72012-05-23 04:04:18 -03003055static void hci_io_capa_request_evt(struct hci_dev *hdev, struct sk_buff *skb)
Marcel Holtmann04936842008-07-14 20:13:48 +02003056{
3057 struct hci_ev_io_capa_request *ev = (void *) skb->data;
3058 struct hci_conn *conn;
3059
3060 BT_DBG("%s", hdev->name);
3061
3062 hci_dev_lock(hdev);
3063
3064 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
Johan Hedberg03b555e2011-01-04 15:40:05 +02003065 if (!conn)
3066 goto unlock;
Marcel Holtmann04936842008-07-14 20:13:48 +02003067
Johan Hedberg03b555e2011-01-04 15:40:05 +02003068 hci_conn_hold(conn);
3069
Johan Hedberga8b2d5c2012-01-08 23:11:15 +02003070 if (!test_bit(HCI_MGMT, &hdev->dev_flags))
Johan Hedberg03b555e2011-01-04 15:40:05 +02003071 goto unlock;
3072
Johan Hedberga8b2d5c2012-01-08 23:11:15 +02003073 if (test_bit(HCI_PAIRABLE, &hdev->dev_flags) ||
Gustavo Padovan807deac2012-05-17 00:36:24 -03003074 (conn->remote_auth & ~0x01) == HCI_AT_NO_BONDING) {
Johan Hedberg17fa4b92011-01-25 13:28:33 +02003075 struct hci_cp_io_capability_reply cp;
3076
3077 bacpy(&cp.bdaddr, &ev->bdaddr);
Hemant Gupta7a7f1e72012-01-16 13:34:29 +05303078 /* Change the IO capability from KeyboardDisplay
3079 * to DisplayYesNo as it is not supported by BT spec. */
3080 cp.capability = (conn->io_capability == 0x04) ?
3081 0x01 : conn->io_capability;
Johan Hedberg7cbc9bd2011-04-28 11:29:04 -07003082 conn->auth_type = hci_get_auth_req(conn);
3083 cp.authentication = conn->auth_type;
Johan Hedberg17fa4b92011-01-25 13:28:33 +02003084
Gustavo Padovan8fc9ced2012-05-23 04:04:21 -03003085 if (hci_find_remote_oob_data(hdev, &conn->dst) &&
3086 (conn->out || test_bit(HCI_CONN_REMOTE_OOB, &conn->flags)))
Szymon Jancce85ee12011-03-22 13:12:23 +01003087 cp.oob_data = 0x01;
3088 else
3089 cp.oob_data = 0x00;
3090
Johan Hedberg17fa4b92011-01-25 13:28:33 +02003091 hci_send_cmd(hdev, HCI_OP_IO_CAPABILITY_REPLY,
Gustavo Padovan807deac2012-05-17 00:36:24 -03003092 sizeof(cp), &cp);
Johan Hedberg03b555e2011-01-04 15:40:05 +02003093 } else {
3094 struct hci_cp_io_capability_neg_reply cp;
3095
3096 bacpy(&cp.bdaddr, &ev->bdaddr);
Andrei Emeltchenko9f5a0d72011-11-07 14:20:25 +02003097 cp.reason = HCI_ERROR_PAIRING_NOT_ALLOWED;
Johan Hedberg03b555e2011-01-04 15:40:05 +02003098
3099 hci_send_cmd(hdev, HCI_OP_IO_CAPABILITY_NEG_REPLY,
Gustavo Padovan807deac2012-05-17 00:36:24 -03003100 sizeof(cp), &cp);
Johan Hedberg03b555e2011-01-04 15:40:05 +02003101 }
3102
3103unlock:
3104 hci_dev_unlock(hdev);
3105}
3106
Gustavo Padovan6039aa72012-05-23 04:04:18 -03003107static void hci_io_capa_reply_evt(struct hci_dev *hdev, struct sk_buff *skb)
Johan Hedberg03b555e2011-01-04 15:40:05 +02003108{
3109 struct hci_ev_io_capa_reply *ev = (void *) skb->data;
3110 struct hci_conn *conn;
3111
3112 BT_DBG("%s", hdev->name);
3113
3114 hci_dev_lock(hdev);
3115
3116 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
3117 if (!conn)
3118 goto unlock;
3119
Johan Hedberg03b555e2011-01-04 15:40:05 +02003120 conn->remote_cap = ev->capability;
Johan Hedberg03b555e2011-01-04 15:40:05 +02003121 conn->remote_auth = ev->authentication;
Johan Hedberg58a681e2012-01-16 06:47:28 +02003122 if (ev->oob_data)
3123 set_bit(HCI_CONN_REMOTE_OOB, &conn->flags);
Johan Hedberg03b555e2011-01-04 15:40:05 +02003124
3125unlock:
Marcel Holtmann04936842008-07-14 20:13:48 +02003126 hci_dev_unlock(hdev);
3127}
3128
Gustavo Padovan6039aa72012-05-23 04:04:18 -03003129static void hci_user_confirm_request_evt(struct hci_dev *hdev,
3130 struct sk_buff *skb)
Johan Hedberga5c29682011-02-19 12:05:57 -03003131{
3132 struct hci_ev_user_confirm_req *ev = (void *) skb->data;
Johan Hedberg55bc1a32011-04-28 11:28:56 -07003133 int loc_mitm, rem_mitm, confirm_hint = 0;
Johan Hedberg7a828902011-04-28 11:28:53 -07003134 struct hci_conn *conn;
Johan Hedberga5c29682011-02-19 12:05:57 -03003135
3136 BT_DBG("%s", hdev->name);
3137
3138 hci_dev_lock(hdev);
3139
Johan Hedberga8b2d5c2012-01-08 23:11:15 +02003140 if (!test_bit(HCI_MGMT, &hdev->dev_flags))
Johan Hedberg7a828902011-04-28 11:28:53 -07003141 goto unlock;
Johan Hedberga5c29682011-02-19 12:05:57 -03003142
Johan Hedberg7a828902011-04-28 11:28:53 -07003143 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
3144 if (!conn)
3145 goto unlock;
3146
3147 loc_mitm = (conn->auth_type & 0x01);
3148 rem_mitm = (conn->remote_auth & 0x01);
3149
3150 /* If we require MITM but the remote device can't provide that
3151 * (it has NoInputNoOutput) then reject the confirmation
3152 * request. The only exception is when we're dedicated bonding
3153 * initiators (connect_cfm_cb set) since then we always have the MITM
3154 * bit set. */
3155 if (!conn->connect_cfm_cb && loc_mitm && conn->remote_cap == 0x03) {
3156 BT_DBG("Rejecting request: remote device can't provide MITM");
3157 hci_send_cmd(hdev, HCI_OP_USER_CONFIRM_NEG_REPLY,
Gustavo Padovan807deac2012-05-17 00:36:24 -03003158 sizeof(ev->bdaddr), &ev->bdaddr);
Johan Hedberg7a828902011-04-28 11:28:53 -07003159 goto unlock;
3160 }
3161
3162 /* If no side requires MITM protection; auto-accept */
3163 if ((!loc_mitm || conn->remote_cap == 0x03) &&
Gustavo Padovan807deac2012-05-17 00:36:24 -03003164 (!rem_mitm || conn->io_capability == 0x03)) {
Johan Hedberg55bc1a32011-04-28 11:28:56 -07003165
3166 /* If we're not the initiators request authorization to
3167 * proceed from user space (mgmt_user_confirm with
3168 * confirm_hint set to 1). */
Johan Hedberg51a8efd2012-01-16 06:10:31 +02003169 if (!test_bit(HCI_CONN_AUTH_PEND, &conn->flags)) {
Johan Hedberg55bc1a32011-04-28 11:28:56 -07003170 BT_DBG("Confirming auto-accept as acceptor");
3171 confirm_hint = 1;
3172 goto confirm;
3173 }
3174
Johan Hedberg9f616562011-04-28 11:28:54 -07003175 BT_DBG("Auto-accept of user confirmation with %ums delay",
Gustavo Padovan807deac2012-05-17 00:36:24 -03003176 hdev->auto_accept_delay);
Johan Hedberg9f616562011-04-28 11:28:54 -07003177
3178 if (hdev->auto_accept_delay > 0) {
3179 int delay = msecs_to_jiffies(hdev->auto_accept_delay);
3180 mod_timer(&conn->auto_accept_timer, jiffies + delay);
3181 goto unlock;
3182 }
3183
Johan Hedberg7a828902011-04-28 11:28:53 -07003184 hci_send_cmd(hdev, HCI_OP_USER_CONFIRM_REPLY,
Gustavo Padovan807deac2012-05-17 00:36:24 -03003185 sizeof(ev->bdaddr), &ev->bdaddr);
Johan Hedberg7a828902011-04-28 11:28:53 -07003186 goto unlock;
3187 }
3188
Johan Hedberg55bc1a32011-04-28 11:28:56 -07003189confirm:
Johan Hedberg272d90d2012-02-09 15:26:12 +02003190 mgmt_user_confirm_request(hdev, &ev->bdaddr, ACL_LINK, 0, ev->passkey,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003191 confirm_hint);
Johan Hedberg7a828902011-04-28 11:28:53 -07003192
3193unlock:
Johan Hedberga5c29682011-02-19 12:05:57 -03003194 hci_dev_unlock(hdev);
3195}
3196
Gustavo Padovan6039aa72012-05-23 04:04:18 -03003197static void hci_user_passkey_request_evt(struct hci_dev *hdev,
3198 struct sk_buff *skb)
Brian Gix1143d452011-11-23 08:28:34 -08003199{
3200 struct hci_ev_user_passkey_req *ev = (void *) skb->data;
3201
3202 BT_DBG("%s", hdev->name);
3203
Johan Hedberga8b2d5c2012-01-08 23:11:15 +02003204 if (test_bit(HCI_MGMT, &hdev->dev_flags))
Johan Hedberg272d90d2012-02-09 15:26:12 +02003205 mgmt_user_passkey_request(hdev, &ev->bdaddr, ACL_LINK, 0);
Brian Gix1143d452011-11-23 08:28:34 -08003206}
3207
Johan Hedberg92a25252012-09-06 18:39:26 +03003208static void hci_user_passkey_notify_evt(struct hci_dev *hdev,
3209 struct sk_buff *skb)
3210{
3211 struct hci_ev_user_passkey_notify *ev = (void *) skb->data;
3212 struct hci_conn *conn;
3213
3214 BT_DBG("%s", hdev->name);
3215
3216 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
3217 if (!conn)
3218 return;
3219
3220 conn->passkey_notify = __le32_to_cpu(ev->passkey);
3221 conn->passkey_entered = 0;
3222
3223 if (test_bit(HCI_MGMT, &hdev->dev_flags))
3224 mgmt_user_passkey_notify(hdev, &conn->dst, conn->type,
3225 conn->dst_type, conn->passkey_notify,
3226 conn->passkey_entered);
3227}
3228
3229static void hci_keypress_notify_evt(struct hci_dev *hdev, struct sk_buff *skb)
3230{
3231 struct hci_ev_keypress_notify *ev = (void *) skb->data;
3232 struct hci_conn *conn;
3233
3234 BT_DBG("%s", hdev->name);
3235
3236 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
3237 if (!conn)
3238 return;
3239
3240 switch (ev->type) {
3241 case HCI_KEYPRESS_STARTED:
3242 conn->passkey_entered = 0;
3243 return;
3244
3245 case HCI_KEYPRESS_ENTERED:
3246 conn->passkey_entered++;
3247 break;
3248
3249 case HCI_KEYPRESS_ERASED:
3250 conn->passkey_entered--;
3251 break;
3252
3253 case HCI_KEYPRESS_CLEARED:
3254 conn->passkey_entered = 0;
3255 break;
3256
3257 case HCI_KEYPRESS_COMPLETED:
3258 return;
3259 }
3260
3261 if (test_bit(HCI_MGMT, &hdev->dev_flags))
3262 mgmt_user_passkey_notify(hdev, &conn->dst, conn->type,
3263 conn->dst_type, conn->passkey_notify,
3264 conn->passkey_entered);
3265}
3266
Gustavo Padovan6039aa72012-05-23 04:04:18 -03003267static void hci_simple_pair_complete_evt(struct hci_dev *hdev,
3268 struct sk_buff *skb)
Marcel Holtmann04936842008-07-14 20:13:48 +02003269{
3270 struct hci_ev_simple_pair_complete *ev = (void *) skb->data;
3271 struct hci_conn *conn;
3272
3273 BT_DBG("%s", hdev->name);
3274
3275 hci_dev_lock(hdev);
3276
3277 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
Johan Hedberg2a611692011-02-19 12:06:00 -03003278 if (!conn)
3279 goto unlock;
Marcel Holtmann04936842008-07-14 20:13:48 +02003280
Johan Hedberg2a611692011-02-19 12:06:00 -03003281 /* To avoid duplicate auth_failed events to user space we check
3282 * the HCI_CONN_AUTH_PEND flag which will be set if we
3283 * initiated the authentication. A traditional auth_complete
3284 * event gets always produced as initiator and is also mapped to
3285 * the mgmt_auth_failed event */
Mikel Astizfa1bd912012-08-09 09:52:29 +02003286 if (!test_bit(HCI_CONN_AUTH_PEND, &conn->flags) && ev->status)
Johan Hedbergbab73cb2012-02-09 16:07:29 +02003287 mgmt_auth_failed(hdev, &conn->dst, conn->type, conn->dst_type,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003288 ev->status);
Johan Hedberg2a611692011-02-19 12:06:00 -03003289
3290 hci_conn_put(conn);
3291
3292unlock:
Marcel Holtmann04936842008-07-14 20:13:48 +02003293 hci_dev_unlock(hdev);
3294}
3295
Gustavo Padovan6039aa72012-05-23 04:04:18 -03003296static void hci_remote_host_features_evt(struct hci_dev *hdev,
3297 struct sk_buff *skb)
Marcel Holtmann41a96212008-07-14 20:13:48 +02003298{
3299 struct hci_ev_remote_host_features *ev = (void *) skb->data;
3300 struct inquiry_entry *ie;
3301
3302 BT_DBG("%s", hdev->name);
3303
3304 hci_dev_lock(hdev);
3305
Andrei Emeltchenkocc11b9c2010-11-22 13:21:37 +02003306 ie = hci_inquiry_cache_lookup(hdev, &ev->bdaddr);
3307 if (ie)
Johan Hedberg02b7cc62012-02-28 02:28:43 +02003308 ie->data.ssp_mode = (ev->features[0] & LMP_HOST_SSP);
Marcel Holtmann41a96212008-07-14 20:13:48 +02003309
3310 hci_dev_unlock(hdev);
3311}
3312
Gustavo Padovan6039aa72012-05-23 04:04:18 -03003313static void hci_remote_oob_data_request_evt(struct hci_dev *hdev,
3314 struct sk_buff *skb)
Szymon Janc2763eda2011-03-22 13:12:22 +01003315{
3316 struct hci_ev_remote_oob_data_request *ev = (void *) skb->data;
3317 struct oob_data *data;
3318
3319 BT_DBG("%s", hdev->name);
3320
3321 hci_dev_lock(hdev);
3322
Johan Hedberga8b2d5c2012-01-08 23:11:15 +02003323 if (!test_bit(HCI_MGMT, &hdev->dev_flags))
Szymon Jance1ba1f12011-04-06 13:01:59 +02003324 goto unlock;
3325
Szymon Janc2763eda2011-03-22 13:12:22 +01003326 data = hci_find_remote_oob_data(hdev, &ev->bdaddr);
3327 if (data) {
3328 struct hci_cp_remote_oob_data_reply cp;
3329
3330 bacpy(&cp.bdaddr, &ev->bdaddr);
3331 memcpy(cp.hash, data->hash, sizeof(cp.hash));
3332 memcpy(cp.randomizer, data->randomizer, sizeof(cp.randomizer));
3333
3334 hci_send_cmd(hdev, HCI_OP_REMOTE_OOB_DATA_REPLY, sizeof(cp),
Gustavo Padovan807deac2012-05-17 00:36:24 -03003335 &cp);
Szymon Janc2763eda2011-03-22 13:12:22 +01003336 } else {
3337 struct hci_cp_remote_oob_data_neg_reply cp;
3338
3339 bacpy(&cp.bdaddr, &ev->bdaddr);
3340 hci_send_cmd(hdev, HCI_OP_REMOTE_OOB_DATA_NEG_REPLY, sizeof(cp),
Gustavo Padovan807deac2012-05-17 00:36:24 -03003341 &cp);
Szymon Janc2763eda2011-03-22 13:12:22 +01003342 }
3343
Szymon Jance1ba1f12011-04-06 13:01:59 +02003344unlock:
Szymon Janc2763eda2011-03-22 13:12:22 +01003345 hci_dev_unlock(hdev);
3346}
3347
Andrei Emeltchenkod5e91192012-10-25 15:20:44 +03003348static void hci_phy_link_complete_evt(struct hci_dev *hdev,
3349 struct sk_buff *skb)
3350{
3351 struct hci_ev_phy_link_complete *ev = (void *) skb->data;
3352 struct hci_conn *hcon, *bredr_hcon;
3353
3354 BT_DBG("%s handle 0x%2.2x status 0x%2.2x", hdev->name, ev->phy_handle,
3355 ev->status);
3356
3357 hci_dev_lock(hdev);
3358
3359 hcon = hci_conn_hash_lookup_handle(hdev, ev->phy_handle);
3360 if (!hcon) {
3361 hci_dev_unlock(hdev);
3362 return;
3363 }
3364
3365 if (ev->status) {
3366 hci_conn_del(hcon);
3367 hci_dev_unlock(hdev);
3368 return;
3369 }
3370
3371 bredr_hcon = hcon->amp_mgr->l2cap_conn->hcon;
3372
3373 hcon->state = BT_CONNECTED;
3374 bacpy(&hcon->dst, &bredr_hcon->dst);
3375
3376 hci_conn_hold(hcon);
3377 hcon->disc_timeout = HCI_DISCONN_TIMEOUT;
3378 hci_conn_put(hcon);
3379
3380 hci_conn_hold_device(hcon);
3381 hci_conn_add_sysfs(hcon);
3382
Andrei Emeltchenkocf70ff22012-10-31 15:46:36 +02003383 amp_physical_cfm(bredr_hcon, hcon);
3384
Andrei Emeltchenkod5e91192012-10-25 15:20:44 +03003385 hci_dev_unlock(hdev);
Andrei Emeltchenkod5e91192012-10-25 15:20:44 +03003386}
3387
Andrei Emeltchenko27695fb2012-10-25 15:20:45 +03003388static void hci_loglink_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
3389{
3390 struct hci_ev_logical_link_complete *ev = (void *) skb->data;
3391 struct hci_conn *hcon;
3392 struct hci_chan *hchan;
3393 struct amp_mgr *mgr;
3394
3395 BT_DBG("%s log_handle 0x%4.4x phy_handle 0x%2.2x status 0x%2.2x",
3396 hdev->name, le16_to_cpu(ev->handle), ev->phy_handle,
3397 ev->status);
3398
3399 hcon = hci_conn_hash_lookup_handle(hdev, ev->phy_handle);
3400 if (!hcon)
3401 return;
3402
3403 /* Create AMP hchan */
3404 hchan = hci_chan_create(hcon);
3405 if (!hchan)
3406 return;
3407
3408 hchan->handle = le16_to_cpu(ev->handle);
3409
3410 BT_DBG("hcon %p mgr %p hchan %p", hcon, hcon->amp_mgr, hchan);
3411
3412 mgr = hcon->amp_mgr;
3413 if (mgr && mgr->bredr_chan) {
3414 struct l2cap_chan *bredr_chan = mgr->bredr_chan;
3415
3416 l2cap_chan_lock(bredr_chan);
3417
3418 bredr_chan->conn->mtu = hdev->block_mtu;
3419 l2cap_logical_cfm(bredr_chan, hchan, 0);
3420 hci_conn_hold(hcon);
3421
3422 l2cap_chan_unlock(bredr_chan);
3423 }
3424}
3425
Andrei Emeltchenko606e2a12012-10-31 15:46:31 +02003426static void hci_disconn_loglink_complete_evt(struct hci_dev *hdev,
3427 struct sk_buff *skb)
3428{
3429 struct hci_ev_disconn_logical_link_complete *ev = (void *) skb->data;
3430 struct hci_chan *hchan;
3431
3432 BT_DBG("%s log handle 0x%4.4x status 0x%2.2x", hdev->name,
3433 le16_to_cpu(ev->handle), ev->status);
3434
3435 if (ev->status)
3436 return;
3437
3438 hci_dev_lock(hdev);
3439
3440 hchan = hci_chan_lookup_handle(hdev, le16_to_cpu(ev->handle));
3441 if (!hchan)
3442 goto unlock;
3443
3444 amp_destroy_logical_link(hchan, ev->reason);
3445
3446unlock:
3447 hci_dev_unlock(hdev);
3448}
3449
Andrei Emeltchenko9eef6b32012-10-31 15:46:32 +02003450static void hci_disconn_phylink_complete_evt(struct hci_dev *hdev,
3451 struct sk_buff *skb)
3452{
3453 struct hci_ev_disconn_phy_link_complete *ev = (void *) skb->data;
3454 struct hci_conn *hcon;
3455
3456 BT_DBG("%s status 0x%2.2x", hdev->name, ev->status);
3457
3458 if (ev->status)
3459 return;
3460
3461 hci_dev_lock(hdev);
3462
3463 hcon = hci_conn_hash_lookup_handle(hdev, ev->phy_handle);
3464 if (hcon) {
3465 hcon->state = BT_CLOSED;
3466 hci_conn_del(hcon);
3467 }
3468
3469 hci_dev_unlock(hdev);
3470}
3471
Gustavo Padovan6039aa72012-05-23 04:04:18 -03003472static void hci_le_conn_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
Ville Tervofcd89c02011-02-10 22:38:47 -03003473{
3474 struct hci_ev_le_conn_complete *ev = (void *) skb->data;
3475 struct hci_conn *conn;
3476
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +03003477 BT_DBG("%s status 0x%2.2x", hdev->name, ev->status);
Ville Tervofcd89c02011-02-10 22:38:47 -03003478
3479 hci_dev_lock(hdev);
3480
Andre Guedesb47a09b2012-07-27 15:10:15 -03003481 conn = hci_conn_hash_lookup_state(hdev, LE_LINK, BT_CONNECT);
Ville Tervob62f3282011-02-10 22:38:50 -03003482 if (!conn) {
3483 conn = hci_conn_add(hdev, LE_LINK, &ev->bdaddr);
3484 if (!conn) {
3485 BT_ERR("No memory for new connection");
Andre Guedes230fd162012-07-27 15:10:10 -03003486 goto unlock;
Ville Tervob62f3282011-02-10 22:38:50 -03003487 }
Andre Guedes29b79882011-05-31 14:20:54 -03003488
3489 conn->dst_type = ev->bdaddr_type;
Andre Guedesb9b343d2012-07-27 15:10:11 -03003490
3491 if (ev->role == LE_CONN_ROLE_MASTER) {
3492 conn->out = true;
3493 conn->link_mode |= HCI_LM_MASTER;
3494 }
Ville Tervob62f3282011-02-10 22:38:50 -03003495 }
Ville Tervofcd89c02011-02-10 22:38:47 -03003496
Andre Guedescd17dec2012-07-27 15:10:16 -03003497 if (ev->status) {
3498 mgmt_connect_failed(hdev, &conn->dst, conn->type,
3499 conn->dst_type, ev->status);
3500 hci_proto_connect_cfm(conn, ev->status);
3501 conn->state = BT_CLOSED;
3502 hci_conn_del(conn);
3503 goto unlock;
3504 }
3505
Johan Hedbergb644ba32012-01-17 21:48:47 +02003506 if (!test_and_set_bit(HCI_CONN_MGMT_CONNECTED, &conn->flags))
3507 mgmt_device_connected(hdev, &ev->bdaddr, conn->type,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003508 conn->dst_type, 0, NULL, 0, NULL);
Vinicius Costa Gomes83bc71b2011-05-06 18:41:43 -03003509
Vinicius Costa Gomes7b5c0d52011-06-09 18:50:50 -03003510 conn->sec_level = BT_SECURITY_LOW;
Ville Tervofcd89c02011-02-10 22:38:47 -03003511 conn->handle = __le16_to_cpu(ev->handle);
3512 conn->state = BT_CONNECTED;
3513
3514 hci_conn_hold_device(conn);
3515 hci_conn_add_sysfs(conn);
3516
3517 hci_proto_connect_cfm(conn, ev->status);
3518
3519unlock:
3520 hci_dev_unlock(hdev);
3521}
3522
Gustavo Padovan6039aa72012-05-23 04:04:18 -03003523static void hci_le_adv_report_evt(struct hci_dev *hdev, struct sk_buff *skb)
Andre Guedes9aa04c92011-05-26 16:23:51 -03003524{
Andre Guedese95beb42011-09-26 20:48:35 -03003525 u8 num_reports = skb->data[0];
3526 void *ptr = &skb->data[1];
Andre Guedes3c9e9192012-01-10 18:20:50 -03003527 s8 rssi;
Andre Guedes9aa04c92011-05-26 16:23:51 -03003528
Andre Guedese95beb42011-09-26 20:48:35 -03003529 while (num_reports--) {
3530 struct hci_ev_le_advertising_info *ev = ptr;
Andre Guedes9aa04c92011-05-26 16:23:51 -03003531
Andre Guedes3c9e9192012-01-10 18:20:50 -03003532 rssi = ev->data[ev->length];
3533 mgmt_device_found(hdev, &ev->bdaddr, LE_LINK, ev->bdaddr_type,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003534 NULL, rssi, 0, 1, ev->data, ev->length);
Andre Guedes3c9e9192012-01-10 18:20:50 -03003535
Andre Guedese95beb42011-09-26 20:48:35 -03003536 ptr += sizeof(*ev) + ev->length + 1;
Andre Guedes9aa04c92011-05-26 16:23:51 -03003537 }
Andre Guedes9aa04c92011-05-26 16:23:51 -03003538}
3539
Gustavo Padovan6039aa72012-05-23 04:04:18 -03003540static void hci_le_ltk_request_evt(struct hci_dev *hdev, struct sk_buff *skb)
Vinicius Costa Gomesa7a595f2011-06-09 18:50:47 -03003541{
3542 struct hci_ev_le_ltk_req *ev = (void *) skb->data;
3543 struct hci_cp_le_ltk_reply cp;
Vinicius Costa Gomesbea710f2011-07-07 18:59:37 -03003544 struct hci_cp_le_ltk_neg_reply neg;
Vinicius Costa Gomesa7a595f2011-06-09 18:50:47 -03003545 struct hci_conn *conn;
Vinicius Costa Gomesc9839a12012-02-02 21:08:01 -03003546 struct smp_ltk *ltk;
Vinicius Costa Gomesa7a595f2011-06-09 18:50:47 -03003547
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +03003548 BT_DBG("%s handle 0x%4.4x", hdev->name, __le16_to_cpu(ev->handle));
Vinicius Costa Gomesa7a595f2011-06-09 18:50:47 -03003549
3550 hci_dev_lock(hdev);
3551
3552 conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
Vinicius Costa Gomesbea710f2011-07-07 18:59:37 -03003553 if (conn == NULL)
3554 goto not_found;
Vinicius Costa Gomesa7a595f2011-06-09 18:50:47 -03003555
Vinicius Costa Gomesbea710f2011-07-07 18:59:37 -03003556 ltk = hci_find_ltk(hdev, ev->ediv, ev->random);
3557 if (ltk == NULL)
3558 goto not_found;
3559
3560 memcpy(cp.ltk, ltk->val, sizeof(ltk->val));
Vinicius Costa Gomesa7a595f2011-06-09 18:50:47 -03003561 cp.handle = cpu_to_le16(conn->handle);
Vinicius Costa Gomesc9839a12012-02-02 21:08:01 -03003562
3563 if (ltk->authenticated)
3564 conn->sec_level = BT_SECURITY_HIGH;
Vinicius Costa Gomesa7a595f2011-06-09 18:50:47 -03003565
3566 hci_send_cmd(hdev, HCI_OP_LE_LTK_REPLY, sizeof(cp), &cp);
3567
Vinicius Costa Gomesc9839a12012-02-02 21:08:01 -03003568 if (ltk->type & HCI_SMP_STK) {
3569 list_del(&ltk->list);
3570 kfree(ltk);
3571 }
3572
Vinicius Costa Gomesa7a595f2011-06-09 18:50:47 -03003573 hci_dev_unlock(hdev);
Vinicius Costa Gomesbea710f2011-07-07 18:59:37 -03003574
3575 return;
3576
3577not_found:
3578 neg.handle = ev->handle;
3579 hci_send_cmd(hdev, HCI_OP_LE_LTK_NEG_REPLY, sizeof(neg), &neg);
3580 hci_dev_unlock(hdev);
Vinicius Costa Gomesa7a595f2011-06-09 18:50:47 -03003581}
3582
Gustavo Padovan6039aa72012-05-23 04:04:18 -03003583static void hci_le_meta_evt(struct hci_dev *hdev, struct sk_buff *skb)
Ville Tervofcd89c02011-02-10 22:38:47 -03003584{
3585 struct hci_ev_le_meta *le_ev = (void *) skb->data;
3586
3587 skb_pull(skb, sizeof(*le_ev));
3588
3589 switch (le_ev->subevent) {
3590 case HCI_EV_LE_CONN_COMPLETE:
3591 hci_le_conn_complete_evt(hdev, skb);
3592 break;
3593
Andre Guedes9aa04c92011-05-26 16:23:51 -03003594 case HCI_EV_LE_ADVERTISING_REPORT:
3595 hci_le_adv_report_evt(hdev, skb);
3596 break;
3597
Vinicius Costa Gomesa7a595f2011-06-09 18:50:47 -03003598 case HCI_EV_LE_LTK_REQ:
3599 hci_le_ltk_request_evt(hdev, skb);
3600 break;
3601
Ville Tervofcd89c02011-02-10 22:38:47 -03003602 default:
3603 break;
3604 }
3605}
3606
Andrei Emeltchenko9495b2e2012-09-27 17:26:22 +03003607static void hci_chan_selected_evt(struct hci_dev *hdev, struct sk_buff *skb)
3608{
3609 struct hci_ev_channel_selected *ev = (void *) skb->data;
3610 struct hci_conn *hcon;
3611
3612 BT_DBG("%s handle 0x%2.2x", hdev->name, ev->phy_handle);
3613
3614 skb_pull(skb, sizeof(*ev));
3615
3616 hcon = hci_conn_hash_lookup_handle(hdev, ev->phy_handle);
3617 if (!hcon)
3618 return;
3619
3620 amp_read_loc_assoc_final_data(hdev, hcon);
3621}
3622
Linus Torvalds1da177e2005-04-16 15:20:36 -07003623void hci_event_packet(struct hci_dev *hdev, struct sk_buff *skb)
3624{
Marcel Holtmanna9de9242007-10-20 13:33:56 +02003625 struct hci_event_hdr *hdr = (void *) skb->data;
3626 __u8 event = hdr->evt;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003627
3628 skb_pull(skb, HCI_EVENT_HDR_SIZE);
3629
Marcel Holtmanna9de9242007-10-20 13:33:56 +02003630 switch (event) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003631 case HCI_EV_INQUIRY_COMPLETE:
3632 hci_inquiry_complete_evt(hdev, skb);
3633 break;
3634
3635 case HCI_EV_INQUIRY_RESULT:
3636 hci_inquiry_result_evt(hdev, skb);
3637 break;
3638
Marcel Holtmanna9de9242007-10-20 13:33:56 +02003639 case HCI_EV_CONN_COMPLETE:
3640 hci_conn_complete_evt(hdev, skb);
Marcel Holtmann21d9e302005-09-13 01:32:25 +02003641 break;
3642
Linus Torvalds1da177e2005-04-16 15:20:36 -07003643 case HCI_EV_CONN_REQUEST:
3644 hci_conn_request_evt(hdev, skb);
3645 break;
3646
Linus Torvalds1da177e2005-04-16 15:20:36 -07003647 case HCI_EV_DISCONN_COMPLETE:
3648 hci_disconn_complete_evt(hdev, skb);
3649 break;
3650
Linus Torvalds1da177e2005-04-16 15:20:36 -07003651 case HCI_EV_AUTH_COMPLETE:
3652 hci_auth_complete_evt(hdev, skb);
3653 break;
3654
Marcel Holtmanna9de9242007-10-20 13:33:56 +02003655 case HCI_EV_REMOTE_NAME:
3656 hci_remote_name_evt(hdev, skb);
3657 break;
3658
Linus Torvalds1da177e2005-04-16 15:20:36 -07003659 case HCI_EV_ENCRYPT_CHANGE:
3660 hci_encrypt_change_evt(hdev, skb);
3661 break;
3662
Marcel Holtmanna9de9242007-10-20 13:33:56 +02003663 case HCI_EV_CHANGE_LINK_KEY_COMPLETE:
3664 hci_change_link_key_complete_evt(hdev, skb);
3665 break;
3666
3667 case HCI_EV_REMOTE_FEATURES:
3668 hci_remote_features_evt(hdev, skb);
3669 break;
3670
Marcel Holtmanna9de9242007-10-20 13:33:56 +02003671 case HCI_EV_CMD_COMPLETE:
3672 hci_cmd_complete_evt(hdev, skb);
3673 break;
3674
3675 case HCI_EV_CMD_STATUS:
3676 hci_cmd_status_evt(hdev, skb);
3677 break;
3678
3679 case HCI_EV_ROLE_CHANGE:
3680 hci_role_change_evt(hdev, skb);
3681 break;
3682
3683 case HCI_EV_NUM_COMP_PKTS:
3684 hci_num_comp_pkts_evt(hdev, skb);
3685 break;
3686
3687 case HCI_EV_MODE_CHANGE:
3688 hci_mode_change_evt(hdev, skb);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003689 break;
3690
3691 case HCI_EV_PIN_CODE_REQ:
3692 hci_pin_code_request_evt(hdev, skb);
3693 break;
3694
3695 case HCI_EV_LINK_KEY_REQ:
3696 hci_link_key_request_evt(hdev, skb);
3697 break;
3698
3699 case HCI_EV_LINK_KEY_NOTIFY:
3700 hci_link_key_notify_evt(hdev, skb);
3701 break;
3702
3703 case HCI_EV_CLOCK_OFFSET:
3704 hci_clock_offset_evt(hdev, skb);
3705 break;
3706
Marcel Holtmanna8746412008-07-14 20:13:46 +02003707 case HCI_EV_PKT_TYPE_CHANGE:
3708 hci_pkt_type_change_evt(hdev, skb);
3709 break;
3710
Marcel Holtmann85a1e932005-08-09 20:28:02 -07003711 case HCI_EV_PSCAN_REP_MODE:
3712 hci_pscan_rep_mode_evt(hdev, skb);
3713 break;
3714
Marcel Holtmanna9de9242007-10-20 13:33:56 +02003715 case HCI_EV_INQUIRY_RESULT_WITH_RSSI:
3716 hci_inquiry_result_with_rssi_evt(hdev, skb);
3717 break;
3718
3719 case HCI_EV_REMOTE_EXT_FEATURES:
3720 hci_remote_ext_features_evt(hdev, skb);
3721 break;
3722
3723 case HCI_EV_SYNC_CONN_COMPLETE:
3724 hci_sync_conn_complete_evt(hdev, skb);
3725 break;
3726
Marcel Holtmanna9de9242007-10-20 13:33:56 +02003727 case HCI_EV_EXTENDED_INQUIRY_RESULT:
3728 hci_extended_inquiry_result_evt(hdev, skb);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003729 break;
3730
Johan Hedberg1c2e0042012-06-08 23:31:13 +08003731 case HCI_EV_KEY_REFRESH_COMPLETE:
3732 hci_key_refresh_complete_evt(hdev, skb);
3733 break;
3734
Marcel Holtmann04936842008-07-14 20:13:48 +02003735 case HCI_EV_IO_CAPA_REQUEST:
3736 hci_io_capa_request_evt(hdev, skb);
3737 break;
3738
Johan Hedberg03b555e2011-01-04 15:40:05 +02003739 case HCI_EV_IO_CAPA_REPLY:
3740 hci_io_capa_reply_evt(hdev, skb);
3741 break;
3742
Johan Hedberga5c29682011-02-19 12:05:57 -03003743 case HCI_EV_USER_CONFIRM_REQUEST:
3744 hci_user_confirm_request_evt(hdev, skb);
3745 break;
3746
Brian Gix1143d452011-11-23 08:28:34 -08003747 case HCI_EV_USER_PASSKEY_REQUEST:
3748 hci_user_passkey_request_evt(hdev, skb);
3749 break;
3750
Johan Hedberg92a25252012-09-06 18:39:26 +03003751 case HCI_EV_USER_PASSKEY_NOTIFY:
3752 hci_user_passkey_notify_evt(hdev, skb);
3753 break;
3754
3755 case HCI_EV_KEYPRESS_NOTIFY:
3756 hci_keypress_notify_evt(hdev, skb);
3757 break;
3758
Marcel Holtmann04936842008-07-14 20:13:48 +02003759 case HCI_EV_SIMPLE_PAIR_COMPLETE:
3760 hci_simple_pair_complete_evt(hdev, skb);
3761 break;
3762
Marcel Holtmann41a96212008-07-14 20:13:48 +02003763 case HCI_EV_REMOTE_HOST_FEATURES:
3764 hci_remote_host_features_evt(hdev, skb);
3765 break;
3766
Ville Tervofcd89c02011-02-10 22:38:47 -03003767 case HCI_EV_LE_META:
3768 hci_le_meta_evt(hdev, skb);
3769 break;
3770
Andrei Emeltchenko9495b2e2012-09-27 17:26:22 +03003771 case HCI_EV_CHANNEL_SELECTED:
3772 hci_chan_selected_evt(hdev, skb);
3773 break;
3774
Szymon Janc2763eda2011-03-22 13:12:22 +01003775 case HCI_EV_REMOTE_OOB_DATA_REQUEST:
3776 hci_remote_oob_data_request_evt(hdev, skb);
3777 break;
3778
Andrei Emeltchenkod5e91192012-10-25 15:20:44 +03003779 case HCI_EV_PHY_LINK_COMPLETE:
3780 hci_phy_link_complete_evt(hdev, skb);
3781 break;
3782
Andrei Emeltchenko27695fb2012-10-25 15:20:45 +03003783 case HCI_EV_LOGICAL_LINK_COMPLETE:
3784 hci_loglink_complete_evt(hdev, skb);
3785 break;
3786
Andrei Emeltchenko606e2a12012-10-31 15:46:31 +02003787 case HCI_EV_DISCONN_LOGICAL_LINK_COMPLETE:
3788 hci_disconn_loglink_complete_evt(hdev, skb);
3789 break;
3790
Andrei Emeltchenko9eef6b32012-10-31 15:46:32 +02003791 case HCI_EV_DISCONN_PHY_LINK_COMPLETE:
3792 hci_disconn_phylink_complete_evt(hdev, skb);
3793 break;
3794
Andrei Emeltchenko25e89e92012-01-04 12:41:58 +02003795 case HCI_EV_NUM_COMP_BLOCKS:
3796 hci_num_comp_blocks_evt(hdev, skb);
3797 break;
3798
Marcel Holtmanna9de9242007-10-20 13:33:56 +02003799 default:
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +03003800 BT_DBG("%s event 0x%2.2x", hdev->name, event);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003801 break;
3802 }
3803
3804 kfree_skb(skb);
3805 hdev->stat.evt_rx++;
3806}