blob: 477726a63512e0160fb550f7c83861266ad585b7 [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 Hedberg23bb5762010-12-21 23:01:27 +020056 hci_req_complete(hdev, HCI_OP_INQUIRY_CANCEL, 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);
186
Johan Hedberg23bb5762010-12-21 23:01:27 +0200187 hci_req_complete(hdev, HCI_OP_WRITE_DEF_LINK_POLICY, status);
Marcel Holtmanne4e8e372008-07-14 20:13:47 +0200188}
189
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200190static void hci_cc_reset(struct hci_dev *hdev, struct sk_buff *skb)
191{
192 __u8 status = *((__u8 *) skb->data);
193
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +0300194 BT_DBG("%s status 0x%2.2x", hdev->name, status);
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200195
Gustavo F. Padovan10572132011-03-16 15:36:29 -0300196 clear_bit(HCI_RESET, &hdev->flags);
197
Johan Hedberg23bb5762010-12-21 23:01:27 +0200198 hci_req_complete(hdev, HCI_OP_RESET, status);
Andre Guedesd23264a2011-11-25 20:53:38 -0300199
Johan Hedberga297e972012-02-21 17:55:47 +0200200 /* Reset all non-persistent flags */
Andre Guedesae854a72012-03-21 00:03:36 -0300201 hdev->dev_flags &= ~(BIT(HCI_LE_SCAN) | BIT(HCI_PENDING_CLASS) |
202 BIT(HCI_PERIODIC_INQ));
Andre Guedes69775ff2012-02-23 16:50:05 +0200203
204 hdev->discovery.state = DISCOVERY_STOPPED;
Johan Hedbergbbaf4442012-11-08 01:22:59 +0100205 hdev->inq_tx_power = HCI_TX_POWER_INVALID;
206 hdev->adv_tx_power = HCI_TX_POWER_INVALID;
Johan Hedberg3f0f5242012-11-08 01:23:00 +0100207
208 memset(hdev->adv_data, 0, sizeof(hdev->adv_data));
209 hdev->adv_data_len = 0;
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200210}
211
212static void hci_cc_write_local_name(struct hci_dev *hdev, struct sk_buff *skb)
213{
214 __u8 status = *((__u8 *) skb->data);
215 void *sent;
216
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +0300217 BT_DBG("%s status 0x%2.2x", hdev->name, status);
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200218
219 sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_LOCAL_NAME);
220 if (!sent)
221 return;
222
Johan Hedberg56e5cb82011-11-08 20:40:16 +0200223 hci_dev_lock(hdev);
224
Johan Hedbergf51d5b22012-02-22 18:17:32 +0200225 if (test_bit(HCI_MGMT, &hdev->dev_flags))
226 mgmt_set_local_name_complete(hdev, sent, status);
Johan Hedberg28cc7bd2012-02-22 21:06:55 +0200227 else if (!status)
228 memcpy(hdev->dev_name, sent, HCI_MAX_NAME_LENGTH);
Johan Hedbergf51d5b22012-02-22 18:17:32 +0200229
Johan Hedberg56e5cb82011-11-08 20:40:16 +0200230 hci_dev_unlock(hdev);
Johan Hedberg3159d382012-02-24 13:47:56 +0200231
Johan Hedberg3f0f5242012-11-08 01:23:00 +0100232 if (!status && !test_bit(HCI_INIT, &hdev->flags))
233 hci_update_ad(hdev);
234
Johan Hedberg3159d382012-02-24 13:47:56 +0200235 hci_req_complete(hdev, HCI_OP_WRITE_LOCAL_NAME, status);
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200236}
237
238static void hci_cc_read_local_name(struct hci_dev *hdev, struct sk_buff *skb)
239{
240 struct hci_rp_read_local_name *rp = (void *) skb->data;
241
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +0300242 BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200243
244 if (rp->status)
245 return;
246
Johan Hedbergdb99b5f2012-02-22 20:14:22 +0200247 if (test_bit(HCI_SETUP, &hdev->dev_flags))
248 memcpy(hdev->dev_name, rp->name, HCI_MAX_NAME_LENGTH);
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200249}
250
251static void hci_cc_write_auth_enable(struct hci_dev *hdev, struct sk_buff *skb)
252{
253 __u8 status = *((__u8 *) skb->data);
254 void *sent;
255
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +0300256 BT_DBG("%s status 0x%2.2x", hdev->name, status);
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200257
258 sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_AUTH_ENABLE);
259 if (!sent)
260 return;
261
262 if (!status) {
263 __u8 param = *((__u8 *) sent);
264
265 if (param == AUTH_ENABLED)
266 set_bit(HCI_AUTH, &hdev->flags);
267 else
268 clear_bit(HCI_AUTH, &hdev->flags);
269 }
270
Johan Hedberg33ef95e2012-02-16 23:56:27 +0200271 if (test_bit(HCI_MGMT, &hdev->dev_flags))
272 mgmt_auth_enable_complete(hdev, status);
273
Johan Hedberg23bb5762010-12-21 23:01:27 +0200274 hci_req_complete(hdev, HCI_OP_WRITE_AUTH_ENABLE, status);
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200275}
276
277static void hci_cc_write_encrypt_mode(struct hci_dev *hdev, struct sk_buff *skb)
278{
279 __u8 status = *((__u8 *) skb->data);
280 void *sent;
281
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +0300282 BT_DBG("%s status 0x%2.2x", hdev->name, status);
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200283
284 sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_ENCRYPT_MODE);
285 if (!sent)
286 return;
287
288 if (!status) {
289 __u8 param = *((__u8 *) sent);
290
291 if (param)
292 set_bit(HCI_ENCRYPT, &hdev->flags);
293 else
294 clear_bit(HCI_ENCRYPT, &hdev->flags);
295 }
296
Johan Hedberg23bb5762010-12-21 23:01:27 +0200297 hci_req_complete(hdev, HCI_OP_WRITE_ENCRYPT_MODE, status);
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200298}
299
300static void hci_cc_write_scan_enable(struct hci_dev *hdev, struct sk_buff *skb)
301{
Johan Hedberg36f7fc72011-11-04 00:17:45 +0200302 __u8 param, status = *((__u8 *) skb->data);
303 int old_pscan, old_iscan;
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200304 void *sent;
305
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +0300306 BT_DBG("%s status 0x%2.2x", hdev->name, status);
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200307
308 sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_SCAN_ENABLE);
309 if (!sent)
310 return;
311
Johan Hedberg36f7fc72011-11-04 00:17:45 +0200312 param = *((__u8 *) sent);
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200313
Johan Hedberg56e5cb82011-11-08 20:40:16 +0200314 hci_dev_lock(hdev);
315
Mikel Astizfa1bd912012-08-09 09:52:29 +0200316 if (status) {
Johan Hedberg744cf192011-11-08 20:40:14 +0200317 mgmt_write_scan_failed(hdev, param, status);
Johan Hedberg2d7cee52011-11-07 22:16:03 +0200318 hdev->discov_timeout = 0;
319 goto done;
320 }
321
Johan Hedberg36f7fc72011-11-04 00:17:45 +0200322 old_pscan = test_and_clear_bit(HCI_PSCAN, &hdev->flags);
323 old_iscan = test_and_clear_bit(HCI_ISCAN, &hdev->flags);
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200324
Johan Hedberg36f7fc72011-11-04 00:17:45 +0200325 if (param & SCAN_INQUIRY) {
326 set_bit(HCI_ISCAN, &hdev->flags);
327 if (!old_iscan)
Johan Hedberg744cf192011-11-08 20:40:14 +0200328 mgmt_discoverable(hdev, 1);
Johan Hedberg16ab91a2011-11-07 22:16:02 +0200329 if (hdev->discov_timeout > 0) {
330 int to = msecs_to_jiffies(hdev->discov_timeout * 1000);
331 queue_delayed_work(hdev->workqueue, &hdev->discov_off,
Gustavo Padovan807deac2012-05-17 00:36:24 -0300332 to);
Johan Hedberg16ab91a2011-11-07 22:16:02 +0200333 }
Johan Hedberg36f7fc72011-11-04 00:17:45 +0200334 } else if (old_iscan)
Johan Hedberg744cf192011-11-08 20:40:14 +0200335 mgmt_discoverable(hdev, 0);
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200336
Johan Hedberg36f7fc72011-11-04 00:17:45 +0200337 if (param & SCAN_PAGE) {
338 set_bit(HCI_PSCAN, &hdev->flags);
339 if (!old_pscan)
Johan Hedberg744cf192011-11-08 20:40:14 +0200340 mgmt_connectable(hdev, 1);
Johan Hedberg36f7fc72011-11-04 00:17:45 +0200341 } else if (old_pscan)
Johan Hedberg744cf192011-11-08 20:40:14 +0200342 mgmt_connectable(hdev, 0);
Johan Hedberg36f7fc72011-11-04 00:17:45 +0200343
344done:
Johan Hedberg56e5cb82011-11-08 20:40:16 +0200345 hci_dev_unlock(hdev);
Johan Hedberg23bb5762010-12-21 23:01:27 +0200346 hci_req_complete(hdev, HCI_OP_WRITE_SCAN_ENABLE, status);
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200347}
348
349static void hci_cc_read_class_of_dev(struct hci_dev *hdev, struct sk_buff *skb)
350{
351 struct hci_rp_read_class_of_dev *rp = (void *) skb->data;
352
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +0300353 BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200354
355 if (rp->status)
356 return;
357
358 memcpy(hdev->dev_class, rp->dev_class, 3);
359
360 BT_DBG("%s class 0x%.2x%.2x%.2x", hdev->name,
Gustavo Padovan807deac2012-05-17 00:36:24 -0300361 hdev->dev_class[2], hdev->dev_class[1], hdev->dev_class[0]);
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200362}
363
364static void hci_cc_write_class_of_dev(struct hci_dev *hdev, struct sk_buff *skb)
365{
366 __u8 status = *((__u8 *) skb->data);
367 void *sent;
368
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +0300369 BT_DBG("%s status 0x%2.2x", hdev->name, status);
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200370
371 sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_CLASS_OF_DEV);
372 if (!sent)
373 return;
374
Marcel Holtmann7f9a9032012-02-22 18:38:01 +0100375 hci_dev_lock(hdev);
376
377 if (status == 0)
378 memcpy(hdev->dev_class, sent, 3);
379
380 if (test_bit(HCI_MGMT, &hdev->dev_flags))
381 mgmt_set_class_of_dev_complete(hdev, sent, status);
382
383 hci_dev_unlock(hdev);
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200384}
385
386static void hci_cc_read_voice_setting(struct hci_dev *hdev, struct sk_buff *skb)
387{
388 struct hci_rp_read_voice_setting *rp = (void *) skb->data;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700389 __u16 setting;
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200390
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +0300391 BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200392
393 if (rp->status)
394 return;
395
396 setting = __le16_to_cpu(rp->voice_setting);
397
Marcel Holtmannf383f272008-07-14 20:13:47 +0200398 if (hdev->voice_setting == setting)
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200399 return;
400
401 hdev->voice_setting = setting;
402
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +0300403 BT_DBG("%s voice setting 0x%4.4x", hdev->name, setting);
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200404
Gustavo F. Padovan3c547112011-12-14 22:58:44 -0200405 if (hdev->notify)
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200406 hdev->notify(hdev, HCI_NOTIFY_VOICE_SETTING);
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200407}
408
Gustavo Padovan8fc9ced2012-05-23 04:04:21 -0300409static void hci_cc_write_voice_setting(struct hci_dev *hdev,
410 struct sk_buff *skb)
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200411{
412 __u8 status = *((__u8 *) skb->data);
Marcel Holtmannf383f272008-07-14 20:13:47 +0200413 __u16 setting;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700414 void *sent;
415
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +0300416 BT_DBG("%s status 0x%2.2x", hdev->name, status);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700417
Marcel Holtmannf383f272008-07-14 20:13:47 +0200418 if (status)
419 return;
420
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200421 sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_VOICE_SETTING);
422 if (!sent)
423 return;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700424
Marcel Holtmannf383f272008-07-14 20:13:47 +0200425 setting = get_unaligned_le16(sent);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700426
Marcel Holtmannf383f272008-07-14 20:13:47 +0200427 if (hdev->voice_setting == setting)
428 return;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700429
Marcel Holtmannf383f272008-07-14 20:13:47 +0200430 hdev->voice_setting = setting;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700431
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +0300432 BT_DBG("%s voice setting 0x%4.4x", hdev->name, setting);
Marcel Holtmannf383f272008-07-14 20:13:47 +0200433
Gustavo F. Padovan3c547112011-12-14 22:58:44 -0200434 if (hdev->notify)
Marcel Holtmannf383f272008-07-14 20:13:47 +0200435 hdev->notify(hdev, HCI_NOTIFY_VOICE_SETTING);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700436}
437
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200438static void hci_cc_host_buffer_size(struct hci_dev *hdev, struct sk_buff *skb)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700439{
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200440 __u8 status = *((__u8 *) skb->data);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700441
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +0300442 BT_DBG("%s status 0x%2.2x", hdev->name, status);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700443
Johan Hedberg23bb5762010-12-21 23:01:27 +0200444 hci_req_complete(hdev, HCI_OP_HOST_BUFFER_SIZE, status);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700445}
446
Marcel Holtmann333140b2008-07-14 20:13:48 +0200447static void hci_cc_write_ssp_mode(struct hci_dev *hdev, struct sk_buff *skb)
448{
449 __u8 status = *((__u8 *) skb->data);
Johan Hedberg5ed8eb22012-10-25 00:09:51 +0300450 struct hci_cp_write_ssp_mode *sent;
Marcel Holtmann333140b2008-07-14 20:13:48 +0200451
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +0300452 BT_DBG("%s status 0x%2.2x", hdev->name, status);
Marcel Holtmann333140b2008-07-14 20:13:48 +0200453
Marcel Holtmann333140b2008-07-14 20:13:48 +0200454 sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_SSP_MODE);
455 if (!sent)
456 return;
457
Johan Hedberg5ed8eb22012-10-25 00:09:51 +0300458 if (!status) {
459 if (sent->mode)
460 hdev->host_features[0] |= LMP_HOST_SSP;
461 else
462 hdev->host_features[0] &= ~LMP_HOST_SSP;
463 }
464
Johan Hedberged2c4ee2012-02-17 00:56:28 +0200465 if (test_bit(HCI_MGMT, &hdev->dev_flags))
Johan Hedberg5ed8eb22012-10-25 00:09:51 +0300466 mgmt_ssp_enable_complete(hdev, sent->mode, status);
Johan Hedbergc0ecddc2012-02-22 12:38:31 +0200467 else if (!status) {
Johan Hedberg5ed8eb22012-10-25 00:09:51 +0300468 if (sent->mode)
Johan Hedbergc0ecddc2012-02-22 12:38:31 +0200469 set_bit(HCI_SSP_ENABLED, &hdev->dev_flags);
470 else
471 clear_bit(HCI_SSP_ENABLED, &hdev->dev_flags);
472 }
Marcel Holtmann333140b2008-07-14 20:13:48 +0200473}
474
Johan Hedbergd5859e22011-01-25 01:19:58 +0200475static u8 hci_get_inquiry_mode(struct hci_dev *hdev)
476{
Johan Hedberg976eb202012-10-24 21:12:01 +0300477 if (lmp_ext_inq_capable(hdev))
Johan Hedbergd5859e22011-01-25 01:19:58 +0200478 return 2;
479
Johan Hedberg976eb202012-10-24 21:12:01 +0300480 if (lmp_inq_rssi_capable(hdev))
Johan Hedbergd5859e22011-01-25 01:19:58 +0200481 return 1;
482
483 if (hdev->manufacturer == 11 && hdev->hci_rev == 0x00 &&
Gustavo Padovan807deac2012-05-17 00:36:24 -0300484 hdev->lmp_subver == 0x0757)
Johan Hedbergd5859e22011-01-25 01:19:58 +0200485 return 1;
486
487 if (hdev->manufacturer == 15) {
488 if (hdev->hci_rev == 0x03 && hdev->lmp_subver == 0x6963)
489 return 1;
490 if (hdev->hci_rev == 0x09 && hdev->lmp_subver == 0x6963)
491 return 1;
492 if (hdev->hci_rev == 0x00 && hdev->lmp_subver == 0x6965)
493 return 1;
494 }
495
496 if (hdev->manufacturer == 31 && hdev->hci_rev == 0x2005 &&
Gustavo Padovan807deac2012-05-17 00:36:24 -0300497 hdev->lmp_subver == 0x1805)
Johan Hedbergd5859e22011-01-25 01:19:58 +0200498 return 1;
499
500 return 0;
501}
502
503static void hci_setup_inquiry_mode(struct hci_dev *hdev)
504{
505 u8 mode;
506
507 mode = hci_get_inquiry_mode(hdev);
508
509 hci_send_cmd(hdev, HCI_OP_WRITE_INQUIRY_MODE, 1, &mode);
510}
511
512static void hci_setup_event_mask(struct hci_dev *hdev)
513{
514 /* The second byte is 0xff instead of 0x9f (two reserved bits
515 * disabled) since a Broadcom 1.2 dongle doesn't respond to the
516 * command otherwise */
517 u8 events[8] = { 0xff, 0xff, 0xfb, 0xff, 0x00, 0x00, 0x00, 0x00 };
518
Ville Tervo6de6c182011-05-27 11:16:21 +0300519 /* CSR 1.1 dongles does not accept any bitfield so don't try to set
520 * any event mask for pre 1.2 devices */
Andrei Emeltchenko5a13b092011-12-01 14:33:28 +0200521 if (hdev->hci_ver < BLUETOOTH_VER_1_2)
Ville Tervo6de6c182011-05-27 11:16:21 +0300522 return;
523
Johan Hedberge1171e82012-10-19 20:57:45 +0300524 if (lmp_bredr_capable(hdev)) {
525 events[4] |= 0x01; /* Flow Specification Complete */
526 events[4] |= 0x02; /* Inquiry Result with RSSI */
527 events[4] |= 0x04; /* Read Remote Extended Features Complete */
528 events[5] |= 0x08; /* Synchronous Connection Complete */
529 events[5] |= 0x10; /* Synchronous Connection Changed */
530 }
Johan Hedbergd5859e22011-01-25 01:19:58 +0200531
Johan Hedberg976eb202012-10-24 21:12:01 +0300532 if (lmp_inq_rssi_capable(hdev))
Johan Hedberga24299e2012-04-26 09:47:46 +0300533 events[4] |= 0x02; /* Inquiry Result with RSSI */
Johan Hedbergd5859e22011-01-25 01:19:58 +0200534
Andre Guedes999dcd12012-07-24 15:03:52 -0300535 if (lmp_sniffsubr_capable(hdev))
Johan Hedbergd5859e22011-01-25 01:19:58 +0200536 events[5] |= 0x20; /* Sniff Subrating */
537
Johan Hedberg976eb202012-10-24 21:12:01 +0300538 if (lmp_pause_enc_capable(hdev))
Johan Hedbergd5859e22011-01-25 01:19:58 +0200539 events[5] |= 0x80; /* Encryption Key Refresh Complete */
540
Johan Hedberg976eb202012-10-24 21:12:01 +0300541 if (lmp_ext_inq_capable(hdev))
Johan Hedbergd5859e22011-01-25 01:19:58 +0200542 events[5] |= 0x40; /* Extended Inquiry Result */
543
Andre Guedesc58e8102012-07-24 15:03:53 -0300544 if (lmp_no_flush_capable(hdev))
Johan Hedbergd5859e22011-01-25 01:19:58 +0200545 events[7] |= 0x01; /* Enhanced Flush Complete */
546
Johan Hedberg976eb202012-10-24 21:12:01 +0300547 if (lmp_lsto_capable(hdev))
Johan Hedbergd5859e22011-01-25 01:19:58 +0200548 events[6] |= 0x80; /* Link Supervision Timeout Changed */
549
Andre Guedes9a1a1992012-07-24 15:03:48 -0300550 if (lmp_ssp_capable(hdev)) {
Johan Hedbergd5859e22011-01-25 01:19:58 +0200551 events[6] |= 0x01; /* IO Capability Request */
552 events[6] |= 0x02; /* IO Capability Response */
553 events[6] |= 0x04; /* User Confirmation Request */
554 events[6] |= 0x08; /* User Passkey Request */
555 events[6] |= 0x10; /* Remote OOB Data Request */
556 events[6] |= 0x20; /* Simple Pairing Complete */
557 events[7] |= 0x04; /* User Passkey Notification */
558 events[7] |= 0x08; /* Keypress Notification */
559 events[7] |= 0x10; /* Remote Host Supported
560 * Features Notification */
561 }
562
Andre Guedesc383ddc2012-07-24 15:03:47 -0300563 if (lmp_le_capable(hdev))
Johan Hedbergd5859e22011-01-25 01:19:58 +0200564 events[7] |= 0x20; /* LE Meta-Event */
565
566 hci_send_cmd(hdev, HCI_OP_SET_EVENT_MASK, sizeof(events), events);
Johan Hedberge36b04c2012-10-19 20:57:47 +0300567
568 if (lmp_le_capable(hdev)) {
569 memset(events, 0, sizeof(events));
570 events[0] = 0x1f;
571 hci_send_cmd(hdev, HCI_OP_LE_SET_EVENT_MASK,
572 sizeof(events), events);
573 }
Johan Hedbergd5859e22011-01-25 01:19:58 +0200574}
575
Gustavo Padovan4611dfa2012-10-24 11:18:41 -0200576static void bredr_setup(struct hci_dev *hdev)
Johan Hedberge1171e82012-10-19 20:57:45 +0300577{
578 struct hci_cp_delete_stored_link_key cp;
579 __le16 param;
580 __u8 flt_type;
581
582 /* Read Buffer Size (ACL mtu, max pkt, etc.) */
583 hci_send_cmd(hdev, HCI_OP_READ_BUFFER_SIZE, 0, NULL);
584
585 /* Read Class of Device */
586 hci_send_cmd(hdev, HCI_OP_READ_CLASS_OF_DEV, 0, NULL);
587
588 /* Read Local Name */
589 hci_send_cmd(hdev, HCI_OP_READ_LOCAL_NAME, 0, NULL);
590
591 /* Read Voice Setting */
592 hci_send_cmd(hdev, HCI_OP_READ_VOICE_SETTING, 0, NULL);
593
594 /* Clear Event Filters */
595 flt_type = HCI_FLT_CLEAR_ALL;
596 hci_send_cmd(hdev, HCI_OP_SET_EVENT_FLT, 1, &flt_type);
597
598 /* Connection accept timeout ~20 secs */
599 param = __constant_cpu_to_le16(0x7d00);
600 hci_send_cmd(hdev, HCI_OP_WRITE_CA_TIMEOUT, 2, &param);
601
602 bacpy(&cp.bdaddr, BDADDR_ANY);
603 cp.delete_all = 1;
604 hci_send_cmd(hdev, HCI_OP_DELETE_STORED_LINK_KEY, sizeof(cp), &cp);
605}
606
Gustavo Padovan4611dfa2012-10-24 11:18:41 -0200607static void le_setup(struct hci_dev *hdev)
Johan Hedberge1171e82012-10-19 20:57:45 +0300608{
609 /* Read LE Buffer Size */
610 hci_send_cmd(hdev, HCI_OP_LE_READ_BUFFER_SIZE, 0, NULL);
Johan Hedberg8fa19092012-10-19 20:57:49 +0300611
Johan Hedberg60e77322013-01-22 14:01:59 +0200612 /* Read LE Local Supported Features */
613 hci_send_cmd(hdev, HCI_OP_LE_READ_LOCAL_FEATURES, 0, NULL);
614
Johan Hedberg8fa19092012-10-19 20:57:49 +0300615 /* Read LE Advertising Channel TX Power */
616 hci_send_cmd(hdev, HCI_OP_LE_READ_ADV_TX_POWER, 0, NULL);
Johan Hedbergcf1d0812013-01-22 14:02:00 +0200617
618 /* Read LE White List Size */
619 hci_send_cmd(hdev, HCI_OP_LE_READ_WHITE_LIST_SIZE, 0, NULL);
Johan Hedberg9b008c02013-01-22 14:02:01 +0200620
621 /* Read LE Supported States */
622 hci_send_cmd(hdev, HCI_OP_LE_READ_SUPPORTED_STATES, 0, NULL);
Johan Hedberge1171e82012-10-19 20:57:45 +0300623}
624
Johan Hedbergd5859e22011-01-25 01:19:58 +0200625static void hci_setup(struct hci_dev *hdev)
626{
Andrei Emeltchenkoe61ef4992011-12-19 16:31:27 +0200627 if (hdev->dev_type != HCI_BREDR)
628 return;
629
Johan Hedberge1171e82012-10-19 20:57:45 +0300630 /* Read BD Address */
631 hci_send_cmd(hdev, HCI_OP_READ_BD_ADDR, 0, NULL);
632
633 if (lmp_bredr_capable(hdev))
Gustavo Padovan4611dfa2012-10-24 11:18:41 -0200634 bredr_setup(hdev);
Johan Hedberge1171e82012-10-19 20:57:45 +0300635
636 if (lmp_le_capable(hdev))
Gustavo Padovan4611dfa2012-10-24 11:18:41 -0200637 le_setup(hdev);
Johan Hedberge1171e82012-10-19 20:57:45 +0300638
Johan Hedbergd5859e22011-01-25 01:19:58 +0200639 hci_setup_event_mask(hdev);
640
Andrei Emeltchenkod095c1e2011-12-01 14:33:27 +0200641 if (hdev->hci_ver > BLUETOOTH_VER_1_1)
Johan Hedbergd5859e22011-01-25 01:19:58 +0200642 hci_send_cmd(hdev, HCI_OP_READ_LOCAL_COMMANDS, 0, NULL);
643
Gustavo Padovan6d3c7302012-05-24 03:36:37 -0300644 if (lmp_ssp_capable(hdev)) {
Johan Hedberg54d04db2012-02-22 15:47:48 +0200645 if (test_bit(HCI_SSP_ENABLED, &hdev->dev_flags)) {
646 u8 mode = 0x01;
647 hci_send_cmd(hdev, HCI_OP_WRITE_SSP_MODE,
Gustavo F. Padovan04124682012-03-08 01:25:00 -0300648 sizeof(mode), &mode);
Johan Hedberg54d04db2012-02-22 15:47:48 +0200649 } else {
650 struct hci_cp_write_eir cp;
651
652 memset(hdev->eir, 0, sizeof(hdev->eir));
653 memset(&cp, 0, sizeof(cp));
654
655 hci_send_cmd(hdev, HCI_OP_WRITE_EIR, sizeof(cp), &cp);
656 }
Johan Hedbergd5859e22011-01-25 01:19:58 +0200657 }
658
Johan Hedberg976eb202012-10-24 21:12:01 +0300659 if (lmp_inq_rssi_capable(hdev))
Johan Hedbergd5859e22011-01-25 01:19:58 +0200660 hci_setup_inquiry_mode(hdev);
661
Johan Hedberg976eb202012-10-24 21:12:01 +0300662 if (lmp_inq_tx_pwr_capable(hdev))
Johan Hedbergd5859e22011-01-25 01:19:58 +0200663 hci_send_cmd(hdev, HCI_OP_READ_INQ_RSP_TX_POWER, 0, NULL);
Andre Guedes971e3a42011-06-30 19:20:52 -0300664
Johan Hedberg976eb202012-10-24 21:12:01 +0300665 if (lmp_ext_feat_capable(hdev)) {
Andre Guedes971e3a42011-06-30 19:20:52 -0300666 struct hci_cp_read_local_ext_features cp;
667
668 cp.page = 0x01;
Gustavo F. Padovan04124682012-03-08 01:25:00 -0300669 hci_send_cmd(hdev, HCI_OP_READ_LOCAL_EXT_FEATURES, sizeof(cp),
670 &cp);
Andre Guedes971e3a42011-06-30 19:20:52 -0300671 }
Andre Guedese6100a22011-06-30 19:20:54 -0300672
Johan Hedberg47990ea2012-02-22 11:58:37 +0200673 if (test_bit(HCI_LINK_SECURITY, &hdev->dev_flags)) {
674 u8 enable = 1;
Gustavo F. Padovan04124682012-03-08 01:25:00 -0300675 hci_send_cmd(hdev, HCI_OP_WRITE_AUTH_ENABLE, sizeof(enable),
676 &enable);
Johan Hedberg47990ea2012-02-22 11:58:37 +0200677 }
Johan Hedbergd5859e22011-01-25 01:19:58 +0200678}
679
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200680static void hci_cc_read_local_version(struct hci_dev *hdev, struct sk_buff *skb)
681{
682 struct hci_rp_read_local_version *rp = (void *) skb->data;
683
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +0300684 BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200685
686 if (rp->status)
Andrei Emeltchenko28b8df72012-02-24 12:45:44 +0200687 goto done;
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200688
689 hdev->hci_ver = rp->hci_ver;
Marcel Holtmanne4e8e372008-07-14 20:13:47 +0200690 hdev->hci_rev = __le16_to_cpu(rp->hci_rev);
Johan Hedbergd5859e22011-01-25 01:19:58 +0200691 hdev->lmp_ver = rp->lmp_ver;
Marcel Holtmanne4e8e372008-07-14 20:13:47 +0200692 hdev->manufacturer = __le16_to_cpu(rp->manufacturer);
Johan Hedbergd5859e22011-01-25 01:19:58 +0200693 hdev->lmp_subver = __le16_to_cpu(rp->lmp_subver);
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200694
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +0300695 BT_DBG("%s manufacturer 0x%4.4x hci ver %d:%d", hdev->name,
Gustavo Padovan807deac2012-05-17 00:36:24 -0300696 hdev->manufacturer, hdev->hci_ver, hdev->hci_rev);
Johan Hedbergd5859e22011-01-25 01:19:58 +0200697
698 if (test_bit(HCI_INIT, &hdev->flags))
699 hci_setup(hdev);
Andrei Emeltchenko28b8df72012-02-24 12:45:44 +0200700
701done:
702 hci_req_complete(hdev, HCI_OP_READ_LOCAL_VERSION, rp->status);
Johan Hedbergd5859e22011-01-25 01:19:58 +0200703}
704
705static void hci_setup_link_policy(struct hci_dev *hdev)
706{
Andrei Emeltchenko035100c2012-03-12 15:59:32 +0200707 struct hci_cp_write_def_link_policy cp;
Johan Hedbergd5859e22011-01-25 01:19:58 +0200708 u16 link_policy = 0;
709
Andre Guedes9f92ebf2012-07-24 15:03:50 -0300710 if (lmp_rswitch_capable(hdev))
Johan Hedbergd5859e22011-01-25 01:19:58 +0200711 link_policy |= HCI_LP_RSWITCH;
Johan Hedberg976eb202012-10-24 21:12:01 +0300712 if (lmp_hold_capable(hdev))
Johan Hedbergd5859e22011-01-25 01:19:58 +0200713 link_policy |= HCI_LP_HOLD;
Andre Guedes6eded102012-07-24 15:03:51 -0300714 if (lmp_sniff_capable(hdev))
Johan Hedbergd5859e22011-01-25 01:19:58 +0200715 link_policy |= HCI_LP_SNIFF;
Johan Hedberg976eb202012-10-24 21:12:01 +0300716 if (lmp_park_capable(hdev))
Johan Hedbergd5859e22011-01-25 01:19:58 +0200717 link_policy |= HCI_LP_PARK;
718
Andrei Emeltchenko035100c2012-03-12 15:59:32 +0200719 cp.policy = cpu_to_le16(link_policy);
720 hci_send_cmd(hdev, HCI_OP_WRITE_DEF_LINK_POLICY, sizeof(cp), &cp);
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200721}
722
Gustavo Padovan8fc9ced2012-05-23 04:04:21 -0300723static void hci_cc_read_local_commands(struct hci_dev *hdev,
724 struct sk_buff *skb)
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200725{
726 struct hci_rp_read_local_commands *rp = (void *) skb->data;
727
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +0300728 BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200729
730 if (rp->status)
Johan Hedbergd5859e22011-01-25 01:19:58 +0200731 goto done;
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200732
733 memcpy(hdev->commands, rp->commands, sizeof(hdev->commands));
Johan Hedbergd5859e22011-01-25 01:19:58 +0200734
735 if (test_bit(HCI_INIT, &hdev->flags) && (hdev->commands[5] & 0x10))
736 hci_setup_link_policy(hdev);
737
738done:
739 hci_req_complete(hdev, HCI_OP_READ_LOCAL_COMMANDS, rp->status);
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200740}
741
Gustavo Padovan8fc9ced2012-05-23 04:04:21 -0300742static void hci_cc_read_local_features(struct hci_dev *hdev,
743 struct sk_buff *skb)
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200744{
745 struct hci_rp_read_local_features *rp = (void *) skb->data;
746
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +0300747 BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200748
749 if (rp->status)
750 return;
751
752 memcpy(hdev->features, rp->features, 8);
753
754 /* Adjust default settings according to features
755 * supported by device. */
756
757 if (hdev->features[0] & LMP_3SLOT)
758 hdev->pkt_type |= (HCI_DM3 | HCI_DH3);
759
760 if (hdev->features[0] & LMP_5SLOT)
761 hdev->pkt_type |= (HCI_DM5 | HCI_DH5);
762
763 if (hdev->features[1] & LMP_HV2) {
764 hdev->pkt_type |= (HCI_HV2);
765 hdev->esco_type |= (ESCO_HV2);
766 }
767
768 if (hdev->features[1] & LMP_HV3) {
769 hdev->pkt_type |= (HCI_HV3);
770 hdev->esco_type |= (ESCO_HV3);
771 }
772
Andre Guedes45db810f2012-07-24 15:03:49 -0300773 if (lmp_esco_capable(hdev))
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200774 hdev->esco_type |= (ESCO_EV3);
775
776 if (hdev->features[4] & LMP_EV4)
777 hdev->esco_type |= (ESCO_EV4);
778
779 if (hdev->features[4] & LMP_EV5)
780 hdev->esco_type |= (ESCO_EV5);
781
Marcel Holtmannefc76882009-02-06 09:13:37 +0100782 if (hdev->features[5] & LMP_EDR_ESCO_2M)
783 hdev->esco_type |= (ESCO_2EV3);
784
785 if (hdev->features[5] & LMP_EDR_ESCO_3M)
786 hdev->esco_type |= (ESCO_3EV3);
787
788 if (hdev->features[5] & LMP_EDR_3S_ESCO)
789 hdev->esco_type |= (ESCO_2EV5 | ESCO_3EV5);
790
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200791 BT_DBG("%s features 0x%.2x%.2x%.2x%.2x%.2x%.2x%.2x%.2x", hdev->name,
Gustavo Padovan807deac2012-05-17 00:36:24 -0300792 hdev->features[0], hdev->features[1],
793 hdev->features[2], hdev->features[3],
794 hdev->features[4], hdev->features[5],
795 hdev->features[6], hdev->features[7]);
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200796}
797
Johan Hedberg8f984df2012-02-28 01:07:22 +0200798static void hci_set_le_support(struct hci_dev *hdev)
799{
800 struct hci_cp_write_le_host_supported cp;
801
802 memset(&cp, 0, sizeof(cp));
803
Marcel Holtmann9d428202012-05-03 07:12:31 +0200804 if (test_bit(HCI_LE_ENABLED, &hdev->dev_flags)) {
Johan Hedberg8f984df2012-02-28 01:07:22 +0200805 cp.le = 1;
Gustavo Padovanffa88e02012-11-23 16:50:51 -0200806 cp.simul = lmp_le_br_capable(hdev);
Johan Hedberg8f984df2012-02-28 01:07:22 +0200807 }
808
Gustavo Padovanffa88e02012-11-23 16:50:51 -0200809 if (cp.le != lmp_host_le_capable(hdev))
Gustavo F. Padovan04124682012-03-08 01:25:00 -0300810 hci_send_cmd(hdev, HCI_OP_WRITE_LE_HOST_SUPPORTED, sizeof(cp),
811 &cp);
Johan Hedberg8f984df2012-02-28 01:07:22 +0200812}
813
Andre Guedes971e3a42011-06-30 19:20:52 -0300814static void hci_cc_read_local_ext_features(struct hci_dev *hdev,
Gustavo Padovan807deac2012-05-17 00:36:24 -0300815 struct sk_buff *skb)
Andre Guedes971e3a42011-06-30 19:20:52 -0300816{
817 struct hci_rp_read_local_ext_features *rp = (void *) skb->data;
818
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +0300819 BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
Andre Guedes971e3a42011-06-30 19:20:52 -0300820
821 if (rp->status)
Johan Hedberg8f984df2012-02-28 01:07:22 +0200822 goto done;
Andre Guedes971e3a42011-06-30 19:20:52 -0300823
Andre Guedesb5b32b62011-12-30 10:34:04 -0300824 switch (rp->page) {
825 case 0:
826 memcpy(hdev->features, rp->features, 8);
827 break;
828 case 1:
829 memcpy(hdev->host_features, rp->features, 8);
830 break;
831 }
Andre Guedes971e3a42011-06-30 19:20:52 -0300832
Andre Guedesc383ddc2012-07-24 15:03:47 -0300833 if (test_bit(HCI_INIT, &hdev->flags) && lmp_le_capable(hdev))
Johan Hedberg8f984df2012-02-28 01:07:22 +0200834 hci_set_le_support(hdev);
835
836done:
Andre Guedes971e3a42011-06-30 19:20:52 -0300837 hci_req_complete(hdev, HCI_OP_READ_LOCAL_EXT_FEATURES, rp->status);
838}
839
Andrei Emeltchenko1e89cff2011-11-24 14:52:02 +0200840static void hci_cc_read_flow_control_mode(struct hci_dev *hdev,
Gustavo Padovan807deac2012-05-17 00:36:24 -0300841 struct sk_buff *skb)
Andrei Emeltchenko1e89cff2011-11-24 14:52:02 +0200842{
843 struct hci_rp_read_flow_control_mode *rp = (void *) skb->data;
844
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +0300845 BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
Andrei Emeltchenko1e89cff2011-11-24 14:52:02 +0200846
847 if (rp->status)
848 return;
849
850 hdev->flow_ctl_mode = rp->mode;
851
852 hci_req_complete(hdev, HCI_OP_READ_FLOW_CONTROL_MODE, rp->status);
853}
854
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200855static void hci_cc_read_buffer_size(struct hci_dev *hdev, struct sk_buff *skb)
856{
857 struct hci_rp_read_buffer_size *rp = (void *) skb->data;
858
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +0300859 BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200860
861 if (rp->status)
862 return;
863
864 hdev->acl_mtu = __le16_to_cpu(rp->acl_mtu);
865 hdev->sco_mtu = rp->sco_mtu;
866 hdev->acl_pkts = __le16_to_cpu(rp->acl_max_pkt);
867 hdev->sco_pkts = __le16_to_cpu(rp->sco_max_pkt);
868
869 if (test_bit(HCI_QUIRK_FIXUP_BUFFER_SIZE, &hdev->quirks)) {
870 hdev->sco_mtu = 64;
871 hdev->sco_pkts = 8;
872 }
873
874 hdev->acl_cnt = hdev->acl_pkts;
875 hdev->sco_cnt = hdev->sco_pkts;
876
Gustavo Padovan807deac2012-05-17 00:36:24 -0300877 BT_DBG("%s acl mtu %d:%d sco mtu %d:%d", hdev->name, hdev->acl_mtu,
878 hdev->acl_pkts, hdev->sco_mtu, hdev->sco_pkts);
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200879}
880
881static void hci_cc_read_bd_addr(struct hci_dev *hdev, struct sk_buff *skb)
882{
883 struct hci_rp_read_bd_addr *rp = (void *) skb->data;
884
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +0300885 BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200886
887 if (!rp->status)
888 bacpy(&hdev->bdaddr, &rp->bdaddr);
889
Johan Hedberg23bb5762010-12-21 23:01:27 +0200890 hci_req_complete(hdev, HCI_OP_READ_BD_ADDR, rp->status);
891}
892
Andrei Emeltchenko350ee4c2011-12-07 15:56:51 +0200893static void hci_cc_read_data_block_size(struct hci_dev *hdev,
Gustavo Padovan807deac2012-05-17 00:36:24 -0300894 struct sk_buff *skb)
Andrei Emeltchenko350ee4c2011-12-07 15:56:51 +0200895{
896 struct hci_rp_read_data_block_size *rp = (void *) skb->data;
897
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +0300898 BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
Andrei Emeltchenko350ee4c2011-12-07 15:56:51 +0200899
900 if (rp->status)
901 return;
902
903 hdev->block_mtu = __le16_to_cpu(rp->max_acl_len);
904 hdev->block_len = __le16_to_cpu(rp->block_len);
905 hdev->num_blocks = __le16_to_cpu(rp->num_blocks);
906
907 hdev->block_cnt = hdev->num_blocks;
908
909 BT_DBG("%s blk mtu %d cnt %d len %d", hdev->name, hdev->block_mtu,
Gustavo Padovan807deac2012-05-17 00:36:24 -0300910 hdev->block_cnt, hdev->block_len);
Andrei Emeltchenko350ee4c2011-12-07 15:56:51 +0200911
912 hci_req_complete(hdev, HCI_OP_READ_DATA_BLOCK_SIZE, rp->status);
913}
914
Johan Hedberg23bb5762010-12-21 23:01:27 +0200915static void hci_cc_write_ca_timeout(struct hci_dev *hdev, struct sk_buff *skb)
916{
917 __u8 status = *((__u8 *) skb->data);
918
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +0300919 BT_DBG("%s status 0x%2.2x", hdev->name, status);
Johan Hedberg23bb5762010-12-21 23:01:27 +0200920
921 hci_req_complete(hdev, HCI_OP_WRITE_CA_TIMEOUT, status);
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200922}
923
Andrei Emeltchenko928abaa2011-10-12 10:53:57 +0300924static void hci_cc_read_local_amp_info(struct hci_dev *hdev,
Gustavo Padovan807deac2012-05-17 00:36:24 -0300925 struct sk_buff *skb)
Andrei Emeltchenko928abaa2011-10-12 10:53:57 +0300926{
927 struct hci_rp_read_local_amp_info *rp = (void *) skb->data;
928
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +0300929 BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
Andrei Emeltchenko928abaa2011-10-12 10:53:57 +0300930
931 if (rp->status)
Andrei Emeltchenko8e2a0d92012-09-27 17:26:08 +0300932 goto a2mp_rsp;
Andrei Emeltchenko928abaa2011-10-12 10:53:57 +0300933
934 hdev->amp_status = rp->amp_status;
935 hdev->amp_total_bw = __le32_to_cpu(rp->total_bw);
936 hdev->amp_max_bw = __le32_to_cpu(rp->max_bw);
937 hdev->amp_min_latency = __le32_to_cpu(rp->min_latency);
938 hdev->amp_max_pdu = __le32_to_cpu(rp->max_pdu);
939 hdev->amp_type = rp->amp_type;
940 hdev->amp_pal_cap = __le16_to_cpu(rp->pal_cap);
941 hdev->amp_assoc_size = __le16_to_cpu(rp->max_assoc_size);
942 hdev->amp_be_flush_to = __le32_to_cpu(rp->be_flush_to);
943 hdev->amp_max_flush_to = __le32_to_cpu(rp->max_flush_to);
944
945 hci_req_complete(hdev, HCI_OP_READ_LOCAL_AMP_INFO, rp->status);
Andrei Emeltchenko8e2a0d92012-09-27 17:26:08 +0300946
947a2mp_rsp:
948 a2mp_send_getinfo_rsp(hdev);
Andrei Emeltchenko928abaa2011-10-12 10:53:57 +0300949}
950
Andrei Emeltchenko903e4542012-09-27 17:26:09 +0300951static void hci_cc_read_local_amp_assoc(struct hci_dev *hdev,
952 struct sk_buff *skb)
953{
954 struct hci_rp_read_local_amp_assoc *rp = (void *) skb->data;
955 struct amp_assoc *assoc = &hdev->loc_assoc;
956 size_t rem_len, frag_len;
957
958 BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
959
960 if (rp->status)
961 goto a2mp_rsp;
962
963 frag_len = skb->len - sizeof(*rp);
964 rem_len = __le16_to_cpu(rp->rem_len);
965
966 if (rem_len > frag_len) {
Andrei Emeltchenko2e430be32012-09-28 14:44:23 +0300967 BT_DBG("frag_len %zu rem_len %zu", frag_len, rem_len);
Andrei Emeltchenko903e4542012-09-27 17:26:09 +0300968
969 memcpy(assoc->data + assoc->offset, rp->frag, frag_len);
970 assoc->offset += frag_len;
971
972 /* Read other fragments */
973 amp_read_loc_assoc_frag(hdev, rp->phy_handle);
974
975 return;
976 }
977
978 memcpy(assoc->data + assoc->offset, rp->frag, rem_len);
979 assoc->len = assoc->offset + rem_len;
980 assoc->offset = 0;
981
982a2mp_rsp:
983 /* Send A2MP Rsp when all fragments are received */
984 a2mp_send_getampassoc_rsp(hdev, rp->status);
Andrei Emeltchenko9495b2e2012-09-27 17:26:22 +0300985 a2mp_send_create_phy_link_req(hdev, rp->status);
Andrei Emeltchenko903e4542012-09-27 17:26:09 +0300986}
987
Johan Hedbergb0916ea2011-01-10 13:44:55 +0200988static void hci_cc_delete_stored_link_key(struct hci_dev *hdev,
Gustavo Padovan807deac2012-05-17 00:36:24 -0300989 struct sk_buff *skb)
Johan Hedbergb0916ea2011-01-10 13:44:55 +0200990{
991 __u8 status = *((__u8 *) skb->data);
992
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +0300993 BT_DBG("%s status 0x%2.2x", hdev->name, status);
Johan Hedbergb0916ea2011-01-10 13:44:55 +0200994
995 hci_req_complete(hdev, HCI_OP_DELETE_STORED_LINK_KEY, status);
996}
997
Johan Hedbergd5859e22011-01-25 01:19:58 +0200998static void hci_cc_set_event_mask(struct hci_dev *hdev, struct sk_buff *skb)
999{
1000 __u8 status = *((__u8 *) skb->data);
1001
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +03001002 BT_DBG("%s status 0x%2.2x", hdev->name, status);
Johan Hedbergd5859e22011-01-25 01:19:58 +02001003
1004 hci_req_complete(hdev, HCI_OP_SET_EVENT_MASK, status);
1005}
1006
1007static void hci_cc_write_inquiry_mode(struct hci_dev *hdev,
Gustavo Padovan807deac2012-05-17 00:36:24 -03001008 struct sk_buff *skb)
Johan Hedbergd5859e22011-01-25 01:19:58 +02001009{
1010 __u8 status = *((__u8 *) skb->data);
1011
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +03001012 BT_DBG("%s status 0x%2.2x", hdev->name, status);
Johan Hedbergd5859e22011-01-25 01:19:58 +02001013
1014 hci_req_complete(hdev, HCI_OP_WRITE_INQUIRY_MODE, status);
1015}
1016
1017static void hci_cc_read_inq_rsp_tx_power(struct hci_dev *hdev,
Gustavo Padovan807deac2012-05-17 00:36:24 -03001018 struct sk_buff *skb)
Johan Hedbergd5859e22011-01-25 01:19:58 +02001019{
Marcel Holtmann91c4e9b2012-03-11 19:27:21 -07001020 struct hci_rp_read_inq_rsp_tx_power *rp = (void *) skb->data;
Johan Hedbergd5859e22011-01-25 01:19:58 +02001021
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +03001022 BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
Johan Hedbergd5859e22011-01-25 01:19:58 +02001023
Marcel Holtmann91c4e9b2012-03-11 19:27:21 -07001024 if (!rp->status)
1025 hdev->inq_tx_power = rp->tx_power;
1026
1027 hci_req_complete(hdev, HCI_OP_READ_INQ_RSP_TX_POWER, rp->status);
Johan Hedbergd5859e22011-01-25 01:19:58 +02001028}
1029
1030static void hci_cc_set_event_flt(struct hci_dev *hdev, struct sk_buff *skb)
1031{
1032 __u8 status = *((__u8 *) skb->data);
1033
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +03001034 BT_DBG("%s status 0x%2.2x", hdev->name, status);
Johan Hedbergd5859e22011-01-25 01:19:58 +02001035
1036 hci_req_complete(hdev, HCI_OP_SET_EVENT_FLT, status);
1037}
1038
Johan Hedberg980e1a52011-01-22 06:10:07 +02001039static void hci_cc_pin_code_reply(struct hci_dev *hdev, struct sk_buff *skb)
1040{
1041 struct hci_rp_pin_code_reply *rp = (void *) skb->data;
1042 struct hci_cp_pin_code_reply *cp;
1043 struct hci_conn *conn;
1044
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +03001045 BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
Johan Hedberg980e1a52011-01-22 06:10:07 +02001046
Johan Hedberg56e5cb82011-11-08 20:40:16 +02001047 hci_dev_lock(hdev);
1048
Johan Hedberga8b2d5c2012-01-08 23:11:15 +02001049 if (test_bit(HCI_MGMT, &hdev->dev_flags))
Johan Hedberg744cf192011-11-08 20:40:14 +02001050 mgmt_pin_code_reply_complete(hdev, &rp->bdaddr, rp->status);
Johan Hedberg980e1a52011-01-22 06:10:07 +02001051
Mikel Astizfa1bd912012-08-09 09:52:29 +02001052 if (rp->status)
Johan Hedberg56e5cb82011-11-08 20:40:16 +02001053 goto unlock;
Johan Hedberg980e1a52011-01-22 06:10:07 +02001054
1055 cp = hci_sent_cmd_data(hdev, HCI_OP_PIN_CODE_REPLY);
1056 if (!cp)
Johan Hedberg56e5cb82011-11-08 20:40:16 +02001057 goto unlock;
Johan Hedberg980e1a52011-01-22 06:10:07 +02001058
1059 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &cp->bdaddr);
1060 if (conn)
1061 conn->pin_length = cp->pin_len;
Johan Hedberg56e5cb82011-11-08 20:40:16 +02001062
1063unlock:
1064 hci_dev_unlock(hdev);
Johan Hedberg980e1a52011-01-22 06:10:07 +02001065}
1066
1067static void hci_cc_pin_code_neg_reply(struct hci_dev *hdev, struct sk_buff *skb)
1068{
1069 struct hci_rp_pin_code_neg_reply *rp = (void *) skb->data;
1070
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +03001071 BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
Johan Hedberg980e1a52011-01-22 06:10:07 +02001072
Johan Hedberg56e5cb82011-11-08 20:40:16 +02001073 hci_dev_lock(hdev);
1074
Johan Hedberga8b2d5c2012-01-08 23:11:15 +02001075 if (test_bit(HCI_MGMT, &hdev->dev_flags))
Johan Hedberg744cf192011-11-08 20:40:14 +02001076 mgmt_pin_code_neg_reply_complete(hdev, &rp->bdaddr,
Gustavo Padovan807deac2012-05-17 00:36:24 -03001077 rp->status);
Johan Hedberg56e5cb82011-11-08 20:40:16 +02001078
1079 hci_dev_unlock(hdev);
Johan Hedberg980e1a52011-01-22 06:10:07 +02001080}
Johan Hedberg56e5cb82011-11-08 20:40:16 +02001081
Ville Tervo6ed58ec2011-02-10 22:38:48 -03001082static void hci_cc_le_read_buffer_size(struct hci_dev *hdev,
1083 struct sk_buff *skb)
1084{
1085 struct hci_rp_le_read_buffer_size *rp = (void *) skb->data;
1086
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +03001087 BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
Ville Tervo6ed58ec2011-02-10 22:38:48 -03001088
1089 if (rp->status)
1090 return;
1091
1092 hdev->le_mtu = __le16_to_cpu(rp->le_mtu);
1093 hdev->le_pkts = rp->le_max_pkt;
1094
1095 hdev->le_cnt = hdev->le_pkts;
1096
1097 BT_DBG("%s le mtu %d:%d", hdev->name, hdev->le_mtu, hdev->le_pkts);
1098
1099 hci_req_complete(hdev, HCI_OP_LE_READ_BUFFER_SIZE, rp->status);
1100}
Johan Hedberg980e1a52011-01-22 06:10:07 +02001101
Johan Hedberg60e77322013-01-22 14:01:59 +02001102static void hci_cc_le_read_local_features(struct hci_dev *hdev,
1103 struct sk_buff *skb)
1104{
1105 struct hci_rp_le_read_local_features *rp = (void *) skb->data;
1106
1107 BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
1108
1109 if (!rp->status)
1110 memcpy(hdev->le_features, rp->features, 8);
1111
1112 hci_req_complete(hdev, HCI_OP_LE_READ_LOCAL_FEATURES, rp->status);
1113}
1114
Johan Hedberg8fa19092012-10-19 20:57:49 +03001115static void hci_cc_le_read_adv_tx_power(struct hci_dev *hdev,
1116 struct sk_buff *skb)
1117{
1118 struct hci_rp_le_read_adv_tx_power *rp = (void *) skb->data;
1119
1120 BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
1121
Johan Hedberg3f0f5242012-11-08 01:23:00 +01001122 if (!rp->status) {
Johan Hedberg8fa19092012-10-19 20:57:49 +03001123 hdev->adv_tx_power = rp->tx_power;
Johan Hedberg3f0f5242012-11-08 01:23:00 +01001124 if (!test_bit(HCI_INIT, &hdev->flags))
1125 hci_update_ad(hdev);
1126 }
Johan Hedberg8fa19092012-10-19 20:57:49 +03001127
1128 hci_req_complete(hdev, HCI_OP_LE_READ_ADV_TX_POWER, rp->status);
1129}
1130
Johan Hedberge36b04c2012-10-19 20:57:47 +03001131static void hci_cc_le_set_event_mask(struct hci_dev *hdev, struct sk_buff *skb)
1132{
1133 __u8 status = *((__u8 *) skb->data);
1134
1135 BT_DBG("%s status 0x%2.2x", hdev->name, status);
1136
1137 hci_req_complete(hdev, HCI_OP_LE_SET_EVENT_MASK, status);
1138}
1139
Johan Hedberga5c29682011-02-19 12:05:57 -03001140static void hci_cc_user_confirm_reply(struct hci_dev *hdev, struct sk_buff *skb)
1141{
1142 struct hci_rp_user_confirm_reply *rp = (void *) skb->data;
1143
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +03001144 BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
Johan Hedberga5c29682011-02-19 12:05:57 -03001145
Johan Hedberg56e5cb82011-11-08 20:40:16 +02001146 hci_dev_lock(hdev);
1147
Johan Hedberga8b2d5c2012-01-08 23:11:15 +02001148 if (test_bit(HCI_MGMT, &hdev->dev_flags))
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001149 mgmt_user_confirm_reply_complete(hdev, &rp->bdaddr, ACL_LINK, 0,
1150 rp->status);
Johan Hedberg56e5cb82011-11-08 20:40:16 +02001151
1152 hci_dev_unlock(hdev);
Johan Hedberga5c29682011-02-19 12:05:57 -03001153}
1154
1155static void hci_cc_user_confirm_neg_reply(struct hci_dev *hdev,
Gustavo Padovan807deac2012-05-17 00:36:24 -03001156 struct sk_buff *skb)
Johan Hedberga5c29682011-02-19 12:05:57 -03001157{
1158 struct hci_rp_user_confirm_reply *rp = (void *) skb->data;
1159
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +03001160 BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
Johan Hedberga5c29682011-02-19 12:05:57 -03001161
Johan Hedberg56e5cb82011-11-08 20:40:16 +02001162 hci_dev_lock(hdev);
1163
Johan Hedberga8b2d5c2012-01-08 23:11:15 +02001164 if (test_bit(HCI_MGMT, &hdev->dev_flags))
Johan Hedberg744cf192011-11-08 20:40:14 +02001165 mgmt_user_confirm_neg_reply_complete(hdev, &rp->bdaddr,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001166 ACL_LINK, 0, rp->status);
Johan Hedberg56e5cb82011-11-08 20:40:16 +02001167
1168 hci_dev_unlock(hdev);
Johan Hedberga5c29682011-02-19 12:05:57 -03001169}
1170
Brian Gix1143d452011-11-23 08:28:34 -08001171static void hci_cc_user_passkey_reply(struct hci_dev *hdev, struct sk_buff *skb)
1172{
1173 struct hci_rp_user_confirm_reply *rp = (void *) skb->data;
1174
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +03001175 BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
Brian Gix1143d452011-11-23 08:28:34 -08001176
1177 hci_dev_lock(hdev);
1178
Johan Hedberga8b2d5c2012-01-08 23:11:15 +02001179 if (test_bit(HCI_MGMT, &hdev->dev_flags))
Johan Hedberg272d90d2012-02-09 15:26:12 +02001180 mgmt_user_passkey_reply_complete(hdev, &rp->bdaddr, ACL_LINK,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001181 0, rp->status);
Brian Gix1143d452011-11-23 08:28:34 -08001182
1183 hci_dev_unlock(hdev);
1184}
1185
1186static void hci_cc_user_passkey_neg_reply(struct hci_dev *hdev,
Gustavo Padovan807deac2012-05-17 00:36:24 -03001187 struct sk_buff *skb)
Brian Gix1143d452011-11-23 08:28:34 -08001188{
1189 struct hci_rp_user_confirm_reply *rp = (void *) skb->data;
1190
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +03001191 BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
Brian Gix1143d452011-11-23 08:28:34 -08001192
1193 hci_dev_lock(hdev);
1194
Johan Hedberga8b2d5c2012-01-08 23:11:15 +02001195 if (test_bit(HCI_MGMT, &hdev->dev_flags))
Brian Gix1143d452011-11-23 08:28:34 -08001196 mgmt_user_passkey_neg_reply_complete(hdev, &rp->bdaddr,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001197 ACL_LINK, 0, rp->status);
Brian Gix1143d452011-11-23 08:28:34 -08001198
1199 hci_dev_unlock(hdev);
1200}
1201
Szymon Jancc35938b2011-03-22 13:12:21 +01001202static void hci_cc_read_local_oob_data_reply(struct hci_dev *hdev,
Gustavo Padovan807deac2012-05-17 00:36:24 -03001203 struct sk_buff *skb)
Szymon Jancc35938b2011-03-22 13:12:21 +01001204{
1205 struct hci_rp_read_local_oob_data *rp = (void *) skb->data;
1206
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +03001207 BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
Szymon Jancc35938b2011-03-22 13:12:21 +01001208
Johan Hedberg56e5cb82011-11-08 20:40:16 +02001209 hci_dev_lock(hdev);
Johan Hedberg744cf192011-11-08 20:40:14 +02001210 mgmt_read_local_oob_data_reply_complete(hdev, rp->hash,
Szymon Jancc35938b2011-03-22 13:12:21 +01001211 rp->randomizer, rp->status);
Johan Hedberg56e5cb82011-11-08 20:40:16 +02001212 hci_dev_unlock(hdev);
Szymon Jancc35938b2011-03-22 13:12:21 +01001213}
1214
Johan Hedbergc1d5dc42012-11-08 01:23:01 +01001215static void hci_cc_le_set_adv_enable(struct hci_dev *hdev, struct sk_buff *skb)
1216{
1217 __u8 *sent, status = *((__u8 *) skb->data);
1218
1219 BT_DBG("%s status 0x%2.2x", hdev->name, status);
1220
1221 sent = hci_sent_cmd_data(hdev, HCI_OP_LE_SET_ADV_ENABLE);
1222 if (!sent)
1223 return;
1224
1225 hci_dev_lock(hdev);
1226
1227 if (!status) {
1228 if (*sent)
1229 set_bit(HCI_LE_PERIPHERAL, &hdev->dev_flags);
1230 else
1231 clear_bit(HCI_LE_PERIPHERAL, &hdev->dev_flags);
1232 }
1233
1234 hci_dev_unlock(hdev);
1235
1236 if (!test_bit(HCI_INIT, &hdev->flags))
1237 hci_update_ad(hdev);
1238
1239 hci_req_complete(hdev, HCI_OP_LE_SET_ADV_ENABLE, status);
1240}
1241
Andre Guedes07f7fa52011-12-02 21:13:31 +09001242static void hci_cc_le_set_scan_param(struct hci_dev *hdev, struct sk_buff *skb)
1243{
1244 __u8 status = *((__u8 *) skb->data);
1245
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +03001246 BT_DBG("%s status 0x%2.2x", hdev->name, status);
Andre Guedes7ba8b4b2012-02-03 17:47:59 -03001247
1248 hci_req_complete(hdev, HCI_OP_LE_SET_SCAN_PARAM, status);
Andre Guedes3fd24152012-02-03 17:48:01 -03001249
1250 if (status) {
1251 hci_dev_lock(hdev);
1252 mgmt_start_discovery_failed(hdev, status);
1253 hci_dev_unlock(hdev);
1254 return;
1255 }
Andre Guedes07f7fa52011-12-02 21:13:31 +09001256}
1257
Andre Guedeseb9d91f2011-05-26 16:23:52 -03001258static void hci_cc_le_set_scan_enable(struct hci_dev *hdev,
Gustavo Padovan807deac2012-05-17 00:36:24 -03001259 struct sk_buff *skb)
Andre Guedeseb9d91f2011-05-26 16:23:52 -03001260{
1261 struct hci_cp_le_set_scan_enable *cp;
1262 __u8 status = *((__u8 *) skb->data);
1263
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +03001264 BT_DBG("%s status 0x%2.2x", hdev->name, status);
Andre Guedeseb9d91f2011-05-26 16:23:52 -03001265
Andre Guedeseb9d91f2011-05-26 16:23:52 -03001266 cp = hci_sent_cmd_data(hdev, HCI_OP_LE_SET_SCAN_ENABLE);
1267 if (!cp)
1268 return;
1269
Andrei Emeltchenko68a8aea2011-12-19 16:14:18 +02001270 switch (cp->enable) {
1271 case LE_SCANNING_ENABLED:
Andre Guedes7ba8b4b2012-02-03 17:47:59 -03001272 hci_req_complete(hdev, HCI_OP_LE_SET_SCAN_ENABLE, status);
1273
Andre Guedes3fd24152012-02-03 17:48:01 -03001274 if (status) {
1275 hci_dev_lock(hdev);
1276 mgmt_start_discovery_failed(hdev, status);
1277 hci_dev_unlock(hdev);
Andre Guedes7ba8b4b2012-02-03 17:47:59 -03001278 return;
Andre Guedes3fd24152012-02-03 17:48:01 -03001279 }
Andre Guedes7ba8b4b2012-02-03 17:47:59 -03001280
Andre Guedesd23264a2011-11-25 20:53:38 -03001281 set_bit(HCI_LE_SCAN, &hdev->dev_flags);
1282
Andre Guedesa8f13c82011-09-09 18:56:24 -03001283 hci_dev_lock(hdev);
Andre Guedes343f9352012-02-17 20:39:37 -03001284 hci_discovery_set_state(hdev, DISCOVERY_FINDING);
Andre Guedesa8f13c82011-09-09 18:56:24 -03001285 hci_dev_unlock(hdev);
Andrei Emeltchenko68a8aea2011-12-19 16:14:18 +02001286 break;
1287
1288 case LE_SCANNING_DISABLED:
Andre Guedesc9ecc482012-03-15 16:52:08 -03001289 if (status) {
1290 hci_dev_lock(hdev);
1291 mgmt_stop_discovery_failed(hdev, status);
1292 hci_dev_unlock(hdev);
Andre Guedes7ba8b4b2012-02-03 17:47:59 -03001293 return;
Andre Guedesc9ecc482012-03-15 16:52:08 -03001294 }
Andre Guedes7ba8b4b2012-02-03 17:47:59 -03001295
Andre Guedesd23264a2011-11-25 20:53:38 -03001296 clear_bit(HCI_LE_SCAN, &hdev->dev_flags);
1297
Andre Guedesbc3dd332012-03-06 19:37:06 -03001298 if (hdev->discovery.type == DISCOV_TYPE_INTERLEAVED &&
1299 hdev->discovery.state == DISCOVERY_FINDING) {
Andre Guedes5e0452c2012-02-17 20:39:38 -03001300 mgmt_interleaved_discovery(hdev);
1301 } else {
1302 hci_dev_lock(hdev);
1303 hci_discovery_set_state(hdev, DISCOVERY_STOPPED);
1304 hci_dev_unlock(hdev);
1305 }
1306
Andrei Emeltchenko68a8aea2011-12-19 16:14:18 +02001307 break;
1308
1309 default:
1310 BT_ERR("Used reserved LE_Scan_Enable param %d", cp->enable);
1311 break;
Andre Guedes35815082011-05-26 16:23:53 -03001312 }
Andre Guedeseb9d91f2011-05-26 16:23:52 -03001313}
1314
Johan Hedbergcf1d0812013-01-22 14:02:00 +02001315static void hci_cc_le_read_white_list_size(struct hci_dev *hdev,
1316 struct sk_buff *skb)
1317{
1318 struct hci_rp_le_read_white_list_size *rp = (void *) skb->data;
1319
1320 BT_DBG("%s status 0x%2.2x size %u", hdev->name, rp->status, rp->size);
1321
1322 if (!rp->status)
1323 hdev->le_white_list_size = rp->size;
1324
1325 hci_req_complete(hdev, HCI_OP_LE_READ_WHITE_LIST_SIZE, rp->status);
1326}
1327
Vinicius Costa Gomesa7a595f2011-06-09 18:50:47 -03001328static void hci_cc_le_ltk_reply(struct hci_dev *hdev, struct sk_buff *skb)
1329{
1330 struct hci_rp_le_ltk_reply *rp = (void *) skb->data;
1331
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +03001332 BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
Vinicius Costa Gomesa7a595f2011-06-09 18:50:47 -03001333
1334 if (rp->status)
1335 return;
1336
1337 hci_req_complete(hdev, HCI_OP_LE_LTK_REPLY, rp->status);
1338}
1339
1340static void hci_cc_le_ltk_neg_reply(struct hci_dev *hdev, struct sk_buff *skb)
1341{
1342 struct hci_rp_le_ltk_neg_reply *rp = (void *) skb->data;
1343
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +03001344 BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
Vinicius Costa Gomesa7a595f2011-06-09 18:50:47 -03001345
1346 if (rp->status)
1347 return;
1348
1349 hci_req_complete(hdev, HCI_OP_LE_LTK_NEG_REPLY, rp->status);
1350}
1351
Johan Hedberg9b008c02013-01-22 14:02:01 +02001352static void hci_cc_le_read_supported_states(struct hci_dev *hdev,
1353 struct sk_buff *skb)
1354{
1355 struct hci_rp_le_read_supported_states *rp = (void *) skb->data;
1356
1357 BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
1358
1359 if (!rp->status)
1360 memcpy(hdev->le_states, rp->le_states, 8);
1361
1362 hci_req_complete(hdev, HCI_OP_LE_READ_SUPPORTED_STATES, rp->status);
1363}
1364
Gustavo Padovan6039aa732012-05-23 04:04:18 -03001365static void hci_cc_write_le_host_supported(struct hci_dev *hdev,
1366 struct sk_buff *skb)
Andre Guedesf9b49302011-06-30 19:20:53 -03001367{
Johan Hedberg06199cf2012-02-22 16:37:11 +02001368 struct hci_cp_write_le_host_supported *sent;
Andre Guedesf9b49302011-06-30 19:20:53 -03001369 __u8 status = *((__u8 *) skb->data);
1370
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +03001371 BT_DBG("%s status 0x%2.2x", hdev->name, status);
Andre Guedesf9b49302011-06-30 19:20:53 -03001372
Johan Hedberg06199cf2012-02-22 16:37:11 +02001373 sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_LE_HOST_SUPPORTED);
Johan Hedberg8f984df2012-02-28 01:07:22 +02001374 if (!sent)
Andre Guedesf9b49302011-06-30 19:20:53 -03001375 return;
1376
Johan Hedberg8f984df2012-02-28 01:07:22 +02001377 if (!status) {
1378 if (sent->le)
1379 hdev->host_features[0] |= LMP_HOST_LE;
1380 else
1381 hdev->host_features[0] &= ~LMP_HOST_LE;
Johan Hedberg53b2caa2012-10-24 21:11:59 +03001382
1383 if (sent->simul)
1384 hdev->host_features[0] |= LMP_HOST_LE_BREDR;
1385 else
1386 hdev->host_features[0] &= ~LMP_HOST_LE_BREDR;
Johan Hedberg8f984df2012-02-28 01:07:22 +02001387 }
1388
1389 if (test_bit(HCI_MGMT, &hdev->dev_flags) &&
Gustavo Padovan807deac2012-05-17 00:36:24 -03001390 !test_bit(HCI_INIT, &hdev->flags))
Johan Hedberg8f984df2012-02-28 01:07:22 +02001391 mgmt_le_enable_complete(hdev, sent->le, status);
1392
1393 hci_req_complete(hdev, HCI_OP_WRITE_LE_HOST_SUPPORTED, status);
Andre Guedesf9b49302011-06-30 19:20:53 -03001394}
1395
Andrei Emeltchenko93c284e2012-09-27 17:26:20 +03001396static void hci_cc_write_remote_amp_assoc(struct hci_dev *hdev,
1397 struct sk_buff *skb)
1398{
1399 struct hci_rp_write_remote_amp_assoc *rp = (void *) skb->data;
1400
1401 BT_DBG("%s status 0x%2.2x phy_handle 0x%2.2x",
1402 hdev->name, rp->status, rp->phy_handle);
1403
1404 if (rp->status)
1405 return;
1406
1407 amp_write_rem_assoc_continue(hdev, rp->phy_handle);
1408}
1409
Gustavo Padovan6039aa732012-05-23 04:04:18 -03001410static void hci_cs_inquiry(struct hci_dev *hdev, __u8 status)
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001411{
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +03001412 BT_DBG("%s status 0x%2.2x", hdev->name, status);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001413
1414 if (status) {
Johan Hedberg23bb5762010-12-21 23:01:27 +02001415 hci_req_complete(hdev, HCI_OP_INQUIRY, status);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001416 hci_conn_check_pending(hdev);
Johan Hedberg56e5cb82011-11-08 20:40:16 +02001417 hci_dev_lock(hdev);
Johan Hedberga8b2d5c2012-01-08 23:11:15 +02001418 if (test_bit(HCI_MGMT, &hdev->dev_flags))
Andre Guedes7a135102011-11-09 17:14:25 -03001419 mgmt_start_discovery_failed(hdev, status);
Johan Hedberg56e5cb82011-11-08 20:40:16 +02001420 hci_dev_unlock(hdev);
Johan Hedberg314b2382011-04-27 10:29:57 -04001421 return;
1422 }
1423
Andre Guedes89352e72011-11-04 14:16:53 -03001424 set_bit(HCI_INQUIRY, &hdev->flags);
1425
Johan Hedberg56e5cb82011-11-08 20:40:16 +02001426 hci_dev_lock(hdev);
Andre Guedes343f9352012-02-17 20:39:37 -03001427 hci_discovery_set_state(hdev, DISCOVERY_FINDING);
Johan Hedberg56e5cb82011-11-08 20:40:16 +02001428 hci_dev_unlock(hdev);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001429}
1430
Gustavo Padovan6039aa732012-05-23 04:04:18 -03001431static void hci_cs_create_conn(struct hci_dev *hdev, __u8 status)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001432{
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001433 struct hci_cp_create_conn *cp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001434 struct hci_conn *conn;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001435
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +03001436 BT_DBG("%s status 0x%2.2x", hdev->name, status);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001437
1438 cp = hci_sent_cmd_data(hdev, HCI_OP_CREATE_CONN);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001439 if (!cp)
1440 return;
1441
1442 hci_dev_lock(hdev);
1443
1444 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &cp->bdaddr);
1445
Andrei Emeltchenko6ed93dc2012-09-25 12:49:43 +03001446 BT_DBG("%s bdaddr %pMR hcon %p", hdev->name, &cp->bdaddr, conn);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001447
1448 if (status) {
1449 if (conn && conn->state == BT_CONNECT) {
Marcel Holtmann4c67bc72006-10-15 17:30:56 +02001450 if (status != 0x0c || conn->attempt > 2) {
1451 conn->state = BT_CLOSED;
1452 hci_proto_connect_cfm(conn, status);
1453 hci_conn_del(conn);
1454 } else
1455 conn->state = BT_CONNECT2;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001456 }
1457 } else {
1458 if (!conn) {
1459 conn = hci_conn_add(hdev, ACL_LINK, &cp->bdaddr);
1460 if (conn) {
Johan Hedberga0c808b2012-01-16 09:49:58 +02001461 conn->out = true;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001462 conn->link_mode |= HCI_LM_MASTER;
1463 } else
Gustavo F. Padovan893ef972010-07-18 15:13:37 -03001464 BT_ERR("No memory for new connection");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001465 }
1466 }
1467
1468 hci_dev_unlock(hdev);
1469}
1470
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001471static void hci_cs_add_sco(struct hci_dev *hdev, __u8 status)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001472{
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001473 struct hci_cp_add_sco *cp;
1474 struct hci_conn *acl, *sco;
1475 __u16 handle;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001476
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +03001477 BT_DBG("%s status 0x%2.2x", hdev->name, status);
Marcel Holtmannb6a0dc82007-10-20 14:55:10 +02001478
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001479 if (!status)
1480 return;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001481
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001482 cp = hci_sent_cmd_data(hdev, HCI_OP_ADD_SCO);
1483 if (!cp)
1484 return;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001485
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001486 handle = __le16_to_cpu(cp->handle);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001487
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +03001488 BT_DBG("%s handle 0x%4.4x", hdev->name, handle);
Marcel Holtmann6bd57412006-11-18 22:14:22 +01001489
1490 hci_dev_lock(hdev);
1491
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001492 acl = hci_conn_hash_lookup_handle(hdev, handle);
Andrei Emeltchenko5a08ecc2011-01-11 17:20:20 +02001493 if (acl) {
1494 sco = acl->link;
1495 if (sco) {
1496 sco->state = BT_CLOSED;
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001497
Andrei Emeltchenko5a08ecc2011-01-11 17:20:20 +02001498 hci_proto_connect_cfm(sco, status);
1499 hci_conn_del(sco);
1500 }
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001501 }
Marcel Holtmann6bd57412006-11-18 22:14:22 +01001502
1503 hci_dev_unlock(hdev);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001504}
1505
Marcel Holtmannf8558552008-07-14 20:13:49 +02001506static void hci_cs_auth_requested(struct hci_dev *hdev, __u8 status)
1507{
1508 struct hci_cp_auth_requested *cp;
1509 struct hci_conn *conn;
1510
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +03001511 BT_DBG("%s status 0x%2.2x", hdev->name, status);
Marcel Holtmannf8558552008-07-14 20:13:49 +02001512
1513 if (!status)
1514 return;
1515
1516 cp = hci_sent_cmd_data(hdev, HCI_OP_AUTH_REQUESTED);
1517 if (!cp)
1518 return;
1519
1520 hci_dev_lock(hdev);
1521
1522 conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(cp->handle));
1523 if (conn) {
1524 if (conn->state == BT_CONFIG) {
1525 hci_proto_connect_cfm(conn, status);
1526 hci_conn_put(conn);
1527 }
1528 }
1529
1530 hci_dev_unlock(hdev);
1531}
1532
1533static void hci_cs_set_conn_encrypt(struct hci_dev *hdev, __u8 status)
1534{
1535 struct hci_cp_set_conn_encrypt *cp;
1536 struct hci_conn *conn;
1537
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +03001538 BT_DBG("%s status 0x%2.2x", hdev->name, status);
Marcel Holtmannf8558552008-07-14 20:13:49 +02001539
1540 if (!status)
1541 return;
1542
1543 cp = hci_sent_cmd_data(hdev, HCI_OP_SET_CONN_ENCRYPT);
1544 if (!cp)
1545 return;
1546
1547 hci_dev_lock(hdev);
1548
1549 conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(cp->handle));
1550 if (conn) {
1551 if (conn->state == BT_CONFIG) {
1552 hci_proto_connect_cfm(conn, status);
1553 hci_conn_put(conn);
1554 }
1555 }
1556
1557 hci_dev_unlock(hdev);
1558}
1559
Johan Hedberg127178d2010-11-18 22:22:29 +02001560static int hci_outgoing_auth_needed(struct hci_dev *hdev,
Gustavo Padovan807deac2012-05-17 00:36:24 -03001561 struct hci_conn *conn)
Johan Hedberg392599b2010-11-18 22:22:28 +02001562{
Johan Hedberg392599b2010-11-18 22:22:28 +02001563 if (conn->state != BT_CONFIG || !conn->out)
1564 return 0;
1565
Johan Hedberg765c2a92011-01-19 12:06:52 +05301566 if (conn->pending_sec_level == BT_SECURITY_SDP)
Johan Hedberg392599b2010-11-18 22:22:28 +02001567 return 0;
1568
1569 /* Only request authentication for SSP connections or non-SSP
Vinicius Costa Gomese9bf2bf2011-09-02 14:51:20 -03001570 * devices with sec_level HIGH or if MITM protection is requested */
Gustavo Padovan807deac2012-05-17 00:36:24 -03001571 if (!hci_conn_ssp_enabled(conn) && !(conn->auth_type & 0x01) &&
1572 conn->pending_sec_level != BT_SECURITY_HIGH)
Johan Hedberg392599b2010-11-18 22:22:28 +02001573 return 0;
1574
Johan Hedberg392599b2010-11-18 22:22:28 +02001575 return 1;
1576}
1577
Gustavo Padovan6039aa732012-05-23 04:04:18 -03001578static int hci_resolve_name(struct hci_dev *hdev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001579 struct inquiry_entry *e)
Johan Hedberg30dc78e2012-01-04 15:44:20 +02001580{
1581 struct hci_cp_remote_name_req cp;
1582
1583 memset(&cp, 0, sizeof(cp));
1584
1585 bacpy(&cp.bdaddr, &e->data.bdaddr);
1586 cp.pscan_rep_mode = e->data.pscan_rep_mode;
1587 cp.pscan_mode = e->data.pscan_mode;
1588 cp.clock_offset = e->data.clock_offset;
1589
1590 return hci_send_cmd(hdev, HCI_OP_REMOTE_NAME_REQ, sizeof(cp), &cp);
1591}
1592
Johan Hedbergb644ba32012-01-17 21:48:47 +02001593static bool hci_resolve_next_name(struct hci_dev *hdev)
Johan Hedberg30dc78e2012-01-04 15:44:20 +02001594{
1595 struct discovery_state *discov = &hdev->discovery;
1596 struct inquiry_entry *e;
1597
Johan Hedbergb644ba32012-01-17 21:48:47 +02001598 if (list_empty(&discov->resolve))
1599 return false;
1600
1601 e = hci_inquiry_cache_lookup_resolve(hdev, BDADDR_ANY, NAME_NEEDED);
Ram Malovanyc8100892012-07-19 10:26:09 +03001602 if (!e)
1603 return false;
1604
Johan Hedbergb644ba32012-01-17 21:48:47 +02001605 if (hci_resolve_name(hdev, e) == 0) {
1606 e->name_state = NAME_PENDING;
1607 return true;
1608 }
1609
1610 return false;
1611}
1612
1613static void hci_check_pending_name(struct hci_dev *hdev, struct hci_conn *conn,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001614 bdaddr_t *bdaddr, u8 *name, u8 name_len)
Johan Hedbergb644ba32012-01-17 21:48:47 +02001615{
1616 struct discovery_state *discov = &hdev->discovery;
1617 struct inquiry_entry *e;
1618
1619 if (conn && !test_and_set_bit(HCI_CONN_MGMT_CONNECTED, &conn->flags))
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001620 mgmt_device_connected(hdev, bdaddr, ACL_LINK, 0x00, 0, name,
1621 name_len, conn->dev_class);
Johan Hedbergb644ba32012-01-17 21:48:47 +02001622
1623 if (discov->state == DISCOVERY_STOPPED)
1624 return;
1625
Johan Hedberg30dc78e2012-01-04 15:44:20 +02001626 if (discov->state == DISCOVERY_STOPPING)
1627 goto discov_complete;
1628
1629 if (discov->state != DISCOVERY_RESOLVING)
1630 return;
1631
1632 e = hci_inquiry_cache_lookup_resolve(hdev, bdaddr, NAME_PENDING);
Ram Malovany7cc83802012-07-19 10:26:10 +03001633 /* If the device was not found in a list of found devices names of which
1634 * are pending. there is no need to continue resolving a next name as it
1635 * will be done upon receiving another Remote Name Request Complete
1636 * Event */
1637 if (!e)
1638 return;
1639
1640 list_del(&e->list);
1641 if (name) {
Johan Hedberg30dc78e2012-01-04 15:44:20 +02001642 e->name_state = NAME_KNOWN;
Ram Malovany7cc83802012-07-19 10:26:10 +03001643 mgmt_remote_name(hdev, bdaddr, ACL_LINK, 0x00,
1644 e->data.rssi, name, name_len);
Ram Malovanyc3e7c0d2012-07-19 10:26:11 +03001645 } else {
1646 e->name_state = NAME_NOT_KNOWN;
Johan Hedberg30dc78e2012-01-04 15:44:20 +02001647 }
1648
Johan Hedbergb644ba32012-01-17 21:48:47 +02001649 if (hci_resolve_next_name(hdev))
Johan Hedberg30dc78e2012-01-04 15:44:20 +02001650 return;
Johan Hedberg30dc78e2012-01-04 15:44:20 +02001651
1652discov_complete:
1653 hci_discovery_set_state(hdev, DISCOVERY_STOPPED);
1654}
1655
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001656static void hci_cs_remote_name_req(struct hci_dev *hdev, __u8 status)
1657{
Johan Hedberg127178d2010-11-18 22:22:29 +02001658 struct hci_cp_remote_name_req *cp;
1659 struct hci_conn *conn;
1660
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +03001661 BT_DBG("%s status 0x%2.2x", hdev->name, status);
Johan Hedberg127178d2010-11-18 22:22:29 +02001662
1663 /* If successful wait for the name req complete event before
1664 * checking for the need to do authentication */
1665 if (!status)
1666 return;
1667
1668 cp = hci_sent_cmd_data(hdev, HCI_OP_REMOTE_NAME_REQ);
1669 if (!cp)
1670 return;
1671
1672 hci_dev_lock(hdev);
1673
1674 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &cp->bdaddr);
Johan Hedbergb644ba32012-01-17 21:48:47 +02001675
1676 if (test_bit(HCI_MGMT, &hdev->dev_flags))
1677 hci_check_pending_name(hdev, conn, &cp->bdaddr, NULL, 0);
1678
Johan Hedberg79c6c702011-04-28 11:28:55 -07001679 if (!conn)
1680 goto unlock;
1681
1682 if (!hci_outgoing_auth_needed(hdev, conn))
1683 goto unlock;
1684
Johan Hedberg51a8efd2012-01-16 06:10:31 +02001685 if (!test_and_set_bit(HCI_CONN_AUTH_PEND, &conn->flags)) {
Johan Hedberg127178d2010-11-18 22:22:29 +02001686 struct hci_cp_auth_requested cp;
1687 cp.handle = __cpu_to_le16(conn->handle);
1688 hci_send_cmd(hdev, HCI_OP_AUTH_REQUESTED, sizeof(cp), &cp);
1689 }
1690
Johan Hedberg79c6c702011-04-28 11:28:55 -07001691unlock:
Johan Hedberg127178d2010-11-18 22:22:29 +02001692 hci_dev_unlock(hdev);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001693}
1694
Marcel Holtmann769be972008-07-14 20:13:49 +02001695static void hci_cs_read_remote_features(struct hci_dev *hdev, __u8 status)
1696{
1697 struct hci_cp_read_remote_features *cp;
1698 struct hci_conn *conn;
1699
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +03001700 BT_DBG("%s status 0x%2.2x", hdev->name, status);
Marcel Holtmann769be972008-07-14 20:13:49 +02001701
1702 if (!status)
1703 return;
1704
1705 cp = hci_sent_cmd_data(hdev, HCI_OP_READ_REMOTE_FEATURES);
1706 if (!cp)
1707 return;
1708
1709 hci_dev_lock(hdev);
1710
1711 conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(cp->handle));
1712 if (conn) {
1713 if (conn->state == BT_CONFIG) {
Marcel Holtmann769be972008-07-14 20:13:49 +02001714 hci_proto_connect_cfm(conn, status);
1715 hci_conn_put(conn);
1716 }
1717 }
1718
1719 hci_dev_unlock(hdev);
1720}
1721
1722static void hci_cs_read_remote_ext_features(struct hci_dev *hdev, __u8 status)
1723{
1724 struct hci_cp_read_remote_ext_features *cp;
1725 struct hci_conn *conn;
1726
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +03001727 BT_DBG("%s status 0x%2.2x", hdev->name, status);
Marcel Holtmann769be972008-07-14 20:13:49 +02001728
1729 if (!status)
1730 return;
1731
1732 cp = hci_sent_cmd_data(hdev, HCI_OP_READ_REMOTE_EXT_FEATURES);
1733 if (!cp)
1734 return;
1735
1736 hci_dev_lock(hdev);
1737
1738 conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(cp->handle));
1739 if (conn) {
1740 if (conn->state == BT_CONFIG) {
Marcel Holtmann769be972008-07-14 20:13:49 +02001741 hci_proto_connect_cfm(conn, status);
1742 hci_conn_put(conn);
1743 }
1744 }
1745
1746 hci_dev_unlock(hdev);
1747}
1748
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001749static void hci_cs_setup_sync_conn(struct hci_dev *hdev, __u8 status)
1750{
Marcel Holtmannb6a0dc82007-10-20 14:55:10 +02001751 struct hci_cp_setup_sync_conn *cp;
1752 struct hci_conn *acl, *sco;
1753 __u16 handle;
1754
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +03001755 BT_DBG("%s status 0x%2.2x", hdev->name, status);
Marcel Holtmannb6a0dc82007-10-20 14:55:10 +02001756
1757 if (!status)
1758 return;
1759
1760 cp = hci_sent_cmd_data(hdev, HCI_OP_SETUP_SYNC_CONN);
1761 if (!cp)
1762 return;
1763
1764 handle = __le16_to_cpu(cp->handle);
1765
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +03001766 BT_DBG("%s handle 0x%4.4x", hdev->name, handle);
Marcel Holtmannb6a0dc82007-10-20 14:55:10 +02001767
1768 hci_dev_lock(hdev);
1769
1770 acl = hci_conn_hash_lookup_handle(hdev, handle);
Andrei Emeltchenko5a08ecc2011-01-11 17:20:20 +02001771 if (acl) {
1772 sco = acl->link;
1773 if (sco) {
1774 sco->state = BT_CLOSED;
Marcel Holtmannb6a0dc82007-10-20 14:55:10 +02001775
Andrei Emeltchenko5a08ecc2011-01-11 17:20:20 +02001776 hci_proto_connect_cfm(sco, status);
1777 hci_conn_del(sco);
1778 }
Marcel Holtmannb6a0dc82007-10-20 14:55:10 +02001779 }
1780
1781 hci_dev_unlock(hdev);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001782}
1783
1784static void hci_cs_sniff_mode(struct hci_dev *hdev, __u8 status)
1785{
1786 struct hci_cp_sniff_mode *cp;
1787 struct hci_conn *conn;
1788
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +03001789 BT_DBG("%s status 0x%2.2x", hdev->name, status);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001790
1791 if (!status)
1792 return;
1793
1794 cp = hci_sent_cmd_data(hdev, HCI_OP_SNIFF_MODE);
1795 if (!cp)
1796 return;
1797
1798 hci_dev_lock(hdev);
1799
1800 conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(cp->handle));
Marcel Holtmanne73439d2010-07-26 10:06:00 -04001801 if (conn) {
Johan Hedberg51a8efd2012-01-16 06:10:31 +02001802 clear_bit(HCI_CONN_MODE_CHANGE_PEND, &conn->flags);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001803
Johan Hedberg51a8efd2012-01-16 06:10:31 +02001804 if (test_and_clear_bit(HCI_CONN_SCO_SETUP_PEND, &conn->flags))
Marcel Holtmanne73439d2010-07-26 10:06:00 -04001805 hci_sco_setup(conn, status);
1806 }
1807
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001808 hci_dev_unlock(hdev);
1809}
1810
1811static void hci_cs_exit_sniff_mode(struct hci_dev *hdev, __u8 status)
1812{
1813 struct hci_cp_exit_sniff_mode *cp;
1814 struct hci_conn *conn;
1815
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +03001816 BT_DBG("%s status 0x%2.2x", hdev->name, status);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001817
1818 if (!status)
1819 return;
1820
1821 cp = hci_sent_cmd_data(hdev, HCI_OP_EXIT_SNIFF_MODE);
1822 if (!cp)
1823 return;
1824
1825 hci_dev_lock(hdev);
1826
1827 conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(cp->handle));
Marcel Holtmanne73439d2010-07-26 10:06:00 -04001828 if (conn) {
Johan Hedberg51a8efd2012-01-16 06:10:31 +02001829 clear_bit(HCI_CONN_MODE_CHANGE_PEND, &conn->flags);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001830
Johan Hedberg51a8efd2012-01-16 06:10:31 +02001831 if (test_and_clear_bit(HCI_CONN_SCO_SETUP_PEND, &conn->flags))
Marcel Holtmanne73439d2010-07-26 10:06:00 -04001832 hci_sco_setup(conn, status);
1833 }
1834
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001835 hci_dev_unlock(hdev);
1836}
1837
Johan Hedberg88c3df12012-02-09 14:27:38 +02001838static void hci_cs_disconnect(struct hci_dev *hdev, u8 status)
1839{
1840 struct hci_cp_disconnect *cp;
1841 struct hci_conn *conn;
1842
1843 if (!status)
1844 return;
1845
1846 cp = hci_sent_cmd_data(hdev, HCI_OP_DISCONNECT);
1847 if (!cp)
1848 return;
1849
1850 hci_dev_lock(hdev);
1851
1852 conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(cp->handle));
1853 if (conn)
1854 mgmt_disconnect_failed(hdev, &conn->dst, conn->type,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001855 conn->dst_type, status);
Johan Hedberg88c3df12012-02-09 14:27:38 +02001856
1857 hci_dev_unlock(hdev);
1858}
1859
Ville Tervofcd89c02011-02-10 22:38:47 -03001860static void hci_cs_le_create_conn(struct hci_dev *hdev, __u8 status)
1861{
Ville Tervofcd89c02011-02-10 22:38:47 -03001862 struct hci_conn *conn;
1863
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +03001864 BT_DBG("%s status 0x%2.2x", hdev->name, status);
Ville Tervofcd89c02011-02-10 22:38:47 -03001865
Ville Tervofcd89c02011-02-10 22:38:47 -03001866 if (status) {
Andre Guedesf00a06a2012-07-27 15:10:13 -03001867 hci_dev_lock(hdev);
Ville Tervofcd89c02011-02-10 22:38:47 -03001868
Andre Guedes0c95ab72012-07-27 15:10:14 -03001869 conn = hci_conn_hash_lookup_state(hdev, LE_LINK, BT_CONNECT);
Andre Guedesf00a06a2012-07-27 15:10:13 -03001870 if (!conn) {
1871 hci_dev_unlock(hdev);
1872 return;
1873 }
1874
Andrei Emeltchenko6ed93dc2012-09-25 12:49:43 +03001875 BT_DBG("%s bdaddr %pMR conn %p", hdev->name, &conn->dst, conn);
Andre Guedesf00a06a2012-07-27 15:10:13 -03001876
1877 conn->state = BT_CLOSED;
Andre Guedes0c95ab72012-07-27 15:10:14 -03001878 mgmt_connect_failed(hdev, &conn->dst, conn->type,
Andre Guedesf00a06a2012-07-27 15:10:13 -03001879 conn->dst_type, status);
1880 hci_proto_connect_cfm(conn, status);
1881 hci_conn_del(conn);
1882
1883 hci_dev_unlock(hdev);
1884 }
Ville Tervofcd89c02011-02-10 22:38:47 -03001885}
1886
Vinicius Costa Gomesa7a595f2011-06-09 18:50:47 -03001887static void hci_cs_le_start_enc(struct hci_dev *hdev, u8 status)
1888{
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +03001889 BT_DBG("%s status 0x%2.2x", hdev->name, status);
Vinicius Costa Gomesa7a595f2011-06-09 18:50:47 -03001890}
1891
Andrei Emeltchenkoa02226d2012-09-27 17:26:19 +03001892static void hci_cs_create_phylink(struct hci_dev *hdev, u8 status)
1893{
Andrei Emeltchenko93c284e2012-09-27 17:26:20 +03001894 struct hci_cp_create_phy_link *cp;
1895
Andrei Emeltchenkoa02226d2012-09-27 17:26:19 +03001896 BT_DBG("%s status 0x%2.2x", hdev->name, status);
Andrei Emeltchenko93c284e2012-09-27 17:26:20 +03001897
Andrei Emeltchenko93c284e2012-09-27 17:26:20 +03001898 cp = hci_sent_cmd_data(hdev, HCI_OP_CREATE_PHY_LINK);
1899 if (!cp)
1900 return;
1901
Andrei Emeltchenkoe58917b2012-10-31 15:46:33 +02001902 hci_dev_lock(hdev);
1903
1904 if (status) {
1905 struct hci_conn *hcon;
1906
1907 hcon = hci_conn_hash_lookup_handle(hdev, cp->phy_handle);
1908 if (hcon)
1909 hci_conn_del(hcon);
1910 } else {
1911 amp_write_remote_assoc(hdev, cp->phy_handle);
1912 }
1913
1914 hci_dev_unlock(hdev);
Andrei Emeltchenkoa02226d2012-09-27 17:26:19 +03001915}
1916
Andrei Emeltchenko0b26ab92012-09-27 17:26:24 +03001917static void hci_cs_accept_phylink(struct hci_dev *hdev, u8 status)
1918{
1919 struct hci_cp_accept_phy_link *cp;
1920
1921 BT_DBG("%s status 0x%2.2x", hdev->name, status);
1922
1923 if (status)
1924 return;
1925
1926 cp = hci_sent_cmd_data(hdev, HCI_OP_ACCEPT_PHY_LINK);
1927 if (!cp)
1928 return;
1929
1930 amp_write_remote_assoc(hdev, cp->phy_handle);
1931}
1932
Andrei Emeltchenko5ce66b52012-10-31 15:46:30 +02001933static void hci_cs_create_logical_link(struct hci_dev *hdev, u8 status)
1934{
1935 BT_DBG("%s status 0x%2.2x", hdev->name, status);
1936}
1937
Gustavo Padovan6039aa732012-05-23 04:04:18 -03001938static void hci_inquiry_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001939{
1940 __u8 status = *((__u8 *) skb->data);
Johan Hedberg30dc78e2012-01-04 15:44:20 +02001941 struct discovery_state *discov = &hdev->discovery;
1942 struct inquiry_entry *e;
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001943
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +03001944 BT_DBG("%s status 0x%2.2x", hdev->name, status);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001945
Johan Hedberg23bb5762010-12-21 23:01:27 +02001946 hci_req_complete(hdev, HCI_OP_INQUIRY, status);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001947
1948 hci_conn_check_pending(hdev);
Andre Guedes89352e72011-11-04 14:16:53 -03001949
1950 if (!test_and_clear_bit(HCI_INQUIRY, &hdev->flags))
1951 return;
1952
Johan Hedberga8b2d5c2012-01-08 23:11:15 +02001953 if (!test_bit(HCI_MGMT, &hdev->dev_flags))
Johan Hedberg30dc78e2012-01-04 15:44:20 +02001954 return;
1955
Johan Hedberg56e5cb82011-11-08 20:40:16 +02001956 hci_dev_lock(hdev);
Johan Hedberg30dc78e2012-01-04 15:44:20 +02001957
Andre Guedes343f9352012-02-17 20:39:37 -03001958 if (discov->state != DISCOVERY_FINDING)
Johan Hedberg30dc78e2012-01-04 15:44:20 +02001959 goto unlock;
1960
1961 if (list_empty(&discov->resolve)) {
1962 hci_discovery_set_state(hdev, DISCOVERY_STOPPED);
1963 goto unlock;
1964 }
1965
1966 e = hci_inquiry_cache_lookup_resolve(hdev, BDADDR_ANY, NAME_NEEDED);
1967 if (e && hci_resolve_name(hdev, e) == 0) {
1968 e->name_state = NAME_PENDING;
1969 hci_discovery_set_state(hdev, DISCOVERY_RESOLVING);
1970 } else {
1971 hci_discovery_set_state(hdev, DISCOVERY_STOPPED);
1972 }
1973
1974unlock:
Johan Hedberg56e5cb82011-11-08 20:40:16 +02001975 hci_dev_unlock(hdev);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001976}
1977
Gustavo Padovan6039aa732012-05-23 04:04:18 -03001978static void hci_inquiry_result_evt(struct hci_dev *hdev, struct sk_buff *skb)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001979{
Marcel Holtmann45bb4bf2005-08-09 20:27:49 -07001980 struct inquiry_data data;
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001981 struct inquiry_info *info = (void *) (skb->data + 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001982 int num_rsp = *((__u8 *) skb->data);
1983
1984 BT_DBG("%s num_rsp %d", hdev->name, num_rsp);
1985
Marcel Holtmann45bb4bf2005-08-09 20:27:49 -07001986 if (!num_rsp)
1987 return;
1988
Andre Guedes1519cc12012-03-21 00:03:38 -03001989 if (test_bit(HCI_PERIODIC_INQ, &hdev->dev_flags))
1990 return;
1991
Linus Torvalds1da177e2005-04-16 15:20:36 -07001992 hci_dev_lock(hdev);
Marcel Holtmann45bb4bf2005-08-09 20:27:49 -07001993
Johan Hedberge17acd42011-03-30 23:57:16 +03001994 for (; num_rsp; num_rsp--, info++) {
Johan Hedberg388fc8f2012-02-23 00:38:59 +02001995 bool name_known, ssp;
Johan Hedberg31754052012-01-04 13:39:52 +02001996
Linus Torvalds1da177e2005-04-16 15:20:36 -07001997 bacpy(&data.bdaddr, &info->bdaddr);
1998 data.pscan_rep_mode = info->pscan_rep_mode;
1999 data.pscan_period_mode = info->pscan_period_mode;
2000 data.pscan_mode = info->pscan_mode;
2001 memcpy(data.dev_class, info->dev_class, 3);
2002 data.clock_offset = info->clock_offset;
2003 data.rssi = 0x00;
Marcel Holtmann41a96212008-07-14 20:13:48 +02002004 data.ssp_mode = 0x00;
Johan Hedberg31754052012-01-04 13:39:52 +02002005
Johan Hedberg388fc8f2012-02-23 00:38:59 +02002006 name_known = hci_inquiry_cache_update(hdev, &data, false, &ssp);
Johan Hedberg48264f02011-11-09 13:58:58 +02002007 mgmt_device_found(hdev, &info->bdaddr, ACL_LINK, 0x00,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002008 info->dev_class, 0, !name_known, ssp, NULL,
2009 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002010 }
Marcel Holtmann45bb4bf2005-08-09 20:27:49 -07002011
Linus Torvalds1da177e2005-04-16 15:20:36 -07002012 hci_dev_unlock(hdev);
2013}
2014
Gustavo Padovan6039aa732012-05-23 04:04:18 -03002015static void hci_conn_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002016{
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002017 struct hci_ev_conn_complete *ev = (void *) skb->data;
2018 struct hci_conn *conn;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002019
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002020 BT_DBG("%s", hdev->name);
Marcel Holtmann45bb4bf2005-08-09 20:27:49 -07002021
Linus Torvalds1da177e2005-04-16 15:20:36 -07002022 hci_dev_lock(hdev);
Marcel Holtmann45bb4bf2005-08-09 20:27:49 -07002023
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002024 conn = hci_conn_hash_lookup_ba(hdev, ev->link_type, &ev->bdaddr);
Marcel Holtmann94992372009-04-19 19:30:03 +02002025 if (!conn) {
2026 if (ev->link_type != SCO_LINK)
2027 goto unlock;
2028
2029 conn = hci_conn_hash_lookup_ba(hdev, ESCO_LINK, &ev->bdaddr);
2030 if (!conn)
2031 goto unlock;
2032
2033 conn->type = SCO_LINK;
2034 }
Marcel Holtmann45bb4bf2005-08-09 20:27:49 -07002035
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002036 if (!ev->status) {
2037 conn->handle = __le16_to_cpu(ev->handle);
Marcel Holtmann769be972008-07-14 20:13:49 +02002038
2039 if (conn->type == ACL_LINK) {
2040 conn->state = BT_CONFIG;
2041 hci_conn_hold(conn);
Szymon Janca9ea3ed2012-07-19 14:46:08 +02002042
2043 if (!conn->out && !hci_conn_ssp_enabled(conn) &&
2044 !hci_find_link_key(hdev, &ev->bdaddr))
2045 conn->disc_timeout = HCI_PAIRING_TIMEOUT;
2046 else
2047 conn->disc_timeout = HCI_DISCONN_TIMEOUT;
Marcel Holtmann769be972008-07-14 20:13:49 +02002048 } else
2049 conn->state = BT_CONNECTED;
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002050
Marcel Holtmann9eba32b2009-08-22 14:19:26 -07002051 hci_conn_hold_device(conn);
Marcel Holtmann7d0db0a2008-07-14 20:13:51 +02002052 hci_conn_add_sysfs(conn);
2053
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002054 if (test_bit(HCI_AUTH, &hdev->flags))
2055 conn->link_mode |= HCI_LM_AUTH;
2056
2057 if (test_bit(HCI_ENCRYPT, &hdev->flags))
2058 conn->link_mode |= HCI_LM_ENCRYPT;
2059
2060 /* Get remote features */
2061 if (conn->type == ACL_LINK) {
2062 struct hci_cp_read_remote_features cp;
2063 cp.handle = ev->handle;
Marcel Holtmann769be972008-07-14 20:13:49 +02002064 hci_send_cmd(hdev, HCI_OP_READ_REMOTE_FEATURES,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002065 sizeof(cp), &cp);
Marcel Holtmann45bb4bf2005-08-09 20:27:49 -07002066 }
Marcel Holtmann45bb4bf2005-08-09 20:27:49 -07002067
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002068 /* Set packet type for incoming connection */
Andrei Emeltchenkod095c1e2011-12-01 14:33:27 +02002069 if (!conn->out && hdev->hci_ver < BLUETOOTH_VER_2_0) {
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002070 struct hci_cp_change_conn_ptype cp;
2071 cp.handle = ev->handle;
Marcel Holtmanna8746412008-07-14 20:13:46 +02002072 cp.pkt_type = cpu_to_le16(conn->pkt_type);
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002073 hci_send_cmd(hdev, HCI_OP_CHANGE_CONN_PTYPE, sizeof(cp),
2074 &cp);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002075 }
Johan Hedberg17d5c042011-01-22 06:09:08 +02002076 } else {
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002077 conn->state = BT_CLOSED;
Johan Hedberg17d5c042011-01-22 06:09:08 +02002078 if (conn->type == ACL_LINK)
Johan Hedberg744cf192011-11-08 20:40:14 +02002079 mgmt_connect_failed(hdev, &ev->bdaddr, conn->type,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002080 conn->dst_type, ev->status);
Johan Hedberg17d5c042011-01-22 06:09:08 +02002081 }
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002082
Marcel Holtmanne73439d2010-07-26 10:06:00 -04002083 if (conn->type == ACL_LINK)
2084 hci_sco_setup(conn, ev->status);
Marcel Holtmann45bb4bf2005-08-09 20:27:49 -07002085
Marcel Holtmann769be972008-07-14 20:13:49 +02002086 if (ev->status) {
2087 hci_proto_connect_cfm(conn, ev->status);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002088 hci_conn_del(conn);
Marcel Holtmannc89b6e62009-01-15 21:57:03 +01002089 } else if (ev->link_type != ACL_LINK)
2090 hci_proto_connect_cfm(conn, ev->status);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002091
2092unlock:
Linus Torvalds1da177e2005-04-16 15:20:36 -07002093 hci_dev_unlock(hdev);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002094
2095 hci_conn_check_pending(hdev);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002096}
2097
Frédéric Dalleau20714bf2012-11-21 10:51:12 +01002098void hci_conn_accept(struct hci_conn *conn, int mask)
2099{
2100 struct hci_dev *hdev = conn->hdev;
2101
2102 BT_DBG("conn %p", conn);
2103
2104 conn->state = BT_CONFIG;
2105
2106 if (!lmp_esco_capable(hdev)) {
2107 struct hci_cp_accept_conn_req cp;
2108
2109 bacpy(&cp.bdaddr, &conn->dst);
2110
2111 if (lmp_rswitch_capable(hdev) && (mask & HCI_LM_MASTER))
2112 cp.role = 0x00; /* Become master */
2113 else
2114 cp.role = 0x01; /* Remain slave */
2115
2116 hci_send_cmd(hdev, HCI_OP_ACCEPT_CONN_REQ, sizeof(cp), &cp);
2117 } else /* lmp_esco_capable(hdev)) */ {
2118 struct hci_cp_accept_sync_conn_req cp;
2119
2120 bacpy(&cp.bdaddr, &conn->dst);
2121 cp.pkt_type = cpu_to_le16(conn->pkt_type);
2122
2123 cp.tx_bandwidth = __constant_cpu_to_le32(0x00001f40);
2124 cp.rx_bandwidth = __constant_cpu_to_le32(0x00001f40);
2125 cp.max_latency = __constant_cpu_to_le16(0xffff);
2126 cp.content_format = cpu_to_le16(hdev->voice_setting);
2127 cp.retrans_effort = 0xff;
2128
2129 hci_send_cmd(hdev, HCI_OP_ACCEPT_SYNC_CONN_REQ,
2130 sizeof(cp), &cp);
2131 }
2132}
2133
Gustavo Padovan6039aa732012-05-23 04:04:18 -03002134static void hci_conn_request_evt(struct hci_dev *hdev, struct sk_buff *skb)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002135{
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002136 struct hci_ev_conn_request *ev = (void *) skb->data;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002137 int mask = hdev->link_mode;
Frédéric Dalleau20714bf2012-11-21 10:51:12 +01002138 __u8 flags = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002139
Andrei Emeltchenko6ed93dc2012-09-25 12:49:43 +03002140 BT_DBG("%s bdaddr %pMR type 0x%x", hdev->name, &ev->bdaddr,
Gustavo Padovan807deac2012-05-17 00:36:24 -03002141 ev->link_type);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002142
Frédéric Dalleau20714bf2012-11-21 10:51:12 +01002143 mask |= hci_proto_connect_ind(hdev, &ev->bdaddr, ev->link_type,
2144 &flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002145
Szymon Janc138d22e2011-02-17 16:44:23 +01002146 if ((mask & HCI_LM_ACCEPT) &&
Gustavo Padovan807deac2012-05-17 00:36:24 -03002147 !hci_blacklist_lookup(hdev, &ev->bdaddr)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002148 /* Connection accepted */
Marcel Holtmannc7bdd502008-07-14 20:13:47 +02002149 struct inquiry_entry *ie;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002150 struct hci_conn *conn;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002151
2152 hci_dev_lock(hdev);
Marcel Holtmannb6a0dc82007-10-20 14:55:10 +02002153
Andrei Emeltchenkocc11b9c2010-11-22 13:21:37 +02002154 ie = hci_inquiry_cache_lookup(hdev, &ev->bdaddr);
2155 if (ie)
Marcel Holtmannc7bdd502008-07-14 20:13:47 +02002156 memcpy(ie->data.dev_class, ev->dev_class, 3);
2157
Gustavo Padovan8fc9ced2012-05-23 04:04:21 -03002158 conn = hci_conn_hash_lookup_ba(hdev, ev->link_type,
2159 &ev->bdaddr);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002160 if (!conn) {
Andrei Emeltchenkocc11b9c2010-11-22 13:21:37 +02002161 conn = hci_conn_add(hdev, ev->link_type, &ev->bdaddr);
2162 if (!conn) {
Gustavo F. Padovan893ef972010-07-18 15:13:37 -03002163 BT_ERR("No memory for new connection");
Linus Torvalds1da177e2005-04-16 15:20:36 -07002164 hci_dev_unlock(hdev);
2165 return;
2166 }
2167 }
Marcel Holtmannb6a0dc82007-10-20 14:55:10 +02002168
Linus Torvalds1da177e2005-04-16 15:20:36 -07002169 memcpy(conn->dev_class, ev->dev_class, 3);
Marcel Holtmannb6a0dc82007-10-20 14:55:10 +02002170
Linus Torvalds1da177e2005-04-16 15:20:36 -07002171 hci_dev_unlock(hdev);
2172
Frédéric Dalleau20714bf2012-11-21 10:51:12 +01002173 if (ev->link_type == ACL_LINK ||
2174 (!(flags & HCI_PROTO_DEFER) && !lmp_esco_capable(hdev))) {
Marcel Holtmannb6a0dc82007-10-20 14:55:10 +02002175 struct hci_cp_accept_conn_req cp;
Frédéric Dalleau20714bf2012-11-21 10:51:12 +01002176 conn->state = BT_CONNECT;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002177
Marcel Holtmannb6a0dc82007-10-20 14:55:10 +02002178 bacpy(&cp.bdaddr, &ev->bdaddr);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002179
Marcel Holtmannb6a0dc82007-10-20 14:55:10 +02002180 if (lmp_rswitch_capable(hdev) && (mask & HCI_LM_MASTER))
2181 cp.role = 0x00; /* Become master */
2182 else
2183 cp.role = 0x01; /* Remain slave */
2184
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002185 hci_send_cmd(hdev, HCI_OP_ACCEPT_CONN_REQ, sizeof(cp),
2186 &cp);
Frédéric Dalleau20714bf2012-11-21 10:51:12 +01002187 } else if (!(flags & HCI_PROTO_DEFER)) {
Marcel Holtmannb6a0dc82007-10-20 14:55:10 +02002188 struct hci_cp_accept_sync_conn_req cp;
Frédéric Dalleau20714bf2012-11-21 10:51:12 +01002189 conn->state = BT_CONNECT;
Marcel Holtmannb6a0dc82007-10-20 14:55:10 +02002190
2191 bacpy(&cp.bdaddr, &ev->bdaddr);
Marcel Holtmanna8746412008-07-14 20:13:46 +02002192 cp.pkt_type = cpu_to_le16(conn->pkt_type);
Marcel Holtmannb6a0dc82007-10-20 14:55:10 +02002193
Andrei Emeltchenko82781e62012-05-25 11:38:27 +03002194 cp.tx_bandwidth = __constant_cpu_to_le32(0x00001f40);
2195 cp.rx_bandwidth = __constant_cpu_to_le32(0x00001f40);
2196 cp.max_latency = __constant_cpu_to_le16(0xffff);
Marcel Holtmannb6a0dc82007-10-20 14:55:10 +02002197 cp.content_format = cpu_to_le16(hdev->voice_setting);
2198 cp.retrans_effort = 0xff;
2199
2200 hci_send_cmd(hdev, HCI_OP_ACCEPT_SYNC_CONN_REQ,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002201 sizeof(cp), &cp);
Frédéric Dalleau20714bf2012-11-21 10:51:12 +01002202 } else {
2203 conn->state = BT_CONNECT2;
2204 hci_proto_connect_cfm(conn, 0);
2205 hci_conn_put(conn);
Marcel Holtmannb6a0dc82007-10-20 14:55:10 +02002206 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002207 } else {
2208 /* Connection rejected */
2209 struct hci_cp_reject_conn_req cp;
2210
2211 bacpy(&cp.bdaddr, &ev->bdaddr);
Andrei Emeltchenko9f5a0d72011-11-07 14:20:25 +02002212 cp.reason = HCI_ERROR_REJ_BAD_ADDR;
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002213 hci_send_cmd(hdev, HCI_OP_REJECT_CONN_REQ, sizeof(cp), &cp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002214 }
2215}
2216
Mikel Astizf0d6a0e2012-08-09 09:52:30 +02002217static u8 hci_to_mgmt_reason(u8 err)
2218{
2219 switch (err) {
2220 case HCI_ERROR_CONNECTION_TIMEOUT:
2221 return MGMT_DEV_DISCONN_TIMEOUT;
2222 case HCI_ERROR_REMOTE_USER_TERM:
2223 case HCI_ERROR_REMOTE_LOW_RESOURCES:
2224 case HCI_ERROR_REMOTE_POWER_OFF:
2225 return MGMT_DEV_DISCONN_REMOTE;
2226 case HCI_ERROR_LOCAL_HOST_TERM:
2227 return MGMT_DEV_DISCONN_LOCAL_HOST;
2228 default:
2229 return MGMT_DEV_DISCONN_UNKNOWN;
2230 }
2231}
2232
Gustavo Padovan6039aa732012-05-23 04:04:18 -03002233static void hci_disconn_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002234{
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002235 struct hci_ev_disconn_complete *ev = (void *) skb->data;
Marcel Holtmann04837f62006-07-03 10:02:33 +02002236 struct hci_conn *conn;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002237
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +03002238 BT_DBG("%s status 0x%2.2x", hdev->name, ev->status);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002239
Linus Torvalds1da177e2005-04-16 15:20:36 -07002240 hci_dev_lock(hdev);
2241
Marcel Holtmann04837f62006-07-03 10:02:33 +02002242 conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
Johan Hedbergf7520542011-01-20 12:34:39 +02002243 if (!conn)
2244 goto unlock;
Marcel Holtmann7d0db0a2008-07-14 20:13:51 +02002245
Johan Hedberg37d9ef72011-11-10 15:54:39 +02002246 if (ev->status == 0)
2247 conn->state = BT_CLOSED;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002248
Johan Hedbergb644ba32012-01-17 21:48:47 +02002249 if (test_and_clear_bit(HCI_CONN_MGMT_CONNECTED, &conn->flags) &&
Gustavo Padovan807deac2012-05-17 00:36:24 -03002250 (conn->type == ACL_LINK || conn->type == LE_LINK)) {
Mikel Astizf0d6a0e2012-08-09 09:52:30 +02002251 if (ev->status) {
Johan Hedberg88c3df12012-02-09 14:27:38 +02002252 mgmt_disconnect_failed(hdev, &conn->dst, conn->type,
Gustavo Padovan807deac2012-05-17 00:36:24 -03002253 conn->dst_type, ev->status);
Mikel Astizf0d6a0e2012-08-09 09:52:30 +02002254 } else {
2255 u8 reason = hci_to_mgmt_reason(ev->reason);
2256
Johan Hedbergafc747a2012-01-15 18:11:07 +02002257 mgmt_device_disconnected(hdev, &conn->dst, conn->type,
Mikel Astizf0d6a0e2012-08-09 09:52:30 +02002258 conn->dst_type, reason);
2259 }
Johan Hedberg37d9ef72011-11-10 15:54:39 +02002260 }
Johan Hedbergf7520542011-01-20 12:34:39 +02002261
Johan Hedberg37d9ef72011-11-10 15:54:39 +02002262 if (ev->status == 0) {
Vishal Agarwal6ec5bca2012-04-16 14:44:44 +05302263 if (conn->type == ACL_LINK && conn->flush_key)
2264 hci_remove_link_key(hdev, &conn->dst);
Johan Hedberg37d9ef72011-11-10 15:54:39 +02002265 hci_proto_disconn_cfm(conn, ev->reason);
2266 hci_conn_del(conn);
2267 }
Johan Hedbergf7520542011-01-20 12:34:39 +02002268
2269unlock:
Linus Torvalds1da177e2005-04-16 15:20:36 -07002270 hci_dev_unlock(hdev);
2271}
2272
Gustavo Padovan6039aa732012-05-23 04:04:18 -03002273static void hci_auth_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002274{
2275 struct hci_ev_auth_complete *ev = (void *) skb->data;
2276 struct hci_conn *conn;
2277
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +03002278 BT_DBG("%s status 0x%2.2x", hdev->name, ev->status);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002279
2280 hci_dev_lock(hdev);
2281
2282 conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
Waldemar Rymarkiewiczd7556e22011-05-31 15:49:26 +02002283 if (!conn)
2284 goto unlock;
2285
2286 if (!ev->status) {
Johan Hedbergaa64a8b2012-01-18 21:33:12 +02002287 if (!hci_conn_ssp_enabled(conn) &&
Gustavo Padovan807deac2012-05-17 00:36:24 -03002288 test_bit(HCI_CONN_REAUTH_PEND, &conn->flags)) {
Waldemar Rymarkiewiczd7556e22011-05-31 15:49:26 +02002289 BT_INFO("re-auth of legacy device is not possible.");
Johan Hedberg2a611692011-02-19 12:06:00 -03002290 } else {
Waldemar Rymarkiewiczd7556e22011-05-31 15:49:26 +02002291 conn->link_mode |= HCI_LM_AUTH;
2292 conn->sec_level = conn->pending_sec_level;
Johan Hedberg2a611692011-02-19 12:06:00 -03002293 }
Waldemar Rymarkiewiczd7556e22011-05-31 15:49:26 +02002294 } else {
Johan Hedbergbab73cb2012-02-09 16:07:29 +02002295 mgmt_auth_failed(hdev, &conn->dst, conn->type, conn->dst_type,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002296 ev->status);
Waldemar Rymarkiewiczd7556e22011-05-31 15:49:26 +02002297 }
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002298
Johan Hedberg51a8efd2012-01-16 06:10:31 +02002299 clear_bit(HCI_CONN_AUTH_PEND, &conn->flags);
2300 clear_bit(HCI_CONN_REAUTH_PEND, &conn->flags);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002301
Waldemar Rymarkiewiczd7556e22011-05-31 15:49:26 +02002302 if (conn->state == BT_CONFIG) {
Johan Hedbergaa64a8b2012-01-18 21:33:12 +02002303 if (!ev->status && hci_conn_ssp_enabled(conn)) {
Waldemar Rymarkiewiczd7556e22011-05-31 15:49:26 +02002304 struct hci_cp_set_conn_encrypt cp;
2305 cp.handle = ev->handle;
2306 cp.encrypt = 0x01;
2307 hci_send_cmd(hdev, HCI_OP_SET_CONN_ENCRYPT, sizeof(cp),
Gustavo Padovan807deac2012-05-17 00:36:24 -03002308 &cp);
Marcel Holtmann052b30b2009-04-26 20:01:22 +02002309 } else {
Waldemar Rymarkiewiczd7556e22011-05-31 15:49:26 +02002310 conn->state = BT_CONNECTED;
2311 hci_proto_connect_cfm(conn, ev->status);
Marcel Holtmann052b30b2009-04-26 20:01:22 +02002312 hci_conn_put(conn);
2313 }
Waldemar Rymarkiewiczd7556e22011-05-31 15:49:26 +02002314 } else {
2315 hci_auth_cfm(conn, ev->status);
Marcel Holtmann052b30b2009-04-26 20:01:22 +02002316
Waldemar Rymarkiewiczd7556e22011-05-31 15:49:26 +02002317 hci_conn_hold(conn);
2318 conn->disc_timeout = HCI_DISCONN_TIMEOUT;
2319 hci_conn_put(conn);
2320 }
2321
Johan Hedberg51a8efd2012-01-16 06:10:31 +02002322 if (test_bit(HCI_CONN_ENCRYPT_PEND, &conn->flags)) {
Waldemar Rymarkiewiczd7556e22011-05-31 15:49:26 +02002323 if (!ev->status) {
2324 struct hci_cp_set_conn_encrypt cp;
2325 cp.handle = ev->handle;
2326 cp.encrypt = 0x01;
2327 hci_send_cmd(hdev, HCI_OP_SET_CONN_ENCRYPT, sizeof(cp),
Gustavo Padovan807deac2012-05-17 00:36:24 -03002328 &cp);
Waldemar Rymarkiewiczd7556e22011-05-31 15:49:26 +02002329 } else {
Johan Hedberg51a8efd2012-01-16 06:10:31 +02002330 clear_bit(HCI_CONN_ENCRYPT_PEND, &conn->flags);
Waldemar Rymarkiewiczd7556e22011-05-31 15:49:26 +02002331 hci_encrypt_cfm(conn, ev->status, 0x00);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002332 }
2333 }
2334
Waldemar Rymarkiewiczd7556e22011-05-31 15:49:26 +02002335unlock:
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002336 hci_dev_unlock(hdev);
2337}
2338
Gustavo Padovan6039aa732012-05-23 04:04:18 -03002339static void hci_remote_name_evt(struct hci_dev *hdev, struct sk_buff *skb)
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002340{
Johan Hedberg127178d2010-11-18 22:22:29 +02002341 struct hci_ev_remote_name *ev = (void *) skb->data;
2342 struct hci_conn *conn;
2343
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002344 BT_DBG("%s", hdev->name);
2345
2346 hci_conn_check_pending(hdev);
Johan Hedberg127178d2010-11-18 22:22:29 +02002347
2348 hci_dev_lock(hdev);
2349
2350 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
Johan Hedbergb644ba32012-01-17 21:48:47 +02002351
2352 if (!test_bit(HCI_MGMT, &hdev->dev_flags))
2353 goto check_auth;
2354
2355 if (ev->status == 0)
2356 hci_check_pending_name(hdev, conn, &ev->bdaddr, ev->name,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002357 strnlen(ev->name, HCI_MAX_NAME_LENGTH));
Johan Hedbergb644ba32012-01-17 21:48:47 +02002358 else
2359 hci_check_pending_name(hdev, conn, &ev->bdaddr, NULL, 0);
2360
2361check_auth:
Johan Hedberg79c6c702011-04-28 11:28:55 -07002362 if (!conn)
2363 goto unlock;
2364
2365 if (!hci_outgoing_auth_needed(hdev, conn))
2366 goto unlock;
2367
Johan Hedberg51a8efd2012-01-16 06:10:31 +02002368 if (!test_and_set_bit(HCI_CONN_AUTH_PEND, &conn->flags)) {
Johan Hedberg127178d2010-11-18 22:22:29 +02002369 struct hci_cp_auth_requested cp;
2370 cp.handle = __cpu_to_le16(conn->handle);
2371 hci_send_cmd(hdev, HCI_OP_AUTH_REQUESTED, sizeof(cp), &cp);
2372 }
2373
Johan Hedberg79c6c702011-04-28 11:28:55 -07002374unlock:
Johan Hedberg127178d2010-11-18 22:22:29 +02002375 hci_dev_unlock(hdev);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002376}
2377
Gustavo Padovan6039aa732012-05-23 04:04:18 -03002378static void hci_encrypt_change_evt(struct hci_dev *hdev, struct sk_buff *skb)
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002379{
2380 struct hci_ev_encrypt_change *ev = (void *) skb->data;
2381 struct hci_conn *conn;
2382
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +03002383 BT_DBG("%s status 0x%2.2x", hdev->name, ev->status);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002384
2385 hci_dev_lock(hdev);
2386
2387 conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
2388 if (conn) {
2389 if (!ev->status) {
Marcel Holtmannae293192008-07-14 20:13:45 +02002390 if (ev->encrypt) {
2391 /* Encryption implies authentication */
2392 conn->link_mode |= HCI_LM_AUTH;
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002393 conn->link_mode |= HCI_LM_ENCRYPT;
Vinicius Costa Gomesda85e5e2011-06-09 18:50:53 -03002394 conn->sec_level = conn->pending_sec_level;
Marcel Holtmannae293192008-07-14 20:13:45 +02002395 } else
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002396 conn->link_mode &= ~HCI_LM_ENCRYPT;
2397 }
2398
Johan Hedberg51a8efd2012-01-16 06:10:31 +02002399 clear_bit(HCI_CONN_ENCRYPT_PEND, &conn->flags);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002400
Gustavo Padovana7d77232012-05-13 03:20:07 -03002401 if (ev->status && conn->state == BT_CONNECTED) {
Gustavo Padovand839c812012-05-16 12:17:12 -03002402 hci_acl_disconn(conn, HCI_ERROR_AUTH_FAILURE);
Gustavo Padovana7d77232012-05-13 03:20:07 -03002403 hci_conn_put(conn);
2404 goto unlock;
2405 }
2406
Marcel Holtmannf8558552008-07-14 20:13:49 +02002407 if (conn->state == BT_CONFIG) {
2408 if (!ev->status)
2409 conn->state = BT_CONNECTED;
2410
2411 hci_proto_connect_cfm(conn, ev->status);
2412 hci_conn_put(conn);
2413 } else
2414 hci_encrypt_cfm(conn, ev->status, ev->encrypt);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002415 }
2416
Gustavo Padovana7d77232012-05-13 03:20:07 -03002417unlock:
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002418 hci_dev_unlock(hdev);
2419}
2420
Gustavo Padovan6039aa732012-05-23 04:04:18 -03002421static void hci_change_link_key_complete_evt(struct hci_dev *hdev,
2422 struct sk_buff *skb)
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002423{
2424 struct hci_ev_change_link_key_complete *ev = (void *) skb->data;
2425 struct hci_conn *conn;
2426
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +03002427 BT_DBG("%s status 0x%2.2x", hdev->name, ev->status);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002428
2429 hci_dev_lock(hdev);
2430
2431 conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
2432 if (conn) {
2433 if (!ev->status)
2434 conn->link_mode |= HCI_LM_SECURE;
2435
Johan Hedberg51a8efd2012-01-16 06:10:31 +02002436 clear_bit(HCI_CONN_AUTH_PEND, &conn->flags);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002437
2438 hci_key_change_cfm(conn, ev->status);
2439 }
2440
2441 hci_dev_unlock(hdev);
2442}
2443
Gustavo Padovan6039aa732012-05-23 04:04:18 -03002444static void hci_remote_features_evt(struct hci_dev *hdev,
2445 struct sk_buff *skb)
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002446{
2447 struct hci_ev_remote_features *ev = (void *) skb->data;
2448 struct hci_conn *conn;
2449
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +03002450 BT_DBG("%s status 0x%2.2x", hdev->name, ev->status);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002451
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002452 hci_dev_lock(hdev);
2453
2454 conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
Johan Hedbergccd556f2010-11-10 17:11:51 +02002455 if (!conn)
2456 goto unlock;
Marcel Holtmann769be972008-07-14 20:13:49 +02002457
Johan Hedbergccd556f2010-11-10 17:11:51 +02002458 if (!ev->status)
2459 memcpy(conn->features, ev->features, 8);
2460
2461 if (conn->state != BT_CONFIG)
2462 goto unlock;
2463
2464 if (!ev->status && lmp_ssp_capable(hdev) && lmp_ssp_capable(conn)) {
2465 struct hci_cp_read_remote_ext_features cp;
2466 cp.handle = ev->handle;
2467 cp.page = 0x01;
2468 hci_send_cmd(hdev, HCI_OP_READ_REMOTE_EXT_FEATURES,
Gustavo Padovan807deac2012-05-17 00:36:24 -03002469 sizeof(cp), &cp);
Johan Hedberg392599b2010-11-18 22:22:28 +02002470 goto unlock;
2471 }
2472
Johan Hedberg671267b2012-05-12 16:11:50 -03002473 if (!ev->status && !test_bit(HCI_CONN_MGMT_CONNECTED, &conn->flags)) {
Johan Hedberg127178d2010-11-18 22:22:29 +02002474 struct hci_cp_remote_name_req cp;
2475 memset(&cp, 0, sizeof(cp));
2476 bacpy(&cp.bdaddr, &conn->dst);
2477 cp.pscan_rep_mode = 0x02;
2478 hci_send_cmd(hdev, HCI_OP_REMOTE_NAME_REQ, sizeof(cp), &cp);
Johan Hedbergb644ba32012-01-17 21:48:47 +02002479 } else if (!test_and_set_bit(HCI_CONN_MGMT_CONNECTED, &conn->flags))
2480 mgmt_device_connected(hdev, &conn->dst, conn->type,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002481 conn->dst_type, 0, NULL, 0,
2482 conn->dev_class);
Johan Hedberg392599b2010-11-18 22:22:28 +02002483
Johan Hedberg127178d2010-11-18 22:22:29 +02002484 if (!hci_outgoing_auth_needed(hdev, conn)) {
Johan Hedbergccd556f2010-11-10 17:11:51 +02002485 conn->state = BT_CONNECTED;
2486 hci_proto_connect_cfm(conn, ev->status);
2487 hci_conn_put(conn);
Marcel Holtmann769be972008-07-14 20:13:49 +02002488 }
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002489
Johan Hedbergccd556f2010-11-10 17:11:51 +02002490unlock:
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002491 hci_dev_unlock(hdev);
2492}
2493
Gustavo Padovan6039aa732012-05-23 04:04:18 -03002494static void hci_remote_version_evt(struct hci_dev *hdev, struct sk_buff *skb)
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002495{
2496 BT_DBG("%s", hdev->name);
2497}
2498
Gustavo Padovan6039aa732012-05-23 04:04:18 -03002499static void hci_qos_setup_complete_evt(struct hci_dev *hdev,
2500 struct sk_buff *skb)
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002501{
2502 BT_DBG("%s", hdev->name);
2503}
2504
Gustavo Padovan6039aa732012-05-23 04:04:18 -03002505static void hci_cmd_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002506{
2507 struct hci_ev_cmd_complete *ev = (void *) skb->data;
2508 __u16 opcode;
2509
2510 skb_pull(skb, sizeof(*ev));
2511
2512 opcode = __le16_to_cpu(ev->opcode);
2513
2514 switch (opcode) {
2515 case HCI_OP_INQUIRY_CANCEL:
2516 hci_cc_inquiry_cancel(hdev, skb);
2517 break;
2518
Andre Guedes4d934832012-03-21 00:03:35 -03002519 case HCI_OP_PERIODIC_INQ:
2520 hci_cc_periodic_inq(hdev, skb);
2521 break;
2522
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002523 case HCI_OP_EXIT_PERIODIC_INQ:
2524 hci_cc_exit_periodic_inq(hdev, skb);
2525 break;
2526
2527 case HCI_OP_REMOTE_NAME_REQ_CANCEL:
2528 hci_cc_remote_name_req_cancel(hdev, skb);
2529 break;
2530
2531 case HCI_OP_ROLE_DISCOVERY:
2532 hci_cc_role_discovery(hdev, skb);
2533 break;
2534
Marcel Holtmanne4e8e372008-07-14 20:13:47 +02002535 case HCI_OP_READ_LINK_POLICY:
2536 hci_cc_read_link_policy(hdev, skb);
2537 break;
2538
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002539 case HCI_OP_WRITE_LINK_POLICY:
2540 hci_cc_write_link_policy(hdev, skb);
2541 break;
2542
Marcel Holtmanne4e8e372008-07-14 20:13:47 +02002543 case HCI_OP_READ_DEF_LINK_POLICY:
2544 hci_cc_read_def_link_policy(hdev, skb);
2545 break;
2546
2547 case HCI_OP_WRITE_DEF_LINK_POLICY:
2548 hci_cc_write_def_link_policy(hdev, skb);
2549 break;
2550
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002551 case HCI_OP_RESET:
2552 hci_cc_reset(hdev, skb);
2553 break;
2554
2555 case HCI_OP_WRITE_LOCAL_NAME:
2556 hci_cc_write_local_name(hdev, skb);
2557 break;
2558
2559 case HCI_OP_READ_LOCAL_NAME:
2560 hci_cc_read_local_name(hdev, skb);
2561 break;
2562
2563 case HCI_OP_WRITE_AUTH_ENABLE:
2564 hci_cc_write_auth_enable(hdev, skb);
2565 break;
2566
2567 case HCI_OP_WRITE_ENCRYPT_MODE:
2568 hci_cc_write_encrypt_mode(hdev, skb);
2569 break;
2570
2571 case HCI_OP_WRITE_SCAN_ENABLE:
2572 hci_cc_write_scan_enable(hdev, skb);
2573 break;
2574
2575 case HCI_OP_READ_CLASS_OF_DEV:
2576 hci_cc_read_class_of_dev(hdev, skb);
2577 break;
2578
2579 case HCI_OP_WRITE_CLASS_OF_DEV:
2580 hci_cc_write_class_of_dev(hdev, skb);
2581 break;
2582
2583 case HCI_OP_READ_VOICE_SETTING:
2584 hci_cc_read_voice_setting(hdev, skb);
2585 break;
2586
2587 case HCI_OP_WRITE_VOICE_SETTING:
2588 hci_cc_write_voice_setting(hdev, skb);
2589 break;
2590
2591 case HCI_OP_HOST_BUFFER_SIZE:
2592 hci_cc_host_buffer_size(hdev, skb);
2593 break;
2594
Marcel Holtmann333140b2008-07-14 20:13:48 +02002595 case HCI_OP_WRITE_SSP_MODE:
2596 hci_cc_write_ssp_mode(hdev, skb);
2597 break;
2598
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002599 case HCI_OP_READ_LOCAL_VERSION:
2600 hci_cc_read_local_version(hdev, skb);
2601 break;
2602
2603 case HCI_OP_READ_LOCAL_COMMANDS:
2604 hci_cc_read_local_commands(hdev, skb);
2605 break;
2606
2607 case HCI_OP_READ_LOCAL_FEATURES:
2608 hci_cc_read_local_features(hdev, skb);
2609 break;
2610
Andre Guedes971e3a42011-06-30 19:20:52 -03002611 case HCI_OP_READ_LOCAL_EXT_FEATURES:
2612 hci_cc_read_local_ext_features(hdev, skb);
2613 break;
2614
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002615 case HCI_OP_READ_BUFFER_SIZE:
2616 hci_cc_read_buffer_size(hdev, skb);
2617 break;
2618
2619 case HCI_OP_READ_BD_ADDR:
2620 hci_cc_read_bd_addr(hdev, skb);
2621 break;
2622
Andrei Emeltchenko350ee4c2011-12-07 15:56:51 +02002623 case HCI_OP_READ_DATA_BLOCK_SIZE:
2624 hci_cc_read_data_block_size(hdev, skb);
2625 break;
2626
Johan Hedberg23bb5762010-12-21 23:01:27 +02002627 case HCI_OP_WRITE_CA_TIMEOUT:
2628 hci_cc_write_ca_timeout(hdev, skb);
2629 break;
2630
Andrei Emeltchenko1e89cff2011-11-24 14:52:02 +02002631 case HCI_OP_READ_FLOW_CONTROL_MODE:
2632 hci_cc_read_flow_control_mode(hdev, skb);
2633 break;
2634
Andrei Emeltchenko928abaa2011-10-12 10:53:57 +03002635 case HCI_OP_READ_LOCAL_AMP_INFO:
2636 hci_cc_read_local_amp_info(hdev, skb);
2637 break;
2638
Andrei Emeltchenko903e4542012-09-27 17:26:09 +03002639 case HCI_OP_READ_LOCAL_AMP_ASSOC:
2640 hci_cc_read_local_amp_assoc(hdev, skb);
2641 break;
2642
Johan Hedbergb0916ea2011-01-10 13:44:55 +02002643 case HCI_OP_DELETE_STORED_LINK_KEY:
2644 hci_cc_delete_stored_link_key(hdev, skb);
2645 break;
2646
Johan Hedbergd5859e22011-01-25 01:19:58 +02002647 case HCI_OP_SET_EVENT_MASK:
2648 hci_cc_set_event_mask(hdev, skb);
2649 break;
2650
2651 case HCI_OP_WRITE_INQUIRY_MODE:
2652 hci_cc_write_inquiry_mode(hdev, skb);
2653 break;
2654
2655 case HCI_OP_READ_INQ_RSP_TX_POWER:
2656 hci_cc_read_inq_rsp_tx_power(hdev, skb);
2657 break;
2658
2659 case HCI_OP_SET_EVENT_FLT:
2660 hci_cc_set_event_flt(hdev, skb);
2661 break;
2662
Johan Hedberg980e1a52011-01-22 06:10:07 +02002663 case HCI_OP_PIN_CODE_REPLY:
2664 hci_cc_pin_code_reply(hdev, skb);
2665 break;
2666
2667 case HCI_OP_PIN_CODE_NEG_REPLY:
2668 hci_cc_pin_code_neg_reply(hdev, skb);
2669 break;
2670
Szymon Jancc35938b2011-03-22 13:12:21 +01002671 case HCI_OP_READ_LOCAL_OOB_DATA:
2672 hci_cc_read_local_oob_data_reply(hdev, skb);
2673 break;
2674
Ville Tervo6ed58ec2011-02-10 22:38:48 -03002675 case HCI_OP_LE_READ_BUFFER_SIZE:
2676 hci_cc_le_read_buffer_size(hdev, skb);
2677 break;
2678
Johan Hedberg60e77322013-01-22 14:01:59 +02002679 case HCI_OP_LE_READ_LOCAL_FEATURES:
2680 hci_cc_le_read_local_features(hdev, skb);
2681 break;
2682
Johan Hedberg8fa19092012-10-19 20:57:49 +03002683 case HCI_OP_LE_READ_ADV_TX_POWER:
2684 hci_cc_le_read_adv_tx_power(hdev, skb);
2685 break;
2686
Johan Hedberge36b04c2012-10-19 20:57:47 +03002687 case HCI_OP_LE_SET_EVENT_MASK:
2688 hci_cc_le_set_event_mask(hdev, skb);
2689 break;
2690
Johan Hedberga5c29682011-02-19 12:05:57 -03002691 case HCI_OP_USER_CONFIRM_REPLY:
2692 hci_cc_user_confirm_reply(hdev, skb);
2693 break;
2694
2695 case HCI_OP_USER_CONFIRM_NEG_REPLY:
2696 hci_cc_user_confirm_neg_reply(hdev, skb);
2697 break;
2698
Brian Gix1143d452011-11-23 08:28:34 -08002699 case HCI_OP_USER_PASSKEY_REPLY:
2700 hci_cc_user_passkey_reply(hdev, skb);
2701 break;
2702
2703 case HCI_OP_USER_PASSKEY_NEG_REPLY:
2704 hci_cc_user_passkey_neg_reply(hdev, skb);
Szymon Janc16cde992012-04-13 12:32:42 +02002705 break;
Andre Guedes07f7fa52011-12-02 21:13:31 +09002706
2707 case HCI_OP_LE_SET_SCAN_PARAM:
2708 hci_cc_le_set_scan_param(hdev, skb);
Brian Gix1143d452011-11-23 08:28:34 -08002709 break;
2710
Johan Hedbergc1d5dc42012-11-08 01:23:01 +01002711 case HCI_OP_LE_SET_ADV_ENABLE:
2712 hci_cc_le_set_adv_enable(hdev, skb);
2713 break;
2714
Andre Guedeseb9d91f2011-05-26 16:23:52 -03002715 case HCI_OP_LE_SET_SCAN_ENABLE:
2716 hci_cc_le_set_scan_enable(hdev, skb);
2717 break;
2718
Johan Hedbergcf1d0812013-01-22 14:02:00 +02002719 case HCI_OP_LE_READ_WHITE_LIST_SIZE:
2720 hci_cc_le_read_white_list_size(hdev, skb);
2721 break;
2722
Vinicius Costa Gomesa7a595f2011-06-09 18:50:47 -03002723 case HCI_OP_LE_LTK_REPLY:
2724 hci_cc_le_ltk_reply(hdev, skb);
2725 break;
2726
2727 case HCI_OP_LE_LTK_NEG_REPLY:
2728 hci_cc_le_ltk_neg_reply(hdev, skb);
2729 break;
2730
Johan Hedberg9b008c02013-01-22 14:02:01 +02002731 case HCI_OP_LE_READ_SUPPORTED_STATES:
2732 hci_cc_le_read_supported_states(hdev, skb);
2733 break;
2734
Andre Guedesf9b49302011-06-30 19:20:53 -03002735 case HCI_OP_WRITE_LE_HOST_SUPPORTED:
2736 hci_cc_write_le_host_supported(hdev, skb);
2737 break;
2738
Andrei Emeltchenko93c284e2012-09-27 17:26:20 +03002739 case HCI_OP_WRITE_REMOTE_AMP_ASSOC:
2740 hci_cc_write_remote_amp_assoc(hdev, skb);
2741 break;
2742
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002743 default:
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +03002744 BT_DBG("%s opcode 0x%4.4x", hdev->name, opcode);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002745 break;
2746 }
2747
Ville Tervo6bd32322011-02-16 16:32:41 +02002748 if (ev->opcode != HCI_OP_NOP)
2749 del_timer(&hdev->cmd_timer);
2750
Szymon Jancdbccd792012-12-11 08:51:19 +01002751 if (ev->ncmd && !test_bit(HCI_RESET, &hdev->flags)) {
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002752 atomic_set(&hdev->cmd_cnt, 1);
2753 if (!skb_queue_empty(&hdev->cmd_q))
Gustavo F. Padovanc347b762011-12-14 23:53:47 -02002754 queue_work(hdev->workqueue, &hdev->cmd_work);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002755 }
2756}
2757
Gustavo Padovan6039aa732012-05-23 04:04:18 -03002758static void hci_cmd_status_evt(struct hci_dev *hdev, struct sk_buff *skb)
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002759{
2760 struct hci_ev_cmd_status *ev = (void *) skb->data;
2761 __u16 opcode;
2762
2763 skb_pull(skb, sizeof(*ev));
2764
2765 opcode = __le16_to_cpu(ev->opcode);
2766
2767 switch (opcode) {
2768 case HCI_OP_INQUIRY:
2769 hci_cs_inquiry(hdev, ev->status);
2770 break;
2771
2772 case HCI_OP_CREATE_CONN:
2773 hci_cs_create_conn(hdev, ev->status);
2774 break;
2775
2776 case HCI_OP_ADD_SCO:
2777 hci_cs_add_sco(hdev, ev->status);
2778 break;
2779
Marcel Holtmannf8558552008-07-14 20:13:49 +02002780 case HCI_OP_AUTH_REQUESTED:
2781 hci_cs_auth_requested(hdev, ev->status);
2782 break;
2783
2784 case HCI_OP_SET_CONN_ENCRYPT:
2785 hci_cs_set_conn_encrypt(hdev, ev->status);
2786 break;
2787
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002788 case HCI_OP_REMOTE_NAME_REQ:
2789 hci_cs_remote_name_req(hdev, ev->status);
2790 break;
2791
Marcel Holtmann769be972008-07-14 20:13:49 +02002792 case HCI_OP_READ_REMOTE_FEATURES:
2793 hci_cs_read_remote_features(hdev, ev->status);
2794 break;
2795
2796 case HCI_OP_READ_REMOTE_EXT_FEATURES:
2797 hci_cs_read_remote_ext_features(hdev, ev->status);
2798 break;
2799
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002800 case HCI_OP_SETUP_SYNC_CONN:
2801 hci_cs_setup_sync_conn(hdev, ev->status);
2802 break;
2803
2804 case HCI_OP_SNIFF_MODE:
2805 hci_cs_sniff_mode(hdev, ev->status);
2806 break;
2807
2808 case HCI_OP_EXIT_SNIFF_MODE:
2809 hci_cs_exit_sniff_mode(hdev, ev->status);
2810 break;
2811
Johan Hedberg8962ee72011-01-20 12:40:27 +02002812 case HCI_OP_DISCONNECT:
Johan Hedberg88c3df12012-02-09 14:27:38 +02002813 hci_cs_disconnect(hdev, ev->status);
Johan Hedberg8962ee72011-01-20 12:40:27 +02002814 break;
2815
Ville Tervofcd89c02011-02-10 22:38:47 -03002816 case HCI_OP_LE_CREATE_CONN:
2817 hci_cs_le_create_conn(hdev, ev->status);
2818 break;
2819
Vinicius Costa Gomesa7a595f2011-06-09 18:50:47 -03002820 case HCI_OP_LE_START_ENC:
2821 hci_cs_le_start_enc(hdev, ev->status);
2822 break;
2823
Andrei Emeltchenkoa02226d2012-09-27 17:26:19 +03002824 case HCI_OP_CREATE_PHY_LINK:
2825 hci_cs_create_phylink(hdev, ev->status);
2826 break;
2827
Andrei Emeltchenko0b26ab92012-09-27 17:26:24 +03002828 case HCI_OP_ACCEPT_PHY_LINK:
2829 hci_cs_accept_phylink(hdev, ev->status);
2830 break;
2831
Andrei Emeltchenko5ce66b52012-10-31 15:46:30 +02002832 case HCI_OP_CREATE_LOGICAL_LINK:
2833 hci_cs_create_logical_link(hdev, ev->status);
2834 break;
2835
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002836 default:
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +03002837 BT_DBG("%s opcode 0x%4.4x", hdev->name, opcode);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002838 break;
2839 }
2840
Ville Tervo6bd32322011-02-16 16:32:41 +02002841 if (ev->opcode != HCI_OP_NOP)
2842 del_timer(&hdev->cmd_timer);
2843
Gustavo F. Padovan10572132011-03-16 15:36:29 -03002844 if (ev->ncmd && !test_bit(HCI_RESET, &hdev->flags)) {
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002845 atomic_set(&hdev->cmd_cnt, 1);
2846 if (!skb_queue_empty(&hdev->cmd_q))
Gustavo F. Padovanc347b762011-12-14 23:53:47 -02002847 queue_work(hdev->workqueue, &hdev->cmd_work);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002848 }
2849}
2850
Gustavo Padovan6039aa732012-05-23 04:04:18 -03002851static void hci_role_change_evt(struct hci_dev *hdev, struct sk_buff *skb)
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002852{
2853 struct hci_ev_role_change *ev = (void *) skb->data;
2854 struct hci_conn *conn;
2855
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +03002856 BT_DBG("%s status 0x%2.2x", hdev->name, ev->status);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002857
2858 hci_dev_lock(hdev);
2859
2860 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
2861 if (conn) {
2862 if (!ev->status) {
2863 if (ev->role)
2864 conn->link_mode &= ~HCI_LM_MASTER;
2865 else
2866 conn->link_mode |= HCI_LM_MASTER;
2867 }
2868
Johan Hedberg51a8efd2012-01-16 06:10:31 +02002869 clear_bit(HCI_CONN_RSWITCH_PEND, &conn->flags);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002870
2871 hci_role_switch_cfm(conn, ev->status, ev->role);
2872 }
2873
2874 hci_dev_unlock(hdev);
2875}
2876
Gustavo Padovan6039aa732012-05-23 04:04:18 -03002877static void hci_num_comp_pkts_evt(struct hci_dev *hdev, struct sk_buff *skb)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002878{
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002879 struct hci_ev_num_comp_pkts *ev = (void *) skb->data;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002880 int i;
2881
Andrei Emeltchenko32ac5b92011-12-19 16:31:29 +02002882 if (hdev->flow_ctl_mode != HCI_FLOW_CTL_MODE_PACKET_BASED) {
2883 BT_ERR("Wrong event for mode %d", hdev->flow_ctl_mode);
2884 return;
2885 }
2886
Andrei Emeltchenkoc5993de2011-12-30 12:07:47 +02002887 if (skb->len < sizeof(*ev) || skb->len < sizeof(*ev) +
Gustavo Padovan807deac2012-05-17 00:36:24 -03002888 ev->num_hndl * sizeof(struct hci_comp_pkts_info)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002889 BT_DBG("%s bad parameters", hdev->name);
2890 return;
2891 }
2892
Andrei Emeltchenkoc5993de2011-12-30 12:07:47 +02002893 BT_DBG("%s num_hndl %d", hdev->name, ev->num_hndl);
2894
Andrei Emeltchenko613a1c02011-12-19 16:31:30 +02002895 for (i = 0; i < ev->num_hndl; i++) {
2896 struct hci_comp_pkts_info *info = &ev->handles[i];
Linus Torvalds1da177e2005-04-16 15:20:36 -07002897 struct hci_conn *conn;
2898 __u16 handle, count;
2899
Andrei Emeltchenko613a1c02011-12-19 16:31:30 +02002900 handle = __le16_to_cpu(info->handle);
2901 count = __le16_to_cpu(info->count);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002902
2903 conn = hci_conn_hash_lookup_handle(hdev, handle);
Andrei Emeltchenkof4280912011-12-07 15:56:52 +02002904 if (!conn)
2905 continue;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002906
Andrei Emeltchenkof4280912011-12-07 15:56:52 +02002907 conn->sent -= count;
2908
2909 switch (conn->type) {
2910 case ACL_LINK:
2911 hdev->acl_cnt += count;
2912 if (hdev->acl_cnt > hdev->acl_pkts)
2913 hdev->acl_cnt = hdev->acl_pkts;
2914 break;
2915
2916 case LE_LINK:
2917 if (hdev->le_pkts) {
2918 hdev->le_cnt += count;
2919 if (hdev->le_cnt > hdev->le_pkts)
2920 hdev->le_cnt = hdev->le_pkts;
2921 } else {
Andrei Emeltchenko70f230202010-12-01 16:58:25 +02002922 hdev->acl_cnt += count;
2923 if (hdev->acl_cnt > hdev->acl_pkts)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002924 hdev->acl_cnt = hdev->acl_pkts;
2925 }
Andrei Emeltchenkof4280912011-12-07 15:56:52 +02002926 break;
2927
2928 case SCO_LINK:
2929 hdev->sco_cnt += count;
2930 if (hdev->sco_cnt > hdev->sco_pkts)
2931 hdev->sco_cnt = hdev->sco_pkts;
2932 break;
2933
2934 default:
2935 BT_ERR("Unknown type %d conn %p", conn->type, conn);
2936 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002937 }
2938 }
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002939
Gustavo F. Padovan3eff45e2011-12-15 00:50:02 -02002940 queue_work(hdev->workqueue, &hdev->tx_work);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002941}
2942
Andrei Emeltchenko76ef7cf2012-10-10 17:38:29 +03002943static struct hci_conn *__hci_conn_lookup_handle(struct hci_dev *hdev,
2944 __u16 handle)
2945{
2946 struct hci_chan *chan;
2947
2948 switch (hdev->dev_type) {
2949 case HCI_BREDR:
2950 return hci_conn_hash_lookup_handle(hdev, handle);
2951 case HCI_AMP:
2952 chan = hci_chan_lookup_handle(hdev, handle);
2953 if (chan)
2954 return chan->conn;
2955 break;
2956 default:
2957 BT_ERR("%s unknown dev_type %d", hdev->name, hdev->dev_type);
2958 break;
2959 }
2960
2961 return NULL;
2962}
2963
Gustavo Padovan6039aa732012-05-23 04:04:18 -03002964static void hci_num_comp_blocks_evt(struct hci_dev *hdev, struct sk_buff *skb)
Andrei Emeltchenko25e89e92012-01-04 12:41:58 +02002965{
2966 struct hci_ev_num_comp_blocks *ev = (void *) skb->data;
2967 int i;
2968
2969 if (hdev->flow_ctl_mode != HCI_FLOW_CTL_MODE_BLOCK_BASED) {
2970 BT_ERR("Wrong event for mode %d", hdev->flow_ctl_mode);
2971 return;
2972 }
2973
2974 if (skb->len < sizeof(*ev) || skb->len < sizeof(*ev) +
Gustavo Padovan807deac2012-05-17 00:36:24 -03002975 ev->num_hndl * sizeof(struct hci_comp_blocks_info)) {
Andrei Emeltchenko25e89e92012-01-04 12:41:58 +02002976 BT_DBG("%s bad parameters", hdev->name);
2977 return;
2978 }
2979
2980 BT_DBG("%s num_blocks %d num_hndl %d", hdev->name, ev->num_blocks,
Gustavo Padovan807deac2012-05-17 00:36:24 -03002981 ev->num_hndl);
Andrei Emeltchenko25e89e92012-01-04 12:41:58 +02002982
2983 for (i = 0; i < ev->num_hndl; i++) {
2984 struct hci_comp_blocks_info *info = &ev->handles[i];
Andrei Emeltchenko76ef7cf2012-10-10 17:38:29 +03002985 struct hci_conn *conn = NULL;
Andrei Emeltchenko25e89e92012-01-04 12:41:58 +02002986 __u16 handle, block_count;
2987
2988 handle = __le16_to_cpu(info->handle);
2989 block_count = __le16_to_cpu(info->blocks);
2990
Andrei Emeltchenko76ef7cf2012-10-10 17:38:29 +03002991 conn = __hci_conn_lookup_handle(hdev, handle);
Andrei Emeltchenko25e89e92012-01-04 12:41:58 +02002992 if (!conn)
2993 continue;
2994
2995 conn->sent -= block_count;
2996
2997 switch (conn->type) {
2998 case ACL_LINK:
Andrei Emeltchenkobd1eb662012-10-10 17:38:30 +03002999 case AMP_LINK:
Andrei Emeltchenko25e89e92012-01-04 12:41:58 +02003000 hdev->block_cnt += block_count;
3001 if (hdev->block_cnt > hdev->num_blocks)
3002 hdev->block_cnt = hdev->num_blocks;
3003 break;
3004
3005 default:
3006 BT_ERR("Unknown type %d conn %p", conn->type, conn);
3007 break;
3008 }
3009 }
3010
3011 queue_work(hdev->workqueue, &hdev->tx_work);
3012}
3013
Gustavo Padovan6039aa732012-05-23 04:04:18 -03003014static void hci_mode_change_evt(struct hci_dev *hdev, struct sk_buff *skb)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003015{
Marcel Holtmanna9de9242007-10-20 13:33:56 +02003016 struct hci_ev_mode_change *ev = (void *) skb->data;
Marcel Holtmann04837f62006-07-03 10:02:33 +02003017 struct hci_conn *conn;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003018
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +03003019 BT_DBG("%s status 0x%2.2x", hdev->name, ev->status);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003020
3021 hci_dev_lock(hdev);
3022
Marcel Holtmann04837f62006-07-03 10:02:33 +02003023 conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
3024 if (conn) {
3025 conn->mode = ev->mode;
3026 conn->interval = __le16_to_cpu(ev->interval);
3027
Gustavo Padovan8fc9ced2012-05-23 04:04:21 -03003028 if (!test_and_clear_bit(HCI_CONN_MODE_CHANGE_PEND,
3029 &conn->flags)) {
Marcel Holtmann04837f62006-07-03 10:02:33 +02003030 if (conn->mode == HCI_CM_ACTIVE)
Johan Hedberg58a681e2012-01-16 06:47:28 +02003031 set_bit(HCI_CONN_POWER_SAVE, &conn->flags);
Marcel Holtmann04837f62006-07-03 10:02:33 +02003032 else
Johan Hedberg58a681e2012-01-16 06:47:28 +02003033 clear_bit(HCI_CONN_POWER_SAVE, &conn->flags);
Marcel Holtmann04837f62006-07-03 10:02:33 +02003034 }
Marcel Holtmanne73439d2010-07-26 10:06:00 -04003035
Johan Hedberg51a8efd2012-01-16 06:10:31 +02003036 if (test_and_clear_bit(HCI_CONN_SCO_SETUP_PEND, &conn->flags))
Marcel Holtmanne73439d2010-07-26 10:06:00 -04003037 hci_sco_setup(conn, ev->status);
Marcel Holtmann04837f62006-07-03 10:02:33 +02003038 }
3039
3040 hci_dev_unlock(hdev);
3041}
3042
Gustavo Padovan6039aa732012-05-23 04:04:18 -03003043static void hci_pin_code_request_evt(struct hci_dev *hdev, struct sk_buff *skb)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003044{
Marcel Holtmann052b30b2009-04-26 20:01:22 +02003045 struct hci_ev_pin_code_req *ev = (void *) skb->data;
3046 struct hci_conn *conn;
3047
Marcel Holtmanna9de9242007-10-20 13:33:56 +02003048 BT_DBG("%s", hdev->name);
Marcel Holtmann052b30b2009-04-26 20:01:22 +02003049
3050 hci_dev_lock(hdev);
3051
3052 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
Waldemar Rymarkiewiczb6f98042011-09-23 10:01:30 +02003053 if (!conn)
3054 goto unlock;
3055
3056 if (conn->state == BT_CONNECTED) {
Marcel Holtmann052b30b2009-04-26 20:01:22 +02003057 hci_conn_hold(conn);
3058 conn->disc_timeout = HCI_PAIRING_TIMEOUT;
3059 hci_conn_put(conn);
3060 }
3061
Johan Hedberga8b2d5c2012-01-08 23:11:15 +02003062 if (!test_bit(HCI_PAIRABLE, &hdev->dev_flags))
Johan Hedberg03b555e2011-01-04 15:40:05 +02003063 hci_send_cmd(hdev, HCI_OP_PIN_CODE_NEG_REPLY,
Gustavo Padovan807deac2012-05-17 00:36:24 -03003064 sizeof(ev->bdaddr), &ev->bdaddr);
Johan Hedberga8b2d5c2012-01-08 23:11:15 +02003065 else if (test_bit(HCI_MGMT, &hdev->dev_flags)) {
Waldemar Rymarkiewicza770bb52011-04-28 12:07:59 +02003066 u8 secure;
3067
3068 if (conn->pending_sec_level == BT_SECURITY_HIGH)
3069 secure = 1;
3070 else
3071 secure = 0;
3072
Johan Hedberg744cf192011-11-08 20:40:14 +02003073 mgmt_pin_code_request(hdev, &ev->bdaddr, secure);
Waldemar Rymarkiewicza770bb52011-04-28 12:07:59 +02003074 }
Johan Hedberg980e1a52011-01-22 06:10:07 +02003075
Waldemar Rymarkiewiczb6f98042011-09-23 10:01:30 +02003076unlock:
Marcel Holtmann052b30b2009-04-26 20:01:22 +02003077 hci_dev_unlock(hdev);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003078}
3079
Gustavo Padovan6039aa732012-05-23 04:04:18 -03003080static void hci_link_key_request_evt(struct hci_dev *hdev, struct sk_buff *skb)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003081{
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02003082 struct hci_ev_link_key_req *ev = (void *) skb->data;
3083 struct hci_cp_link_key_reply cp;
3084 struct hci_conn *conn;
3085 struct link_key *key;
3086
Marcel Holtmanna9de9242007-10-20 13:33:56 +02003087 BT_DBG("%s", hdev->name);
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02003088
Johan Hedberga8b2d5c2012-01-08 23:11:15 +02003089 if (!test_bit(HCI_LINK_KEYS, &hdev->dev_flags))
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02003090 return;
3091
3092 hci_dev_lock(hdev);
3093
3094 key = hci_find_link_key(hdev, &ev->bdaddr);
3095 if (!key) {
Andrei Emeltchenko6ed93dc2012-09-25 12:49:43 +03003096 BT_DBG("%s link key not found for %pMR", hdev->name,
3097 &ev->bdaddr);
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02003098 goto not_found;
3099 }
3100
Andrei Emeltchenko6ed93dc2012-09-25 12:49:43 +03003101 BT_DBG("%s found key type %u for %pMR", hdev->name, key->type,
3102 &ev->bdaddr);
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02003103
Johan Hedberga8b2d5c2012-01-08 23:11:15 +02003104 if (!test_bit(HCI_DEBUG_KEYS, &hdev->dev_flags) &&
Gustavo Padovan807deac2012-05-17 00:36:24 -03003105 key->type == HCI_LK_DEBUG_COMBINATION) {
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02003106 BT_DBG("%s ignoring debug key", hdev->name);
3107 goto not_found;
3108 }
3109
3110 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
Waldemar Rymarkiewicz60b83f52011-04-28 12:07:56 +02003111 if (conn) {
3112 if (key->type == HCI_LK_UNAUTH_COMBINATION &&
Gustavo Padovan807deac2012-05-17 00:36:24 -03003113 conn->auth_type != 0xff && (conn->auth_type & 0x01)) {
Waldemar Rymarkiewicz60b83f52011-04-28 12:07:56 +02003114 BT_DBG("%s ignoring unauthenticated key", hdev->name);
3115 goto not_found;
3116 }
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02003117
Waldemar Rymarkiewicz60b83f52011-04-28 12:07:56 +02003118 if (key->type == HCI_LK_COMBINATION && key->pin_len < 16 &&
Gustavo Padovan807deac2012-05-17 00:36:24 -03003119 conn->pending_sec_level == BT_SECURITY_HIGH) {
Gustavo Padovan8fc9ced2012-05-23 04:04:21 -03003120 BT_DBG("%s ignoring key unauthenticated for high security",
3121 hdev->name);
Waldemar Rymarkiewicz60b83f52011-04-28 12:07:56 +02003122 goto not_found;
3123 }
3124
3125 conn->key_type = key->type;
3126 conn->pin_length = key->pin_len;
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02003127 }
3128
3129 bacpy(&cp.bdaddr, &ev->bdaddr);
Andrei Emeltchenko9b3b4462012-05-23 11:31:20 +03003130 memcpy(cp.link_key, key->val, HCI_LINK_KEY_SIZE);
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02003131
3132 hci_send_cmd(hdev, HCI_OP_LINK_KEY_REPLY, sizeof(cp), &cp);
3133
3134 hci_dev_unlock(hdev);
3135
3136 return;
3137
3138not_found:
3139 hci_send_cmd(hdev, HCI_OP_LINK_KEY_NEG_REPLY, 6, &ev->bdaddr);
3140 hci_dev_unlock(hdev);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003141}
3142
Gustavo Padovan6039aa732012-05-23 04:04:18 -03003143static void hci_link_key_notify_evt(struct hci_dev *hdev, struct sk_buff *skb)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003144{
Marcel Holtmann052b30b2009-04-26 20:01:22 +02003145 struct hci_ev_link_key_notify *ev = (void *) skb->data;
3146 struct hci_conn *conn;
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02003147 u8 pin_len = 0;
Marcel Holtmann052b30b2009-04-26 20:01:22 +02003148
Marcel Holtmanna9de9242007-10-20 13:33:56 +02003149 BT_DBG("%s", hdev->name);
Marcel Holtmann052b30b2009-04-26 20:01:22 +02003150
3151 hci_dev_lock(hdev);
3152
3153 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
3154 if (conn) {
3155 hci_conn_hold(conn);
3156 conn->disc_timeout = HCI_DISCONN_TIMEOUT;
Johan Hedberg980e1a52011-01-22 06:10:07 +02003157 pin_len = conn->pin_length;
Waldemar Rymarkiewicz13d39312011-04-28 12:07:55 +02003158
3159 if (ev->key_type != HCI_LK_CHANGED_COMBINATION)
3160 conn->key_type = ev->key_type;
3161
Marcel Holtmann052b30b2009-04-26 20:01:22 +02003162 hci_conn_put(conn);
3163 }
3164
Johan Hedberga8b2d5c2012-01-08 23:11:15 +02003165 if (test_bit(HCI_LINK_KEYS, &hdev->dev_flags))
Johan Hedbergd25e28a2011-04-28 11:28:59 -07003166 hci_add_link_key(hdev, conn, 1, &ev->bdaddr, ev->link_key,
Gustavo Padovan807deac2012-05-17 00:36:24 -03003167 ev->key_type, pin_len);
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02003168
Marcel Holtmann052b30b2009-04-26 20:01:22 +02003169 hci_dev_unlock(hdev);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003170}
3171
Gustavo Padovan6039aa732012-05-23 04:04:18 -03003172static void hci_clock_offset_evt(struct hci_dev *hdev, struct sk_buff *skb)
Marcel Holtmann04837f62006-07-03 10:02:33 +02003173{
Marcel Holtmanna9de9242007-10-20 13:33:56 +02003174 struct hci_ev_clock_offset *ev = (void *) skb->data;
Marcel Holtmann04837f62006-07-03 10:02:33 +02003175 struct hci_conn *conn;
3176
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +03003177 BT_DBG("%s status 0x%2.2x", hdev->name, ev->status);
Marcel Holtmann04837f62006-07-03 10:02:33 +02003178
3179 hci_dev_lock(hdev);
3180
3181 conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
Linus Torvalds1da177e2005-04-16 15:20:36 -07003182 if (conn && !ev->status) {
3183 struct inquiry_entry *ie;
3184
Andrei Emeltchenkocc11b9c2010-11-22 13:21:37 +02003185 ie = hci_inquiry_cache_lookup(hdev, &conn->dst);
3186 if (ie) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003187 ie->data.clock_offset = ev->clock_offset;
3188 ie->timestamp = jiffies;
3189 }
3190 }
3191
3192 hci_dev_unlock(hdev);
3193}
3194
Gustavo Padovan6039aa732012-05-23 04:04:18 -03003195static void hci_pkt_type_change_evt(struct hci_dev *hdev, struct sk_buff *skb)
Marcel Holtmanna8746412008-07-14 20:13:46 +02003196{
3197 struct hci_ev_pkt_type_change *ev = (void *) skb->data;
3198 struct hci_conn *conn;
3199
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +03003200 BT_DBG("%s status 0x%2.2x", hdev->name, ev->status);
Marcel Holtmanna8746412008-07-14 20:13:46 +02003201
3202 hci_dev_lock(hdev);
3203
3204 conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
3205 if (conn && !ev->status)
3206 conn->pkt_type = __le16_to_cpu(ev->pkt_type);
3207
3208 hci_dev_unlock(hdev);
3209}
3210
Gustavo Padovan6039aa732012-05-23 04:04:18 -03003211static void hci_pscan_rep_mode_evt(struct hci_dev *hdev, struct sk_buff *skb)
Marcel Holtmann85a1e932005-08-09 20:28:02 -07003212{
Marcel Holtmanna9de9242007-10-20 13:33:56 +02003213 struct hci_ev_pscan_rep_mode *ev = (void *) skb->data;
Marcel Holtmann85a1e932005-08-09 20:28:02 -07003214 struct inquiry_entry *ie;
3215
3216 BT_DBG("%s", hdev->name);
3217
3218 hci_dev_lock(hdev);
3219
Andrei Emeltchenkocc11b9c2010-11-22 13:21:37 +02003220 ie = hci_inquiry_cache_lookup(hdev, &ev->bdaddr);
3221 if (ie) {
Marcel Holtmann85a1e932005-08-09 20:28:02 -07003222 ie->data.pscan_rep_mode = ev->pscan_rep_mode;
3223 ie->timestamp = jiffies;
3224 }
3225
3226 hci_dev_unlock(hdev);
3227}
3228
Gustavo Padovan6039aa732012-05-23 04:04:18 -03003229static void hci_inquiry_result_with_rssi_evt(struct hci_dev *hdev,
3230 struct sk_buff *skb)
Marcel Holtmanna9de9242007-10-20 13:33:56 +02003231{
3232 struct inquiry_data data;
3233 int num_rsp = *((__u8 *) skb->data);
Johan Hedberg388fc8f2012-02-23 00:38:59 +02003234 bool name_known, ssp;
Marcel Holtmanna9de9242007-10-20 13:33:56 +02003235
3236 BT_DBG("%s num_rsp %d", hdev->name, num_rsp);
3237
3238 if (!num_rsp)
3239 return;
3240
Andre Guedes1519cc12012-03-21 00:03:38 -03003241 if (test_bit(HCI_PERIODIC_INQ, &hdev->dev_flags))
3242 return;
3243
Marcel Holtmanna9de9242007-10-20 13:33:56 +02003244 hci_dev_lock(hdev);
3245
3246 if ((skb->len - 1) / num_rsp != sizeof(struct inquiry_info_with_rssi)) {
Szymon Janc138d22e2011-02-17 16:44:23 +01003247 struct inquiry_info_with_rssi_and_pscan_mode *info;
3248 info = (void *) (skb->data + 1);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02003249
Johan Hedberge17acd42011-03-30 23:57:16 +03003250 for (; num_rsp; num_rsp--, info++) {
Marcel Holtmanna9de9242007-10-20 13:33:56 +02003251 bacpy(&data.bdaddr, &info->bdaddr);
3252 data.pscan_rep_mode = info->pscan_rep_mode;
3253 data.pscan_period_mode = info->pscan_period_mode;
3254 data.pscan_mode = info->pscan_mode;
3255 memcpy(data.dev_class, info->dev_class, 3);
3256 data.clock_offset = info->clock_offset;
3257 data.rssi = info->rssi;
Marcel Holtmann41a96212008-07-14 20:13:48 +02003258 data.ssp_mode = 0x00;
Johan Hedberg31754052012-01-04 13:39:52 +02003259
3260 name_known = hci_inquiry_cache_update(hdev, &data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003261 false, &ssp);
Johan Hedberg48264f02011-11-09 13:58:58 +02003262 mgmt_device_found(hdev, &info->bdaddr, ACL_LINK, 0x00,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003263 info->dev_class, info->rssi,
3264 !name_known, ssp, NULL, 0);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02003265 }
3266 } else {
3267 struct inquiry_info_with_rssi *info = (void *) (skb->data + 1);
3268
Johan Hedberge17acd42011-03-30 23:57:16 +03003269 for (; num_rsp; num_rsp--, info++) {
Marcel Holtmanna9de9242007-10-20 13:33:56 +02003270 bacpy(&data.bdaddr, &info->bdaddr);
3271 data.pscan_rep_mode = info->pscan_rep_mode;
3272 data.pscan_period_mode = info->pscan_period_mode;
3273 data.pscan_mode = 0x00;
3274 memcpy(data.dev_class, info->dev_class, 3);
3275 data.clock_offset = info->clock_offset;
3276 data.rssi = info->rssi;
Marcel Holtmann41a96212008-07-14 20:13:48 +02003277 data.ssp_mode = 0x00;
Johan Hedberg31754052012-01-04 13:39:52 +02003278 name_known = hci_inquiry_cache_update(hdev, &data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003279 false, &ssp);
Johan Hedberg48264f02011-11-09 13:58:58 +02003280 mgmt_device_found(hdev, &info->bdaddr, ACL_LINK, 0x00,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003281 info->dev_class, info->rssi,
3282 !name_known, ssp, NULL, 0);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02003283 }
3284 }
3285
3286 hci_dev_unlock(hdev);
3287}
3288
Gustavo Padovan6039aa732012-05-23 04:04:18 -03003289static void hci_remote_ext_features_evt(struct hci_dev *hdev,
3290 struct sk_buff *skb)
Marcel Holtmanna9de9242007-10-20 13:33:56 +02003291{
Marcel Holtmann41a96212008-07-14 20:13:48 +02003292 struct hci_ev_remote_ext_features *ev = (void *) skb->data;
3293 struct hci_conn *conn;
3294
Marcel Holtmanna9de9242007-10-20 13:33:56 +02003295 BT_DBG("%s", hdev->name);
Marcel Holtmann41a96212008-07-14 20:13:48 +02003296
Marcel Holtmann41a96212008-07-14 20:13:48 +02003297 hci_dev_lock(hdev);
3298
3299 conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
Johan Hedbergccd556f2010-11-10 17:11:51 +02003300 if (!conn)
3301 goto unlock;
Marcel Holtmann41a96212008-07-14 20:13:48 +02003302
Johan Hedbergccd556f2010-11-10 17:11:51 +02003303 if (!ev->status && ev->page == 0x01) {
3304 struct inquiry_entry *ie;
Marcel Holtmann41a96212008-07-14 20:13:48 +02003305
Andrei Emeltchenkocc11b9c2010-11-22 13:21:37 +02003306 ie = hci_inquiry_cache_lookup(hdev, &conn->dst);
3307 if (ie)
Johan Hedberg02b7cc62012-02-28 02:28:43 +02003308 ie->data.ssp_mode = (ev->features[0] & LMP_HOST_SSP);
Marcel Holtmann769be972008-07-14 20:13:49 +02003309
Johan Hedberg02b7cc62012-02-28 02:28:43 +02003310 if (ev->features[0] & LMP_HOST_SSP)
Johan Hedberg58a681e2012-01-16 06:47:28 +02003311 set_bit(HCI_CONN_SSP_ENABLED, &conn->flags);
Marcel Holtmann41a96212008-07-14 20:13:48 +02003312 }
3313
Johan Hedbergccd556f2010-11-10 17:11:51 +02003314 if (conn->state != BT_CONFIG)
3315 goto unlock;
3316
Johan Hedberg671267b2012-05-12 16:11:50 -03003317 if (!ev->status && !test_bit(HCI_CONN_MGMT_CONNECTED, &conn->flags)) {
Johan Hedberg127178d2010-11-18 22:22:29 +02003318 struct hci_cp_remote_name_req cp;
3319 memset(&cp, 0, sizeof(cp));
3320 bacpy(&cp.bdaddr, &conn->dst);
3321 cp.pscan_rep_mode = 0x02;
3322 hci_send_cmd(hdev, HCI_OP_REMOTE_NAME_REQ, sizeof(cp), &cp);
Johan Hedbergb644ba32012-01-17 21:48:47 +02003323 } else if (!test_and_set_bit(HCI_CONN_MGMT_CONNECTED, &conn->flags))
3324 mgmt_device_connected(hdev, &conn->dst, conn->type,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003325 conn->dst_type, 0, NULL, 0,
3326 conn->dev_class);
Johan Hedberg392599b2010-11-18 22:22:28 +02003327
Johan Hedberg127178d2010-11-18 22:22:29 +02003328 if (!hci_outgoing_auth_needed(hdev, conn)) {
Johan Hedbergccd556f2010-11-10 17:11:51 +02003329 conn->state = BT_CONNECTED;
3330 hci_proto_connect_cfm(conn, ev->status);
3331 hci_conn_put(conn);
3332 }
3333
3334unlock:
Marcel Holtmann41a96212008-07-14 20:13:48 +02003335 hci_dev_unlock(hdev);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02003336}
3337
Gustavo Padovan6039aa732012-05-23 04:04:18 -03003338static void hci_sync_conn_complete_evt(struct hci_dev *hdev,
3339 struct sk_buff *skb)
Marcel Holtmanna9de9242007-10-20 13:33:56 +02003340{
Marcel Holtmannb6a0dc82007-10-20 14:55:10 +02003341 struct hci_ev_sync_conn_complete *ev = (void *) skb->data;
3342 struct hci_conn *conn;
3343
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +03003344 BT_DBG("%s status 0x%2.2x", hdev->name, ev->status);
Marcel Holtmannb6a0dc82007-10-20 14:55:10 +02003345
3346 hci_dev_lock(hdev);
3347
3348 conn = hci_conn_hash_lookup_ba(hdev, ev->link_type, &ev->bdaddr);
Marcel Holtmann9dc0a3a2008-07-14 20:13:46 +02003349 if (!conn) {
3350 if (ev->link_type == ESCO_LINK)
3351 goto unlock;
3352
3353 conn = hci_conn_hash_lookup_ba(hdev, ESCO_LINK, &ev->bdaddr);
3354 if (!conn)
3355 goto unlock;
3356
3357 conn->type = SCO_LINK;
3358 }
Marcel Holtmannb6a0dc82007-10-20 14:55:10 +02003359
Marcel Holtmann732547f2009-04-19 19:14:14 +02003360 switch (ev->status) {
3361 case 0x00:
Marcel Holtmannb6a0dc82007-10-20 14:55:10 +02003362 conn->handle = __le16_to_cpu(ev->handle);
3363 conn->state = BT_CONNECTED;
Marcel Holtmann7d0db0a2008-07-14 20:13:51 +02003364
Marcel Holtmann9eba32b2009-08-22 14:19:26 -07003365 hci_conn_hold_device(conn);
Marcel Holtmann7d0db0a2008-07-14 20:13:51 +02003366 hci_conn_add_sysfs(conn);
Marcel Holtmann732547f2009-04-19 19:14:14 +02003367 break;
3368
Stephen Coe705e5712010-02-16 11:29:44 -05003369 case 0x11: /* Unsupported Feature or Parameter Value */
Marcel Holtmann732547f2009-04-19 19:14:14 +02003370 case 0x1c: /* SCO interval rejected */
Nick Pelly1038a002010-02-03 11:42:26 -08003371 case 0x1a: /* Unsupported Remote Feature */
Marcel Holtmann732547f2009-04-19 19:14:14 +02003372 case 0x1f: /* Unspecified error */
3373 if (conn->out && conn->attempt < 2) {
3374 conn->pkt_type = (hdev->esco_type & SCO_ESCO_MASK) |
3375 (hdev->esco_type & EDR_ESCO_MASK);
3376 hci_setup_sync(conn, conn->link->handle);
3377 goto unlock;
3378 }
3379 /* fall through */
3380
3381 default:
Marcel Holtmannb6a0dc82007-10-20 14:55:10 +02003382 conn->state = BT_CLOSED;
Marcel Holtmann732547f2009-04-19 19:14:14 +02003383 break;
3384 }
Marcel Holtmannb6a0dc82007-10-20 14:55:10 +02003385
3386 hci_proto_connect_cfm(conn, ev->status);
3387 if (ev->status)
3388 hci_conn_del(conn);
3389
3390unlock:
3391 hci_dev_unlock(hdev);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02003392}
3393
Gustavo Padovan6039aa732012-05-23 04:04:18 -03003394static void hci_sync_conn_changed_evt(struct hci_dev *hdev, struct sk_buff *skb)
Marcel Holtmanna9de9242007-10-20 13:33:56 +02003395{
3396 BT_DBG("%s", hdev->name);
3397}
3398
Gustavo Padovan6039aa732012-05-23 04:04:18 -03003399static void hci_sniff_subrate_evt(struct hci_dev *hdev, struct sk_buff *skb)
Marcel Holtmann04837f62006-07-03 10:02:33 +02003400{
Marcel Holtmanna9de9242007-10-20 13:33:56 +02003401 struct hci_ev_sniff_subrate *ev = (void *) skb->data;
Marcel Holtmann04837f62006-07-03 10:02:33 +02003402
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +03003403 BT_DBG("%s status 0x%2.2x", hdev->name, ev->status);
Marcel Holtmann04837f62006-07-03 10:02:33 +02003404}
3405
Gustavo Padovan6039aa732012-05-23 04:04:18 -03003406static void hci_extended_inquiry_result_evt(struct hci_dev *hdev,
3407 struct sk_buff *skb)
Marcel Holtmanna9de9242007-10-20 13:33:56 +02003408{
3409 struct inquiry_data data;
3410 struct extended_inquiry_info *info = (void *) (skb->data + 1);
3411 int num_rsp = *((__u8 *) skb->data);
Vishal Agarwal9d939d92012-04-26 19:19:56 +05303412 size_t eir_len;
Marcel Holtmanna9de9242007-10-20 13:33:56 +02003413
3414 BT_DBG("%s num_rsp %d", hdev->name, num_rsp);
3415
3416 if (!num_rsp)
3417 return;
3418
Andre Guedes1519cc12012-03-21 00:03:38 -03003419 if (test_bit(HCI_PERIODIC_INQ, &hdev->dev_flags))
3420 return;
3421
Marcel Holtmanna9de9242007-10-20 13:33:56 +02003422 hci_dev_lock(hdev);
3423
Johan Hedberge17acd42011-03-30 23:57:16 +03003424 for (; num_rsp; num_rsp--, info++) {
Johan Hedberg388fc8f2012-02-23 00:38:59 +02003425 bool name_known, ssp;
Johan Hedberg561aafb2012-01-04 13:31:59 +02003426
Marcel Holtmanna9de9242007-10-20 13:33:56 +02003427 bacpy(&data.bdaddr, &info->bdaddr);
Szymon Janc138d22e2011-02-17 16:44:23 +01003428 data.pscan_rep_mode = info->pscan_rep_mode;
3429 data.pscan_period_mode = info->pscan_period_mode;
3430 data.pscan_mode = 0x00;
Marcel Holtmanna9de9242007-10-20 13:33:56 +02003431 memcpy(data.dev_class, info->dev_class, 3);
Szymon Janc138d22e2011-02-17 16:44:23 +01003432 data.clock_offset = info->clock_offset;
3433 data.rssi = info->rssi;
Marcel Holtmann41a96212008-07-14 20:13:48 +02003434 data.ssp_mode = 0x01;
Johan Hedberg561aafb2012-01-04 13:31:59 +02003435
Johan Hedberga8b2d5c2012-01-08 23:11:15 +02003436 if (test_bit(HCI_MGMT, &hdev->dev_flags))
Johan Hedberg4ddb1932012-01-15 20:04:43 +02003437 name_known = eir_has_data_type(info->data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003438 sizeof(info->data),
3439 EIR_NAME_COMPLETE);
Johan Hedberg561aafb2012-01-04 13:31:59 +02003440 else
3441 name_known = true;
3442
Johan Hedberg388fc8f2012-02-23 00:38:59 +02003443 name_known = hci_inquiry_cache_update(hdev, &data, name_known,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003444 &ssp);
Vishal Agarwal9d939d92012-04-26 19:19:56 +05303445 eir_len = eir_get_length(info->data, sizeof(info->data));
Johan Hedberg48264f02011-11-09 13:58:58 +02003446 mgmt_device_found(hdev, &info->bdaddr, ACL_LINK, 0x00,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003447 info->dev_class, info->rssi, !name_known,
Vishal Agarwal9d939d92012-04-26 19:19:56 +05303448 ssp, info->data, eir_len);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02003449 }
3450
3451 hci_dev_unlock(hdev);
3452}
3453
Johan Hedberg1c2e0042012-06-08 23:31:13 +08003454static void hci_key_refresh_complete_evt(struct hci_dev *hdev,
3455 struct sk_buff *skb)
3456{
3457 struct hci_ev_key_refresh_complete *ev = (void *) skb->data;
3458 struct hci_conn *conn;
3459
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +03003460 BT_DBG("%s status 0x%2.2x handle 0x%4.4x", hdev->name, ev->status,
Johan Hedberg1c2e0042012-06-08 23:31:13 +08003461 __le16_to_cpu(ev->handle));
3462
3463 hci_dev_lock(hdev);
3464
3465 conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
3466 if (!conn)
3467 goto unlock;
3468
3469 if (!ev->status)
3470 conn->sec_level = conn->pending_sec_level;
3471
3472 clear_bit(HCI_CONN_ENCRYPT_PEND, &conn->flags);
3473
3474 if (ev->status && conn->state == BT_CONNECTED) {
3475 hci_acl_disconn(conn, HCI_ERROR_AUTH_FAILURE);
3476 hci_conn_put(conn);
3477 goto unlock;
3478 }
3479
3480 if (conn->state == BT_CONFIG) {
3481 if (!ev->status)
3482 conn->state = BT_CONNECTED;
3483
3484 hci_proto_connect_cfm(conn, ev->status);
3485 hci_conn_put(conn);
3486 } else {
3487 hci_auth_cfm(conn, ev->status);
3488
3489 hci_conn_hold(conn);
3490 conn->disc_timeout = HCI_DISCONN_TIMEOUT;
3491 hci_conn_put(conn);
3492 }
3493
3494unlock:
3495 hci_dev_unlock(hdev);
3496}
3497
Gustavo Padovan6039aa732012-05-23 04:04:18 -03003498static u8 hci_get_auth_req(struct hci_conn *conn)
Johan Hedberg17fa4b92011-01-25 13:28:33 +02003499{
3500 /* If remote requests dedicated bonding follow that lead */
3501 if (conn->remote_auth == 0x02 || conn->remote_auth == 0x03) {
3502 /* If both remote and local IO capabilities allow MITM
3503 * protection then require it, otherwise don't */
3504 if (conn->remote_cap == 0x03 || conn->io_capability == 0x03)
3505 return 0x02;
3506 else
3507 return 0x03;
3508 }
3509
3510 /* If remote requests no-bonding follow that lead */
3511 if (conn->remote_auth == 0x00 || conn->remote_auth == 0x01)
Waldemar Rymarkiewicz58797bf2011-04-28 12:07:58 +02003512 return conn->remote_auth | (conn->auth_type & 0x01);
Johan Hedberg17fa4b92011-01-25 13:28:33 +02003513
3514 return conn->auth_type;
3515}
3516
Gustavo Padovan6039aa732012-05-23 04:04:18 -03003517static void hci_io_capa_request_evt(struct hci_dev *hdev, struct sk_buff *skb)
Marcel Holtmann04936842008-07-14 20:13:48 +02003518{
3519 struct hci_ev_io_capa_request *ev = (void *) skb->data;
3520 struct hci_conn *conn;
3521
3522 BT_DBG("%s", hdev->name);
3523
3524 hci_dev_lock(hdev);
3525
3526 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
Johan Hedberg03b555e2011-01-04 15:40:05 +02003527 if (!conn)
3528 goto unlock;
Marcel Holtmann04936842008-07-14 20:13:48 +02003529
Johan Hedberg03b555e2011-01-04 15:40:05 +02003530 hci_conn_hold(conn);
3531
Johan Hedberga8b2d5c2012-01-08 23:11:15 +02003532 if (!test_bit(HCI_MGMT, &hdev->dev_flags))
Johan Hedberg03b555e2011-01-04 15:40:05 +02003533 goto unlock;
3534
Johan Hedberga8b2d5c2012-01-08 23:11:15 +02003535 if (test_bit(HCI_PAIRABLE, &hdev->dev_flags) ||
Gustavo Padovan807deac2012-05-17 00:36:24 -03003536 (conn->remote_auth & ~0x01) == HCI_AT_NO_BONDING) {
Johan Hedberg17fa4b92011-01-25 13:28:33 +02003537 struct hci_cp_io_capability_reply cp;
3538
3539 bacpy(&cp.bdaddr, &ev->bdaddr);
Hemant Gupta7a7f1e72012-01-16 13:34:29 +05303540 /* Change the IO capability from KeyboardDisplay
3541 * to DisplayYesNo as it is not supported by BT spec. */
3542 cp.capability = (conn->io_capability == 0x04) ?
3543 0x01 : conn->io_capability;
Johan Hedberg7cbc9bd2011-04-28 11:29:04 -07003544 conn->auth_type = hci_get_auth_req(conn);
3545 cp.authentication = conn->auth_type;
Johan Hedberg17fa4b92011-01-25 13:28:33 +02003546
Gustavo Padovan8fc9ced2012-05-23 04:04:21 -03003547 if (hci_find_remote_oob_data(hdev, &conn->dst) &&
3548 (conn->out || test_bit(HCI_CONN_REMOTE_OOB, &conn->flags)))
Szymon Jancce85ee12011-03-22 13:12:23 +01003549 cp.oob_data = 0x01;
3550 else
3551 cp.oob_data = 0x00;
3552
Johan Hedberg17fa4b92011-01-25 13:28:33 +02003553 hci_send_cmd(hdev, HCI_OP_IO_CAPABILITY_REPLY,
Gustavo Padovan807deac2012-05-17 00:36:24 -03003554 sizeof(cp), &cp);
Johan Hedberg03b555e2011-01-04 15:40:05 +02003555 } else {
3556 struct hci_cp_io_capability_neg_reply cp;
3557
3558 bacpy(&cp.bdaddr, &ev->bdaddr);
Andrei Emeltchenko9f5a0d72011-11-07 14:20:25 +02003559 cp.reason = HCI_ERROR_PAIRING_NOT_ALLOWED;
Johan Hedberg03b555e2011-01-04 15:40:05 +02003560
3561 hci_send_cmd(hdev, HCI_OP_IO_CAPABILITY_NEG_REPLY,
Gustavo Padovan807deac2012-05-17 00:36:24 -03003562 sizeof(cp), &cp);
Johan Hedberg03b555e2011-01-04 15:40:05 +02003563 }
3564
3565unlock:
3566 hci_dev_unlock(hdev);
3567}
3568
Gustavo Padovan6039aa732012-05-23 04:04:18 -03003569static void hci_io_capa_reply_evt(struct hci_dev *hdev, struct sk_buff *skb)
Johan Hedberg03b555e2011-01-04 15:40:05 +02003570{
3571 struct hci_ev_io_capa_reply *ev = (void *) skb->data;
3572 struct hci_conn *conn;
3573
3574 BT_DBG("%s", hdev->name);
3575
3576 hci_dev_lock(hdev);
3577
3578 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
3579 if (!conn)
3580 goto unlock;
3581
Johan Hedberg03b555e2011-01-04 15:40:05 +02003582 conn->remote_cap = ev->capability;
Johan Hedberg03b555e2011-01-04 15:40:05 +02003583 conn->remote_auth = ev->authentication;
Johan Hedberg58a681e2012-01-16 06:47:28 +02003584 if (ev->oob_data)
3585 set_bit(HCI_CONN_REMOTE_OOB, &conn->flags);
Johan Hedberg03b555e2011-01-04 15:40:05 +02003586
3587unlock:
Marcel Holtmann04936842008-07-14 20:13:48 +02003588 hci_dev_unlock(hdev);
3589}
3590
Gustavo Padovan6039aa732012-05-23 04:04:18 -03003591static void hci_user_confirm_request_evt(struct hci_dev *hdev,
3592 struct sk_buff *skb)
Johan Hedberga5c29682011-02-19 12:05:57 -03003593{
3594 struct hci_ev_user_confirm_req *ev = (void *) skb->data;
Johan Hedberg55bc1a32011-04-28 11:28:56 -07003595 int loc_mitm, rem_mitm, confirm_hint = 0;
Johan Hedberg7a828902011-04-28 11:28:53 -07003596 struct hci_conn *conn;
Johan Hedberga5c29682011-02-19 12:05:57 -03003597
3598 BT_DBG("%s", hdev->name);
3599
3600 hci_dev_lock(hdev);
3601
Johan Hedberga8b2d5c2012-01-08 23:11:15 +02003602 if (!test_bit(HCI_MGMT, &hdev->dev_flags))
Johan Hedberg7a828902011-04-28 11:28:53 -07003603 goto unlock;
Johan Hedberga5c29682011-02-19 12:05:57 -03003604
Johan Hedberg7a828902011-04-28 11:28:53 -07003605 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
3606 if (!conn)
3607 goto unlock;
3608
3609 loc_mitm = (conn->auth_type & 0x01);
3610 rem_mitm = (conn->remote_auth & 0x01);
3611
3612 /* If we require MITM but the remote device can't provide that
3613 * (it has NoInputNoOutput) then reject the confirmation
3614 * request. The only exception is when we're dedicated bonding
3615 * initiators (connect_cfm_cb set) since then we always have the MITM
3616 * bit set. */
3617 if (!conn->connect_cfm_cb && loc_mitm && conn->remote_cap == 0x03) {
3618 BT_DBG("Rejecting request: remote device can't provide MITM");
3619 hci_send_cmd(hdev, HCI_OP_USER_CONFIRM_NEG_REPLY,
Gustavo Padovan807deac2012-05-17 00:36:24 -03003620 sizeof(ev->bdaddr), &ev->bdaddr);
Johan Hedberg7a828902011-04-28 11:28:53 -07003621 goto unlock;
3622 }
3623
3624 /* If no side requires MITM protection; auto-accept */
3625 if ((!loc_mitm || conn->remote_cap == 0x03) &&
Gustavo Padovan807deac2012-05-17 00:36:24 -03003626 (!rem_mitm || conn->io_capability == 0x03)) {
Johan Hedberg55bc1a32011-04-28 11:28:56 -07003627
3628 /* If we're not the initiators request authorization to
3629 * proceed from user space (mgmt_user_confirm with
3630 * confirm_hint set to 1). */
Johan Hedberg51a8efd2012-01-16 06:10:31 +02003631 if (!test_bit(HCI_CONN_AUTH_PEND, &conn->flags)) {
Johan Hedberg55bc1a32011-04-28 11:28:56 -07003632 BT_DBG("Confirming auto-accept as acceptor");
3633 confirm_hint = 1;
3634 goto confirm;
3635 }
3636
Johan Hedberg9f616562011-04-28 11:28:54 -07003637 BT_DBG("Auto-accept of user confirmation with %ums delay",
Gustavo Padovan807deac2012-05-17 00:36:24 -03003638 hdev->auto_accept_delay);
Johan Hedberg9f616562011-04-28 11:28:54 -07003639
3640 if (hdev->auto_accept_delay > 0) {
3641 int delay = msecs_to_jiffies(hdev->auto_accept_delay);
3642 mod_timer(&conn->auto_accept_timer, jiffies + delay);
3643 goto unlock;
3644 }
3645
Johan Hedberg7a828902011-04-28 11:28:53 -07003646 hci_send_cmd(hdev, HCI_OP_USER_CONFIRM_REPLY,
Gustavo Padovan807deac2012-05-17 00:36:24 -03003647 sizeof(ev->bdaddr), &ev->bdaddr);
Johan Hedberg7a828902011-04-28 11:28:53 -07003648 goto unlock;
3649 }
3650
Johan Hedberg55bc1a32011-04-28 11:28:56 -07003651confirm:
Johan Hedberg272d90d2012-02-09 15:26:12 +02003652 mgmt_user_confirm_request(hdev, &ev->bdaddr, ACL_LINK, 0, ev->passkey,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003653 confirm_hint);
Johan Hedberg7a828902011-04-28 11:28:53 -07003654
3655unlock:
Johan Hedberga5c29682011-02-19 12:05:57 -03003656 hci_dev_unlock(hdev);
3657}
3658
Gustavo Padovan6039aa732012-05-23 04:04:18 -03003659static void hci_user_passkey_request_evt(struct hci_dev *hdev,
3660 struct sk_buff *skb)
Brian Gix1143d452011-11-23 08:28:34 -08003661{
3662 struct hci_ev_user_passkey_req *ev = (void *) skb->data;
3663
3664 BT_DBG("%s", hdev->name);
3665
Johan Hedberga8b2d5c2012-01-08 23:11:15 +02003666 if (test_bit(HCI_MGMT, &hdev->dev_flags))
Johan Hedberg272d90d2012-02-09 15:26:12 +02003667 mgmt_user_passkey_request(hdev, &ev->bdaddr, ACL_LINK, 0);
Brian Gix1143d452011-11-23 08:28:34 -08003668}
3669
Johan Hedberg92a25252012-09-06 18:39:26 +03003670static void hci_user_passkey_notify_evt(struct hci_dev *hdev,
3671 struct sk_buff *skb)
3672{
3673 struct hci_ev_user_passkey_notify *ev = (void *) skb->data;
3674 struct hci_conn *conn;
3675
3676 BT_DBG("%s", hdev->name);
3677
3678 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
3679 if (!conn)
3680 return;
3681
3682 conn->passkey_notify = __le32_to_cpu(ev->passkey);
3683 conn->passkey_entered = 0;
3684
3685 if (test_bit(HCI_MGMT, &hdev->dev_flags))
3686 mgmt_user_passkey_notify(hdev, &conn->dst, conn->type,
3687 conn->dst_type, conn->passkey_notify,
3688 conn->passkey_entered);
3689}
3690
3691static void hci_keypress_notify_evt(struct hci_dev *hdev, struct sk_buff *skb)
3692{
3693 struct hci_ev_keypress_notify *ev = (void *) skb->data;
3694 struct hci_conn *conn;
3695
3696 BT_DBG("%s", hdev->name);
3697
3698 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
3699 if (!conn)
3700 return;
3701
3702 switch (ev->type) {
3703 case HCI_KEYPRESS_STARTED:
3704 conn->passkey_entered = 0;
3705 return;
3706
3707 case HCI_KEYPRESS_ENTERED:
3708 conn->passkey_entered++;
3709 break;
3710
3711 case HCI_KEYPRESS_ERASED:
3712 conn->passkey_entered--;
3713 break;
3714
3715 case HCI_KEYPRESS_CLEARED:
3716 conn->passkey_entered = 0;
3717 break;
3718
3719 case HCI_KEYPRESS_COMPLETED:
3720 return;
3721 }
3722
3723 if (test_bit(HCI_MGMT, &hdev->dev_flags))
3724 mgmt_user_passkey_notify(hdev, &conn->dst, conn->type,
3725 conn->dst_type, conn->passkey_notify,
3726 conn->passkey_entered);
3727}
3728
Gustavo Padovan6039aa732012-05-23 04:04:18 -03003729static void hci_simple_pair_complete_evt(struct hci_dev *hdev,
3730 struct sk_buff *skb)
Marcel Holtmann04936842008-07-14 20:13:48 +02003731{
3732 struct hci_ev_simple_pair_complete *ev = (void *) skb->data;
3733 struct hci_conn *conn;
3734
3735 BT_DBG("%s", hdev->name);
3736
3737 hci_dev_lock(hdev);
3738
3739 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
Johan Hedberg2a611692011-02-19 12:06:00 -03003740 if (!conn)
3741 goto unlock;
Marcel Holtmann04936842008-07-14 20:13:48 +02003742
Johan Hedberg2a611692011-02-19 12:06:00 -03003743 /* To avoid duplicate auth_failed events to user space we check
3744 * the HCI_CONN_AUTH_PEND flag which will be set if we
3745 * initiated the authentication. A traditional auth_complete
3746 * event gets always produced as initiator and is also mapped to
3747 * the mgmt_auth_failed event */
Mikel Astizfa1bd912012-08-09 09:52:29 +02003748 if (!test_bit(HCI_CONN_AUTH_PEND, &conn->flags) && ev->status)
Johan Hedbergbab73cb2012-02-09 16:07:29 +02003749 mgmt_auth_failed(hdev, &conn->dst, conn->type, conn->dst_type,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003750 ev->status);
Johan Hedberg2a611692011-02-19 12:06:00 -03003751
3752 hci_conn_put(conn);
3753
3754unlock:
Marcel Holtmann04936842008-07-14 20:13:48 +02003755 hci_dev_unlock(hdev);
3756}
3757
Gustavo Padovan6039aa732012-05-23 04:04:18 -03003758static void hci_remote_host_features_evt(struct hci_dev *hdev,
3759 struct sk_buff *skb)
Marcel Holtmann41a96212008-07-14 20:13:48 +02003760{
3761 struct hci_ev_remote_host_features *ev = (void *) skb->data;
3762 struct inquiry_entry *ie;
3763
3764 BT_DBG("%s", hdev->name);
3765
3766 hci_dev_lock(hdev);
3767
Andrei Emeltchenkocc11b9c2010-11-22 13:21:37 +02003768 ie = hci_inquiry_cache_lookup(hdev, &ev->bdaddr);
3769 if (ie)
Johan Hedberg02b7cc62012-02-28 02:28:43 +02003770 ie->data.ssp_mode = (ev->features[0] & LMP_HOST_SSP);
Marcel Holtmann41a96212008-07-14 20:13:48 +02003771
3772 hci_dev_unlock(hdev);
3773}
3774
Gustavo Padovan6039aa732012-05-23 04:04:18 -03003775static void hci_remote_oob_data_request_evt(struct hci_dev *hdev,
3776 struct sk_buff *skb)
Szymon Janc2763eda2011-03-22 13:12:22 +01003777{
3778 struct hci_ev_remote_oob_data_request *ev = (void *) skb->data;
3779 struct oob_data *data;
3780
3781 BT_DBG("%s", hdev->name);
3782
3783 hci_dev_lock(hdev);
3784
Johan Hedberga8b2d5c2012-01-08 23:11:15 +02003785 if (!test_bit(HCI_MGMT, &hdev->dev_flags))
Szymon Jance1ba1f12011-04-06 13:01:59 +02003786 goto unlock;
3787
Szymon Janc2763eda2011-03-22 13:12:22 +01003788 data = hci_find_remote_oob_data(hdev, &ev->bdaddr);
3789 if (data) {
3790 struct hci_cp_remote_oob_data_reply cp;
3791
3792 bacpy(&cp.bdaddr, &ev->bdaddr);
3793 memcpy(cp.hash, data->hash, sizeof(cp.hash));
3794 memcpy(cp.randomizer, data->randomizer, sizeof(cp.randomizer));
3795
3796 hci_send_cmd(hdev, HCI_OP_REMOTE_OOB_DATA_REPLY, sizeof(cp),
Gustavo Padovan807deac2012-05-17 00:36:24 -03003797 &cp);
Szymon Janc2763eda2011-03-22 13:12:22 +01003798 } else {
3799 struct hci_cp_remote_oob_data_neg_reply cp;
3800
3801 bacpy(&cp.bdaddr, &ev->bdaddr);
3802 hci_send_cmd(hdev, HCI_OP_REMOTE_OOB_DATA_NEG_REPLY, sizeof(cp),
Gustavo Padovan807deac2012-05-17 00:36:24 -03003803 &cp);
Szymon Janc2763eda2011-03-22 13:12:22 +01003804 }
3805
Szymon Jance1ba1f12011-04-06 13:01:59 +02003806unlock:
Szymon Janc2763eda2011-03-22 13:12:22 +01003807 hci_dev_unlock(hdev);
3808}
3809
Andrei Emeltchenkod5e91192012-10-25 15:20:44 +03003810static void hci_phy_link_complete_evt(struct hci_dev *hdev,
3811 struct sk_buff *skb)
3812{
3813 struct hci_ev_phy_link_complete *ev = (void *) skb->data;
3814 struct hci_conn *hcon, *bredr_hcon;
3815
3816 BT_DBG("%s handle 0x%2.2x status 0x%2.2x", hdev->name, ev->phy_handle,
3817 ev->status);
3818
3819 hci_dev_lock(hdev);
3820
3821 hcon = hci_conn_hash_lookup_handle(hdev, ev->phy_handle);
3822 if (!hcon) {
3823 hci_dev_unlock(hdev);
3824 return;
3825 }
3826
3827 if (ev->status) {
3828 hci_conn_del(hcon);
3829 hci_dev_unlock(hdev);
3830 return;
3831 }
3832
3833 bredr_hcon = hcon->amp_mgr->l2cap_conn->hcon;
3834
3835 hcon->state = BT_CONNECTED;
3836 bacpy(&hcon->dst, &bredr_hcon->dst);
3837
3838 hci_conn_hold(hcon);
3839 hcon->disc_timeout = HCI_DISCONN_TIMEOUT;
3840 hci_conn_put(hcon);
3841
3842 hci_conn_hold_device(hcon);
3843 hci_conn_add_sysfs(hcon);
3844
Andrei Emeltchenkocf70ff22012-10-31 15:46:36 +02003845 amp_physical_cfm(bredr_hcon, hcon);
3846
Andrei Emeltchenkod5e91192012-10-25 15:20:44 +03003847 hci_dev_unlock(hdev);
Andrei Emeltchenkod5e91192012-10-25 15:20:44 +03003848}
3849
Andrei Emeltchenko27695fb2012-10-25 15:20:45 +03003850static void hci_loglink_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
3851{
3852 struct hci_ev_logical_link_complete *ev = (void *) skb->data;
3853 struct hci_conn *hcon;
3854 struct hci_chan *hchan;
3855 struct amp_mgr *mgr;
3856
3857 BT_DBG("%s log_handle 0x%4.4x phy_handle 0x%2.2x status 0x%2.2x",
3858 hdev->name, le16_to_cpu(ev->handle), ev->phy_handle,
3859 ev->status);
3860
3861 hcon = hci_conn_hash_lookup_handle(hdev, ev->phy_handle);
3862 if (!hcon)
3863 return;
3864
3865 /* Create AMP hchan */
3866 hchan = hci_chan_create(hcon);
3867 if (!hchan)
3868 return;
3869
3870 hchan->handle = le16_to_cpu(ev->handle);
3871
3872 BT_DBG("hcon %p mgr %p hchan %p", hcon, hcon->amp_mgr, hchan);
3873
3874 mgr = hcon->amp_mgr;
3875 if (mgr && mgr->bredr_chan) {
3876 struct l2cap_chan *bredr_chan = mgr->bredr_chan;
3877
3878 l2cap_chan_lock(bredr_chan);
3879
3880 bredr_chan->conn->mtu = hdev->block_mtu;
3881 l2cap_logical_cfm(bredr_chan, hchan, 0);
3882 hci_conn_hold(hcon);
3883
3884 l2cap_chan_unlock(bredr_chan);
3885 }
3886}
3887
Andrei Emeltchenko606e2a12012-10-31 15:46:31 +02003888static void hci_disconn_loglink_complete_evt(struct hci_dev *hdev,
3889 struct sk_buff *skb)
3890{
3891 struct hci_ev_disconn_logical_link_complete *ev = (void *) skb->data;
3892 struct hci_chan *hchan;
3893
3894 BT_DBG("%s log handle 0x%4.4x status 0x%2.2x", hdev->name,
3895 le16_to_cpu(ev->handle), ev->status);
3896
3897 if (ev->status)
3898 return;
3899
3900 hci_dev_lock(hdev);
3901
3902 hchan = hci_chan_lookup_handle(hdev, le16_to_cpu(ev->handle));
3903 if (!hchan)
3904 goto unlock;
3905
3906 amp_destroy_logical_link(hchan, ev->reason);
3907
3908unlock:
3909 hci_dev_unlock(hdev);
3910}
3911
Andrei Emeltchenko9eef6b32012-10-31 15:46:32 +02003912static void hci_disconn_phylink_complete_evt(struct hci_dev *hdev,
3913 struct sk_buff *skb)
3914{
3915 struct hci_ev_disconn_phy_link_complete *ev = (void *) skb->data;
3916 struct hci_conn *hcon;
3917
3918 BT_DBG("%s status 0x%2.2x", hdev->name, ev->status);
3919
3920 if (ev->status)
3921 return;
3922
3923 hci_dev_lock(hdev);
3924
3925 hcon = hci_conn_hash_lookup_handle(hdev, ev->phy_handle);
3926 if (hcon) {
3927 hcon->state = BT_CLOSED;
3928 hci_conn_del(hcon);
3929 }
3930
3931 hci_dev_unlock(hdev);
3932}
3933
Gustavo Padovan6039aa732012-05-23 04:04:18 -03003934static void hci_le_conn_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
Ville Tervofcd89c02011-02-10 22:38:47 -03003935{
3936 struct hci_ev_le_conn_complete *ev = (void *) skb->data;
3937 struct hci_conn *conn;
3938
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +03003939 BT_DBG("%s status 0x%2.2x", hdev->name, ev->status);
Ville Tervofcd89c02011-02-10 22:38:47 -03003940
3941 hci_dev_lock(hdev);
3942
Andre Guedesb47a09b2012-07-27 15:10:15 -03003943 conn = hci_conn_hash_lookup_state(hdev, LE_LINK, BT_CONNECT);
Ville Tervob62f3282011-02-10 22:38:50 -03003944 if (!conn) {
3945 conn = hci_conn_add(hdev, LE_LINK, &ev->bdaddr);
3946 if (!conn) {
3947 BT_ERR("No memory for new connection");
Andre Guedes230fd162012-07-27 15:10:10 -03003948 goto unlock;
Ville Tervob62f3282011-02-10 22:38:50 -03003949 }
Andre Guedes29b79882011-05-31 14:20:54 -03003950
3951 conn->dst_type = ev->bdaddr_type;
Andre Guedesb9b343d2012-07-27 15:10:11 -03003952
3953 if (ev->role == LE_CONN_ROLE_MASTER) {
3954 conn->out = true;
3955 conn->link_mode |= HCI_LM_MASTER;
3956 }
Ville Tervob62f3282011-02-10 22:38:50 -03003957 }
Ville Tervofcd89c02011-02-10 22:38:47 -03003958
Andre Guedescd17dec2012-07-27 15:10:16 -03003959 if (ev->status) {
3960 mgmt_connect_failed(hdev, &conn->dst, conn->type,
3961 conn->dst_type, ev->status);
3962 hci_proto_connect_cfm(conn, ev->status);
3963 conn->state = BT_CLOSED;
3964 hci_conn_del(conn);
3965 goto unlock;
3966 }
3967
Johan Hedbergb644ba32012-01-17 21:48:47 +02003968 if (!test_and_set_bit(HCI_CONN_MGMT_CONNECTED, &conn->flags))
3969 mgmt_device_connected(hdev, &ev->bdaddr, conn->type,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003970 conn->dst_type, 0, NULL, 0, NULL);
Vinicius Costa Gomes83bc71b2011-05-06 18:41:43 -03003971
Vinicius Costa Gomes7b5c0d52011-06-09 18:50:50 -03003972 conn->sec_level = BT_SECURITY_LOW;
Ville Tervofcd89c02011-02-10 22:38:47 -03003973 conn->handle = __le16_to_cpu(ev->handle);
3974 conn->state = BT_CONNECTED;
3975
3976 hci_conn_hold_device(conn);
3977 hci_conn_add_sysfs(conn);
3978
3979 hci_proto_connect_cfm(conn, ev->status);
3980
3981unlock:
3982 hci_dev_unlock(hdev);
3983}
3984
Gustavo Padovan6039aa732012-05-23 04:04:18 -03003985static void hci_le_adv_report_evt(struct hci_dev *hdev, struct sk_buff *skb)
Andre Guedes9aa04c92011-05-26 16:23:51 -03003986{
Andre Guedese95beb42011-09-26 20:48:35 -03003987 u8 num_reports = skb->data[0];
3988 void *ptr = &skb->data[1];
Andre Guedes3c9e9192012-01-10 18:20:50 -03003989 s8 rssi;
Andre Guedes9aa04c92011-05-26 16:23:51 -03003990
Andre Guedese95beb42011-09-26 20:48:35 -03003991 while (num_reports--) {
3992 struct hci_ev_le_advertising_info *ev = ptr;
Andre Guedes9aa04c92011-05-26 16:23:51 -03003993
Andre Guedes3c9e9192012-01-10 18:20:50 -03003994 rssi = ev->data[ev->length];
3995 mgmt_device_found(hdev, &ev->bdaddr, LE_LINK, ev->bdaddr_type,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003996 NULL, rssi, 0, 1, ev->data, ev->length);
Andre Guedes3c9e9192012-01-10 18:20:50 -03003997
Andre Guedese95beb42011-09-26 20:48:35 -03003998 ptr += sizeof(*ev) + ev->length + 1;
Andre Guedes9aa04c92011-05-26 16:23:51 -03003999 }
Andre Guedes9aa04c92011-05-26 16:23:51 -03004000}
4001
Gustavo Padovan6039aa732012-05-23 04:04:18 -03004002static void hci_le_ltk_request_evt(struct hci_dev *hdev, struct sk_buff *skb)
Vinicius Costa Gomesa7a595f2011-06-09 18:50:47 -03004003{
4004 struct hci_ev_le_ltk_req *ev = (void *) skb->data;
4005 struct hci_cp_le_ltk_reply cp;
Vinicius Costa Gomesbea710f2011-07-07 18:59:37 -03004006 struct hci_cp_le_ltk_neg_reply neg;
Vinicius Costa Gomesa7a595f2011-06-09 18:50:47 -03004007 struct hci_conn *conn;
Vinicius Costa Gomesc9839a12012-02-02 21:08:01 -03004008 struct smp_ltk *ltk;
Vinicius Costa Gomesa7a595f2011-06-09 18:50:47 -03004009
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +03004010 BT_DBG("%s handle 0x%4.4x", hdev->name, __le16_to_cpu(ev->handle));
Vinicius Costa Gomesa7a595f2011-06-09 18:50:47 -03004011
4012 hci_dev_lock(hdev);
4013
4014 conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
Vinicius Costa Gomesbea710f2011-07-07 18:59:37 -03004015 if (conn == NULL)
4016 goto not_found;
Vinicius Costa Gomesa7a595f2011-06-09 18:50:47 -03004017
Vinicius Costa Gomesbea710f2011-07-07 18:59:37 -03004018 ltk = hci_find_ltk(hdev, ev->ediv, ev->random);
4019 if (ltk == NULL)
4020 goto not_found;
4021
4022 memcpy(cp.ltk, ltk->val, sizeof(ltk->val));
Vinicius Costa Gomesa7a595f2011-06-09 18:50:47 -03004023 cp.handle = cpu_to_le16(conn->handle);
Vinicius Costa Gomesc9839a12012-02-02 21:08:01 -03004024
4025 if (ltk->authenticated)
4026 conn->sec_level = BT_SECURITY_HIGH;
Vinicius Costa Gomesa7a595f2011-06-09 18:50:47 -03004027
4028 hci_send_cmd(hdev, HCI_OP_LE_LTK_REPLY, sizeof(cp), &cp);
4029
Vinicius Costa Gomesc9839a12012-02-02 21:08:01 -03004030 if (ltk->type & HCI_SMP_STK) {
4031 list_del(&ltk->list);
4032 kfree(ltk);
4033 }
4034
Vinicius Costa Gomesa7a595f2011-06-09 18:50:47 -03004035 hci_dev_unlock(hdev);
Vinicius Costa Gomesbea710f2011-07-07 18:59:37 -03004036
4037 return;
4038
4039not_found:
4040 neg.handle = ev->handle;
4041 hci_send_cmd(hdev, HCI_OP_LE_LTK_NEG_REPLY, sizeof(neg), &neg);
4042 hci_dev_unlock(hdev);
Vinicius Costa Gomesa7a595f2011-06-09 18:50:47 -03004043}
4044
Gustavo Padovan6039aa732012-05-23 04:04:18 -03004045static void hci_le_meta_evt(struct hci_dev *hdev, struct sk_buff *skb)
Ville Tervofcd89c02011-02-10 22:38:47 -03004046{
4047 struct hci_ev_le_meta *le_ev = (void *) skb->data;
4048
4049 skb_pull(skb, sizeof(*le_ev));
4050
4051 switch (le_ev->subevent) {
4052 case HCI_EV_LE_CONN_COMPLETE:
4053 hci_le_conn_complete_evt(hdev, skb);
4054 break;
4055
Andre Guedes9aa04c92011-05-26 16:23:51 -03004056 case HCI_EV_LE_ADVERTISING_REPORT:
4057 hci_le_adv_report_evt(hdev, skb);
4058 break;
4059
Vinicius Costa Gomesa7a595f2011-06-09 18:50:47 -03004060 case HCI_EV_LE_LTK_REQ:
4061 hci_le_ltk_request_evt(hdev, skb);
4062 break;
4063
Ville Tervofcd89c02011-02-10 22:38:47 -03004064 default:
4065 break;
4066 }
4067}
4068
Andrei Emeltchenko9495b2e2012-09-27 17:26:22 +03004069static void hci_chan_selected_evt(struct hci_dev *hdev, struct sk_buff *skb)
4070{
4071 struct hci_ev_channel_selected *ev = (void *) skb->data;
4072 struct hci_conn *hcon;
4073
4074 BT_DBG("%s handle 0x%2.2x", hdev->name, ev->phy_handle);
4075
4076 skb_pull(skb, sizeof(*ev));
4077
4078 hcon = hci_conn_hash_lookup_handle(hdev, ev->phy_handle);
4079 if (!hcon)
4080 return;
4081
4082 amp_read_loc_assoc_final_data(hdev, hcon);
4083}
4084
Linus Torvalds1da177e2005-04-16 15:20:36 -07004085void hci_event_packet(struct hci_dev *hdev, struct sk_buff *skb)
4086{
Marcel Holtmanna9de9242007-10-20 13:33:56 +02004087 struct hci_event_hdr *hdr = (void *) skb->data;
4088 __u8 event = hdr->evt;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004089
4090 skb_pull(skb, HCI_EVENT_HDR_SIZE);
4091
Marcel Holtmanna9de9242007-10-20 13:33:56 +02004092 switch (event) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07004093 case HCI_EV_INQUIRY_COMPLETE:
4094 hci_inquiry_complete_evt(hdev, skb);
4095 break;
4096
4097 case HCI_EV_INQUIRY_RESULT:
4098 hci_inquiry_result_evt(hdev, skb);
4099 break;
4100
Marcel Holtmanna9de9242007-10-20 13:33:56 +02004101 case HCI_EV_CONN_COMPLETE:
4102 hci_conn_complete_evt(hdev, skb);
Marcel Holtmann21d9e302005-09-13 01:32:25 +02004103 break;
4104
Linus Torvalds1da177e2005-04-16 15:20:36 -07004105 case HCI_EV_CONN_REQUEST:
4106 hci_conn_request_evt(hdev, skb);
4107 break;
4108
Linus Torvalds1da177e2005-04-16 15:20:36 -07004109 case HCI_EV_DISCONN_COMPLETE:
4110 hci_disconn_complete_evt(hdev, skb);
4111 break;
4112
Linus Torvalds1da177e2005-04-16 15:20:36 -07004113 case HCI_EV_AUTH_COMPLETE:
4114 hci_auth_complete_evt(hdev, skb);
4115 break;
4116
Marcel Holtmanna9de9242007-10-20 13:33:56 +02004117 case HCI_EV_REMOTE_NAME:
4118 hci_remote_name_evt(hdev, skb);
4119 break;
4120
Linus Torvalds1da177e2005-04-16 15:20:36 -07004121 case HCI_EV_ENCRYPT_CHANGE:
4122 hci_encrypt_change_evt(hdev, skb);
4123 break;
4124
Marcel Holtmanna9de9242007-10-20 13:33:56 +02004125 case HCI_EV_CHANGE_LINK_KEY_COMPLETE:
4126 hci_change_link_key_complete_evt(hdev, skb);
4127 break;
4128
4129 case HCI_EV_REMOTE_FEATURES:
4130 hci_remote_features_evt(hdev, skb);
4131 break;
4132
4133 case HCI_EV_REMOTE_VERSION:
4134 hci_remote_version_evt(hdev, skb);
4135 break;
4136
4137 case HCI_EV_QOS_SETUP_COMPLETE:
4138 hci_qos_setup_complete_evt(hdev, skb);
4139 break;
4140
4141 case HCI_EV_CMD_COMPLETE:
4142 hci_cmd_complete_evt(hdev, skb);
4143 break;
4144
4145 case HCI_EV_CMD_STATUS:
4146 hci_cmd_status_evt(hdev, skb);
4147 break;
4148
4149 case HCI_EV_ROLE_CHANGE:
4150 hci_role_change_evt(hdev, skb);
4151 break;
4152
4153 case HCI_EV_NUM_COMP_PKTS:
4154 hci_num_comp_pkts_evt(hdev, skb);
4155 break;
4156
4157 case HCI_EV_MODE_CHANGE:
4158 hci_mode_change_evt(hdev, skb);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004159 break;
4160
4161 case HCI_EV_PIN_CODE_REQ:
4162 hci_pin_code_request_evt(hdev, skb);
4163 break;
4164
4165 case HCI_EV_LINK_KEY_REQ:
4166 hci_link_key_request_evt(hdev, skb);
4167 break;
4168
4169 case HCI_EV_LINK_KEY_NOTIFY:
4170 hci_link_key_notify_evt(hdev, skb);
4171 break;
4172
4173 case HCI_EV_CLOCK_OFFSET:
4174 hci_clock_offset_evt(hdev, skb);
4175 break;
4176
Marcel Holtmanna8746412008-07-14 20:13:46 +02004177 case HCI_EV_PKT_TYPE_CHANGE:
4178 hci_pkt_type_change_evt(hdev, skb);
4179 break;
4180
Marcel Holtmann85a1e932005-08-09 20:28:02 -07004181 case HCI_EV_PSCAN_REP_MODE:
4182 hci_pscan_rep_mode_evt(hdev, skb);
4183 break;
4184
Marcel Holtmanna9de9242007-10-20 13:33:56 +02004185 case HCI_EV_INQUIRY_RESULT_WITH_RSSI:
4186 hci_inquiry_result_with_rssi_evt(hdev, skb);
4187 break;
4188
4189 case HCI_EV_REMOTE_EXT_FEATURES:
4190 hci_remote_ext_features_evt(hdev, skb);
4191 break;
4192
4193 case HCI_EV_SYNC_CONN_COMPLETE:
4194 hci_sync_conn_complete_evt(hdev, skb);
4195 break;
4196
4197 case HCI_EV_SYNC_CONN_CHANGED:
4198 hci_sync_conn_changed_evt(hdev, skb);
4199 break;
4200
Marcel Holtmann04837f62006-07-03 10:02:33 +02004201 case HCI_EV_SNIFF_SUBRATE:
4202 hci_sniff_subrate_evt(hdev, skb);
4203 break;
4204
Marcel Holtmanna9de9242007-10-20 13:33:56 +02004205 case HCI_EV_EXTENDED_INQUIRY_RESULT:
4206 hci_extended_inquiry_result_evt(hdev, skb);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004207 break;
4208
Johan Hedberg1c2e0042012-06-08 23:31:13 +08004209 case HCI_EV_KEY_REFRESH_COMPLETE:
4210 hci_key_refresh_complete_evt(hdev, skb);
4211 break;
4212
Marcel Holtmann04936842008-07-14 20:13:48 +02004213 case HCI_EV_IO_CAPA_REQUEST:
4214 hci_io_capa_request_evt(hdev, skb);
4215 break;
4216
Johan Hedberg03b555e2011-01-04 15:40:05 +02004217 case HCI_EV_IO_CAPA_REPLY:
4218 hci_io_capa_reply_evt(hdev, skb);
4219 break;
4220
Johan Hedberga5c29682011-02-19 12:05:57 -03004221 case HCI_EV_USER_CONFIRM_REQUEST:
4222 hci_user_confirm_request_evt(hdev, skb);
4223 break;
4224
Brian Gix1143d452011-11-23 08:28:34 -08004225 case HCI_EV_USER_PASSKEY_REQUEST:
4226 hci_user_passkey_request_evt(hdev, skb);
4227 break;
4228
Johan Hedberg92a25252012-09-06 18:39:26 +03004229 case HCI_EV_USER_PASSKEY_NOTIFY:
4230 hci_user_passkey_notify_evt(hdev, skb);
4231 break;
4232
4233 case HCI_EV_KEYPRESS_NOTIFY:
4234 hci_keypress_notify_evt(hdev, skb);
4235 break;
4236
Marcel Holtmann04936842008-07-14 20:13:48 +02004237 case HCI_EV_SIMPLE_PAIR_COMPLETE:
4238 hci_simple_pair_complete_evt(hdev, skb);
4239 break;
4240
Marcel Holtmann41a96212008-07-14 20:13:48 +02004241 case HCI_EV_REMOTE_HOST_FEATURES:
4242 hci_remote_host_features_evt(hdev, skb);
4243 break;
4244
Ville Tervofcd89c02011-02-10 22:38:47 -03004245 case HCI_EV_LE_META:
4246 hci_le_meta_evt(hdev, skb);
4247 break;
4248
Andrei Emeltchenko9495b2e2012-09-27 17:26:22 +03004249 case HCI_EV_CHANNEL_SELECTED:
4250 hci_chan_selected_evt(hdev, skb);
4251 break;
4252
Szymon Janc2763eda2011-03-22 13:12:22 +01004253 case HCI_EV_REMOTE_OOB_DATA_REQUEST:
4254 hci_remote_oob_data_request_evt(hdev, skb);
4255 break;
4256
Andrei Emeltchenkod5e91192012-10-25 15:20:44 +03004257 case HCI_EV_PHY_LINK_COMPLETE:
4258 hci_phy_link_complete_evt(hdev, skb);
4259 break;
4260
Andrei Emeltchenko27695fb2012-10-25 15:20:45 +03004261 case HCI_EV_LOGICAL_LINK_COMPLETE:
4262 hci_loglink_complete_evt(hdev, skb);
4263 break;
4264
Andrei Emeltchenko606e2a12012-10-31 15:46:31 +02004265 case HCI_EV_DISCONN_LOGICAL_LINK_COMPLETE:
4266 hci_disconn_loglink_complete_evt(hdev, skb);
4267 break;
4268
Andrei Emeltchenko9eef6b32012-10-31 15:46:32 +02004269 case HCI_EV_DISCONN_PHY_LINK_COMPLETE:
4270 hci_disconn_phylink_complete_evt(hdev, skb);
4271 break;
4272
Andrei Emeltchenko25e89e92012-01-04 12:41:58 +02004273 case HCI_EV_NUM_COMP_BLOCKS:
4274 hci_num_comp_blocks_evt(hdev, skb);
4275 break;
4276
Marcel Holtmanna9de9242007-10-20 13:33:56 +02004277 default:
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +03004278 BT_DBG("%s event 0x%2.2x", hdev->name, event);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004279 break;
4280 }
4281
4282 kfree_skb(skb);
4283 hdev->stat.evt_rx++;
4284}