blob: d2fee64b728c8f7bb2cd460901e31412f5fb63c2 [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 Hedberge1171e82012-10-19 20:57:45 +0300620}
621
Johan Hedbergd5859e22011-01-25 01:19:58 +0200622static void hci_setup(struct hci_dev *hdev)
623{
Andrei Emeltchenkoe61ef4992011-12-19 16:31:27 +0200624 if (hdev->dev_type != HCI_BREDR)
625 return;
626
Johan Hedberge1171e82012-10-19 20:57:45 +0300627 /* Read BD Address */
628 hci_send_cmd(hdev, HCI_OP_READ_BD_ADDR, 0, NULL);
629
630 if (lmp_bredr_capable(hdev))
Gustavo Padovan4611dfa2012-10-24 11:18:41 -0200631 bredr_setup(hdev);
Johan Hedberge1171e82012-10-19 20:57:45 +0300632
633 if (lmp_le_capable(hdev))
Gustavo Padovan4611dfa2012-10-24 11:18:41 -0200634 le_setup(hdev);
Johan Hedberge1171e82012-10-19 20:57:45 +0300635
Johan Hedbergd5859e22011-01-25 01:19:58 +0200636 hci_setup_event_mask(hdev);
637
Andrei Emeltchenkod095c1e2011-12-01 14:33:27 +0200638 if (hdev->hci_ver > BLUETOOTH_VER_1_1)
Johan Hedbergd5859e22011-01-25 01:19:58 +0200639 hci_send_cmd(hdev, HCI_OP_READ_LOCAL_COMMANDS, 0, NULL);
640
Gustavo Padovan6d3c7302012-05-24 03:36:37 -0300641 if (lmp_ssp_capable(hdev)) {
Johan Hedberg54d04db2012-02-22 15:47:48 +0200642 if (test_bit(HCI_SSP_ENABLED, &hdev->dev_flags)) {
643 u8 mode = 0x01;
644 hci_send_cmd(hdev, HCI_OP_WRITE_SSP_MODE,
Gustavo F. Padovan04124682012-03-08 01:25:00 -0300645 sizeof(mode), &mode);
Johan Hedberg54d04db2012-02-22 15:47:48 +0200646 } else {
647 struct hci_cp_write_eir cp;
648
649 memset(hdev->eir, 0, sizeof(hdev->eir));
650 memset(&cp, 0, sizeof(cp));
651
652 hci_send_cmd(hdev, HCI_OP_WRITE_EIR, sizeof(cp), &cp);
653 }
Johan Hedbergd5859e22011-01-25 01:19:58 +0200654 }
655
Johan Hedberg976eb202012-10-24 21:12:01 +0300656 if (lmp_inq_rssi_capable(hdev))
Johan Hedbergd5859e22011-01-25 01:19:58 +0200657 hci_setup_inquiry_mode(hdev);
658
Johan Hedberg976eb202012-10-24 21:12:01 +0300659 if (lmp_inq_tx_pwr_capable(hdev))
Johan Hedbergd5859e22011-01-25 01:19:58 +0200660 hci_send_cmd(hdev, HCI_OP_READ_INQ_RSP_TX_POWER, 0, NULL);
Andre Guedes971e3a42011-06-30 19:20:52 -0300661
Johan Hedberg976eb202012-10-24 21:12:01 +0300662 if (lmp_ext_feat_capable(hdev)) {
Andre Guedes971e3a42011-06-30 19:20:52 -0300663 struct hci_cp_read_local_ext_features cp;
664
665 cp.page = 0x01;
Gustavo F. Padovan04124682012-03-08 01:25:00 -0300666 hci_send_cmd(hdev, HCI_OP_READ_LOCAL_EXT_FEATURES, sizeof(cp),
667 &cp);
Andre Guedes971e3a42011-06-30 19:20:52 -0300668 }
Andre Guedese6100a22011-06-30 19:20:54 -0300669
Johan Hedberg47990ea2012-02-22 11:58:37 +0200670 if (test_bit(HCI_LINK_SECURITY, &hdev->dev_flags)) {
671 u8 enable = 1;
Gustavo F. Padovan04124682012-03-08 01:25:00 -0300672 hci_send_cmd(hdev, HCI_OP_WRITE_AUTH_ENABLE, sizeof(enable),
673 &enable);
Johan Hedberg47990ea2012-02-22 11:58:37 +0200674 }
Johan Hedbergd5859e22011-01-25 01:19:58 +0200675}
676
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200677static void hci_cc_read_local_version(struct hci_dev *hdev, struct sk_buff *skb)
678{
679 struct hci_rp_read_local_version *rp = (void *) skb->data;
680
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +0300681 BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200682
683 if (rp->status)
Andrei Emeltchenko28b8df72012-02-24 12:45:44 +0200684 goto done;
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200685
686 hdev->hci_ver = rp->hci_ver;
Marcel Holtmanne4e8e372008-07-14 20:13:47 +0200687 hdev->hci_rev = __le16_to_cpu(rp->hci_rev);
Johan Hedbergd5859e22011-01-25 01:19:58 +0200688 hdev->lmp_ver = rp->lmp_ver;
Marcel Holtmanne4e8e372008-07-14 20:13:47 +0200689 hdev->manufacturer = __le16_to_cpu(rp->manufacturer);
Johan Hedbergd5859e22011-01-25 01:19:58 +0200690 hdev->lmp_subver = __le16_to_cpu(rp->lmp_subver);
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200691
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +0300692 BT_DBG("%s manufacturer 0x%4.4x hci ver %d:%d", hdev->name,
Gustavo Padovan807deac2012-05-17 00:36:24 -0300693 hdev->manufacturer, hdev->hci_ver, hdev->hci_rev);
Johan Hedbergd5859e22011-01-25 01:19:58 +0200694
695 if (test_bit(HCI_INIT, &hdev->flags))
696 hci_setup(hdev);
Andrei Emeltchenko28b8df72012-02-24 12:45:44 +0200697
698done:
699 hci_req_complete(hdev, HCI_OP_READ_LOCAL_VERSION, rp->status);
Johan Hedbergd5859e22011-01-25 01:19:58 +0200700}
701
702static void hci_setup_link_policy(struct hci_dev *hdev)
703{
Andrei Emeltchenko035100c2012-03-12 15:59:32 +0200704 struct hci_cp_write_def_link_policy cp;
Johan Hedbergd5859e22011-01-25 01:19:58 +0200705 u16 link_policy = 0;
706
Andre Guedes9f92ebf2012-07-24 15:03:50 -0300707 if (lmp_rswitch_capable(hdev))
Johan Hedbergd5859e22011-01-25 01:19:58 +0200708 link_policy |= HCI_LP_RSWITCH;
Johan Hedberg976eb202012-10-24 21:12:01 +0300709 if (lmp_hold_capable(hdev))
Johan Hedbergd5859e22011-01-25 01:19:58 +0200710 link_policy |= HCI_LP_HOLD;
Andre Guedes6eded102012-07-24 15:03:51 -0300711 if (lmp_sniff_capable(hdev))
Johan Hedbergd5859e22011-01-25 01:19:58 +0200712 link_policy |= HCI_LP_SNIFF;
Johan Hedberg976eb202012-10-24 21:12:01 +0300713 if (lmp_park_capable(hdev))
Johan Hedbergd5859e22011-01-25 01:19:58 +0200714 link_policy |= HCI_LP_PARK;
715
Andrei Emeltchenko035100c2012-03-12 15:59:32 +0200716 cp.policy = cpu_to_le16(link_policy);
717 hci_send_cmd(hdev, HCI_OP_WRITE_DEF_LINK_POLICY, sizeof(cp), &cp);
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200718}
719
Gustavo Padovan8fc9ced2012-05-23 04:04:21 -0300720static void hci_cc_read_local_commands(struct hci_dev *hdev,
721 struct sk_buff *skb)
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200722{
723 struct hci_rp_read_local_commands *rp = (void *) skb->data;
724
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +0300725 BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200726
727 if (rp->status)
Johan Hedbergd5859e22011-01-25 01:19:58 +0200728 goto done;
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200729
730 memcpy(hdev->commands, rp->commands, sizeof(hdev->commands));
Johan Hedbergd5859e22011-01-25 01:19:58 +0200731
732 if (test_bit(HCI_INIT, &hdev->flags) && (hdev->commands[5] & 0x10))
733 hci_setup_link_policy(hdev);
734
735done:
736 hci_req_complete(hdev, HCI_OP_READ_LOCAL_COMMANDS, rp->status);
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200737}
738
Gustavo Padovan8fc9ced2012-05-23 04:04:21 -0300739static void hci_cc_read_local_features(struct hci_dev *hdev,
740 struct sk_buff *skb)
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200741{
742 struct hci_rp_read_local_features *rp = (void *) skb->data;
743
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +0300744 BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200745
746 if (rp->status)
747 return;
748
749 memcpy(hdev->features, rp->features, 8);
750
751 /* Adjust default settings according to features
752 * supported by device. */
753
754 if (hdev->features[0] & LMP_3SLOT)
755 hdev->pkt_type |= (HCI_DM3 | HCI_DH3);
756
757 if (hdev->features[0] & LMP_5SLOT)
758 hdev->pkt_type |= (HCI_DM5 | HCI_DH5);
759
760 if (hdev->features[1] & LMP_HV2) {
761 hdev->pkt_type |= (HCI_HV2);
762 hdev->esco_type |= (ESCO_HV2);
763 }
764
765 if (hdev->features[1] & LMP_HV3) {
766 hdev->pkt_type |= (HCI_HV3);
767 hdev->esco_type |= (ESCO_HV3);
768 }
769
Andre Guedes45db810f2012-07-24 15:03:49 -0300770 if (lmp_esco_capable(hdev))
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200771 hdev->esco_type |= (ESCO_EV3);
772
773 if (hdev->features[4] & LMP_EV4)
774 hdev->esco_type |= (ESCO_EV4);
775
776 if (hdev->features[4] & LMP_EV5)
777 hdev->esco_type |= (ESCO_EV5);
778
Marcel Holtmannefc76882009-02-06 09:13:37 +0100779 if (hdev->features[5] & LMP_EDR_ESCO_2M)
780 hdev->esco_type |= (ESCO_2EV3);
781
782 if (hdev->features[5] & LMP_EDR_ESCO_3M)
783 hdev->esco_type |= (ESCO_3EV3);
784
785 if (hdev->features[5] & LMP_EDR_3S_ESCO)
786 hdev->esco_type |= (ESCO_2EV5 | ESCO_3EV5);
787
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200788 BT_DBG("%s features 0x%.2x%.2x%.2x%.2x%.2x%.2x%.2x%.2x", hdev->name,
Gustavo Padovan807deac2012-05-17 00:36:24 -0300789 hdev->features[0], hdev->features[1],
790 hdev->features[2], hdev->features[3],
791 hdev->features[4], hdev->features[5],
792 hdev->features[6], hdev->features[7]);
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200793}
794
Johan Hedberg8f984df2012-02-28 01:07:22 +0200795static void hci_set_le_support(struct hci_dev *hdev)
796{
797 struct hci_cp_write_le_host_supported cp;
798
799 memset(&cp, 0, sizeof(cp));
800
Marcel Holtmann9d428202012-05-03 07:12:31 +0200801 if (test_bit(HCI_LE_ENABLED, &hdev->dev_flags)) {
Johan Hedberg8f984df2012-02-28 01:07:22 +0200802 cp.le = 1;
Gustavo Padovanffa88e02012-11-23 16:50:51 -0200803 cp.simul = lmp_le_br_capable(hdev);
Johan Hedberg8f984df2012-02-28 01:07:22 +0200804 }
805
Gustavo Padovanffa88e02012-11-23 16:50:51 -0200806 if (cp.le != lmp_host_le_capable(hdev))
Gustavo F. Padovan04124682012-03-08 01:25:00 -0300807 hci_send_cmd(hdev, HCI_OP_WRITE_LE_HOST_SUPPORTED, sizeof(cp),
808 &cp);
Johan Hedberg8f984df2012-02-28 01:07:22 +0200809}
810
Andre Guedes971e3a42011-06-30 19:20:52 -0300811static void hci_cc_read_local_ext_features(struct hci_dev *hdev,
Gustavo Padovan807deac2012-05-17 00:36:24 -0300812 struct sk_buff *skb)
Andre Guedes971e3a42011-06-30 19:20:52 -0300813{
814 struct hci_rp_read_local_ext_features *rp = (void *) skb->data;
815
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +0300816 BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
Andre Guedes971e3a42011-06-30 19:20:52 -0300817
818 if (rp->status)
Johan Hedberg8f984df2012-02-28 01:07:22 +0200819 goto done;
Andre Guedes971e3a42011-06-30 19:20:52 -0300820
Andre Guedesb5b32b62011-12-30 10:34:04 -0300821 switch (rp->page) {
822 case 0:
823 memcpy(hdev->features, rp->features, 8);
824 break;
825 case 1:
826 memcpy(hdev->host_features, rp->features, 8);
827 break;
828 }
Andre Guedes971e3a42011-06-30 19:20:52 -0300829
Andre Guedesc383ddc2012-07-24 15:03:47 -0300830 if (test_bit(HCI_INIT, &hdev->flags) && lmp_le_capable(hdev))
Johan Hedberg8f984df2012-02-28 01:07:22 +0200831 hci_set_le_support(hdev);
832
833done:
Andre Guedes971e3a42011-06-30 19:20:52 -0300834 hci_req_complete(hdev, HCI_OP_READ_LOCAL_EXT_FEATURES, rp->status);
835}
836
Andrei Emeltchenko1e89cff2011-11-24 14:52:02 +0200837static void hci_cc_read_flow_control_mode(struct hci_dev *hdev,
Gustavo Padovan807deac2012-05-17 00:36:24 -0300838 struct sk_buff *skb)
Andrei Emeltchenko1e89cff2011-11-24 14:52:02 +0200839{
840 struct hci_rp_read_flow_control_mode *rp = (void *) skb->data;
841
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +0300842 BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
Andrei Emeltchenko1e89cff2011-11-24 14:52:02 +0200843
844 if (rp->status)
845 return;
846
847 hdev->flow_ctl_mode = rp->mode;
848
849 hci_req_complete(hdev, HCI_OP_READ_FLOW_CONTROL_MODE, rp->status);
850}
851
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200852static void hci_cc_read_buffer_size(struct hci_dev *hdev, struct sk_buff *skb)
853{
854 struct hci_rp_read_buffer_size *rp = (void *) skb->data;
855
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +0300856 BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200857
858 if (rp->status)
859 return;
860
861 hdev->acl_mtu = __le16_to_cpu(rp->acl_mtu);
862 hdev->sco_mtu = rp->sco_mtu;
863 hdev->acl_pkts = __le16_to_cpu(rp->acl_max_pkt);
864 hdev->sco_pkts = __le16_to_cpu(rp->sco_max_pkt);
865
866 if (test_bit(HCI_QUIRK_FIXUP_BUFFER_SIZE, &hdev->quirks)) {
867 hdev->sco_mtu = 64;
868 hdev->sco_pkts = 8;
869 }
870
871 hdev->acl_cnt = hdev->acl_pkts;
872 hdev->sco_cnt = hdev->sco_pkts;
873
Gustavo Padovan807deac2012-05-17 00:36:24 -0300874 BT_DBG("%s acl mtu %d:%d sco mtu %d:%d", hdev->name, hdev->acl_mtu,
875 hdev->acl_pkts, hdev->sco_mtu, hdev->sco_pkts);
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200876}
877
878static void hci_cc_read_bd_addr(struct hci_dev *hdev, struct sk_buff *skb)
879{
880 struct hci_rp_read_bd_addr *rp = (void *) skb->data;
881
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +0300882 BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200883
884 if (!rp->status)
885 bacpy(&hdev->bdaddr, &rp->bdaddr);
886
Johan Hedberg23bb5762010-12-21 23:01:27 +0200887 hci_req_complete(hdev, HCI_OP_READ_BD_ADDR, rp->status);
888}
889
Andrei Emeltchenko350ee4c2011-12-07 15:56:51 +0200890static void hci_cc_read_data_block_size(struct hci_dev *hdev,
Gustavo Padovan807deac2012-05-17 00:36:24 -0300891 struct sk_buff *skb)
Andrei Emeltchenko350ee4c2011-12-07 15:56:51 +0200892{
893 struct hci_rp_read_data_block_size *rp = (void *) skb->data;
894
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +0300895 BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
Andrei Emeltchenko350ee4c2011-12-07 15:56:51 +0200896
897 if (rp->status)
898 return;
899
900 hdev->block_mtu = __le16_to_cpu(rp->max_acl_len);
901 hdev->block_len = __le16_to_cpu(rp->block_len);
902 hdev->num_blocks = __le16_to_cpu(rp->num_blocks);
903
904 hdev->block_cnt = hdev->num_blocks;
905
906 BT_DBG("%s blk mtu %d cnt %d len %d", hdev->name, hdev->block_mtu,
Gustavo Padovan807deac2012-05-17 00:36:24 -0300907 hdev->block_cnt, hdev->block_len);
Andrei Emeltchenko350ee4c2011-12-07 15:56:51 +0200908
909 hci_req_complete(hdev, HCI_OP_READ_DATA_BLOCK_SIZE, rp->status);
910}
911
Johan Hedberg23bb5762010-12-21 23:01:27 +0200912static void hci_cc_write_ca_timeout(struct hci_dev *hdev, struct sk_buff *skb)
913{
914 __u8 status = *((__u8 *) skb->data);
915
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +0300916 BT_DBG("%s status 0x%2.2x", hdev->name, status);
Johan Hedberg23bb5762010-12-21 23:01:27 +0200917
918 hci_req_complete(hdev, HCI_OP_WRITE_CA_TIMEOUT, status);
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200919}
920
Andrei Emeltchenko928abaa2011-10-12 10:53:57 +0300921static void hci_cc_read_local_amp_info(struct hci_dev *hdev,
Gustavo Padovan807deac2012-05-17 00:36:24 -0300922 struct sk_buff *skb)
Andrei Emeltchenko928abaa2011-10-12 10:53:57 +0300923{
924 struct hci_rp_read_local_amp_info *rp = (void *) skb->data;
925
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +0300926 BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
Andrei Emeltchenko928abaa2011-10-12 10:53:57 +0300927
928 if (rp->status)
Andrei Emeltchenko8e2a0d92012-09-27 17:26:08 +0300929 goto a2mp_rsp;
Andrei Emeltchenko928abaa2011-10-12 10:53:57 +0300930
931 hdev->amp_status = rp->amp_status;
932 hdev->amp_total_bw = __le32_to_cpu(rp->total_bw);
933 hdev->amp_max_bw = __le32_to_cpu(rp->max_bw);
934 hdev->amp_min_latency = __le32_to_cpu(rp->min_latency);
935 hdev->amp_max_pdu = __le32_to_cpu(rp->max_pdu);
936 hdev->amp_type = rp->amp_type;
937 hdev->amp_pal_cap = __le16_to_cpu(rp->pal_cap);
938 hdev->amp_assoc_size = __le16_to_cpu(rp->max_assoc_size);
939 hdev->amp_be_flush_to = __le32_to_cpu(rp->be_flush_to);
940 hdev->amp_max_flush_to = __le32_to_cpu(rp->max_flush_to);
941
942 hci_req_complete(hdev, HCI_OP_READ_LOCAL_AMP_INFO, rp->status);
Andrei Emeltchenko8e2a0d92012-09-27 17:26:08 +0300943
944a2mp_rsp:
945 a2mp_send_getinfo_rsp(hdev);
Andrei Emeltchenko928abaa2011-10-12 10:53:57 +0300946}
947
Andrei Emeltchenko903e4542012-09-27 17:26:09 +0300948static void hci_cc_read_local_amp_assoc(struct hci_dev *hdev,
949 struct sk_buff *skb)
950{
951 struct hci_rp_read_local_amp_assoc *rp = (void *) skb->data;
952 struct amp_assoc *assoc = &hdev->loc_assoc;
953 size_t rem_len, frag_len;
954
955 BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
956
957 if (rp->status)
958 goto a2mp_rsp;
959
960 frag_len = skb->len - sizeof(*rp);
961 rem_len = __le16_to_cpu(rp->rem_len);
962
963 if (rem_len > frag_len) {
Andrei Emeltchenko2e430be32012-09-28 14:44:23 +0300964 BT_DBG("frag_len %zu rem_len %zu", frag_len, rem_len);
Andrei Emeltchenko903e4542012-09-27 17:26:09 +0300965
966 memcpy(assoc->data + assoc->offset, rp->frag, frag_len);
967 assoc->offset += frag_len;
968
969 /* Read other fragments */
970 amp_read_loc_assoc_frag(hdev, rp->phy_handle);
971
972 return;
973 }
974
975 memcpy(assoc->data + assoc->offset, rp->frag, rem_len);
976 assoc->len = assoc->offset + rem_len;
977 assoc->offset = 0;
978
979a2mp_rsp:
980 /* Send A2MP Rsp when all fragments are received */
981 a2mp_send_getampassoc_rsp(hdev, rp->status);
Andrei Emeltchenko9495b2e2012-09-27 17:26:22 +0300982 a2mp_send_create_phy_link_req(hdev, rp->status);
Andrei Emeltchenko903e4542012-09-27 17:26:09 +0300983}
984
Johan Hedbergb0916ea2011-01-10 13:44:55 +0200985static void hci_cc_delete_stored_link_key(struct hci_dev *hdev,
Gustavo Padovan807deac2012-05-17 00:36:24 -0300986 struct sk_buff *skb)
Johan Hedbergb0916ea2011-01-10 13:44:55 +0200987{
988 __u8 status = *((__u8 *) skb->data);
989
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +0300990 BT_DBG("%s status 0x%2.2x", hdev->name, status);
Johan Hedbergb0916ea2011-01-10 13:44:55 +0200991
992 hci_req_complete(hdev, HCI_OP_DELETE_STORED_LINK_KEY, status);
993}
994
Johan Hedbergd5859e22011-01-25 01:19:58 +0200995static void hci_cc_set_event_mask(struct hci_dev *hdev, struct sk_buff *skb)
996{
997 __u8 status = *((__u8 *) skb->data);
998
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +0300999 BT_DBG("%s status 0x%2.2x", hdev->name, status);
Johan Hedbergd5859e22011-01-25 01:19:58 +02001000
1001 hci_req_complete(hdev, HCI_OP_SET_EVENT_MASK, status);
1002}
1003
1004static void hci_cc_write_inquiry_mode(struct hci_dev *hdev,
Gustavo Padovan807deac2012-05-17 00:36:24 -03001005 struct sk_buff *skb)
Johan Hedbergd5859e22011-01-25 01:19:58 +02001006{
1007 __u8 status = *((__u8 *) skb->data);
1008
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +03001009 BT_DBG("%s status 0x%2.2x", hdev->name, status);
Johan Hedbergd5859e22011-01-25 01:19:58 +02001010
1011 hci_req_complete(hdev, HCI_OP_WRITE_INQUIRY_MODE, status);
1012}
1013
1014static void hci_cc_read_inq_rsp_tx_power(struct hci_dev *hdev,
Gustavo Padovan807deac2012-05-17 00:36:24 -03001015 struct sk_buff *skb)
Johan Hedbergd5859e22011-01-25 01:19:58 +02001016{
Marcel Holtmann91c4e9b2012-03-11 19:27:21 -07001017 struct hci_rp_read_inq_rsp_tx_power *rp = (void *) skb->data;
Johan Hedbergd5859e22011-01-25 01:19:58 +02001018
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +03001019 BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
Johan Hedbergd5859e22011-01-25 01:19:58 +02001020
Marcel Holtmann91c4e9b2012-03-11 19:27:21 -07001021 if (!rp->status)
1022 hdev->inq_tx_power = rp->tx_power;
1023
1024 hci_req_complete(hdev, HCI_OP_READ_INQ_RSP_TX_POWER, rp->status);
Johan Hedbergd5859e22011-01-25 01:19:58 +02001025}
1026
1027static void hci_cc_set_event_flt(struct hci_dev *hdev, struct sk_buff *skb)
1028{
1029 __u8 status = *((__u8 *) skb->data);
1030
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +03001031 BT_DBG("%s status 0x%2.2x", hdev->name, status);
Johan Hedbergd5859e22011-01-25 01:19:58 +02001032
1033 hci_req_complete(hdev, HCI_OP_SET_EVENT_FLT, status);
1034}
1035
Johan Hedberg980e1a52011-01-22 06:10:07 +02001036static void hci_cc_pin_code_reply(struct hci_dev *hdev, struct sk_buff *skb)
1037{
1038 struct hci_rp_pin_code_reply *rp = (void *) skb->data;
1039 struct hci_cp_pin_code_reply *cp;
1040 struct hci_conn *conn;
1041
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +03001042 BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
Johan Hedberg980e1a52011-01-22 06:10:07 +02001043
Johan Hedberg56e5cb82011-11-08 20:40:16 +02001044 hci_dev_lock(hdev);
1045
Johan Hedberga8b2d5c2012-01-08 23:11:15 +02001046 if (test_bit(HCI_MGMT, &hdev->dev_flags))
Johan Hedberg744cf192011-11-08 20:40:14 +02001047 mgmt_pin_code_reply_complete(hdev, &rp->bdaddr, rp->status);
Johan Hedberg980e1a52011-01-22 06:10:07 +02001048
Mikel Astizfa1bd912012-08-09 09:52:29 +02001049 if (rp->status)
Johan Hedberg56e5cb82011-11-08 20:40:16 +02001050 goto unlock;
Johan Hedberg980e1a52011-01-22 06:10:07 +02001051
1052 cp = hci_sent_cmd_data(hdev, HCI_OP_PIN_CODE_REPLY);
1053 if (!cp)
Johan Hedberg56e5cb82011-11-08 20:40:16 +02001054 goto unlock;
Johan Hedberg980e1a52011-01-22 06:10:07 +02001055
1056 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &cp->bdaddr);
1057 if (conn)
1058 conn->pin_length = cp->pin_len;
Johan Hedberg56e5cb82011-11-08 20:40:16 +02001059
1060unlock:
1061 hci_dev_unlock(hdev);
Johan Hedberg980e1a52011-01-22 06:10:07 +02001062}
1063
1064static void hci_cc_pin_code_neg_reply(struct hci_dev *hdev, struct sk_buff *skb)
1065{
1066 struct hci_rp_pin_code_neg_reply *rp = (void *) skb->data;
1067
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +03001068 BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
Johan Hedberg980e1a52011-01-22 06:10:07 +02001069
Johan Hedberg56e5cb82011-11-08 20:40:16 +02001070 hci_dev_lock(hdev);
1071
Johan Hedberga8b2d5c2012-01-08 23:11:15 +02001072 if (test_bit(HCI_MGMT, &hdev->dev_flags))
Johan Hedberg744cf192011-11-08 20:40:14 +02001073 mgmt_pin_code_neg_reply_complete(hdev, &rp->bdaddr,
Gustavo Padovan807deac2012-05-17 00:36:24 -03001074 rp->status);
Johan Hedberg56e5cb82011-11-08 20:40:16 +02001075
1076 hci_dev_unlock(hdev);
Johan Hedberg980e1a52011-01-22 06:10:07 +02001077}
Johan Hedberg56e5cb82011-11-08 20:40:16 +02001078
Ville Tervo6ed58ec2011-02-10 22:38:48 -03001079static void hci_cc_le_read_buffer_size(struct hci_dev *hdev,
1080 struct sk_buff *skb)
1081{
1082 struct hci_rp_le_read_buffer_size *rp = (void *) skb->data;
1083
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +03001084 BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
Ville Tervo6ed58ec2011-02-10 22:38:48 -03001085
1086 if (rp->status)
1087 return;
1088
1089 hdev->le_mtu = __le16_to_cpu(rp->le_mtu);
1090 hdev->le_pkts = rp->le_max_pkt;
1091
1092 hdev->le_cnt = hdev->le_pkts;
1093
1094 BT_DBG("%s le mtu %d:%d", hdev->name, hdev->le_mtu, hdev->le_pkts);
1095
1096 hci_req_complete(hdev, HCI_OP_LE_READ_BUFFER_SIZE, rp->status);
1097}
Johan Hedberg980e1a52011-01-22 06:10:07 +02001098
Johan Hedberg60e77322013-01-22 14:01:59 +02001099static void hci_cc_le_read_local_features(struct hci_dev *hdev,
1100 struct sk_buff *skb)
1101{
1102 struct hci_rp_le_read_local_features *rp = (void *) skb->data;
1103
1104 BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
1105
1106 if (!rp->status)
1107 memcpy(hdev->le_features, rp->features, 8);
1108
1109 hci_req_complete(hdev, HCI_OP_LE_READ_LOCAL_FEATURES, rp->status);
1110}
1111
Johan Hedberg8fa19092012-10-19 20:57:49 +03001112static void hci_cc_le_read_adv_tx_power(struct hci_dev *hdev,
1113 struct sk_buff *skb)
1114{
1115 struct hci_rp_le_read_adv_tx_power *rp = (void *) skb->data;
1116
1117 BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
1118
Johan Hedberg3f0f5242012-11-08 01:23:00 +01001119 if (!rp->status) {
Johan Hedberg8fa19092012-10-19 20:57:49 +03001120 hdev->adv_tx_power = rp->tx_power;
Johan Hedberg3f0f5242012-11-08 01:23:00 +01001121 if (!test_bit(HCI_INIT, &hdev->flags))
1122 hci_update_ad(hdev);
1123 }
Johan Hedberg8fa19092012-10-19 20:57:49 +03001124
1125 hci_req_complete(hdev, HCI_OP_LE_READ_ADV_TX_POWER, rp->status);
1126}
1127
Johan Hedberge36b04c2012-10-19 20:57:47 +03001128static void hci_cc_le_set_event_mask(struct hci_dev *hdev, struct sk_buff *skb)
1129{
1130 __u8 status = *((__u8 *) skb->data);
1131
1132 BT_DBG("%s status 0x%2.2x", hdev->name, status);
1133
1134 hci_req_complete(hdev, HCI_OP_LE_SET_EVENT_MASK, status);
1135}
1136
Johan Hedberga5c29682011-02-19 12:05:57 -03001137static void hci_cc_user_confirm_reply(struct hci_dev *hdev, struct sk_buff *skb)
1138{
1139 struct hci_rp_user_confirm_reply *rp = (void *) skb->data;
1140
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +03001141 BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
Johan Hedberga5c29682011-02-19 12:05:57 -03001142
Johan Hedberg56e5cb82011-11-08 20:40:16 +02001143 hci_dev_lock(hdev);
1144
Johan Hedberga8b2d5c2012-01-08 23:11:15 +02001145 if (test_bit(HCI_MGMT, &hdev->dev_flags))
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001146 mgmt_user_confirm_reply_complete(hdev, &rp->bdaddr, ACL_LINK, 0,
1147 rp->status);
Johan Hedberg56e5cb82011-11-08 20:40:16 +02001148
1149 hci_dev_unlock(hdev);
Johan Hedberga5c29682011-02-19 12:05:57 -03001150}
1151
1152static void hci_cc_user_confirm_neg_reply(struct hci_dev *hdev,
Gustavo Padovan807deac2012-05-17 00:36:24 -03001153 struct sk_buff *skb)
Johan Hedberga5c29682011-02-19 12:05:57 -03001154{
1155 struct hci_rp_user_confirm_reply *rp = (void *) skb->data;
1156
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +03001157 BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
Johan Hedberga5c29682011-02-19 12:05:57 -03001158
Johan Hedberg56e5cb82011-11-08 20:40:16 +02001159 hci_dev_lock(hdev);
1160
Johan Hedberga8b2d5c2012-01-08 23:11:15 +02001161 if (test_bit(HCI_MGMT, &hdev->dev_flags))
Johan Hedberg744cf192011-11-08 20:40:14 +02001162 mgmt_user_confirm_neg_reply_complete(hdev, &rp->bdaddr,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001163 ACL_LINK, 0, rp->status);
Johan Hedberg56e5cb82011-11-08 20:40:16 +02001164
1165 hci_dev_unlock(hdev);
Johan Hedberga5c29682011-02-19 12:05:57 -03001166}
1167
Brian Gix1143d452011-11-23 08:28:34 -08001168static void hci_cc_user_passkey_reply(struct hci_dev *hdev, struct sk_buff *skb)
1169{
1170 struct hci_rp_user_confirm_reply *rp = (void *) skb->data;
1171
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +03001172 BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
Brian Gix1143d452011-11-23 08:28:34 -08001173
1174 hci_dev_lock(hdev);
1175
Johan Hedberga8b2d5c2012-01-08 23:11:15 +02001176 if (test_bit(HCI_MGMT, &hdev->dev_flags))
Johan Hedberg272d90d2012-02-09 15:26:12 +02001177 mgmt_user_passkey_reply_complete(hdev, &rp->bdaddr, ACL_LINK,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001178 0, rp->status);
Brian Gix1143d452011-11-23 08:28:34 -08001179
1180 hci_dev_unlock(hdev);
1181}
1182
1183static void hci_cc_user_passkey_neg_reply(struct hci_dev *hdev,
Gustavo Padovan807deac2012-05-17 00:36:24 -03001184 struct sk_buff *skb)
Brian Gix1143d452011-11-23 08:28:34 -08001185{
1186 struct hci_rp_user_confirm_reply *rp = (void *) skb->data;
1187
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +03001188 BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
Brian Gix1143d452011-11-23 08:28:34 -08001189
1190 hci_dev_lock(hdev);
1191
Johan Hedberga8b2d5c2012-01-08 23:11:15 +02001192 if (test_bit(HCI_MGMT, &hdev->dev_flags))
Brian Gix1143d452011-11-23 08:28:34 -08001193 mgmt_user_passkey_neg_reply_complete(hdev, &rp->bdaddr,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001194 ACL_LINK, 0, rp->status);
Brian Gix1143d452011-11-23 08:28:34 -08001195
1196 hci_dev_unlock(hdev);
1197}
1198
Szymon Jancc35938b2011-03-22 13:12:21 +01001199static void hci_cc_read_local_oob_data_reply(struct hci_dev *hdev,
Gustavo Padovan807deac2012-05-17 00:36:24 -03001200 struct sk_buff *skb)
Szymon Jancc35938b2011-03-22 13:12:21 +01001201{
1202 struct hci_rp_read_local_oob_data *rp = (void *) skb->data;
1203
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +03001204 BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
Szymon Jancc35938b2011-03-22 13:12:21 +01001205
Johan Hedberg56e5cb82011-11-08 20:40:16 +02001206 hci_dev_lock(hdev);
Johan Hedberg744cf192011-11-08 20:40:14 +02001207 mgmt_read_local_oob_data_reply_complete(hdev, rp->hash,
Szymon Jancc35938b2011-03-22 13:12:21 +01001208 rp->randomizer, rp->status);
Johan Hedberg56e5cb82011-11-08 20:40:16 +02001209 hci_dev_unlock(hdev);
Szymon Jancc35938b2011-03-22 13:12:21 +01001210}
1211
Johan Hedbergc1d5dc42012-11-08 01:23:01 +01001212static void hci_cc_le_set_adv_enable(struct hci_dev *hdev, struct sk_buff *skb)
1213{
1214 __u8 *sent, status = *((__u8 *) skb->data);
1215
1216 BT_DBG("%s status 0x%2.2x", hdev->name, status);
1217
1218 sent = hci_sent_cmd_data(hdev, HCI_OP_LE_SET_ADV_ENABLE);
1219 if (!sent)
1220 return;
1221
1222 hci_dev_lock(hdev);
1223
1224 if (!status) {
1225 if (*sent)
1226 set_bit(HCI_LE_PERIPHERAL, &hdev->dev_flags);
1227 else
1228 clear_bit(HCI_LE_PERIPHERAL, &hdev->dev_flags);
1229 }
1230
1231 hci_dev_unlock(hdev);
1232
1233 if (!test_bit(HCI_INIT, &hdev->flags))
1234 hci_update_ad(hdev);
1235
1236 hci_req_complete(hdev, HCI_OP_LE_SET_ADV_ENABLE, status);
1237}
1238
Andre Guedes07f7fa52011-12-02 21:13:31 +09001239static void hci_cc_le_set_scan_param(struct hci_dev *hdev, struct sk_buff *skb)
1240{
1241 __u8 status = *((__u8 *) skb->data);
1242
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +03001243 BT_DBG("%s status 0x%2.2x", hdev->name, status);
Andre Guedes7ba8b4b2012-02-03 17:47:59 -03001244
1245 hci_req_complete(hdev, HCI_OP_LE_SET_SCAN_PARAM, status);
Andre Guedes3fd24152012-02-03 17:48:01 -03001246
1247 if (status) {
1248 hci_dev_lock(hdev);
1249 mgmt_start_discovery_failed(hdev, status);
1250 hci_dev_unlock(hdev);
1251 return;
1252 }
Andre Guedes07f7fa52011-12-02 21:13:31 +09001253}
1254
Andre Guedeseb9d91f2011-05-26 16:23:52 -03001255static void hci_cc_le_set_scan_enable(struct hci_dev *hdev,
Gustavo Padovan807deac2012-05-17 00:36:24 -03001256 struct sk_buff *skb)
Andre Guedeseb9d91f2011-05-26 16:23:52 -03001257{
1258 struct hci_cp_le_set_scan_enable *cp;
1259 __u8 status = *((__u8 *) skb->data);
1260
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +03001261 BT_DBG("%s status 0x%2.2x", hdev->name, status);
Andre Guedeseb9d91f2011-05-26 16:23:52 -03001262
Andre Guedeseb9d91f2011-05-26 16:23:52 -03001263 cp = hci_sent_cmd_data(hdev, HCI_OP_LE_SET_SCAN_ENABLE);
1264 if (!cp)
1265 return;
1266
Andrei Emeltchenko68a8aea2011-12-19 16:14:18 +02001267 switch (cp->enable) {
1268 case LE_SCANNING_ENABLED:
Andre Guedes7ba8b4b2012-02-03 17:47:59 -03001269 hci_req_complete(hdev, HCI_OP_LE_SET_SCAN_ENABLE, status);
1270
Andre Guedes3fd24152012-02-03 17:48:01 -03001271 if (status) {
1272 hci_dev_lock(hdev);
1273 mgmt_start_discovery_failed(hdev, status);
1274 hci_dev_unlock(hdev);
Andre Guedes7ba8b4b2012-02-03 17:47:59 -03001275 return;
Andre Guedes3fd24152012-02-03 17:48:01 -03001276 }
Andre Guedes7ba8b4b2012-02-03 17:47:59 -03001277
Andre Guedesd23264a2011-11-25 20:53:38 -03001278 set_bit(HCI_LE_SCAN, &hdev->dev_flags);
1279
Andre Guedesa8f13c82011-09-09 18:56:24 -03001280 hci_dev_lock(hdev);
Andre Guedes343f9352012-02-17 20:39:37 -03001281 hci_discovery_set_state(hdev, DISCOVERY_FINDING);
Andre Guedesa8f13c82011-09-09 18:56:24 -03001282 hci_dev_unlock(hdev);
Andrei Emeltchenko68a8aea2011-12-19 16:14:18 +02001283 break;
1284
1285 case LE_SCANNING_DISABLED:
Andre Guedesc9ecc482012-03-15 16:52:08 -03001286 if (status) {
1287 hci_dev_lock(hdev);
1288 mgmt_stop_discovery_failed(hdev, status);
1289 hci_dev_unlock(hdev);
Andre Guedes7ba8b4b2012-02-03 17:47:59 -03001290 return;
Andre Guedesc9ecc482012-03-15 16:52:08 -03001291 }
Andre Guedes7ba8b4b2012-02-03 17:47:59 -03001292
Andre Guedesd23264a2011-11-25 20:53:38 -03001293 clear_bit(HCI_LE_SCAN, &hdev->dev_flags);
1294
Andre Guedesbc3dd332012-03-06 19:37:06 -03001295 if (hdev->discovery.type == DISCOV_TYPE_INTERLEAVED &&
1296 hdev->discovery.state == DISCOVERY_FINDING) {
Andre Guedes5e0452c2012-02-17 20:39:38 -03001297 mgmt_interleaved_discovery(hdev);
1298 } else {
1299 hci_dev_lock(hdev);
1300 hci_discovery_set_state(hdev, DISCOVERY_STOPPED);
1301 hci_dev_unlock(hdev);
1302 }
1303
Andrei Emeltchenko68a8aea2011-12-19 16:14:18 +02001304 break;
1305
1306 default:
1307 BT_ERR("Used reserved LE_Scan_Enable param %d", cp->enable);
1308 break;
Andre Guedes35815082011-05-26 16:23:53 -03001309 }
Andre Guedeseb9d91f2011-05-26 16:23:52 -03001310}
1311
Johan Hedbergcf1d0812013-01-22 14:02:00 +02001312static void hci_cc_le_read_white_list_size(struct hci_dev *hdev,
1313 struct sk_buff *skb)
1314{
1315 struct hci_rp_le_read_white_list_size *rp = (void *) skb->data;
1316
1317 BT_DBG("%s status 0x%2.2x size %u", hdev->name, rp->status, rp->size);
1318
1319 if (!rp->status)
1320 hdev->le_white_list_size = rp->size;
1321
1322 hci_req_complete(hdev, HCI_OP_LE_READ_WHITE_LIST_SIZE, rp->status);
1323}
1324
Vinicius Costa Gomesa7a595f2011-06-09 18:50:47 -03001325static void hci_cc_le_ltk_reply(struct hci_dev *hdev, struct sk_buff *skb)
1326{
1327 struct hci_rp_le_ltk_reply *rp = (void *) skb->data;
1328
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +03001329 BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
Vinicius Costa Gomesa7a595f2011-06-09 18:50:47 -03001330
1331 if (rp->status)
1332 return;
1333
1334 hci_req_complete(hdev, HCI_OP_LE_LTK_REPLY, rp->status);
1335}
1336
1337static void hci_cc_le_ltk_neg_reply(struct hci_dev *hdev, struct sk_buff *skb)
1338{
1339 struct hci_rp_le_ltk_neg_reply *rp = (void *) skb->data;
1340
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +03001341 BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
Vinicius Costa Gomesa7a595f2011-06-09 18:50:47 -03001342
1343 if (rp->status)
1344 return;
1345
1346 hci_req_complete(hdev, HCI_OP_LE_LTK_NEG_REPLY, rp->status);
1347}
1348
Gustavo Padovan6039aa72012-05-23 04:04:18 -03001349static void hci_cc_write_le_host_supported(struct hci_dev *hdev,
1350 struct sk_buff *skb)
Andre Guedesf9b49302011-06-30 19:20:53 -03001351{
Johan Hedberg06199cf2012-02-22 16:37:11 +02001352 struct hci_cp_write_le_host_supported *sent;
Andre Guedesf9b49302011-06-30 19:20:53 -03001353 __u8 status = *((__u8 *) skb->data);
1354
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +03001355 BT_DBG("%s status 0x%2.2x", hdev->name, status);
Andre Guedesf9b49302011-06-30 19:20:53 -03001356
Johan Hedberg06199cf2012-02-22 16:37:11 +02001357 sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_LE_HOST_SUPPORTED);
Johan Hedberg8f984df2012-02-28 01:07:22 +02001358 if (!sent)
Andre Guedesf9b49302011-06-30 19:20:53 -03001359 return;
1360
Johan Hedberg8f984df2012-02-28 01:07:22 +02001361 if (!status) {
1362 if (sent->le)
1363 hdev->host_features[0] |= LMP_HOST_LE;
1364 else
1365 hdev->host_features[0] &= ~LMP_HOST_LE;
Johan Hedberg53b2caa2012-10-24 21:11:59 +03001366
1367 if (sent->simul)
1368 hdev->host_features[0] |= LMP_HOST_LE_BREDR;
1369 else
1370 hdev->host_features[0] &= ~LMP_HOST_LE_BREDR;
Johan Hedberg8f984df2012-02-28 01:07:22 +02001371 }
1372
1373 if (test_bit(HCI_MGMT, &hdev->dev_flags) &&
Gustavo Padovan807deac2012-05-17 00:36:24 -03001374 !test_bit(HCI_INIT, &hdev->flags))
Johan Hedberg8f984df2012-02-28 01:07:22 +02001375 mgmt_le_enable_complete(hdev, sent->le, status);
1376
1377 hci_req_complete(hdev, HCI_OP_WRITE_LE_HOST_SUPPORTED, status);
Andre Guedesf9b49302011-06-30 19:20:53 -03001378}
1379
Andrei Emeltchenko93c284e2012-09-27 17:26:20 +03001380static void hci_cc_write_remote_amp_assoc(struct hci_dev *hdev,
1381 struct sk_buff *skb)
1382{
1383 struct hci_rp_write_remote_amp_assoc *rp = (void *) skb->data;
1384
1385 BT_DBG("%s status 0x%2.2x phy_handle 0x%2.2x",
1386 hdev->name, rp->status, rp->phy_handle);
1387
1388 if (rp->status)
1389 return;
1390
1391 amp_write_rem_assoc_continue(hdev, rp->phy_handle);
1392}
1393
Gustavo Padovan6039aa72012-05-23 04:04:18 -03001394static void hci_cs_inquiry(struct hci_dev *hdev, __u8 status)
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001395{
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +03001396 BT_DBG("%s status 0x%2.2x", hdev->name, status);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001397
1398 if (status) {
Johan Hedberg23bb5762010-12-21 23:01:27 +02001399 hci_req_complete(hdev, HCI_OP_INQUIRY, status);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001400 hci_conn_check_pending(hdev);
Johan Hedberg56e5cb82011-11-08 20:40:16 +02001401 hci_dev_lock(hdev);
Johan Hedberga8b2d5c2012-01-08 23:11:15 +02001402 if (test_bit(HCI_MGMT, &hdev->dev_flags))
Andre Guedes7a135102011-11-09 17:14:25 -03001403 mgmt_start_discovery_failed(hdev, status);
Johan Hedberg56e5cb82011-11-08 20:40:16 +02001404 hci_dev_unlock(hdev);
Johan Hedberg314b2382011-04-27 10:29:57 -04001405 return;
1406 }
1407
Andre Guedes89352e72011-11-04 14:16:53 -03001408 set_bit(HCI_INQUIRY, &hdev->flags);
1409
Johan Hedberg56e5cb82011-11-08 20:40:16 +02001410 hci_dev_lock(hdev);
Andre Guedes343f9352012-02-17 20:39:37 -03001411 hci_discovery_set_state(hdev, DISCOVERY_FINDING);
Johan Hedberg56e5cb82011-11-08 20:40:16 +02001412 hci_dev_unlock(hdev);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001413}
1414
Gustavo Padovan6039aa72012-05-23 04:04:18 -03001415static void hci_cs_create_conn(struct hci_dev *hdev, __u8 status)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001416{
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001417 struct hci_cp_create_conn *cp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001418 struct hci_conn *conn;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001419
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +03001420 BT_DBG("%s status 0x%2.2x", hdev->name, status);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001421
1422 cp = hci_sent_cmd_data(hdev, HCI_OP_CREATE_CONN);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001423 if (!cp)
1424 return;
1425
1426 hci_dev_lock(hdev);
1427
1428 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &cp->bdaddr);
1429
Andrei Emeltchenko6ed93dc2012-09-25 12:49:43 +03001430 BT_DBG("%s bdaddr %pMR hcon %p", hdev->name, &cp->bdaddr, conn);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001431
1432 if (status) {
1433 if (conn && conn->state == BT_CONNECT) {
Marcel Holtmann4c67bc72006-10-15 17:30:56 +02001434 if (status != 0x0c || conn->attempt > 2) {
1435 conn->state = BT_CLOSED;
1436 hci_proto_connect_cfm(conn, status);
1437 hci_conn_del(conn);
1438 } else
1439 conn->state = BT_CONNECT2;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001440 }
1441 } else {
1442 if (!conn) {
1443 conn = hci_conn_add(hdev, ACL_LINK, &cp->bdaddr);
1444 if (conn) {
Johan Hedberga0c808b2012-01-16 09:49:58 +02001445 conn->out = true;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001446 conn->link_mode |= HCI_LM_MASTER;
1447 } else
Gustavo F. Padovan893ef972010-07-18 15:13:37 -03001448 BT_ERR("No memory for new connection");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001449 }
1450 }
1451
1452 hci_dev_unlock(hdev);
1453}
1454
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001455static void hci_cs_add_sco(struct hci_dev *hdev, __u8 status)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001456{
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001457 struct hci_cp_add_sco *cp;
1458 struct hci_conn *acl, *sco;
1459 __u16 handle;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001460
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +03001461 BT_DBG("%s status 0x%2.2x", hdev->name, status);
Marcel Holtmannb6a0dc82007-10-20 14:55:10 +02001462
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001463 if (!status)
1464 return;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001465
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001466 cp = hci_sent_cmd_data(hdev, HCI_OP_ADD_SCO);
1467 if (!cp)
1468 return;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001469
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001470 handle = __le16_to_cpu(cp->handle);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001471
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +03001472 BT_DBG("%s handle 0x%4.4x", hdev->name, handle);
Marcel Holtmann6bd57412006-11-18 22:14:22 +01001473
1474 hci_dev_lock(hdev);
1475
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001476 acl = hci_conn_hash_lookup_handle(hdev, handle);
Andrei Emeltchenko5a08ecc2011-01-11 17:20:20 +02001477 if (acl) {
1478 sco = acl->link;
1479 if (sco) {
1480 sco->state = BT_CLOSED;
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001481
Andrei Emeltchenko5a08ecc2011-01-11 17:20:20 +02001482 hci_proto_connect_cfm(sco, status);
1483 hci_conn_del(sco);
1484 }
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001485 }
Marcel Holtmann6bd57412006-11-18 22:14:22 +01001486
1487 hci_dev_unlock(hdev);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001488}
1489
Marcel Holtmannf8558552008-07-14 20:13:49 +02001490static void hci_cs_auth_requested(struct hci_dev *hdev, __u8 status)
1491{
1492 struct hci_cp_auth_requested *cp;
1493 struct hci_conn *conn;
1494
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +03001495 BT_DBG("%s status 0x%2.2x", hdev->name, status);
Marcel Holtmannf8558552008-07-14 20:13:49 +02001496
1497 if (!status)
1498 return;
1499
1500 cp = hci_sent_cmd_data(hdev, HCI_OP_AUTH_REQUESTED);
1501 if (!cp)
1502 return;
1503
1504 hci_dev_lock(hdev);
1505
1506 conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(cp->handle));
1507 if (conn) {
1508 if (conn->state == BT_CONFIG) {
1509 hci_proto_connect_cfm(conn, status);
1510 hci_conn_put(conn);
1511 }
1512 }
1513
1514 hci_dev_unlock(hdev);
1515}
1516
1517static void hci_cs_set_conn_encrypt(struct hci_dev *hdev, __u8 status)
1518{
1519 struct hci_cp_set_conn_encrypt *cp;
1520 struct hci_conn *conn;
1521
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +03001522 BT_DBG("%s status 0x%2.2x", hdev->name, status);
Marcel Holtmannf8558552008-07-14 20:13:49 +02001523
1524 if (!status)
1525 return;
1526
1527 cp = hci_sent_cmd_data(hdev, HCI_OP_SET_CONN_ENCRYPT);
1528 if (!cp)
1529 return;
1530
1531 hci_dev_lock(hdev);
1532
1533 conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(cp->handle));
1534 if (conn) {
1535 if (conn->state == BT_CONFIG) {
1536 hci_proto_connect_cfm(conn, status);
1537 hci_conn_put(conn);
1538 }
1539 }
1540
1541 hci_dev_unlock(hdev);
1542}
1543
Johan Hedberg127178d2010-11-18 22:22:29 +02001544static int hci_outgoing_auth_needed(struct hci_dev *hdev,
Gustavo Padovan807deac2012-05-17 00:36:24 -03001545 struct hci_conn *conn)
Johan Hedberg392599b2010-11-18 22:22:28 +02001546{
Johan Hedberg392599b2010-11-18 22:22:28 +02001547 if (conn->state != BT_CONFIG || !conn->out)
1548 return 0;
1549
Johan Hedberg765c2a92011-01-19 12:06:52 +05301550 if (conn->pending_sec_level == BT_SECURITY_SDP)
Johan Hedberg392599b2010-11-18 22:22:28 +02001551 return 0;
1552
1553 /* Only request authentication for SSP connections or non-SSP
Vinicius Costa Gomese9bf2bf2011-09-02 14:51:20 -03001554 * devices with sec_level HIGH or if MITM protection is requested */
Gustavo Padovan807deac2012-05-17 00:36:24 -03001555 if (!hci_conn_ssp_enabled(conn) && !(conn->auth_type & 0x01) &&
1556 conn->pending_sec_level != BT_SECURITY_HIGH)
Johan Hedberg392599b2010-11-18 22:22:28 +02001557 return 0;
1558
Johan Hedberg392599b2010-11-18 22:22:28 +02001559 return 1;
1560}
1561
Gustavo Padovan6039aa72012-05-23 04:04:18 -03001562static int hci_resolve_name(struct hci_dev *hdev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001563 struct inquiry_entry *e)
Johan Hedberg30dc78e2012-01-04 15:44:20 +02001564{
1565 struct hci_cp_remote_name_req cp;
1566
1567 memset(&cp, 0, sizeof(cp));
1568
1569 bacpy(&cp.bdaddr, &e->data.bdaddr);
1570 cp.pscan_rep_mode = e->data.pscan_rep_mode;
1571 cp.pscan_mode = e->data.pscan_mode;
1572 cp.clock_offset = e->data.clock_offset;
1573
1574 return hci_send_cmd(hdev, HCI_OP_REMOTE_NAME_REQ, sizeof(cp), &cp);
1575}
1576
Johan Hedbergb644ba32012-01-17 21:48:47 +02001577static bool hci_resolve_next_name(struct hci_dev *hdev)
Johan Hedberg30dc78e2012-01-04 15:44:20 +02001578{
1579 struct discovery_state *discov = &hdev->discovery;
1580 struct inquiry_entry *e;
1581
Johan Hedbergb644ba32012-01-17 21:48:47 +02001582 if (list_empty(&discov->resolve))
1583 return false;
1584
1585 e = hci_inquiry_cache_lookup_resolve(hdev, BDADDR_ANY, NAME_NEEDED);
Ram Malovanyc8100892012-07-19 10:26:09 +03001586 if (!e)
1587 return false;
1588
Johan Hedbergb644ba32012-01-17 21:48:47 +02001589 if (hci_resolve_name(hdev, e) == 0) {
1590 e->name_state = NAME_PENDING;
1591 return true;
1592 }
1593
1594 return false;
1595}
1596
1597static void hci_check_pending_name(struct hci_dev *hdev, struct hci_conn *conn,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001598 bdaddr_t *bdaddr, u8 *name, u8 name_len)
Johan Hedbergb644ba32012-01-17 21:48:47 +02001599{
1600 struct discovery_state *discov = &hdev->discovery;
1601 struct inquiry_entry *e;
1602
1603 if (conn && !test_and_set_bit(HCI_CONN_MGMT_CONNECTED, &conn->flags))
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001604 mgmt_device_connected(hdev, bdaddr, ACL_LINK, 0x00, 0, name,
1605 name_len, conn->dev_class);
Johan Hedbergb644ba32012-01-17 21:48:47 +02001606
1607 if (discov->state == DISCOVERY_STOPPED)
1608 return;
1609
Johan Hedberg30dc78e2012-01-04 15:44:20 +02001610 if (discov->state == DISCOVERY_STOPPING)
1611 goto discov_complete;
1612
1613 if (discov->state != DISCOVERY_RESOLVING)
1614 return;
1615
1616 e = hci_inquiry_cache_lookup_resolve(hdev, bdaddr, NAME_PENDING);
Ram Malovany7cc83802012-07-19 10:26:10 +03001617 /* If the device was not found in a list of found devices names of which
1618 * are pending. there is no need to continue resolving a next name as it
1619 * will be done upon receiving another Remote Name Request Complete
1620 * Event */
1621 if (!e)
1622 return;
1623
1624 list_del(&e->list);
1625 if (name) {
Johan Hedberg30dc78e2012-01-04 15:44:20 +02001626 e->name_state = NAME_KNOWN;
Ram Malovany7cc83802012-07-19 10:26:10 +03001627 mgmt_remote_name(hdev, bdaddr, ACL_LINK, 0x00,
1628 e->data.rssi, name, name_len);
Ram Malovanyc3e7c0d2012-07-19 10:26:11 +03001629 } else {
1630 e->name_state = NAME_NOT_KNOWN;
Johan Hedberg30dc78e2012-01-04 15:44:20 +02001631 }
1632
Johan Hedbergb644ba32012-01-17 21:48:47 +02001633 if (hci_resolve_next_name(hdev))
Johan Hedberg30dc78e2012-01-04 15:44:20 +02001634 return;
Johan Hedberg30dc78e2012-01-04 15:44:20 +02001635
1636discov_complete:
1637 hci_discovery_set_state(hdev, DISCOVERY_STOPPED);
1638}
1639
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001640static void hci_cs_remote_name_req(struct hci_dev *hdev, __u8 status)
1641{
Johan Hedberg127178d2010-11-18 22:22:29 +02001642 struct hci_cp_remote_name_req *cp;
1643 struct hci_conn *conn;
1644
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +03001645 BT_DBG("%s status 0x%2.2x", hdev->name, status);
Johan Hedberg127178d2010-11-18 22:22:29 +02001646
1647 /* If successful wait for the name req complete event before
1648 * checking for the need to do authentication */
1649 if (!status)
1650 return;
1651
1652 cp = hci_sent_cmd_data(hdev, HCI_OP_REMOTE_NAME_REQ);
1653 if (!cp)
1654 return;
1655
1656 hci_dev_lock(hdev);
1657
1658 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &cp->bdaddr);
Johan Hedbergb644ba32012-01-17 21:48:47 +02001659
1660 if (test_bit(HCI_MGMT, &hdev->dev_flags))
1661 hci_check_pending_name(hdev, conn, &cp->bdaddr, NULL, 0);
1662
Johan Hedberg79c6c702011-04-28 11:28:55 -07001663 if (!conn)
1664 goto unlock;
1665
1666 if (!hci_outgoing_auth_needed(hdev, conn))
1667 goto unlock;
1668
Johan Hedberg51a8efd2012-01-16 06:10:31 +02001669 if (!test_and_set_bit(HCI_CONN_AUTH_PEND, &conn->flags)) {
Johan Hedberg127178d2010-11-18 22:22:29 +02001670 struct hci_cp_auth_requested cp;
1671 cp.handle = __cpu_to_le16(conn->handle);
1672 hci_send_cmd(hdev, HCI_OP_AUTH_REQUESTED, sizeof(cp), &cp);
1673 }
1674
Johan Hedberg79c6c702011-04-28 11:28:55 -07001675unlock:
Johan Hedberg127178d2010-11-18 22:22:29 +02001676 hci_dev_unlock(hdev);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001677}
1678
Marcel Holtmann769be972008-07-14 20:13:49 +02001679static void hci_cs_read_remote_features(struct hci_dev *hdev, __u8 status)
1680{
1681 struct hci_cp_read_remote_features *cp;
1682 struct hci_conn *conn;
1683
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +03001684 BT_DBG("%s status 0x%2.2x", hdev->name, status);
Marcel Holtmann769be972008-07-14 20:13:49 +02001685
1686 if (!status)
1687 return;
1688
1689 cp = hci_sent_cmd_data(hdev, HCI_OP_READ_REMOTE_FEATURES);
1690 if (!cp)
1691 return;
1692
1693 hci_dev_lock(hdev);
1694
1695 conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(cp->handle));
1696 if (conn) {
1697 if (conn->state == BT_CONFIG) {
Marcel Holtmann769be972008-07-14 20:13:49 +02001698 hci_proto_connect_cfm(conn, status);
1699 hci_conn_put(conn);
1700 }
1701 }
1702
1703 hci_dev_unlock(hdev);
1704}
1705
1706static void hci_cs_read_remote_ext_features(struct hci_dev *hdev, __u8 status)
1707{
1708 struct hci_cp_read_remote_ext_features *cp;
1709 struct hci_conn *conn;
1710
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +03001711 BT_DBG("%s status 0x%2.2x", hdev->name, status);
Marcel Holtmann769be972008-07-14 20:13:49 +02001712
1713 if (!status)
1714 return;
1715
1716 cp = hci_sent_cmd_data(hdev, HCI_OP_READ_REMOTE_EXT_FEATURES);
1717 if (!cp)
1718 return;
1719
1720 hci_dev_lock(hdev);
1721
1722 conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(cp->handle));
1723 if (conn) {
1724 if (conn->state == BT_CONFIG) {
Marcel Holtmann769be972008-07-14 20:13:49 +02001725 hci_proto_connect_cfm(conn, status);
1726 hci_conn_put(conn);
1727 }
1728 }
1729
1730 hci_dev_unlock(hdev);
1731}
1732
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001733static void hci_cs_setup_sync_conn(struct hci_dev *hdev, __u8 status)
1734{
Marcel Holtmannb6a0dc82007-10-20 14:55:10 +02001735 struct hci_cp_setup_sync_conn *cp;
1736 struct hci_conn *acl, *sco;
1737 __u16 handle;
1738
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +03001739 BT_DBG("%s status 0x%2.2x", hdev->name, status);
Marcel Holtmannb6a0dc82007-10-20 14:55:10 +02001740
1741 if (!status)
1742 return;
1743
1744 cp = hci_sent_cmd_data(hdev, HCI_OP_SETUP_SYNC_CONN);
1745 if (!cp)
1746 return;
1747
1748 handle = __le16_to_cpu(cp->handle);
1749
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +03001750 BT_DBG("%s handle 0x%4.4x", hdev->name, handle);
Marcel Holtmannb6a0dc82007-10-20 14:55:10 +02001751
1752 hci_dev_lock(hdev);
1753
1754 acl = hci_conn_hash_lookup_handle(hdev, handle);
Andrei Emeltchenko5a08ecc2011-01-11 17:20:20 +02001755 if (acl) {
1756 sco = acl->link;
1757 if (sco) {
1758 sco->state = BT_CLOSED;
Marcel Holtmannb6a0dc82007-10-20 14:55:10 +02001759
Andrei Emeltchenko5a08ecc2011-01-11 17:20:20 +02001760 hci_proto_connect_cfm(sco, status);
1761 hci_conn_del(sco);
1762 }
Marcel Holtmannb6a0dc82007-10-20 14:55:10 +02001763 }
1764
1765 hci_dev_unlock(hdev);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001766}
1767
1768static void hci_cs_sniff_mode(struct hci_dev *hdev, __u8 status)
1769{
1770 struct hci_cp_sniff_mode *cp;
1771 struct hci_conn *conn;
1772
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +03001773 BT_DBG("%s status 0x%2.2x", hdev->name, status);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001774
1775 if (!status)
1776 return;
1777
1778 cp = hci_sent_cmd_data(hdev, HCI_OP_SNIFF_MODE);
1779 if (!cp)
1780 return;
1781
1782 hci_dev_lock(hdev);
1783
1784 conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(cp->handle));
Marcel Holtmanne73439d2010-07-26 10:06:00 -04001785 if (conn) {
Johan Hedberg51a8efd2012-01-16 06:10:31 +02001786 clear_bit(HCI_CONN_MODE_CHANGE_PEND, &conn->flags);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001787
Johan Hedberg51a8efd2012-01-16 06:10:31 +02001788 if (test_and_clear_bit(HCI_CONN_SCO_SETUP_PEND, &conn->flags))
Marcel Holtmanne73439d2010-07-26 10:06:00 -04001789 hci_sco_setup(conn, status);
1790 }
1791
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001792 hci_dev_unlock(hdev);
1793}
1794
1795static void hci_cs_exit_sniff_mode(struct hci_dev *hdev, __u8 status)
1796{
1797 struct hci_cp_exit_sniff_mode *cp;
1798 struct hci_conn *conn;
1799
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +03001800 BT_DBG("%s status 0x%2.2x", hdev->name, status);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001801
1802 if (!status)
1803 return;
1804
1805 cp = hci_sent_cmd_data(hdev, HCI_OP_EXIT_SNIFF_MODE);
1806 if (!cp)
1807 return;
1808
1809 hci_dev_lock(hdev);
1810
1811 conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(cp->handle));
Marcel Holtmanne73439d2010-07-26 10:06:00 -04001812 if (conn) {
Johan Hedberg51a8efd2012-01-16 06:10:31 +02001813 clear_bit(HCI_CONN_MODE_CHANGE_PEND, &conn->flags);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001814
Johan Hedberg51a8efd2012-01-16 06:10:31 +02001815 if (test_and_clear_bit(HCI_CONN_SCO_SETUP_PEND, &conn->flags))
Marcel Holtmanne73439d2010-07-26 10:06:00 -04001816 hci_sco_setup(conn, status);
1817 }
1818
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001819 hci_dev_unlock(hdev);
1820}
1821
Johan Hedberg88c3df12012-02-09 14:27:38 +02001822static void hci_cs_disconnect(struct hci_dev *hdev, u8 status)
1823{
1824 struct hci_cp_disconnect *cp;
1825 struct hci_conn *conn;
1826
1827 if (!status)
1828 return;
1829
1830 cp = hci_sent_cmd_data(hdev, HCI_OP_DISCONNECT);
1831 if (!cp)
1832 return;
1833
1834 hci_dev_lock(hdev);
1835
1836 conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(cp->handle));
1837 if (conn)
1838 mgmt_disconnect_failed(hdev, &conn->dst, conn->type,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001839 conn->dst_type, status);
Johan Hedberg88c3df12012-02-09 14:27:38 +02001840
1841 hci_dev_unlock(hdev);
1842}
1843
Ville Tervofcd89c02011-02-10 22:38:47 -03001844static void hci_cs_le_create_conn(struct hci_dev *hdev, __u8 status)
1845{
Ville Tervofcd89c02011-02-10 22:38:47 -03001846 struct hci_conn *conn;
1847
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +03001848 BT_DBG("%s status 0x%2.2x", hdev->name, status);
Ville Tervofcd89c02011-02-10 22:38:47 -03001849
Ville Tervofcd89c02011-02-10 22:38:47 -03001850 if (status) {
Andre Guedesf00a06a2012-07-27 15:10:13 -03001851 hci_dev_lock(hdev);
Ville Tervofcd89c02011-02-10 22:38:47 -03001852
Andre Guedes0c95ab72012-07-27 15:10:14 -03001853 conn = hci_conn_hash_lookup_state(hdev, LE_LINK, BT_CONNECT);
Andre Guedesf00a06a2012-07-27 15:10:13 -03001854 if (!conn) {
1855 hci_dev_unlock(hdev);
1856 return;
1857 }
1858
Andrei Emeltchenko6ed93dc2012-09-25 12:49:43 +03001859 BT_DBG("%s bdaddr %pMR conn %p", hdev->name, &conn->dst, conn);
Andre Guedesf00a06a2012-07-27 15:10:13 -03001860
1861 conn->state = BT_CLOSED;
Andre Guedes0c95ab72012-07-27 15:10:14 -03001862 mgmt_connect_failed(hdev, &conn->dst, conn->type,
Andre Guedesf00a06a2012-07-27 15:10:13 -03001863 conn->dst_type, status);
1864 hci_proto_connect_cfm(conn, status);
1865 hci_conn_del(conn);
1866
1867 hci_dev_unlock(hdev);
1868 }
Ville Tervofcd89c02011-02-10 22:38:47 -03001869}
1870
Vinicius Costa Gomesa7a595f2011-06-09 18:50:47 -03001871static void hci_cs_le_start_enc(struct hci_dev *hdev, u8 status)
1872{
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +03001873 BT_DBG("%s status 0x%2.2x", hdev->name, status);
Vinicius Costa Gomesa7a595f2011-06-09 18:50:47 -03001874}
1875
Andrei Emeltchenkoa02226d2012-09-27 17:26:19 +03001876static void hci_cs_create_phylink(struct hci_dev *hdev, u8 status)
1877{
Andrei Emeltchenko93c284e2012-09-27 17:26:20 +03001878 struct hci_cp_create_phy_link *cp;
1879
Andrei Emeltchenkoa02226d2012-09-27 17:26:19 +03001880 BT_DBG("%s status 0x%2.2x", hdev->name, status);
Andrei Emeltchenko93c284e2012-09-27 17:26:20 +03001881
Andrei Emeltchenko93c284e2012-09-27 17:26:20 +03001882 cp = hci_sent_cmd_data(hdev, HCI_OP_CREATE_PHY_LINK);
1883 if (!cp)
1884 return;
1885
Andrei Emeltchenkoe58917b2012-10-31 15:46:33 +02001886 hci_dev_lock(hdev);
1887
1888 if (status) {
1889 struct hci_conn *hcon;
1890
1891 hcon = hci_conn_hash_lookup_handle(hdev, cp->phy_handle);
1892 if (hcon)
1893 hci_conn_del(hcon);
1894 } else {
1895 amp_write_remote_assoc(hdev, cp->phy_handle);
1896 }
1897
1898 hci_dev_unlock(hdev);
Andrei Emeltchenkoa02226d2012-09-27 17:26:19 +03001899}
1900
Andrei Emeltchenko0b26ab92012-09-27 17:26:24 +03001901static void hci_cs_accept_phylink(struct hci_dev *hdev, u8 status)
1902{
1903 struct hci_cp_accept_phy_link *cp;
1904
1905 BT_DBG("%s status 0x%2.2x", hdev->name, status);
1906
1907 if (status)
1908 return;
1909
1910 cp = hci_sent_cmd_data(hdev, HCI_OP_ACCEPT_PHY_LINK);
1911 if (!cp)
1912 return;
1913
1914 amp_write_remote_assoc(hdev, cp->phy_handle);
1915}
1916
Andrei Emeltchenko5ce66b52012-10-31 15:46:30 +02001917static void hci_cs_create_logical_link(struct hci_dev *hdev, u8 status)
1918{
1919 BT_DBG("%s status 0x%2.2x", hdev->name, status);
1920}
1921
Gustavo Padovan6039aa72012-05-23 04:04:18 -03001922static void hci_inquiry_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001923{
1924 __u8 status = *((__u8 *) skb->data);
Johan Hedberg30dc78e2012-01-04 15:44:20 +02001925 struct discovery_state *discov = &hdev->discovery;
1926 struct inquiry_entry *e;
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001927
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +03001928 BT_DBG("%s status 0x%2.2x", hdev->name, status);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001929
Johan Hedberg23bb5762010-12-21 23:01:27 +02001930 hci_req_complete(hdev, HCI_OP_INQUIRY, status);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001931
1932 hci_conn_check_pending(hdev);
Andre Guedes89352e72011-11-04 14:16:53 -03001933
1934 if (!test_and_clear_bit(HCI_INQUIRY, &hdev->flags))
1935 return;
1936
Johan Hedberga8b2d5c2012-01-08 23:11:15 +02001937 if (!test_bit(HCI_MGMT, &hdev->dev_flags))
Johan Hedberg30dc78e2012-01-04 15:44:20 +02001938 return;
1939
Johan Hedberg56e5cb82011-11-08 20:40:16 +02001940 hci_dev_lock(hdev);
Johan Hedberg30dc78e2012-01-04 15:44:20 +02001941
Andre Guedes343f9352012-02-17 20:39:37 -03001942 if (discov->state != DISCOVERY_FINDING)
Johan Hedberg30dc78e2012-01-04 15:44:20 +02001943 goto unlock;
1944
1945 if (list_empty(&discov->resolve)) {
1946 hci_discovery_set_state(hdev, DISCOVERY_STOPPED);
1947 goto unlock;
1948 }
1949
1950 e = hci_inquiry_cache_lookup_resolve(hdev, BDADDR_ANY, NAME_NEEDED);
1951 if (e && hci_resolve_name(hdev, e) == 0) {
1952 e->name_state = NAME_PENDING;
1953 hci_discovery_set_state(hdev, DISCOVERY_RESOLVING);
1954 } else {
1955 hci_discovery_set_state(hdev, DISCOVERY_STOPPED);
1956 }
1957
1958unlock:
Johan Hedberg56e5cb82011-11-08 20:40:16 +02001959 hci_dev_unlock(hdev);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001960}
1961
Gustavo Padovan6039aa72012-05-23 04:04:18 -03001962static void hci_inquiry_result_evt(struct hci_dev *hdev, struct sk_buff *skb)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001963{
Marcel Holtmann45bb4bf2005-08-09 20:27:49 -07001964 struct inquiry_data data;
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001965 struct inquiry_info *info = (void *) (skb->data + 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001966 int num_rsp = *((__u8 *) skb->data);
1967
1968 BT_DBG("%s num_rsp %d", hdev->name, num_rsp);
1969
Marcel Holtmann45bb4bf2005-08-09 20:27:49 -07001970 if (!num_rsp)
1971 return;
1972
Andre Guedes1519cc12012-03-21 00:03:38 -03001973 if (test_bit(HCI_PERIODIC_INQ, &hdev->dev_flags))
1974 return;
1975
Linus Torvalds1da177e2005-04-16 15:20:36 -07001976 hci_dev_lock(hdev);
Marcel Holtmann45bb4bf2005-08-09 20:27:49 -07001977
Johan Hedberge17acd42011-03-30 23:57:16 +03001978 for (; num_rsp; num_rsp--, info++) {
Johan Hedberg388fc8f2012-02-23 00:38:59 +02001979 bool name_known, ssp;
Johan Hedberg31754052012-01-04 13:39:52 +02001980
Linus Torvalds1da177e2005-04-16 15:20:36 -07001981 bacpy(&data.bdaddr, &info->bdaddr);
1982 data.pscan_rep_mode = info->pscan_rep_mode;
1983 data.pscan_period_mode = info->pscan_period_mode;
1984 data.pscan_mode = info->pscan_mode;
1985 memcpy(data.dev_class, info->dev_class, 3);
1986 data.clock_offset = info->clock_offset;
1987 data.rssi = 0x00;
Marcel Holtmann41a96212008-07-14 20:13:48 +02001988 data.ssp_mode = 0x00;
Johan Hedberg31754052012-01-04 13:39:52 +02001989
Johan Hedberg388fc8f2012-02-23 00:38:59 +02001990 name_known = hci_inquiry_cache_update(hdev, &data, false, &ssp);
Johan Hedberg48264f02011-11-09 13:58:58 +02001991 mgmt_device_found(hdev, &info->bdaddr, ACL_LINK, 0x00,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001992 info->dev_class, 0, !name_known, ssp, NULL,
1993 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001994 }
Marcel Holtmann45bb4bf2005-08-09 20:27:49 -07001995
Linus Torvalds1da177e2005-04-16 15:20:36 -07001996 hci_dev_unlock(hdev);
1997}
1998
Gustavo Padovan6039aa72012-05-23 04:04:18 -03001999static void hci_conn_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002000{
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002001 struct hci_ev_conn_complete *ev = (void *) skb->data;
2002 struct hci_conn *conn;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002003
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002004 BT_DBG("%s", hdev->name);
Marcel Holtmann45bb4bf2005-08-09 20:27:49 -07002005
Linus Torvalds1da177e2005-04-16 15:20:36 -07002006 hci_dev_lock(hdev);
Marcel Holtmann45bb4bf2005-08-09 20:27:49 -07002007
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002008 conn = hci_conn_hash_lookup_ba(hdev, ev->link_type, &ev->bdaddr);
Marcel Holtmann94992372009-04-19 19:30:03 +02002009 if (!conn) {
2010 if (ev->link_type != SCO_LINK)
2011 goto unlock;
2012
2013 conn = hci_conn_hash_lookup_ba(hdev, ESCO_LINK, &ev->bdaddr);
2014 if (!conn)
2015 goto unlock;
2016
2017 conn->type = SCO_LINK;
2018 }
Marcel Holtmann45bb4bf2005-08-09 20:27:49 -07002019
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002020 if (!ev->status) {
2021 conn->handle = __le16_to_cpu(ev->handle);
Marcel Holtmann769be972008-07-14 20:13:49 +02002022
2023 if (conn->type == ACL_LINK) {
2024 conn->state = BT_CONFIG;
2025 hci_conn_hold(conn);
Szymon Janca9ea3ed2012-07-19 14:46:08 +02002026
2027 if (!conn->out && !hci_conn_ssp_enabled(conn) &&
2028 !hci_find_link_key(hdev, &ev->bdaddr))
2029 conn->disc_timeout = HCI_PAIRING_TIMEOUT;
2030 else
2031 conn->disc_timeout = HCI_DISCONN_TIMEOUT;
Marcel Holtmann769be972008-07-14 20:13:49 +02002032 } else
2033 conn->state = BT_CONNECTED;
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002034
Marcel Holtmann9eba32b2009-08-22 14:19:26 -07002035 hci_conn_hold_device(conn);
Marcel Holtmann7d0db0a2008-07-14 20:13:51 +02002036 hci_conn_add_sysfs(conn);
2037
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002038 if (test_bit(HCI_AUTH, &hdev->flags))
2039 conn->link_mode |= HCI_LM_AUTH;
2040
2041 if (test_bit(HCI_ENCRYPT, &hdev->flags))
2042 conn->link_mode |= HCI_LM_ENCRYPT;
2043
2044 /* Get remote features */
2045 if (conn->type == ACL_LINK) {
2046 struct hci_cp_read_remote_features cp;
2047 cp.handle = ev->handle;
Marcel Holtmann769be972008-07-14 20:13:49 +02002048 hci_send_cmd(hdev, HCI_OP_READ_REMOTE_FEATURES,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002049 sizeof(cp), &cp);
Marcel Holtmann45bb4bf2005-08-09 20:27:49 -07002050 }
Marcel Holtmann45bb4bf2005-08-09 20:27:49 -07002051
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002052 /* Set packet type for incoming connection */
Andrei Emeltchenkod095c1e2011-12-01 14:33:27 +02002053 if (!conn->out && hdev->hci_ver < BLUETOOTH_VER_2_0) {
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002054 struct hci_cp_change_conn_ptype cp;
2055 cp.handle = ev->handle;
Marcel Holtmanna8746412008-07-14 20:13:46 +02002056 cp.pkt_type = cpu_to_le16(conn->pkt_type);
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002057 hci_send_cmd(hdev, HCI_OP_CHANGE_CONN_PTYPE, sizeof(cp),
2058 &cp);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002059 }
Johan Hedberg17d5c042011-01-22 06:09:08 +02002060 } else {
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002061 conn->state = BT_CLOSED;
Johan Hedberg17d5c042011-01-22 06:09:08 +02002062 if (conn->type == ACL_LINK)
Johan Hedberg744cf192011-11-08 20:40:14 +02002063 mgmt_connect_failed(hdev, &ev->bdaddr, conn->type,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002064 conn->dst_type, ev->status);
Johan Hedberg17d5c042011-01-22 06:09:08 +02002065 }
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002066
Marcel Holtmanne73439d2010-07-26 10:06:00 -04002067 if (conn->type == ACL_LINK)
2068 hci_sco_setup(conn, ev->status);
Marcel Holtmann45bb4bf2005-08-09 20:27:49 -07002069
Marcel Holtmann769be972008-07-14 20:13:49 +02002070 if (ev->status) {
2071 hci_proto_connect_cfm(conn, ev->status);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002072 hci_conn_del(conn);
Marcel Holtmannc89b6e62009-01-15 21:57:03 +01002073 } else if (ev->link_type != ACL_LINK)
2074 hci_proto_connect_cfm(conn, ev->status);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002075
2076unlock:
Linus Torvalds1da177e2005-04-16 15:20:36 -07002077 hci_dev_unlock(hdev);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002078
2079 hci_conn_check_pending(hdev);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002080}
2081
Frédéric Dalleau20714bf2012-11-21 10:51:12 +01002082void hci_conn_accept(struct hci_conn *conn, int mask)
2083{
2084 struct hci_dev *hdev = conn->hdev;
2085
2086 BT_DBG("conn %p", conn);
2087
2088 conn->state = BT_CONFIG;
2089
2090 if (!lmp_esco_capable(hdev)) {
2091 struct hci_cp_accept_conn_req cp;
2092
2093 bacpy(&cp.bdaddr, &conn->dst);
2094
2095 if (lmp_rswitch_capable(hdev) && (mask & HCI_LM_MASTER))
2096 cp.role = 0x00; /* Become master */
2097 else
2098 cp.role = 0x01; /* Remain slave */
2099
2100 hci_send_cmd(hdev, HCI_OP_ACCEPT_CONN_REQ, sizeof(cp), &cp);
2101 } else /* lmp_esco_capable(hdev)) */ {
2102 struct hci_cp_accept_sync_conn_req cp;
2103
2104 bacpy(&cp.bdaddr, &conn->dst);
2105 cp.pkt_type = cpu_to_le16(conn->pkt_type);
2106
2107 cp.tx_bandwidth = __constant_cpu_to_le32(0x00001f40);
2108 cp.rx_bandwidth = __constant_cpu_to_le32(0x00001f40);
2109 cp.max_latency = __constant_cpu_to_le16(0xffff);
2110 cp.content_format = cpu_to_le16(hdev->voice_setting);
2111 cp.retrans_effort = 0xff;
2112
2113 hci_send_cmd(hdev, HCI_OP_ACCEPT_SYNC_CONN_REQ,
2114 sizeof(cp), &cp);
2115 }
2116}
2117
Gustavo Padovan6039aa72012-05-23 04:04:18 -03002118static void hci_conn_request_evt(struct hci_dev *hdev, struct sk_buff *skb)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002119{
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002120 struct hci_ev_conn_request *ev = (void *) skb->data;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002121 int mask = hdev->link_mode;
Frédéric Dalleau20714bf2012-11-21 10:51:12 +01002122 __u8 flags = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002123
Andrei Emeltchenko6ed93dc2012-09-25 12:49:43 +03002124 BT_DBG("%s bdaddr %pMR type 0x%x", hdev->name, &ev->bdaddr,
Gustavo Padovan807deac2012-05-17 00:36:24 -03002125 ev->link_type);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002126
Frédéric Dalleau20714bf2012-11-21 10:51:12 +01002127 mask |= hci_proto_connect_ind(hdev, &ev->bdaddr, ev->link_type,
2128 &flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002129
Szymon Janc138d22e2011-02-17 16:44:23 +01002130 if ((mask & HCI_LM_ACCEPT) &&
Gustavo Padovan807deac2012-05-17 00:36:24 -03002131 !hci_blacklist_lookup(hdev, &ev->bdaddr)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002132 /* Connection accepted */
Marcel Holtmannc7bdd502008-07-14 20:13:47 +02002133 struct inquiry_entry *ie;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002134 struct hci_conn *conn;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002135
2136 hci_dev_lock(hdev);
Marcel Holtmannb6a0dc82007-10-20 14:55:10 +02002137
Andrei Emeltchenkocc11b9c2010-11-22 13:21:37 +02002138 ie = hci_inquiry_cache_lookup(hdev, &ev->bdaddr);
2139 if (ie)
Marcel Holtmannc7bdd502008-07-14 20:13:47 +02002140 memcpy(ie->data.dev_class, ev->dev_class, 3);
2141
Gustavo Padovan8fc9ced2012-05-23 04:04:21 -03002142 conn = hci_conn_hash_lookup_ba(hdev, ev->link_type,
2143 &ev->bdaddr);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002144 if (!conn) {
Andrei Emeltchenkocc11b9c2010-11-22 13:21:37 +02002145 conn = hci_conn_add(hdev, ev->link_type, &ev->bdaddr);
2146 if (!conn) {
Gustavo F. Padovan893ef972010-07-18 15:13:37 -03002147 BT_ERR("No memory for new connection");
Linus Torvalds1da177e2005-04-16 15:20:36 -07002148 hci_dev_unlock(hdev);
2149 return;
2150 }
2151 }
Marcel Holtmannb6a0dc82007-10-20 14:55:10 +02002152
Linus Torvalds1da177e2005-04-16 15:20:36 -07002153 memcpy(conn->dev_class, ev->dev_class, 3);
Marcel Holtmannb6a0dc82007-10-20 14:55:10 +02002154
Linus Torvalds1da177e2005-04-16 15:20:36 -07002155 hci_dev_unlock(hdev);
2156
Frédéric Dalleau20714bf2012-11-21 10:51:12 +01002157 if (ev->link_type == ACL_LINK ||
2158 (!(flags & HCI_PROTO_DEFER) && !lmp_esco_capable(hdev))) {
Marcel Holtmannb6a0dc82007-10-20 14:55:10 +02002159 struct hci_cp_accept_conn_req cp;
Frédéric Dalleau20714bf2012-11-21 10:51:12 +01002160 conn->state = BT_CONNECT;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002161
Marcel Holtmannb6a0dc82007-10-20 14:55:10 +02002162 bacpy(&cp.bdaddr, &ev->bdaddr);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002163
Marcel Holtmannb6a0dc82007-10-20 14:55:10 +02002164 if (lmp_rswitch_capable(hdev) && (mask & HCI_LM_MASTER))
2165 cp.role = 0x00; /* Become master */
2166 else
2167 cp.role = 0x01; /* Remain slave */
2168
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002169 hci_send_cmd(hdev, HCI_OP_ACCEPT_CONN_REQ, sizeof(cp),
2170 &cp);
Frédéric Dalleau20714bf2012-11-21 10:51:12 +01002171 } else if (!(flags & HCI_PROTO_DEFER)) {
Marcel Holtmannb6a0dc82007-10-20 14:55:10 +02002172 struct hci_cp_accept_sync_conn_req cp;
Frédéric Dalleau20714bf2012-11-21 10:51:12 +01002173 conn->state = BT_CONNECT;
Marcel Holtmannb6a0dc82007-10-20 14:55:10 +02002174
2175 bacpy(&cp.bdaddr, &ev->bdaddr);
Marcel Holtmanna8746412008-07-14 20:13:46 +02002176 cp.pkt_type = cpu_to_le16(conn->pkt_type);
Marcel Holtmannb6a0dc82007-10-20 14:55:10 +02002177
Andrei Emeltchenko82781e62012-05-25 11:38:27 +03002178 cp.tx_bandwidth = __constant_cpu_to_le32(0x00001f40);
2179 cp.rx_bandwidth = __constant_cpu_to_le32(0x00001f40);
2180 cp.max_latency = __constant_cpu_to_le16(0xffff);
Marcel Holtmannb6a0dc82007-10-20 14:55:10 +02002181 cp.content_format = cpu_to_le16(hdev->voice_setting);
2182 cp.retrans_effort = 0xff;
2183
2184 hci_send_cmd(hdev, HCI_OP_ACCEPT_SYNC_CONN_REQ,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002185 sizeof(cp), &cp);
Frédéric Dalleau20714bf2012-11-21 10:51:12 +01002186 } else {
2187 conn->state = BT_CONNECT2;
2188 hci_proto_connect_cfm(conn, 0);
2189 hci_conn_put(conn);
Marcel Holtmannb6a0dc82007-10-20 14:55:10 +02002190 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002191 } else {
2192 /* Connection rejected */
2193 struct hci_cp_reject_conn_req cp;
2194
2195 bacpy(&cp.bdaddr, &ev->bdaddr);
Andrei Emeltchenko9f5a0d72011-11-07 14:20:25 +02002196 cp.reason = HCI_ERROR_REJ_BAD_ADDR;
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002197 hci_send_cmd(hdev, HCI_OP_REJECT_CONN_REQ, sizeof(cp), &cp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002198 }
2199}
2200
Mikel Astizf0d6a0e2012-08-09 09:52:30 +02002201static u8 hci_to_mgmt_reason(u8 err)
2202{
2203 switch (err) {
2204 case HCI_ERROR_CONNECTION_TIMEOUT:
2205 return MGMT_DEV_DISCONN_TIMEOUT;
2206 case HCI_ERROR_REMOTE_USER_TERM:
2207 case HCI_ERROR_REMOTE_LOW_RESOURCES:
2208 case HCI_ERROR_REMOTE_POWER_OFF:
2209 return MGMT_DEV_DISCONN_REMOTE;
2210 case HCI_ERROR_LOCAL_HOST_TERM:
2211 return MGMT_DEV_DISCONN_LOCAL_HOST;
2212 default:
2213 return MGMT_DEV_DISCONN_UNKNOWN;
2214 }
2215}
2216
Gustavo Padovan6039aa72012-05-23 04:04:18 -03002217static void hci_disconn_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002218{
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002219 struct hci_ev_disconn_complete *ev = (void *) skb->data;
Marcel Holtmann04837f62006-07-03 10:02:33 +02002220 struct hci_conn *conn;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002221
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +03002222 BT_DBG("%s status 0x%2.2x", hdev->name, ev->status);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002223
Linus Torvalds1da177e2005-04-16 15:20:36 -07002224 hci_dev_lock(hdev);
2225
Marcel Holtmann04837f62006-07-03 10:02:33 +02002226 conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
Johan Hedbergf7520542011-01-20 12:34:39 +02002227 if (!conn)
2228 goto unlock;
Marcel Holtmann7d0db0a2008-07-14 20:13:51 +02002229
Johan Hedberg37d9ef72011-11-10 15:54:39 +02002230 if (ev->status == 0)
2231 conn->state = BT_CLOSED;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002232
Johan Hedbergb644ba32012-01-17 21:48:47 +02002233 if (test_and_clear_bit(HCI_CONN_MGMT_CONNECTED, &conn->flags) &&
Gustavo Padovan807deac2012-05-17 00:36:24 -03002234 (conn->type == ACL_LINK || conn->type == LE_LINK)) {
Mikel Astizf0d6a0e2012-08-09 09:52:30 +02002235 if (ev->status) {
Johan Hedberg88c3df12012-02-09 14:27:38 +02002236 mgmt_disconnect_failed(hdev, &conn->dst, conn->type,
Gustavo Padovan807deac2012-05-17 00:36:24 -03002237 conn->dst_type, ev->status);
Mikel Astizf0d6a0e2012-08-09 09:52:30 +02002238 } else {
2239 u8 reason = hci_to_mgmt_reason(ev->reason);
2240
Johan Hedbergafc747a2012-01-15 18:11:07 +02002241 mgmt_device_disconnected(hdev, &conn->dst, conn->type,
Mikel Astizf0d6a0e2012-08-09 09:52:30 +02002242 conn->dst_type, reason);
2243 }
Johan Hedberg37d9ef72011-11-10 15:54:39 +02002244 }
Johan Hedbergf7520542011-01-20 12:34:39 +02002245
Johan Hedberg37d9ef72011-11-10 15:54:39 +02002246 if (ev->status == 0) {
Vishal Agarwal6ec5bca2012-04-16 14:44:44 +05302247 if (conn->type == ACL_LINK && conn->flush_key)
2248 hci_remove_link_key(hdev, &conn->dst);
Johan Hedberg37d9ef72011-11-10 15:54:39 +02002249 hci_proto_disconn_cfm(conn, ev->reason);
2250 hci_conn_del(conn);
2251 }
Johan Hedbergf7520542011-01-20 12:34:39 +02002252
2253unlock:
Linus Torvalds1da177e2005-04-16 15:20:36 -07002254 hci_dev_unlock(hdev);
2255}
2256
Gustavo Padovan6039aa72012-05-23 04:04:18 -03002257static void hci_auth_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002258{
2259 struct hci_ev_auth_complete *ev = (void *) skb->data;
2260 struct hci_conn *conn;
2261
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +03002262 BT_DBG("%s status 0x%2.2x", hdev->name, ev->status);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002263
2264 hci_dev_lock(hdev);
2265
2266 conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
Waldemar Rymarkiewiczd7556e22011-05-31 15:49:26 +02002267 if (!conn)
2268 goto unlock;
2269
2270 if (!ev->status) {
Johan Hedbergaa64a8b2012-01-18 21:33:12 +02002271 if (!hci_conn_ssp_enabled(conn) &&
Gustavo Padovan807deac2012-05-17 00:36:24 -03002272 test_bit(HCI_CONN_REAUTH_PEND, &conn->flags)) {
Waldemar Rymarkiewiczd7556e22011-05-31 15:49:26 +02002273 BT_INFO("re-auth of legacy device is not possible.");
Johan Hedberg2a611692011-02-19 12:06:00 -03002274 } else {
Waldemar Rymarkiewiczd7556e22011-05-31 15:49:26 +02002275 conn->link_mode |= HCI_LM_AUTH;
2276 conn->sec_level = conn->pending_sec_level;
Johan Hedberg2a611692011-02-19 12:06:00 -03002277 }
Waldemar Rymarkiewiczd7556e22011-05-31 15:49:26 +02002278 } else {
Johan Hedbergbab73cb2012-02-09 16:07:29 +02002279 mgmt_auth_failed(hdev, &conn->dst, conn->type, conn->dst_type,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002280 ev->status);
Waldemar Rymarkiewiczd7556e22011-05-31 15:49:26 +02002281 }
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002282
Johan Hedberg51a8efd2012-01-16 06:10:31 +02002283 clear_bit(HCI_CONN_AUTH_PEND, &conn->flags);
2284 clear_bit(HCI_CONN_REAUTH_PEND, &conn->flags);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002285
Waldemar Rymarkiewiczd7556e22011-05-31 15:49:26 +02002286 if (conn->state == BT_CONFIG) {
Johan Hedbergaa64a8b2012-01-18 21:33:12 +02002287 if (!ev->status && hci_conn_ssp_enabled(conn)) {
Waldemar Rymarkiewiczd7556e22011-05-31 15:49:26 +02002288 struct hci_cp_set_conn_encrypt cp;
2289 cp.handle = ev->handle;
2290 cp.encrypt = 0x01;
2291 hci_send_cmd(hdev, HCI_OP_SET_CONN_ENCRYPT, sizeof(cp),
Gustavo Padovan807deac2012-05-17 00:36:24 -03002292 &cp);
Marcel Holtmann052b30b2009-04-26 20:01:22 +02002293 } else {
Waldemar Rymarkiewiczd7556e22011-05-31 15:49:26 +02002294 conn->state = BT_CONNECTED;
2295 hci_proto_connect_cfm(conn, ev->status);
Marcel Holtmann052b30b2009-04-26 20:01:22 +02002296 hci_conn_put(conn);
2297 }
Waldemar Rymarkiewiczd7556e22011-05-31 15:49:26 +02002298 } else {
2299 hci_auth_cfm(conn, ev->status);
Marcel Holtmann052b30b2009-04-26 20:01:22 +02002300
Waldemar Rymarkiewiczd7556e22011-05-31 15:49:26 +02002301 hci_conn_hold(conn);
2302 conn->disc_timeout = HCI_DISCONN_TIMEOUT;
2303 hci_conn_put(conn);
2304 }
2305
Johan Hedberg51a8efd2012-01-16 06:10:31 +02002306 if (test_bit(HCI_CONN_ENCRYPT_PEND, &conn->flags)) {
Waldemar Rymarkiewiczd7556e22011-05-31 15:49:26 +02002307 if (!ev->status) {
2308 struct hci_cp_set_conn_encrypt cp;
2309 cp.handle = ev->handle;
2310 cp.encrypt = 0x01;
2311 hci_send_cmd(hdev, HCI_OP_SET_CONN_ENCRYPT, sizeof(cp),
Gustavo Padovan807deac2012-05-17 00:36:24 -03002312 &cp);
Waldemar Rymarkiewiczd7556e22011-05-31 15:49:26 +02002313 } else {
Johan Hedberg51a8efd2012-01-16 06:10:31 +02002314 clear_bit(HCI_CONN_ENCRYPT_PEND, &conn->flags);
Waldemar Rymarkiewiczd7556e22011-05-31 15:49:26 +02002315 hci_encrypt_cfm(conn, ev->status, 0x00);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002316 }
2317 }
2318
Waldemar Rymarkiewiczd7556e22011-05-31 15:49:26 +02002319unlock:
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002320 hci_dev_unlock(hdev);
2321}
2322
Gustavo Padovan6039aa72012-05-23 04:04:18 -03002323static void hci_remote_name_evt(struct hci_dev *hdev, struct sk_buff *skb)
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002324{
Johan Hedberg127178d2010-11-18 22:22:29 +02002325 struct hci_ev_remote_name *ev = (void *) skb->data;
2326 struct hci_conn *conn;
2327
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002328 BT_DBG("%s", hdev->name);
2329
2330 hci_conn_check_pending(hdev);
Johan Hedberg127178d2010-11-18 22:22:29 +02002331
2332 hci_dev_lock(hdev);
2333
2334 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
Johan Hedbergb644ba32012-01-17 21:48:47 +02002335
2336 if (!test_bit(HCI_MGMT, &hdev->dev_flags))
2337 goto check_auth;
2338
2339 if (ev->status == 0)
2340 hci_check_pending_name(hdev, conn, &ev->bdaddr, ev->name,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002341 strnlen(ev->name, HCI_MAX_NAME_LENGTH));
Johan Hedbergb644ba32012-01-17 21:48:47 +02002342 else
2343 hci_check_pending_name(hdev, conn, &ev->bdaddr, NULL, 0);
2344
2345check_auth:
Johan Hedberg79c6c702011-04-28 11:28:55 -07002346 if (!conn)
2347 goto unlock;
2348
2349 if (!hci_outgoing_auth_needed(hdev, conn))
2350 goto unlock;
2351
Johan Hedberg51a8efd2012-01-16 06:10:31 +02002352 if (!test_and_set_bit(HCI_CONN_AUTH_PEND, &conn->flags)) {
Johan Hedberg127178d2010-11-18 22:22:29 +02002353 struct hci_cp_auth_requested cp;
2354 cp.handle = __cpu_to_le16(conn->handle);
2355 hci_send_cmd(hdev, HCI_OP_AUTH_REQUESTED, sizeof(cp), &cp);
2356 }
2357
Johan Hedberg79c6c702011-04-28 11:28:55 -07002358unlock:
Johan Hedberg127178d2010-11-18 22:22:29 +02002359 hci_dev_unlock(hdev);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002360}
2361
Gustavo Padovan6039aa72012-05-23 04:04:18 -03002362static void hci_encrypt_change_evt(struct hci_dev *hdev, struct sk_buff *skb)
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002363{
2364 struct hci_ev_encrypt_change *ev = (void *) skb->data;
2365 struct hci_conn *conn;
2366
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +03002367 BT_DBG("%s status 0x%2.2x", hdev->name, ev->status);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002368
2369 hci_dev_lock(hdev);
2370
2371 conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
2372 if (conn) {
2373 if (!ev->status) {
Marcel Holtmannae293192008-07-14 20:13:45 +02002374 if (ev->encrypt) {
2375 /* Encryption implies authentication */
2376 conn->link_mode |= HCI_LM_AUTH;
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002377 conn->link_mode |= HCI_LM_ENCRYPT;
Vinicius Costa Gomesda85e5e2011-06-09 18:50:53 -03002378 conn->sec_level = conn->pending_sec_level;
Marcel Holtmannae293192008-07-14 20:13:45 +02002379 } else
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002380 conn->link_mode &= ~HCI_LM_ENCRYPT;
2381 }
2382
Johan Hedberg51a8efd2012-01-16 06:10:31 +02002383 clear_bit(HCI_CONN_ENCRYPT_PEND, &conn->flags);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002384
Gustavo Padovana7d77232012-05-13 03:20:07 -03002385 if (ev->status && conn->state == BT_CONNECTED) {
Gustavo Padovand839c812012-05-16 12:17:12 -03002386 hci_acl_disconn(conn, HCI_ERROR_AUTH_FAILURE);
Gustavo Padovana7d77232012-05-13 03:20:07 -03002387 hci_conn_put(conn);
2388 goto unlock;
2389 }
2390
Marcel Holtmannf8558552008-07-14 20:13:49 +02002391 if (conn->state == BT_CONFIG) {
2392 if (!ev->status)
2393 conn->state = BT_CONNECTED;
2394
2395 hci_proto_connect_cfm(conn, ev->status);
2396 hci_conn_put(conn);
2397 } else
2398 hci_encrypt_cfm(conn, ev->status, ev->encrypt);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002399 }
2400
Gustavo Padovana7d77232012-05-13 03:20:07 -03002401unlock:
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002402 hci_dev_unlock(hdev);
2403}
2404
Gustavo Padovan6039aa72012-05-23 04:04:18 -03002405static void hci_change_link_key_complete_evt(struct hci_dev *hdev,
2406 struct sk_buff *skb)
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002407{
2408 struct hci_ev_change_link_key_complete *ev = (void *) skb->data;
2409 struct hci_conn *conn;
2410
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +03002411 BT_DBG("%s status 0x%2.2x", hdev->name, ev->status);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002412
2413 hci_dev_lock(hdev);
2414
2415 conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
2416 if (conn) {
2417 if (!ev->status)
2418 conn->link_mode |= HCI_LM_SECURE;
2419
Johan Hedberg51a8efd2012-01-16 06:10:31 +02002420 clear_bit(HCI_CONN_AUTH_PEND, &conn->flags);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002421
2422 hci_key_change_cfm(conn, ev->status);
2423 }
2424
2425 hci_dev_unlock(hdev);
2426}
2427
Gustavo Padovan6039aa72012-05-23 04:04:18 -03002428static void hci_remote_features_evt(struct hci_dev *hdev,
2429 struct sk_buff *skb)
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002430{
2431 struct hci_ev_remote_features *ev = (void *) skb->data;
2432 struct hci_conn *conn;
2433
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +03002434 BT_DBG("%s status 0x%2.2x", hdev->name, ev->status);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002435
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002436 hci_dev_lock(hdev);
2437
2438 conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
Johan Hedbergccd556f2010-11-10 17:11:51 +02002439 if (!conn)
2440 goto unlock;
Marcel Holtmann769be972008-07-14 20:13:49 +02002441
Johan Hedbergccd556f2010-11-10 17:11:51 +02002442 if (!ev->status)
2443 memcpy(conn->features, ev->features, 8);
2444
2445 if (conn->state != BT_CONFIG)
2446 goto unlock;
2447
2448 if (!ev->status && lmp_ssp_capable(hdev) && lmp_ssp_capable(conn)) {
2449 struct hci_cp_read_remote_ext_features cp;
2450 cp.handle = ev->handle;
2451 cp.page = 0x01;
2452 hci_send_cmd(hdev, HCI_OP_READ_REMOTE_EXT_FEATURES,
Gustavo Padovan807deac2012-05-17 00:36:24 -03002453 sizeof(cp), &cp);
Johan Hedberg392599b2010-11-18 22:22:28 +02002454 goto unlock;
2455 }
2456
Johan Hedberg671267b2012-05-12 16:11:50 -03002457 if (!ev->status && !test_bit(HCI_CONN_MGMT_CONNECTED, &conn->flags)) {
Johan Hedberg127178d2010-11-18 22:22:29 +02002458 struct hci_cp_remote_name_req cp;
2459 memset(&cp, 0, sizeof(cp));
2460 bacpy(&cp.bdaddr, &conn->dst);
2461 cp.pscan_rep_mode = 0x02;
2462 hci_send_cmd(hdev, HCI_OP_REMOTE_NAME_REQ, sizeof(cp), &cp);
Johan Hedbergb644ba32012-01-17 21:48:47 +02002463 } else if (!test_and_set_bit(HCI_CONN_MGMT_CONNECTED, &conn->flags))
2464 mgmt_device_connected(hdev, &conn->dst, conn->type,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002465 conn->dst_type, 0, NULL, 0,
2466 conn->dev_class);
Johan Hedberg392599b2010-11-18 22:22:28 +02002467
Johan Hedberg127178d2010-11-18 22:22:29 +02002468 if (!hci_outgoing_auth_needed(hdev, conn)) {
Johan Hedbergccd556f2010-11-10 17:11:51 +02002469 conn->state = BT_CONNECTED;
2470 hci_proto_connect_cfm(conn, ev->status);
2471 hci_conn_put(conn);
Marcel Holtmann769be972008-07-14 20:13:49 +02002472 }
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002473
Johan Hedbergccd556f2010-11-10 17:11:51 +02002474unlock:
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002475 hci_dev_unlock(hdev);
2476}
2477
Gustavo Padovan6039aa72012-05-23 04:04:18 -03002478static void hci_remote_version_evt(struct hci_dev *hdev, struct sk_buff *skb)
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002479{
2480 BT_DBG("%s", hdev->name);
2481}
2482
Gustavo Padovan6039aa72012-05-23 04:04:18 -03002483static void hci_qos_setup_complete_evt(struct hci_dev *hdev,
2484 struct sk_buff *skb)
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002485{
2486 BT_DBG("%s", hdev->name);
2487}
2488
Gustavo Padovan6039aa72012-05-23 04:04:18 -03002489static void hci_cmd_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002490{
2491 struct hci_ev_cmd_complete *ev = (void *) skb->data;
2492 __u16 opcode;
2493
2494 skb_pull(skb, sizeof(*ev));
2495
2496 opcode = __le16_to_cpu(ev->opcode);
2497
2498 switch (opcode) {
2499 case HCI_OP_INQUIRY_CANCEL:
2500 hci_cc_inquiry_cancel(hdev, skb);
2501 break;
2502
Andre Guedes4d934832012-03-21 00:03:35 -03002503 case HCI_OP_PERIODIC_INQ:
2504 hci_cc_periodic_inq(hdev, skb);
2505 break;
2506
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002507 case HCI_OP_EXIT_PERIODIC_INQ:
2508 hci_cc_exit_periodic_inq(hdev, skb);
2509 break;
2510
2511 case HCI_OP_REMOTE_NAME_REQ_CANCEL:
2512 hci_cc_remote_name_req_cancel(hdev, skb);
2513 break;
2514
2515 case HCI_OP_ROLE_DISCOVERY:
2516 hci_cc_role_discovery(hdev, skb);
2517 break;
2518
Marcel Holtmanne4e8e372008-07-14 20:13:47 +02002519 case HCI_OP_READ_LINK_POLICY:
2520 hci_cc_read_link_policy(hdev, skb);
2521 break;
2522
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002523 case HCI_OP_WRITE_LINK_POLICY:
2524 hci_cc_write_link_policy(hdev, skb);
2525 break;
2526
Marcel Holtmanne4e8e372008-07-14 20:13:47 +02002527 case HCI_OP_READ_DEF_LINK_POLICY:
2528 hci_cc_read_def_link_policy(hdev, skb);
2529 break;
2530
2531 case HCI_OP_WRITE_DEF_LINK_POLICY:
2532 hci_cc_write_def_link_policy(hdev, skb);
2533 break;
2534
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002535 case HCI_OP_RESET:
2536 hci_cc_reset(hdev, skb);
2537 break;
2538
2539 case HCI_OP_WRITE_LOCAL_NAME:
2540 hci_cc_write_local_name(hdev, skb);
2541 break;
2542
2543 case HCI_OP_READ_LOCAL_NAME:
2544 hci_cc_read_local_name(hdev, skb);
2545 break;
2546
2547 case HCI_OP_WRITE_AUTH_ENABLE:
2548 hci_cc_write_auth_enable(hdev, skb);
2549 break;
2550
2551 case HCI_OP_WRITE_ENCRYPT_MODE:
2552 hci_cc_write_encrypt_mode(hdev, skb);
2553 break;
2554
2555 case HCI_OP_WRITE_SCAN_ENABLE:
2556 hci_cc_write_scan_enable(hdev, skb);
2557 break;
2558
2559 case HCI_OP_READ_CLASS_OF_DEV:
2560 hci_cc_read_class_of_dev(hdev, skb);
2561 break;
2562
2563 case HCI_OP_WRITE_CLASS_OF_DEV:
2564 hci_cc_write_class_of_dev(hdev, skb);
2565 break;
2566
2567 case HCI_OP_READ_VOICE_SETTING:
2568 hci_cc_read_voice_setting(hdev, skb);
2569 break;
2570
2571 case HCI_OP_WRITE_VOICE_SETTING:
2572 hci_cc_write_voice_setting(hdev, skb);
2573 break;
2574
2575 case HCI_OP_HOST_BUFFER_SIZE:
2576 hci_cc_host_buffer_size(hdev, skb);
2577 break;
2578
Marcel Holtmann333140b2008-07-14 20:13:48 +02002579 case HCI_OP_WRITE_SSP_MODE:
2580 hci_cc_write_ssp_mode(hdev, skb);
2581 break;
2582
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002583 case HCI_OP_READ_LOCAL_VERSION:
2584 hci_cc_read_local_version(hdev, skb);
2585 break;
2586
2587 case HCI_OP_READ_LOCAL_COMMANDS:
2588 hci_cc_read_local_commands(hdev, skb);
2589 break;
2590
2591 case HCI_OP_READ_LOCAL_FEATURES:
2592 hci_cc_read_local_features(hdev, skb);
2593 break;
2594
Andre Guedes971e3a42011-06-30 19:20:52 -03002595 case HCI_OP_READ_LOCAL_EXT_FEATURES:
2596 hci_cc_read_local_ext_features(hdev, skb);
2597 break;
2598
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002599 case HCI_OP_READ_BUFFER_SIZE:
2600 hci_cc_read_buffer_size(hdev, skb);
2601 break;
2602
2603 case HCI_OP_READ_BD_ADDR:
2604 hci_cc_read_bd_addr(hdev, skb);
2605 break;
2606
Andrei Emeltchenko350ee4c2011-12-07 15:56:51 +02002607 case HCI_OP_READ_DATA_BLOCK_SIZE:
2608 hci_cc_read_data_block_size(hdev, skb);
2609 break;
2610
Johan Hedberg23bb5762010-12-21 23:01:27 +02002611 case HCI_OP_WRITE_CA_TIMEOUT:
2612 hci_cc_write_ca_timeout(hdev, skb);
2613 break;
2614
Andrei Emeltchenko1e89cff2011-11-24 14:52:02 +02002615 case HCI_OP_READ_FLOW_CONTROL_MODE:
2616 hci_cc_read_flow_control_mode(hdev, skb);
2617 break;
2618
Andrei Emeltchenko928abaa2011-10-12 10:53:57 +03002619 case HCI_OP_READ_LOCAL_AMP_INFO:
2620 hci_cc_read_local_amp_info(hdev, skb);
2621 break;
2622
Andrei Emeltchenko903e4542012-09-27 17:26:09 +03002623 case HCI_OP_READ_LOCAL_AMP_ASSOC:
2624 hci_cc_read_local_amp_assoc(hdev, skb);
2625 break;
2626
Johan Hedbergb0916ea2011-01-10 13:44:55 +02002627 case HCI_OP_DELETE_STORED_LINK_KEY:
2628 hci_cc_delete_stored_link_key(hdev, skb);
2629 break;
2630
Johan Hedbergd5859e22011-01-25 01:19:58 +02002631 case HCI_OP_SET_EVENT_MASK:
2632 hci_cc_set_event_mask(hdev, skb);
2633 break;
2634
2635 case HCI_OP_WRITE_INQUIRY_MODE:
2636 hci_cc_write_inquiry_mode(hdev, skb);
2637 break;
2638
2639 case HCI_OP_READ_INQ_RSP_TX_POWER:
2640 hci_cc_read_inq_rsp_tx_power(hdev, skb);
2641 break;
2642
2643 case HCI_OP_SET_EVENT_FLT:
2644 hci_cc_set_event_flt(hdev, skb);
2645 break;
2646
Johan Hedberg980e1a52011-01-22 06:10:07 +02002647 case HCI_OP_PIN_CODE_REPLY:
2648 hci_cc_pin_code_reply(hdev, skb);
2649 break;
2650
2651 case HCI_OP_PIN_CODE_NEG_REPLY:
2652 hci_cc_pin_code_neg_reply(hdev, skb);
2653 break;
2654
Szymon Jancc35938b2011-03-22 13:12:21 +01002655 case HCI_OP_READ_LOCAL_OOB_DATA:
2656 hci_cc_read_local_oob_data_reply(hdev, skb);
2657 break;
2658
Ville Tervo6ed58ec2011-02-10 22:38:48 -03002659 case HCI_OP_LE_READ_BUFFER_SIZE:
2660 hci_cc_le_read_buffer_size(hdev, skb);
2661 break;
2662
Johan Hedberg60e77322013-01-22 14:01:59 +02002663 case HCI_OP_LE_READ_LOCAL_FEATURES:
2664 hci_cc_le_read_local_features(hdev, skb);
2665 break;
2666
Johan Hedberg8fa19092012-10-19 20:57:49 +03002667 case HCI_OP_LE_READ_ADV_TX_POWER:
2668 hci_cc_le_read_adv_tx_power(hdev, skb);
2669 break;
2670
Johan Hedberge36b04c2012-10-19 20:57:47 +03002671 case HCI_OP_LE_SET_EVENT_MASK:
2672 hci_cc_le_set_event_mask(hdev, skb);
2673 break;
2674
Johan Hedberga5c29682011-02-19 12:05:57 -03002675 case HCI_OP_USER_CONFIRM_REPLY:
2676 hci_cc_user_confirm_reply(hdev, skb);
2677 break;
2678
2679 case HCI_OP_USER_CONFIRM_NEG_REPLY:
2680 hci_cc_user_confirm_neg_reply(hdev, skb);
2681 break;
2682
Brian Gix1143d452011-11-23 08:28:34 -08002683 case HCI_OP_USER_PASSKEY_REPLY:
2684 hci_cc_user_passkey_reply(hdev, skb);
2685 break;
2686
2687 case HCI_OP_USER_PASSKEY_NEG_REPLY:
2688 hci_cc_user_passkey_neg_reply(hdev, skb);
Szymon Janc16cde992012-04-13 12:32:42 +02002689 break;
Andre Guedes07f7fa52011-12-02 21:13:31 +09002690
2691 case HCI_OP_LE_SET_SCAN_PARAM:
2692 hci_cc_le_set_scan_param(hdev, skb);
Brian Gix1143d452011-11-23 08:28:34 -08002693 break;
2694
Johan Hedbergc1d5dc42012-11-08 01:23:01 +01002695 case HCI_OP_LE_SET_ADV_ENABLE:
2696 hci_cc_le_set_adv_enable(hdev, skb);
2697 break;
2698
Andre Guedeseb9d91f2011-05-26 16:23:52 -03002699 case HCI_OP_LE_SET_SCAN_ENABLE:
2700 hci_cc_le_set_scan_enable(hdev, skb);
2701 break;
2702
Johan Hedbergcf1d0812013-01-22 14:02:00 +02002703 case HCI_OP_LE_READ_WHITE_LIST_SIZE:
2704 hci_cc_le_read_white_list_size(hdev, skb);
2705 break;
2706
Vinicius Costa Gomesa7a595f2011-06-09 18:50:47 -03002707 case HCI_OP_LE_LTK_REPLY:
2708 hci_cc_le_ltk_reply(hdev, skb);
2709 break;
2710
2711 case HCI_OP_LE_LTK_NEG_REPLY:
2712 hci_cc_le_ltk_neg_reply(hdev, skb);
2713 break;
2714
Andre Guedesf9b49302011-06-30 19:20:53 -03002715 case HCI_OP_WRITE_LE_HOST_SUPPORTED:
2716 hci_cc_write_le_host_supported(hdev, skb);
2717 break;
2718
Andrei Emeltchenko93c284e2012-09-27 17:26:20 +03002719 case HCI_OP_WRITE_REMOTE_AMP_ASSOC:
2720 hci_cc_write_remote_amp_assoc(hdev, skb);
2721 break;
2722
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002723 default:
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +03002724 BT_DBG("%s opcode 0x%4.4x", hdev->name, opcode);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002725 break;
2726 }
2727
Ville Tervo6bd32322011-02-16 16:32:41 +02002728 if (ev->opcode != HCI_OP_NOP)
2729 del_timer(&hdev->cmd_timer);
2730
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002731 if (ev->ncmd) {
2732 atomic_set(&hdev->cmd_cnt, 1);
2733 if (!skb_queue_empty(&hdev->cmd_q))
Gustavo F. Padovanc347b762011-12-14 23:53:47 -02002734 queue_work(hdev->workqueue, &hdev->cmd_work);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002735 }
2736}
2737
Gustavo Padovan6039aa72012-05-23 04:04:18 -03002738static void hci_cmd_status_evt(struct hci_dev *hdev, struct sk_buff *skb)
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002739{
2740 struct hci_ev_cmd_status *ev = (void *) skb->data;
2741 __u16 opcode;
2742
2743 skb_pull(skb, sizeof(*ev));
2744
2745 opcode = __le16_to_cpu(ev->opcode);
2746
2747 switch (opcode) {
2748 case HCI_OP_INQUIRY:
2749 hci_cs_inquiry(hdev, ev->status);
2750 break;
2751
2752 case HCI_OP_CREATE_CONN:
2753 hci_cs_create_conn(hdev, ev->status);
2754 break;
2755
2756 case HCI_OP_ADD_SCO:
2757 hci_cs_add_sco(hdev, ev->status);
2758 break;
2759
Marcel Holtmannf8558552008-07-14 20:13:49 +02002760 case HCI_OP_AUTH_REQUESTED:
2761 hci_cs_auth_requested(hdev, ev->status);
2762 break;
2763
2764 case HCI_OP_SET_CONN_ENCRYPT:
2765 hci_cs_set_conn_encrypt(hdev, ev->status);
2766 break;
2767
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002768 case HCI_OP_REMOTE_NAME_REQ:
2769 hci_cs_remote_name_req(hdev, ev->status);
2770 break;
2771
Marcel Holtmann769be972008-07-14 20:13:49 +02002772 case HCI_OP_READ_REMOTE_FEATURES:
2773 hci_cs_read_remote_features(hdev, ev->status);
2774 break;
2775
2776 case HCI_OP_READ_REMOTE_EXT_FEATURES:
2777 hci_cs_read_remote_ext_features(hdev, ev->status);
2778 break;
2779
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002780 case HCI_OP_SETUP_SYNC_CONN:
2781 hci_cs_setup_sync_conn(hdev, ev->status);
2782 break;
2783
2784 case HCI_OP_SNIFF_MODE:
2785 hci_cs_sniff_mode(hdev, ev->status);
2786 break;
2787
2788 case HCI_OP_EXIT_SNIFF_MODE:
2789 hci_cs_exit_sniff_mode(hdev, ev->status);
2790 break;
2791
Johan Hedberg8962ee72011-01-20 12:40:27 +02002792 case HCI_OP_DISCONNECT:
Johan Hedberg88c3df12012-02-09 14:27:38 +02002793 hci_cs_disconnect(hdev, ev->status);
Johan Hedberg8962ee72011-01-20 12:40:27 +02002794 break;
2795
Ville Tervofcd89c02011-02-10 22:38:47 -03002796 case HCI_OP_LE_CREATE_CONN:
2797 hci_cs_le_create_conn(hdev, ev->status);
2798 break;
2799
Vinicius Costa Gomesa7a595f2011-06-09 18:50:47 -03002800 case HCI_OP_LE_START_ENC:
2801 hci_cs_le_start_enc(hdev, ev->status);
2802 break;
2803
Andrei Emeltchenkoa02226d2012-09-27 17:26:19 +03002804 case HCI_OP_CREATE_PHY_LINK:
2805 hci_cs_create_phylink(hdev, ev->status);
2806 break;
2807
Andrei Emeltchenko0b26ab92012-09-27 17:26:24 +03002808 case HCI_OP_ACCEPT_PHY_LINK:
2809 hci_cs_accept_phylink(hdev, ev->status);
2810 break;
2811
Andrei Emeltchenko5ce66b52012-10-31 15:46:30 +02002812 case HCI_OP_CREATE_LOGICAL_LINK:
2813 hci_cs_create_logical_link(hdev, ev->status);
2814 break;
2815
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002816 default:
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +03002817 BT_DBG("%s opcode 0x%4.4x", hdev->name, opcode);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002818 break;
2819 }
2820
Ville Tervo6bd32322011-02-16 16:32:41 +02002821 if (ev->opcode != HCI_OP_NOP)
2822 del_timer(&hdev->cmd_timer);
2823
Gustavo F. Padovan10572132011-03-16 15:36:29 -03002824 if (ev->ncmd && !test_bit(HCI_RESET, &hdev->flags)) {
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002825 atomic_set(&hdev->cmd_cnt, 1);
2826 if (!skb_queue_empty(&hdev->cmd_q))
Gustavo F. Padovanc347b762011-12-14 23:53:47 -02002827 queue_work(hdev->workqueue, &hdev->cmd_work);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002828 }
2829}
2830
Gustavo Padovan6039aa72012-05-23 04:04:18 -03002831static void hci_role_change_evt(struct hci_dev *hdev, struct sk_buff *skb)
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002832{
2833 struct hci_ev_role_change *ev = (void *) skb->data;
2834 struct hci_conn *conn;
2835
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +03002836 BT_DBG("%s status 0x%2.2x", hdev->name, ev->status);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002837
2838 hci_dev_lock(hdev);
2839
2840 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
2841 if (conn) {
2842 if (!ev->status) {
2843 if (ev->role)
2844 conn->link_mode &= ~HCI_LM_MASTER;
2845 else
2846 conn->link_mode |= HCI_LM_MASTER;
2847 }
2848
Johan Hedberg51a8efd2012-01-16 06:10:31 +02002849 clear_bit(HCI_CONN_RSWITCH_PEND, &conn->flags);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002850
2851 hci_role_switch_cfm(conn, ev->status, ev->role);
2852 }
2853
2854 hci_dev_unlock(hdev);
2855}
2856
Gustavo Padovan6039aa72012-05-23 04:04:18 -03002857static void hci_num_comp_pkts_evt(struct hci_dev *hdev, struct sk_buff *skb)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002858{
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002859 struct hci_ev_num_comp_pkts *ev = (void *) skb->data;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002860 int i;
2861
Andrei Emeltchenko32ac5b92011-12-19 16:31:29 +02002862 if (hdev->flow_ctl_mode != HCI_FLOW_CTL_MODE_PACKET_BASED) {
2863 BT_ERR("Wrong event for mode %d", hdev->flow_ctl_mode);
2864 return;
2865 }
2866
Andrei Emeltchenkoc5993de2011-12-30 12:07:47 +02002867 if (skb->len < sizeof(*ev) || skb->len < sizeof(*ev) +
Gustavo Padovan807deac2012-05-17 00:36:24 -03002868 ev->num_hndl * sizeof(struct hci_comp_pkts_info)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002869 BT_DBG("%s bad parameters", hdev->name);
2870 return;
2871 }
2872
Andrei Emeltchenkoc5993de2011-12-30 12:07:47 +02002873 BT_DBG("%s num_hndl %d", hdev->name, ev->num_hndl);
2874
Andrei Emeltchenko613a1c02011-12-19 16:31:30 +02002875 for (i = 0; i < ev->num_hndl; i++) {
2876 struct hci_comp_pkts_info *info = &ev->handles[i];
Linus Torvalds1da177e2005-04-16 15:20:36 -07002877 struct hci_conn *conn;
2878 __u16 handle, count;
2879
Andrei Emeltchenko613a1c02011-12-19 16:31:30 +02002880 handle = __le16_to_cpu(info->handle);
2881 count = __le16_to_cpu(info->count);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002882
2883 conn = hci_conn_hash_lookup_handle(hdev, handle);
Andrei Emeltchenkof4280912011-12-07 15:56:52 +02002884 if (!conn)
2885 continue;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002886
Andrei Emeltchenkof4280912011-12-07 15:56:52 +02002887 conn->sent -= count;
2888
2889 switch (conn->type) {
2890 case ACL_LINK:
2891 hdev->acl_cnt += count;
2892 if (hdev->acl_cnt > hdev->acl_pkts)
2893 hdev->acl_cnt = hdev->acl_pkts;
2894 break;
2895
2896 case LE_LINK:
2897 if (hdev->le_pkts) {
2898 hdev->le_cnt += count;
2899 if (hdev->le_cnt > hdev->le_pkts)
2900 hdev->le_cnt = hdev->le_pkts;
2901 } else {
Andrei Emeltchenko70f230202010-12-01 16:58:25 +02002902 hdev->acl_cnt += count;
2903 if (hdev->acl_cnt > hdev->acl_pkts)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002904 hdev->acl_cnt = hdev->acl_pkts;
2905 }
Andrei Emeltchenkof4280912011-12-07 15:56:52 +02002906 break;
2907
2908 case SCO_LINK:
2909 hdev->sco_cnt += count;
2910 if (hdev->sco_cnt > hdev->sco_pkts)
2911 hdev->sco_cnt = hdev->sco_pkts;
2912 break;
2913
2914 default:
2915 BT_ERR("Unknown type %d conn %p", conn->type, conn);
2916 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002917 }
2918 }
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002919
Gustavo F. Padovan3eff45e2011-12-15 00:50:02 -02002920 queue_work(hdev->workqueue, &hdev->tx_work);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002921}
2922
Andrei Emeltchenko76ef7cf2012-10-10 17:38:29 +03002923static struct hci_conn *__hci_conn_lookup_handle(struct hci_dev *hdev,
2924 __u16 handle)
2925{
2926 struct hci_chan *chan;
2927
2928 switch (hdev->dev_type) {
2929 case HCI_BREDR:
2930 return hci_conn_hash_lookup_handle(hdev, handle);
2931 case HCI_AMP:
2932 chan = hci_chan_lookup_handle(hdev, handle);
2933 if (chan)
2934 return chan->conn;
2935 break;
2936 default:
2937 BT_ERR("%s unknown dev_type %d", hdev->name, hdev->dev_type);
2938 break;
2939 }
2940
2941 return NULL;
2942}
2943
Gustavo Padovan6039aa72012-05-23 04:04:18 -03002944static void hci_num_comp_blocks_evt(struct hci_dev *hdev, struct sk_buff *skb)
Andrei Emeltchenko25e89e92012-01-04 12:41:58 +02002945{
2946 struct hci_ev_num_comp_blocks *ev = (void *) skb->data;
2947 int i;
2948
2949 if (hdev->flow_ctl_mode != HCI_FLOW_CTL_MODE_BLOCK_BASED) {
2950 BT_ERR("Wrong event for mode %d", hdev->flow_ctl_mode);
2951 return;
2952 }
2953
2954 if (skb->len < sizeof(*ev) || skb->len < sizeof(*ev) +
Gustavo Padovan807deac2012-05-17 00:36:24 -03002955 ev->num_hndl * sizeof(struct hci_comp_blocks_info)) {
Andrei Emeltchenko25e89e92012-01-04 12:41:58 +02002956 BT_DBG("%s bad parameters", hdev->name);
2957 return;
2958 }
2959
2960 BT_DBG("%s num_blocks %d num_hndl %d", hdev->name, ev->num_blocks,
Gustavo Padovan807deac2012-05-17 00:36:24 -03002961 ev->num_hndl);
Andrei Emeltchenko25e89e92012-01-04 12:41:58 +02002962
2963 for (i = 0; i < ev->num_hndl; i++) {
2964 struct hci_comp_blocks_info *info = &ev->handles[i];
Andrei Emeltchenko76ef7cf2012-10-10 17:38:29 +03002965 struct hci_conn *conn = NULL;
Andrei Emeltchenko25e89e92012-01-04 12:41:58 +02002966 __u16 handle, block_count;
2967
2968 handle = __le16_to_cpu(info->handle);
2969 block_count = __le16_to_cpu(info->blocks);
2970
Andrei Emeltchenko76ef7cf2012-10-10 17:38:29 +03002971 conn = __hci_conn_lookup_handle(hdev, handle);
Andrei Emeltchenko25e89e92012-01-04 12:41:58 +02002972 if (!conn)
2973 continue;
2974
2975 conn->sent -= block_count;
2976
2977 switch (conn->type) {
2978 case ACL_LINK:
Andrei Emeltchenkobd1eb662012-10-10 17:38:30 +03002979 case AMP_LINK:
Andrei Emeltchenko25e89e92012-01-04 12:41:58 +02002980 hdev->block_cnt += block_count;
2981 if (hdev->block_cnt > hdev->num_blocks)
2982 hdev->block_cnt = hdev->num_blocks;
2983 break;
2984
2985 default:
2986 BT_ERR("Unknown type %d conn %p", conn->type, conn);
2987 break;
2988 }
2989 }
2990
2991 queue_work(hdev->workqueue, &hdev->tx_work);
2992}
2993
Gustavo Padovan6039aa72012-05-23 04:04:18 -03002994static void hci_mode_change_evt(struct hci_dev *hdev, struct sk_buff *skb)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002995{
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002996 struct hci_ev_mode_change *ev = (void *) skb->data;
Marcel Holtmann04837f62006-07-03 10:02:33 +02002997 struct hci_conn *conn;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002998
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +03002999 BT_DBG("%s status 0x%2.2x", hdev->name, ev->status);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003000
3001 hci_dev_lock(hdev);
3002
Marcel Holtmann04837f62006-07-03 10:02:33 +02003003 conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
3004 if (conn) {
3005 conn->mode = ev->mode;
3006 conn->interval = __le16_to_cpu(ev->interval);
3007
Gustavo Padovan8fc9ced2012-05-23 04:04:21 -03003008 if (!test_and_clear_bit(HCI_CONN_MODE_CHANGE_PEND,
3009 &conn->flags)) {
Marcel Holtmann04837f62006-07-03 10:02:33 +02003010 if (conn->mode == HCI_CM_ACTIVE)
Johan Hedberg58a681e2012-01-16 06:47:28 +02003011 set_bit(HCI_CONN_POWER_SAVE, &conn->flags);
Marcel Holtmann04837f62006-07-03 10:02:33 +02003012 else
Johan Hedberg58a681e2012-01-16 06:47:28 +02003013 clear_bit(HCI_CONN_POWER_SAVE, &conn->flags);
Marcel Holtmann04837f62006-07-03 10:02:33 +02003014 }
Marcel Holtmanne73439d2010-07-26 10:06:00 -04003015
Johan Hedberg51a8efd2012-01-16 06:10:31 +02003016 if (test_and_clear_bit(HCI_CONN_SCO_SETUP_PEND, &conn->flags))
Marcel Holtmanne73439d2010-07-26 10:06:00 -04003017 hci_sco_setup(conn, ev->status);
Marcel Holtmann04837f62006-07-03 10:02:33 +02003018 }
3019
3020 hci_dev_unlock(hdev);
3021}
3022
Gustavo Padovan6039aa72012-05-23 04:04:18 -03003023static void hci_pin_code_request_evt(struct hci_dev *hdev, struct sk_buff *skb)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003024{
Marcel Holtmann052b30b2009-04-26 20:01:22 +02003025 struct hci_ev_pin_code_req *ev = (void *) skb->data;
3026 struct hci_conn *conn;
3027
Marcel Holtmanna9de9242007-10-20 13:33:56 +02003028 BT_DBG("%s", hdev->name);
Marcel Holtmann052b30b2009-04-26 20:01:22 +02003029
3030 hci_dev_lock(hdev);
3031
3032 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
Waldemar Rymarkiewiczb6f98042011-09-23 10:01:30 +02003033 if (!conn)
3034 goto unlock;
3035
3036 if (conn->state == BT_CONNECTED) {
Marcel Holtmann052b30b2009-04-26 20:01:22 +02003037 hci_conn_hold(conn);
3038 conn->disc_timeout = HCI_PAIRING_TIMEOUT;
3039 hci_conn_put(conn);
3040 }
3041
Johan Hedberga8b2d5c2012-01-08 23:11:15 +02003042 if (!test_bit(HCI_PAIRABLE, &hdev->dev_flags))
Johan Hedberg03b555e2011-01-04 15:40:05 +02003043 hci_send_cmd(hdev, HCI_OP_PIN_CODE_NEG_REPLY,
Gustavo Padovan807deac2012-05-17 00:36:24 -03003044 sizeof(ev->bdaddr), &ev->bdaddr);
Johan Hedberga8b2d5c2012-01-08 23:11:15 +02003045 else if (test_bit(HCI_MGMT, &hdev->dev_flags)) {
Waldemar Rymarkiewicza770bb52011-04-28 12:07:59 +02003046 u8 secure;
3047
3048 if (conn->pending_sec_level == BT_SECURITY_HIGH)
3049 secure = 1;
3050 else
3051 secure = 0;
3052
Johan Hedberg744cf192011-11-08 20:40:14 +02003053 mgmt_pin_code_request(hdev, &ev->bdaddr, secure);
Waldemar Rymarkiewicza770bb52011-04-28 12:07:59 +02003054 }
Johan Hedberg980e1a52011-01-22 06:10:07 +02003055
Waldemar Rymarkiewiczb6f98042011-09-23 10:01:30 +02003056unlock:
Marcel Holtmann052b30b2009-04-26 20:01:22 +02003057 hci_dev_unlock(hdev);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003058}
3059
Gustavo Padovan6039aa72012-05-23 04:04:18 -03003060static void hci_link_key_request_evt(struct hci_dev *hdev, struct sk_buff *skb)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003061{
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02003062 struct hci_ev_link_key_req *ev = (void *) skb->data;
3063 struct hci_cp_link_key_reply cp;
3064 struct hci_conn *conn;
3065 struct link_key *key;
3066
Marcel Holtmanna9de9242007-10-20 13:33:56 +02003067 BT_DBG("%s", hdev->name);
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02003068
Johan Hedberga8b2d5c2012-01-08 23:11:15 +02003069 if (!test_bit(HCI_LINK_KEYS, &hdev->dev_flags))
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02003070 return;
3071
3072 hci_dev_lock(hdev);
3073
3074 key = hci_find_link_key(hdev, &ev->bdaddr);
3075 if (!key) {
Andrei Emeltchenko6ed93dc2012-09-25 12:49:43 +03003076 BT_DBG("%s link key not found for %pMR", hdev->name,
3077 &ev->bdaddr);
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02003078 goto not_found;
3079 }
3080
Andrei Emeltchenko6ed93dc2012-09-25 12:49:43 +03003081 BT_DBG("%s found key type %u for %pMR", hdev->name, key->type,
3082 &ev->bdaddr);
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02003083
Johan Hedberga8b2d5c2012-01-08 23:11:15 +02003084 if (!test_bit(HCI_DEBUG_KEYS, &hdev->dev_flags) &&
Gustavo Padovan807deac2012-05-17 00:36:24 -03003085 key->type == HCI_LK_DEBUG_COMBINATION) {
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02003086 BT_DBG("%s ignoring debug key", hdev->name);
3087 goto not_found;
3088 }
3089
3090 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
Waldemar Rymarkiewicz60b83f52011-04-28 12:07:56 +02003091 if (conn) {
3092 if (key->type == HCI_LK_UNAUTH_COMBINATION &&
Gustavo Padovan807deac2012-05-17 00:36:24 -03003093 conn->auth_type != 0xff && (conn->auth_type & 0x01)) {
Waldemar Rymarkiewicz60b83f52011-04-28 12:07:56 +02003094 BT_DBG("%s ignoring unauthenticated key", hdev->name);
3095 goto not_found;
3096 }
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02003097
Waldemar Rymarkiewicz60b83f52011-04-28 12:07:56 +02003098 if (key->type == HCI_LK_COMBINATION && key->pin_len < 16 &&
Gustavo Padovan807deac2012-05-17 00:36:24 -03003099 conn->pending_sec_level == BT_SECURITY_HIGH) {
Gustavo Padovan8fc9ced2012-05-23 04:04:21 -03003100 BT_DBG("%s ignoring key unauthenticated for high security",
3101 hdev->name);
Waldemar Rymarkiewicz60b83f52011-04-28 12:07:56 +02003102 goto not_found;
3103 }
3104
3105 conn->key_type = key->type;
3106 conn->pin_length = key->pin_len;
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02003107 }
3108
3109 bacpy(&cp.bdaddr, &ev->bdaddr);
Andrei Emeltchenko9b3b4462012-05-23 11:31:20 +03003110 memcpy(cp.link_key, key->val, HCI_LINK_KEY_SIZE);
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02003111
3112 hci_send_cmd(hdev, HCI_OP_LINK_KEY_REPLY, sizeof(cp), &cp);
3113
3114 hci_dev_unlock(hdev);
3115
3116 return;
3117
3118not_found:
3119 hci_send_cmd(hdev, HCI_OP_LINK_KEY_NEG_REPLY, 6, &ev->bdaddr);
3120 hci_dev_unlock(hdev);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003121}
3122
Gustavo Padovan6039aa72012-05-23 04:04:18 -03003123static void hci_link_key_notify_evt(struct hci_dev *hdev, struct sk_buff *skb)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003124{
Marcel Holtmann052b30b2009-04-26 20:01:22 +02003125 struct hci_ev_link_key_notify *ev = (void *) skb->data;
3126 struct hci_conn *conn;
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02003127 u8 pin_len = 0;
Marcel Holtmann052b30b2009-04-26 20:01:22 +02003128
Marcel Holtmanna9de9242007-10-20 13:33:56 +02003129 BT_DBG("%s", hdev->name);
Marcel Holtmann052b30b2009-04-26 20:01:22 +02003130
3131 hci_dev_lock(hdev);
3132
3133 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
3134 if (conn) {
3135 hci_conn_hold(conn);
3136 conn->disc_timeout = HCI_DISCONN_TIMEOUT;
Johan Hedberg980e1a52011-01-22 06:10:07 +02003137 pin_len = conn->pin_length;
Waldemar Rymarkiewicz13d39312011-04-28 12:07:55 +02003138
3139 if (ev->key_type != HCI_LK_CHANGED_COMBINATION)
3140 conn->key_type = ev->key_type;
3141
Marcel Holtmann052b30b2009-04-26 20:01:22 +02003142 hci_conn_put(conn);
3143 }
3144
Johan Hedberga8b2d5c2012-01-08 23:11:15 +02003145 if (test_bit(HCI_LINK_KEYS, &hdev->dev_flags))
Johan Hedbergd25e28a2011-04-28 11:28:59 -07003146 hci_add_link_key(hdev, conn, 1, &ev->bdaddr, ev->link_key,
Gustavo Padovan807deac2012-05-17 00:36:24 -03003147 ev->key_type, pin_len);
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02003148
Marcel Holtmann052b30b2009-04-26 20:01:22 +02003149 hci_dev_unlock(hdev);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003150}
3151
Gustavo Padovan6039aa72012-05-23 04:04:18 -03003152static void hci_clock_offset_evt(struct hci_dev *hdev, struct sk_buff *skb)
Marcel Holtmann04837f62006-07-03 10:02:33 +02003153{
Marcel Holtmanna9de9242007-10-20 13:33:56 +02003154 struct hci_ev_clock_offset *ev = (void *) skb->data;
Marcel Holtmann04837f62006-07-03 10:02:33 +02003155 struct hci_conn *conn;
3156
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +03003157 BT_DBG("%s status 0x%2.2x", hdev->name, ev->status);
Marcel Holtmann04837f62006-07-03 10:02:33 +02003158
3159 hci_dev_lock(hdev);
3160
3161 conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
Linus Torvalds1da177e2005-04-16 15:20:36 -07003162 if (conn && !ev->status) {
3163 struct inquiry_entry *ie;
3164
Andrei Emeltchenkocc11b9c2010-11-22 13:21:37 +02003165 ie = hci_inquiry_cache_lookup(hdev, &conn->dst);
3166 if (ie) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003167 ie->data.clock_offset = ev->clock_offset;
3168 ie->timestamp = jiffies;
3169 }
3170 }
3171
3172 hci_dev_unlock(hdev);
3173}
3174
Gustavo Padovan6039aa72012-05-23 04:04:18 -03003175static void hci_pkt_type_change_evt(struct hci_dev *hdev, struct sk_buff *skb)
Marcel Holtmanna8746412008-07-14 20:13:46 +02003176{
3177 struct hci_ev_pkt_type_change *ev = (void *) skb->data;
3178 struct hci_conn *conn;
3179
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +03003180 BT_DBG("%s status 0x%2.2x", hdev->name, ev->status);
Marcel Holtmanna8746412008-07-14 20:13:46 +02003181
3182 hci_dev_lock(hdev);
3183
3184 conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
3185 if (conn && !ev->status)
3186 conn->pkt_type = __le16_to_cpu(ev->pkt_type);
3187
3188 hci_dev_unlock(hdev);
3189}
3190
Gustavo Padovan6039aa72012-05-23 04:04:18 -03003191static void hci_pscan_rep_mode_evt(struct hci_dev *hdev, struct sk_buff *skb)
Marcel Holtmann85a1e932005-08-09 20:28:02 -07003192{
Marcel Holtmanna9de9242007-10-20 13:33:56 +02003193 struct hci_ev_pscan_rep_mode *ev = (void *) skb->data;
Marcel Holtmann85a1e932005-08-09 20:28:02 -07003194 struct inquiry_entry *ie;
3195
3196 BT_DBG("%s", hdev->name);
3197
3198 hci_dev_lock(hdev);
3199
Andrei Emeltchenkocc11b9c2010-11-22 13:21:37 +02003200 ie = hci_inquiry_cache_lookup(hdev, &ev->bdaddr);
3201 if (ie) {
Marcel Holtmann85a1e932005-08-09 20:28:02 -07003202 ie->data.pscan_rep_mode = ev->pscan_rep_mode;
3203 ie->timestamp = jiffies;
3204 }
3205
3206 hci_dev_unlock(hdev);
3207}
3208
Gustavo Padovan6039aa72012-05-23 04:04:18 -03003209static void hci_inquiry_result_with_rssi_evt(struct hci_dev *hdev,
3210 struct sk_buff *skb)
Marcel Holtmanna9de9242007-10-20 13:33:56 +02003211{
3212 struct inquiry_data data;
3213 int num_rsp = *((__u8 *) skb->data);
Johan Hedberg388fc8f2012-02-23 00:38:59 +02003214 bool name_known, ssp;
Marcel Holtmanna9de9242007-10-20 13:33:56 +02003215
3216 BT_DBG("%s num_rsp %d", hdev->name, num_rsp);
3217
3218 if (!num_rsp)
3219 return;
3220
Andre Guedes1519cc12012-03-21 00:03:38 -03003221 if (test_bit(HCI_PERIODIC_INQ, &hdev->dev_flags))
3222 return;
3223
Marcel Holtmanna9de9242007-10-20 13:33:56 +02003224 hci_dev_lock(hdev);
3225
3226 if ((skb->len - 1) / num_rsp != sizeof(struct inquiry_info_with_rssi)) {
Szymon Janc138d22e2011-02-17 16:44:23 +01003227 struct inquiry_info_with_rssi_and_pscan_mode *info;
3228 info = (void *) (skb->data + 1);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02003229
Johan Hedberge17acd42011-03-30 23:57:16 +03003230 for (; num_rsp; num_rsp--, info++) {
Marcel Holtmanna9de9242007-10-20 13:33:56 +02003231 bacpy(&data.bdaddr, &info->bdaddr);
3232 data.pscan_rep_mode = info->pscan_rep_mode;
3233 data.pscan_period_mode = info->pscan_period_mode;
3234 data.pscan_mode = info->pscan_mode;
3235 memcpy(data.dev_class, info->dev_class, 3);
3236 data.clock_offset = info->clock_offset;
3237 data.rssi = info->rssi;
Marcel Holtmann41a96212008-07-14 20:13:48 +02003238 data.ssp_mode = 0x00;
Johan Hedberg31754052012-01-04 13:39:52 +02003239
3240 name_known = hci_inquiry_cache_update(hdev, &data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003241 false, &ssp);
Johan Hedberg48264f02011-11-09 13:58:58 +02003242 mgmt_device_found(hdev, &info->bdaddr, ACL_LINK, 0x00,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003243 info->dev_class, info->rssi,
3244 !name_known, ssp, NULL, 0);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02003245 }
3246 } else {
3247 struct inquiry_info_with_rssi *info = (void *) (skb->data + 1);
3248
Johan Hedberge17acd42011-03-30 23:57:16 +03003249 for (; num_rsp; num_rsp--, info++) {
Marcel Holtmanna9de9242007-10-20 13:33:56 +02003250 bacpy(&data.bdaddr, &info->bdaddr);
3251 data.pscan_rep_mode = info->pscan_rep_mode;
3252 data.pscan_period_mode = info->pscan_period_mode;
3253 data.pscan_mode = 0x00;
3254 memcpy(data.dev_class, info->dev_class, 3);
3255 data.clock_offset = info->clock_offset;
3256 data.rssi = info->rssi;
Marcel Holtmann41a96212008-07-14 20:13:48 +02003257 data.ssp_mode = 0x00;
Johan Hedberg31754052012-01-04 13:39:52 +02003258 name_known = hci_inquiry_cache_update(hdev, &data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003259 false, &ssp);
Johan Hedberg48264f02011-11-09 13:58:58 +02003260 mgmt_device_found(hdev, &info->bdaddr, ACL_LINK, 0x00,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003261 info->dev_class, info->rssi,
3262 !name_known, ssp, NULL, 0);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02003263 }
3264 }
3265
3266 hci_dev_unlock(hdev);
3267}
3268
Gustavo Padovan6039aa72012-05-23 04:04:18 -03003269static void hci_remote_ext_features_evt(struct hci_dev *hdev,
3270 struct sk_buff *skb)
Marcel Holtmanna9de9242007-10-20 13:33:56 +02003271{
Marcel Holtmann41a96212008-07-14 20:13:48 +02003272 struct hci_ev_remote_ext_features *ev = (void *) skb->data;
3273 struct hci_conn *conn;
3274
Marcel Holtmanna9de9242007-10-20 13:33:56 +02003275 BT_DBG("%s", hdev->name);
Marcel Holtmann41a96212008-07-14 20:13:48 +02003276
Marcel Holtmann41a96212008-07-14 20:13:48 +02003277 hci_dev_lock(hdev);
3278
3279 conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
Johan Hedbergccd556f2010-11-10 17:11:51 +02003280 if (!conn)
3281 goto unlock;
Marcel Holtmann41a96212008-07-14 20:13:48 +02003282
Johan Hedbergccd556f2010-11-10 17:11:51 +02003283 if (!ev->status && ev->page == 0x01) {
3284 struct inquiry_entry *ie;
Marcel Holtmann41a96212008-07-14 20:13:48 +02003285
Andrei Emeltchenkocc11b9c2010-11-22 13:21:37 +02003286 ie = hci_inquiry_cache_lookup(hdev, &conn->dst);
3287 if (ie)
Johan Hedberg02b7cc62012-02-28 02:28:43 +02003288 ie->data.ssp_mode = (ev->features[0] & LMP_HOST_SSP);
Marcel Holtmann769be972008-07-14 20:13:49 +02003289
Johan Hedberg02b7cc62012-02-28 02:28:43 +02003290 if (ev->features[0] & LMP_HOST_SSP)
Johan Hedberg58a681e2012-01-16 06:47:28 +02003291 set_bit(HCI_CONN_SSP_ENABLED, &conn->flags);
Marcel Holtmann41a96212008-07-14 20:13:48 +02003292 }
3293
Johan Hedbergccd556f2010-11-10 17:11:51 +02003294 if (conn->state != BT_CONFIG)
3295 goto unlock;
3296
Johan Hedberg671267b2012-05-12 16:11:50 -03003297 if (!ev->status && !test_bit(HCI_CONN_MGMT_CONNECTED, &conn->flags)) {
Johan Hedberg127178d2010-11-18 22:22:29 +02003298 struct hci_cp_remote_name_req cp;
3299 memset(&cp, 0, sizeof(cp));
3300 bacpy(&cp.bdaddr, &conn->dst);
3301 cp.pscan_rep_mode = 0x02;
3302 hci_send_cmd(hdev, HCI_OP_REMOTE_NAME_REQ, sizeof(cp), &cp);
Johan Hedbergb644ba32012-01-17 21:48:47 +02003303 } else if (!test_and_set_bit(HCI_CONN_MGMT_CONNECTED, &conn->flags))
3304 mgmt_device_connected(hdev, &conn->dst, conn->type,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003305 conn->dst_type, 0, NULL, 0,
3306 conn->dev_class);
Johan Hedberg392599b2010-11-18 22:22:28 +02003307
Johan Hedberg127178d2010-11-18 22:22:29 +02003308 if (!hci_outgoing_auth_needed(hdev, conn)) {
Johan Hedbergccd556f2010-11-10 17:11:51 +02003309 conn->state = BT_CONNECTED;
3310 hci_proto_connect_cfm(conn, ev->status);
3311 hci_conn_put(conn);
3312 }
3313
3314unlock:
Marcel Holtmann41a96212008-07-14 20:13:48 +02003315 hci_dev_unlock(hdev);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02003316}
3317
Gustavo Padovan6039aa72012-05-23 04:04:18 -03003318static void hci_sync_conn_complete_evt(struct hci_dev *hdev,
3319 struct sk_buff *skb)
Marcel Holtmanna9de9242007-10-20 13:33:56 +02003320{
Marcel Holtmannb6a0dc82007-10-20 14:55:10 +02003321 struct hci_ev_sync_conn_complete *ev = (void *) skb->data;
3322 struct hci_conn *conn;
3323
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +03003324 BT_DBG("%s status 0x%2.2x", hdev->name, ev->status);
Marcel Holtmannb6a0dc82007-10-20 14:55:10 +02003325
3326 hci_dev_lock(hdev);
3327
3328 conn = hci_conn_hash_lookup_ba(hdev, ev->link_type, &ev->bdaddr);
Marcel Holtmann9dc0a3a2008-07-14 20:13:46 +02003329 if (!conn) {
3330 if (ev->link_type == ESCO_LINK)
3331 goto unlock;
3332
3333 conn = hci_conn_hash_lookup_ba(hdev, ESCO_LINK, &ev->bdaddr);
3334 if (!conn)
3335 goto unlock;
3336
3337 conn->type = SCO_LINK;
3338 }
Marcel Holtmannb6a0dc82007-10-20 14:55:10 +02003339
Marcel Holtmann732547f2009-04-19 19:14:14 +02003340 switch (ev->status) {
3341 case 0x00:
Marcel Holtmannb6a0dc82007-10-20 14:55:10 +02003342 conn->handle = __le16_to_cpu(ev->handle);
3343 conn->state = BT_CONNECTED;
Marcel Holtmann7d0db0a2008-07-14 20:13:51 +02003344
Marcel Holtmann9eba32b2009-08-22 14:19:26 -07003345 hci_conn_hold_device(conn);
Marcel Holtmann7d0db0a2008-07-14 20:13:51 +02003346 hci_conn_add_sysfs(conn);
Marcel Holtmann732547f2009-04-19 19:14:14 +02003347 break;
3348
Stephen Coe705e5712010-02-16 11:29:44 -05003349 case 0x11: /* Unsupported Feature or Parameter Value */
Marcel Holtmann732547f2009-04-19 19:14:14 +02003350 case 0x1c: /* SCO interval rejected */
Nick Pelly1038a002010-02-03 11:42:26 -08003351 case 0x1a: /* Unsupported Remote Feature */
Marcel Holtmann732547f2009-04-19 19:14:14 +02003352 case 0x1f: /* Unspecified error */
3353 if (conn->out && conn->attempt < 2) {
3354 conn->pkt_type = (hdev->esco_type & SCO_ESCO_MASK) |
3355 (hdev->esco_type & EDR_ESCO_MASK);
3356 hci_setup_sync(conn, conn->link->handle);
3357 goto unlock;
3358 }
3359 /* fall through */
3360
3361 default:
Marcel Holtmannb6a0dc82007-10-20 14:55:10 +02003362 conn->state = BT_CLOSED;
Marcel Holtmann732547f2009-04-19 19:14:14 +02003363 break;
3364 }
Marcel Holtmannb6a0dc82007-10-20 14:55:10 +02003365
3366 hci_proto_connect_cfm(conn, ev->status);
3367 if (ev->status)
3368 hci_conn_del(conn);
3369
3370unlock:
3371 hci_dev_unlock(hdev);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02003372}
3373
Gustavo Padovan6039aa72012-05-23 04:04:18 -03003374static void hci_sync_conn_changed_evt(struct hci_dev *hdev, struct sk_buff *skb)
Marcel Holtmanna9de9242007-10-20 13:33:56 +02003375{
3376 BT_DBG("%s", hdev->name);
3377}
3378
Gustavo Padovan6039aa72012-05-23 04:04:18 -03003379static void hci_sniff_subrate_evt(struct hci_dev *hdev, struct sk_buff *skb)
Marcel Holtmann04837f62006-07-03 10:02:33 +02003380{
Marcel Holtmanna9de9242007-10-20 13:33:56 +02003381 struct hci_ev_sniff_subrate *ev = (void *) skb->data;
Marcel Holtmann04837f62006-07-03 10:02:33 +02003382
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +03003383 BT_DBG("%s status 0x%2.2x", hdev->name, ev->status);
Marcel Holtmann04837f62006-07-03 10:02:33 +02003384}
3385
Gustavo Padovan6039aa72012-05-23 04:04:18 -03003386static void hci_extended_inquiry_result_evt(struct hci_dev *hdev,
3387 struct sk_buff *skb)
Marcel Holtmanna9de9242007-10-20 13:33:56 +02003388{
3389 struct inquiry_data data;
3390 struct extended_inquiry_info *info = (void *) (skb->data + 1);
3391 int num_rsp = *((__u8 *) skb->data);
Vishal Agarwal9d939d92012-04-26 19:19:56 +05303392 size_t eir_len;
Marcel Holtmanna9de9242007-10-20 13:33:56 +02003393
3394 BT_DBG("%s num_rsp %d", hdev->name, num_rsp);
3395
3396 if (!num_rsp)
3397 return;
3398
Andre Guedes1519cc12012-03-21 00:03:38 -03003399 if (test_bit(HCI_PERIODIC_INQ, &hdev->dev_flags))
3400 return;
3401
Marcel Holtmanna9de9242007-10-20 13:33:56 +02003402 hci_dev_lock(hdev);
3403
Johan Hedberge17acd42011-03-30 23:57:16 +03003404 for (; num_rsp; num_rsp--, info++) {
Johan Hedberg388fc8f2012-02-23 00:38:59 +02003405 bool name_known, ssp;
Johan Hedberg561aafb2012-01-04 13:31:59 +02003406
Marcel Holtmanna9de9242007-10-20 13:33:56 +02003407 bacpy(&data.bdaddr, &info->bdaddr);
Szymon Janc138d22e2011-02-17 16:44:23 +01003408 data.pscan_rep_mode = info->pscan_rep_mode;
3409 data.pscan_period_mode = info->pscan_period_mode;
3410 data.pscan_mode = 0x00;
Marcel Holtmanna9de9242007-10-20 13:33:56 +02003411 memcpy(data.dev_class, info->dev_class, 3);
Szymon Janc138d22e2011-02-17 16:44:23 +01003412 data.clock_offset = info->clock_offset;
3413 data.rssi = info->rssi;
Marcel Holtmann41a96212008-07-14 20:13:48 +02003414 data.ssp_mode = 0x01;
Johan Hedberg561aafb2012-01-04 13:31:59 +02003415
Johan Hedberga8b2d5c2012-01-08 23:11:15 +02003416 if (test_bit(HCI_MGMT, &hdev->dev_flags))
Johan Hedberg4ddb1932012-01-15 20:04:43 +02003417 name_known = eir_has_data_type(info->data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003418 sizeof(info->data),
3419 EIR_NAME_COMPLETE);
Johan Hedberg561aafb2012-01-04 13:31:59 +02003420 else
3421 name_known = true;
3422
Johan Hedberg388fc8f2012-02-23 00:38:59 +02003423 name_known = hci_inquiry_cache_update(hdev, &data, name_known,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003424 &ssp);
Vishal Agarwal9d939d92012-04-26 19:19:56 +05303425 eir_len = eir_get_length(info->data, sizeof(info->data));
Johan Hedberg48264f02011-11-09 13:58:58 +02003426 mgmt_device_found(hdev, &info->bdaddr, ACL_LINK, 0x00,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003427 info->dev_class, info->rssi, !name_known,
Vishal Agarwal9d939d92012-04-26 19:19:56 +05303428 ssp, info->data, eir_len);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02003429 }
3430
3431 hci_dev_unlock(hdev);
3432}
3433
Johan Hedberg1c2e0042012-06-08 23:31:13 +08003434static void hci_key_refresh_complete_evt(struct hci_dev *hdev,
3435 struct sk_buff *skb)
3436{
3437 struct hci_ev_key_refresh_complete *ev = (void *) skb->data;
3438 struct hci_conn *conn;
3439
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +03003440 BT_DBG("%s status 0x%2.2x handle 0x%4.4x", hdev->name, ev->status,
Johan Hedberg1c2e0042012-06-08 23:31:13 +08003441 __le16_to_cpu(ev->handle));
3442
3443 hci_dev_lock(hdev);
3444
3445 conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
3446 if (!conn)
3447 goto unlock;
3448
3449 if (!ev->status)
3450 conn->sec_level = conn->pending_sec_level;
3451
3452 clear_bit(HCI_CONN_ENCRYPT_PEND, &conn->flags);
3453
3454 if (ev->status && conn->state == BT_CONNECTED) {
3455 hci_acl_disconn(conn, HCI_ERROR_AUTH_FAILURE);
3456 hci_conn_put(conn);
3457 goto unlock;
3458 }
3459
3460 if (conn->state == BT_CONFIG) {
3461 if (!ev->status)
3462 conn->state = BT_CONNECTED;
3463
3464 hci_proto_connect_cfm(conn, ev->status);
3465 hci_conn_put(conn);
3466 } else {
3467 hci_auth_cfm(conn, ev->status);
3468
3469 hci_conn_hold(conn);
3470 conn->disc_timeout = HCI_DISCONN_TIMEOUT;
3471 hci_conn_put(conn);
3472 }
3473
3474unlock:
3475 hci_dev_unlock(hdev);
3476}
3477
Gustavo Padovan6039aa72012-05-23 04:04:18 -03003478static u8 hci_get_auth_req(struct hci_conn *conn)
Johan Hedberg17fa4b92011-01-25 13:28:33 +02003479{
3480 /* If remote requests dedicated bonding follow that lead */
3481 if (conn->remote_auth == 0x02 || conn->remote_auth == 0x03) {
3482 /* If both remote and local IO capabilities allow MITM
3483 * protection then require it, otherwise don't */
3484 if (conn->remote_cap == 0x03 || conn->io_capability == 0x03)
3485 return 0x02;
3486 else
3487 return 0x03;
3488 }
3489
3490 /* If remote requests no-bonding follow that lead */
3491 if (conn->remote_auth == 0x00 || conn->remote_auth == 0x01)
Waldemar Rymarkiewicz58797bf2011-04-28 12:07:58 +02003492 return conn->remote_auth | (conn->auth_type & 0x01);
Johan Hedberg17fa4b92011-01-25 13:28:33 +02003493
3494 return conn->auth_type;
3495}
3496
Gustavo Padovan6039aa72012-05-23 04:04:18 -03003497static void hci_io_capa_request_evt(struct hci_dev *hdev, struct sk_buff *skb)
Marcel Holtmann04936842008-07-14 20:13:48 +02003498{
3499 struct hci_ev_io_capa_request *ev = (void *) skb->data;
3500 struct hci_conn *conn;
3501
3502 BT_DBG("%s", hdev->name);
3503
3504 hci_dev_lock(hdev);
3505
3506 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
Johan Hedberg03b555e2011-01-04 15:40:05 +02003507 if (!conn)
3508 goto unlock;
Marcel Holtmann04936842008-07-14 20:13:48 +02003509
Johan Hedberg03b555e2011-01-04 15:40:05 +02003510 hci_conn_hold(conn);
3511
Johan Hedberga8b2d5c2012-01-08 23:11:15 +02003512 if (!test_bit(HCI_MGMT, &hdev->dev_flags))
Johan Hedberg03b555e2011-01-04 15:40:05 +02003513 goto unlock;
3514
Johan Hedberga8b2d5c2012-01-08 23:11:15 +02003515 if (test_bit(HCI_PAIRABLE, &hdev->dev_flags) ||
Gustavo Padovan807deac2012-05-17 00:36:24 -03003516 (conn->remote_auth & ~0x01) == HCI_AT_NO_BONDING) {
Johan Hedberg17fa4b92011-01-25 13:28:33 +02003517 struct hci_cp_io_capability_reply cp;
3518
3519 bacpy(&cp.bdaddr, &ev->bdaddr);
Hemant Gupta7a7f1e72012-01-16 13:34:29 +05303520 /* Change the IO capability from KeyboardDisplay
3521 * to DisplayYesNo as it is not supported by BT spec. */
3522 cp.capability = (conn->io_capability == 0x04) ?
3523 0x01 : conn->io_capability;
Johan Hedberg7cbc9bd2011-04-28 11:29:04 -07003524 conn->auth_type = hci_get_auth_req(conn);
3525 cp.authentication = conn->auth_type;
Johan Hedberg17fa4b92011-01-25 13:28:33 +02003526
Gustavo Padovan8fc9ced2012-05-23 04:04:21 -03003527 if (hci_find_remote_oob_data(hdev, &conn->dst) &&
3528 (conn->out || test_bit(HCI_CONN_REMOTE_OOB, &conn->flags)))
Szymon Jancce85ee12011-03-22 13:12:23 +01003529 cp.oob_data = 0x01;
3530 else
3531 cp.oob_data = 0x00;
3532
Johan Hedberg17fa4b92011-01-25 13:28:33 +02003533 hci_send_cmd(hdev, HCI_OP_IO_CAPABILITY_REPLY,
Gustavo Padovan807deac2012-05-17 00:36:24 -03003534 sizeof(cp), &cp);
Johan Hedberg03b555e2011-01-04 15:40:05 +02003535 } else {
3536 struct hci_cp_io_capability_neg_reply cp;
3537
3538 bacpy(&cp.bdaddr, &ev->bdaddr);
Andrei Emeltchenko9f5a0d72011-11-07 14:20:25 +02003539 cp.reason = HCI_ERROR_PAIRING_NOT_ALLOWED;
Johan Hedberg03b555e2011-01-04 15:40:05 +02003540
3541 hci_send_cmd(hdev, HCI_OP_IO_CAPABILITY_NEG_REPLY,
Gustavo Padovan807deac2012-05-17 00:36:24 -03003542 sizeof(cp), &cp);
Johan Hedberg03b555e2011-01-04 15:40:05 +02003543 }
3544
3545unlock:
3546 hci_dev_unlock(hdev);
3547}
3548
Gustavo Padovan6039aa72012-05-23 04:04:18 -03003549static void hci_io_capa_reply_evt(struct hci_dev *hdev, struct sk_buff *skb)
Johan Hedberg03b555e2011-01-04 15:40:05 +02003550{
3551 struct hci_ev_io_capa_reply *ev = (void *) skb->data;
3552 struct hci_conn *conn;
3553
3554 BT_DBG("%s", hdev->name);
3555
3556 hci_dev_lock(hdev);
3557
3558 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
3559 if (!conn)
3560 goto unlock;
3561
Johan Hedberg03b555e2011-01-04 15:40:05 +02003562 conn->remote_cap = ev->capability;
Johan Hedberg03b555e2011-01-04 15:40:05 +02003563 conn->remote_auth = ev->authentication;
Johan Hedberg58a681e2012-01-16 06:47:28 +02003564 if (ev->oob_data)
3565 set_bit(HCI_CONN_REMOTE_OOB, &conn->flags);
Johan Hedberg03b555e2011-01-04 15:40:05 +02003566
3567unlock:
Marcel Holtmann04936842008-07-14 20:13:48 +02003568 hci_dev_unlock(hdev);
3569}
3570
Gustavo Padovan6039aa72012-05-23 04:04:18 -03003571static void hci_user_confirm_request_evt(struct hci_dev *hdev,
3572 struct sk_buff *skb)
Johan Hedberga5c29682011-02-19 12:05:57 -03003573{
3574 struct hci_ev_user_confirm_req *ev = (void *) skb->data;
Johan Hedberg55bc1a32011-04-28 11:28:56 -07003575 int loc_mitm, rem_mitm, confirm_hint = 0;
Johan Hedberg7a828902011-04-28 11:28:53 -07003576 struct hci_conn *conn;
Johan Hedberga5c29682011-02-19 12:05:57 -03003577
3578 BT_DBG("%s", hdev->name);
3579
3580 hci_dev_lock(hdev);
3581
Johan Hedberga8b2d5c2012-01-08 23:11:15 +02003582 if (!test_bit(HCI_MGMT, &hdev->dev_flags))
Johan Hedberg7a828902011-04-28 11:28:53 -07003583 goto unlock;
Johan Hedberga5c29682011-02-19 12:05:57 -03003584
Johan Hedberg7a828902011-04-28 11:28:53 -07003585 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
3586 if (!conn)
3587 goto unlock;
3588
3589 loc_mitm = (conn->auth_type & 0x01);
3590 rem_mitm = (conn->remote_auth & 0x01);
3591
3592 /* If we require MITM but the remote device can't provide that
3593 * (it has NoInputNoOutput) then reject the confirmation
3594 * request. The only exception is when we're dedicated bonding
3595 * initiators (connect_cfm_cb set) since then we always have the MITM
3596 * bit set. */
3597 if (!conn->connect_cfm_cb && loc_mitm && conn->remote_cap == 0x03) {
3598 BT_DBG("Rejecting request: remote device can't provide MITM");
3599 hci_send_cmd(hdev, HCI_OP_USER_CONFIRM_NEG_REPLY,
Gustavo Padovan807deac2012-05-17 00:36:24 -03003600 sizeof(ev->bdaddr), &ev->bdaddr);
Johan Hedberg7a828902011-04-28 11:28:53 -07003601 goto unlock;
3602 }
3603
3604 /* If no side requires MITM protection; auto-accept */
3605 if ((!loc_mitm || conn->remote_cap == 0x03) &&
Gustavo Padovan807deac2012-05-17 00:36:24 -03003606 (!rem_mitm || conn->io_capability == 0x03)) {
Johan Hedberg55bc1a32011-04-28 11:28:56 -07003607
3608 /* If we're not the initiators request authorization to
3609 * proceed from user space (mgmt_user_confirm with
3610 * confirm_hint set to 1). */
Johan Hedberg51a8efd2012-01-16 06:10:31 +02003611 if (!test_bit(HCI_CONN_AUTH_PEND, &conn->flags)) {
Johan Hedberg55bc1a32011-04-28 11:28:56 -07003612 BT_DBG("Confirming auto-accept as acceptor");
3613 confirm_hint = 1;
3614 goto confirm;
3615 }
3616
Johan Hedberg9f616562011-04-28 11:28:54 -07003617 BT_DBG("Auto-accept of user confirmation with %ums delay",
Gustavo Padovan807deac2012-05-17 00:36:24 -03003618 hdev->auto_accept_delay);
Johan Hedberg9f616562011-04-28 11:28:54 -07003619
3620 if (hdev->auto_accept_delay > 0) {
3621 int delay = msecs_to_jiffies(hdev->auto_accept_delay);
3622 mod_timer(&conn->auto_accept_timer, jiffies + delay);
3623 goto unlock;
3624 }
3625
Johan Hedberg7a828902011-04-28 11:28:53 -07003626 hci_send_cmd(hdev, HCI_OP_USER_CONFIRM_REPLY,
Gustavo Padovan807deac2012-05-17 00:36:24 -03003627 sizeof(ev->bdaddr), &ev->bdaddr);
Johan Hedberg7a828902011-04-28 11:28:53 -07003628 goto unlock;
3629 }
3630
Johan Hedberg55bc1a32011-04-28 11:28:56 -07003631confirm:
Johan Hedberg272d90d2012-02-09 15:26:12 +02003632 mgmt_user_confirm_request(hdev, &ev->bdaddr, ACL_LINK, 0, ev->passkey,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003633 confirm_hint);
Johan Hedberg7a828902011-04-28 11:28:53 -07003634
3635unlock:
Johan Hedberga5c29682011-02-19 12:05:57 -03003636 hci_dev_unlock(hdev);
3637}
3638
Gustavo Padovan6039aa72012-05-23 04:04:18 -03003639static void hci_user_passkey_request_evt(struct hci_dev *hdev,
3640 struct sk_buff *skb)
Brian Gix1143d452011-11-23 08:28:34 -08003641{
3642 struct hci_ev_user_passkey_req *ev = (void *) skb->data;
3643
3644 BT_DBG("%s", hdev->name);
3645
Johan Hedberga8b2d5c2012-01-08 23:11:15 +02003646 if (test_bit(HCI_MGMT, &hdev->dev_flags))
Johan Hedberg272d90d2012-02-09 15:26:12 +02003647 mgmt_user_passkey_request(hdev, &ev->bdaddr, ACL_LINK, 0);
Brian Gix1143d452011-11-23 08:28:34 -08003648}
3649
Johan Hedberg92a25252012-09-06 18:39:26 +03003650static void hci_user_passkey_notify_evt(struct hci_dev *hdev,
3651 struct sk_buff *skb)
3652{
3653 struct hci_ev_user_passkey_notify *ev = (void *) skb->data;
3654 struct hci_conn *conn;
3655
3656 BT_DBG("%s", hdev->name);
3657
3658 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
3659 if (!conn)
3660 return;
3661
3662 conn->passkey_notify = __le32_to_cpu(ev->passkey);
3663 conn->passkey_entered = 0;
3664
3665 if (test_bit(HCI_MGMT, &hdev->dev_flags))
3666 mgmt_user_passkey_notify(hdev, &conn->dst, conn->type,
3667 conn->dst_type, conn->passkey_notify,
3668 conn->passkey_entered);
3669}
3670
3671static void hci_keypress_notify_evt(struct hci_dev *hdev, struct sk_buff *skb)
3672{
3673 struct hci_ev_keypress_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 switch (ev->type) {
3683 case HCI_KEYPRESS_STARTED:
3684 conn->passkey_entered = 0;
3685 return;
3686
3687 case HCI_KEYPRESS_ENTERED:
3688 conn->passkey_entered++;
3689 break;
3690
3691 case HCI_KEYPRESS_ERASED:
3692 conn->passkey_entered--;
3693 break;
3694
3695 case HCI_KEYPRESS_CLEARED:
3696 conn->passkey_entered = 0;
3697 break;
3698
3699 case HCI_KEYPRESS_COMPLETED:
3700 return;
3701 }
3702
3703 if (test_bit(HCI_MGMT, &hdev->dev_flags))
3704 mgmt_user_passkey_notify(hdev, &conn->dst, conn->type,
3705 conn->dst_type, conn->passkey_notify,
3706 conn->passkey_entered);
3707}
3708
Gustavo Padovan6039aa72012-05-23 04:04:18 -03003709static void hci_simple_pair_complete_evt(struct hci_dev *hdev,
3710 struct sk_buff *skb)
Marcel Holtmann04936842008-07-14 20:13:48 +02003711{
3712 struct hci_ev_simple_pair_complete *ev = (void *) skb->data;
3713 struct hci_conn *conn;
3714
3715 BT_DBG("%s", hdev->name);
3716
3717 hci_dev_lock(hdev);
3718
3719 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
Johan Hedberg2a611692011-02-19 12:06:00 -03003720 if (!conn)
3721 goto unlock;
Marcel Holtmann04936842008-07-14 20:13:48 +02003722
Johan Hedberg2a611692011-02-19 12:06:00 -03003723 /* To avoid duplicate auth_failed events to user space we check
3724 * the HCI_CONN_AUTH_PEND flag which will be set if we
3725 * initiated the authentication. A traditional auth_complete
3726 * event gets always produced as initiator and is also mapped to
3727 * the mgmt_auth_failed event */
Mikel Astizfa1bd912012-08-09 09:52:29 +02003728 if (!test_bit(HCI_CONN_AUTH_PEND, &conn->flags) && ev->status)
Johan Hedbergbab73cb2012-02-09 16:07:29 +02003729 mgmt_auth_failed(hdev, &conn->dst, conn->type, conn->dst_type,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003730 ev->status);
Johan Hedberg2a611692011-02-19 12:06:00 -03003731
3732 hci_conn_put(conn);
3733
3734unlock:
Marcel Holtmann04936842008-07-14 20:13:48 +02003735 hci_dev_unlock(hdev);
3736}
3737
Gustavo Padovan6039aa72012-05-23 04:04:18 -03003738static void hci_remote_host_features_evt(struct hci_dev *hdev,
3739 struct sk_buff *skb)
Marcel Holtmann41a96212008-07-14 20:13:48 +02003740{
3741 struct hci_ev_remote_host_features *ev = (void *) skb->data;
3742 struct inquiry_entry *ie;
3743
3744 BT_DBG("%s", hdev->name);
3745
3746 hci_dev_lock(hdev);
3747
Andrei Emeltchenkocc11b9c2010-11-22 13:21:37 +02003748 ie = hci_inquiry_cache_lookup(hdev, &ev->bdaddr);
3749 if (ie)
Johan Hedberg02b7cc62012-02-28 02:28:43 +02003750 ie->data.ssp_mode = (ev->features[0] & LMP_HOST_SSP);
Marcel Holtmann41a96212008-07-14 20:13:48 +02003751
3752 hci_dev_unlock(hdev);
3753}
3754
Gustavo Padovan6039aa72012-05-23 04:04:18 -03003755static void hci_remote_oob_data_request_evt(struct hci_dev *hdev,
3756 struct sk_buff *skb)
Szymon Janc2763eda2011-03-22 13:12:22 +01003757{
3758 struct hci_ev_remote_oob_data_request *ev = (void *) skb->data;
3759 struct oob_data *data;
3760
3761 BT_DBG("%s", hdev->name);
3762
3763 hci_dev_lock(hdev);
3764
Johan Hedberga8b2d5c2012-01-08 23:11:15 +02003765 if (!test_bit(HCI_MGMT, &hdev->dev_flags))
Szymon Jance1ba1f12011-04-06 13:01:59 +02003766 goto unlock;
3767
Szymon Janc2763eda2011-03-22 13:12:22 +01003768 data = hci_find_remote_oob_data(hdev, &ev->bdaddr);
3769 if (data) {
3770 struct hci_cp_remote_oob_data_reply cp;
3771
3772 bacpy(&cp.bdaddr, &ev->bdaddr);
3773 memcpy(cp.hash, data->hash, sizeof(cp.hash));
3774 memcpy(cp.randomizer, data->randomizer, sizeof(cp.randomizer));
3775
3776 hci_send_cmd(hdev, HCI_OP_REMOTE_OOB_DATA_REPLY, sizeof(cp),
Gustavo Padovan807deac2012-05-17 00:36:24 -03003777 &cp);
Szymon Janc2763eda2011-03-22 13:12:22 +01003778 } else {
3779 struct hci_cp_remote_oob_data_neg_reply cp;
3780
3781 bacpy(&cp.bdaddr, &ev->bdaddr);
3782 hci_send_cmd(hdev, HCI_OP_REMOTE_OOB_DATA_NEG_REPLY, sizeof(cp),
Gustavo Padovan807deac2012-05-17 00:36:24 -03003783 &cp);
Szymon Janc2763eda2011-03-22 13:12:22 +01003784 }
3785
Szymon Jance1ba1f12011-04-06 13:01:59 +02003786unlock:
Szymon Janc2763eda2011-03-22 13:12:22 +01003787 hci_dev_unlock(hdev);
3788}
3789
Andrei Emeltchenkod5e91192012-10-25 15:20:44 +03003790static void hci_phy_link_complete_evt(struct hci_dev *hdev,
3791 struct sk_buff *skb)
3792{
3793 struct hci_ev_phy_link_complete *ev = (void *) skb->data;
3794 struct hci_conn *hcon, *bredr_hcon;
3795
3796 BT_DBG("%s handle 0x%2.2x status 0x%2.2x", hdev->name, ev->phy_handle,
3797 ev->status);
3798
3799 hci_dev_lock(hdev);
3800
3801 hcon = hci_conn_hash_lookup_handle(hdev, ev->phy_handle);
3802 if (!hcon) {
3803 hci_dev_unlock(hdev);
3804 return;
3805 }
3806
3807 if (ev->status) {
3808 hci_conn_del(hcon);
3809 hci_dev_unlock(hdev);
3810 return;
3811 }
3812
3813 bredr_hcon = hcon->amp_mgr->l2cap_conn->hcon;
3814
3815 hcon->state = BT_CONNECTED;
3816 bacpy(&hcon->dst, &bredr_hcon->dst);
3817
3818 hci_conn_hold(hcon);
3819 hcon->disc_timeout = HCI_DISCONN_TIMEOUT;
3820 hci_conn_put(hcon);
3821
3822 hci_conn_hold_device(hcon);
3823 hci_conn_add_sysfs(hcon);
3824
Andrei Emeltchenkocf70ff22012-10-31 15:46:36 +02003825 amp_physical_cfm(bredr_hcon, hcon);
3826
Andrei Emeltchenkod5e91192012-10-25 15:20:44 +03003827 hci_dev_unlock(hdev);
Andrei Emeltchenkod5e91192012-10-25 15:20:44 +03003828}
3829
Andrei Emeltchenko27695fb2012-10-25 15:20:45 +03003830static void hci_loglink_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
3831{
3832 struct hci_ev_logical_link_complete *ev = (void *) skb->data;
3833 struct hci_conn *hcon;
3834 struct hci_chan *hchan;
3835 struct amp_mgr *mgr;
3836
3837 BT_DBG("%s log_handle 0x%4.4x phy_handle 0x%2.2x status 0x%2.2x",
3838 hdev->name, le16_to_cpu(ev->handle), ev->phy_handle,
3839 ev->status);
3840
3841 hcon = hci_conn_hash_lookup_handle(hdev, ev->phy_handle);
3842 if (!hcon)
3843 return;
3844
3845 /* Create AMP hchan */
3846 hchan = hci_chan_create(hcon);
3847 if (!hchan)
3848 return;
3849
3850 hchan->handle = le16_to_cpu(ev->handle);
3851
3852 BT_DBG("hcon %p mgr %p hchan %p", hcon, hcon->amp_mgr, hchan);
3853
3854 mgr = hcon->amp_mgr;
3855 if (mgr && mgr->bredr_chan) {
3856 struct l2cap_chan *bredr_chan = mgr->bredr_chan;
3857
3858 l2cap_chan_lock(bredr_chan);
3859
3860 bredr_chan->conn->mtu = hdev->block_mtu;
3861 l2cap_logical_cfm(bredr_chan, hchan, 0);
3862 hci_conn_hold(hcon);
3863
3864 l2cap_chan_unlock(bredr_chan);
3865 }
3866}
3867
Andrei Emeltchenko606e2a12012-10-31 15:46:31 +02003868static void hci_disconn_loglink_complete_evt(struct hci_dev *hdev,
3869 struct sk_buff *skb)
3870{
3871 struct hci_ev_disconn_logical_link_complete *ev = (void *) skb->data;
3872 struct hci_chan *hchan;
3873
3874 BT_DBG("%s log handle 0x%4.4x status 0x%2.2x", hdev->name,
3875 le16_to_cpu(ev->handle), ev->status);
3876
3877 if (ev->status)
3878 return;
3879
3880 hci_dev_lock(hdev);
3881
3882 hchan = hci_chan_lookup_handle(hdev, le16_to_cpu(ev->handle));
3883 if (!hchan)
3884 goto unlock;
3885
3886 amp_destroy_logical_link(hchan, ev->reason);
3887
3888unlock:
3889 hci_dev_unlock(hdev);
3890}
3891
Andrei Emeltchenko9eef6b32012-10-31 15:46:32 +02003892static void hci_disconn_phylink_complete_evt(struct hci_dev *hdev,
3893 struct sk_buff *skb)
3894{
3895 struct hci_ev_disconn_phy_link_complete *ev = (void *) skb->data;
3896 struct hci_conn *hcon;
3897
3898 BT_DBG("%s status 0x%2.2x", hdev->name, ev->status);
3899
3900 if (ev->status)
3901 return;
3902
3903 hci_dev_lock(hdev);
3904
3905 hcon = hci_conn_hash_lookup_handle(hdev, ev->phy_handle);
3906 if (hcon) {
3907 hcon->state = BT_CLOSED;
3908 hci_conn_del(hcon);
3909 }
3910
3911 hci_dev_unlock(hdev);
3912}
3913
Gustavo Padovan6039aa72012-05-23 04:04:18 -03003914static void hci_le_conn_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
Ville Tervofcd89c02011-02-10 22:38:47 -03003915{
3916 struct hci_ev_le_conn_complete *ev = (void *) skb->data;
3917 struct hci_conn *conn;
3918
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +03003919 BT_DBG("%s status 0x%2.2x", hdev->name, ev->status);
Ville Tervofcd89c02011-02-10 22:38:47 -03003920
3921 hci_dev_lock(hdev);
3922
Andre Guedesb47a09b2012-07-27 15:10:15 -03003923 conn = hci_conn_hash_lookup_state(hdev, LE_LINK, BT_CONNECT);
Ville Tervob62f3282011-02-10 22:38:50 -03003924 if (!conn) {
3925 conn = hci_conn_add(hdev, LE_LINK, &ev->bdaddr);
3926 if (!conn) {
3927 BT_ERR("No memory for new connection");
Andre Guedes230fd162012-07-27 15:10:10 -03003928 goto unlock;
Ville Tervob62f3282011-02-10 22:38:50 -03003929 }
Andre Guedes29b79882011-05-31 14:20:54 -03003930
3931 conn->dst_type = ev->bdaddr_type;
Andre Guedesb9b343d2012-07-27 15:10:11 -03003932
3933 if (ev->role == LE_CONN_ROLE_MASTER) {
3934 conn->out = true;
3935 conn->link_mode |= HCI_LM_MASTER;
3936 }
Ville Tervob62f3282011-02-10 22:38:50 -03003937 }
Ville Tervofcd89c02011-02-10 22:38:47 -03003938
Andre Guedescd17dec2012-07-27 15:10:16 -03003939 if (ev->status) {
3940 mgmt_connect_failed(hdev, &conn->dst, conn->type,
3941 conn->dst_type, ev->status);
3942 hci_proto_connect_cfm(conn, ev->status);
3943 conn->state = BT_CLOSED;
3944 hci_conn_del(conn);
3945 goto unlock;
3946 }
3947
Johan Hedbergb644ba32012-01-17 21:48:47 +02003948 if (!test_and_set_bit(HCI_CONN_MGMT_CONNECTED, &conn->flags))
3949 mgmt_device_connected(hdev, &ev->bdaddr, conn->type,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003950 conn->dst_type, 0, NULL, 0, NULL);
Vinicius Costa Gomes83bc71b2011-05-06 18:41:43 -03003951
Vinicius Costa Gomes7b5c0d52011-06-09 18:50:50 -03003952 conn->sec_level = BT_SECURITY_LOW;
Ville Tervofcd89c02011-02-10 22:38:47 -03003953 conn->handle = __le16_to_cpu(ev->handle);
3954 conn->state = BT_CONNECTED;
3955
3956 hci_conn_hold_device(conn);
3957 hci_conn_add_sysfs(conn);
3958
3959 hci_proto_connect_cfm(conn, ev->status);
3960
3961unlock:
3962 hci_dev_unlock(hdev);
3963}
3964
Gustavo Padovan6039aa72012-05-23 04:04:18 -03003965static void hci_le_adv_report_evt(struct hci_dev *hdev, struct sk_buff *skb)
Andre Guedes9aa04c92011-05-26 16:23:51 -03003966{
Andre Guedese95beb42011-09-26 20:48:35 -03003967 u8 num_reports = skb->data[0];
3968 void *ptr = &skb->data[1];
Andre Guedes3c9e9192012-01-10 18:20:50 -03003969 s8 rssi;
Andre Guedes9aa04c92011-05-26 16:23:51 -03003970
3971 hci_dev_lock(hdev);
3972
Andre Guedese95beb42011-09-26 20:48:35 -03003973 while (num_reports--) {
3974 struct hci_ev_le_advertising_info *ev = ptr;
Andre Guedes9aa04c92011-05-26 16:23:51 -03003975
Andre Guedes3c9e9192012-01-10 18:20:50 -03003976 rssi = ev->data[ev->length];
3977 mgmt_device_found(hdev, &ev->bdaddr, LE_LINK, ev->bdaddr_type,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003978 NULL, rssi, 0, 1, ev->data, ev->length);
Andre Guedes3c9e9192012-01-10 18:20:50 -03003979
Andre Guedese95beb42011-09-26 20:48:35 -03003980 ptr += sizeof(*ev) + ev->length + 1;
Andre Guedes9aa04c92011-05-26 16:23:51 -03003981 }
3982
3983 hci_dev_unlock(hdev);
3984}
3985
Gustavo Padovan6039aa72012-05-23 04:04:18 -03003986static void hci_le_ltk_request_evt(struct hci_dev *hdev, struct sk_buff *skb)
Vinicius Costa Gomesa7a595f2011-06-09 18:50:47 -03003987{
3988 struct hci_ev_le_ltk_req *ev = (void *) skb->data;
3989 struct hci_cp_le_ltk_reply cp;
Vinicius Costa Gomesbea710f2011-07-07 18:59:37 -03003990 struct hci_cp_le_ltk_neg_reply neg;
Vinicius Costa Gomesa7a595f2011-06-09 18:50:47 -03003991 struct hci_conn *conn;
Vinicius Costa Gomesc9839a12012-02-02 21:08:01 -03003992 struct smp_ltk *ltk;
Vinicius Costa Gomesa7a595f2011-06-09 18:50:47 -03003993
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +03003994 BT_DBG("%s handle 0x%4.4x", hdev->name, __le16_to_cpu(ev->handle));
Vinicius Costa Gomesa7a595f2011-06-09 18:50:47 -03003995
3996 hci_dev_lock(hdev);
3997
3998 conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
Vinicius Costa Gomesbea710f2011-07-07 18:59:37 -03003999 if (conn == NULL)
4000 goto not_found;
Vinicius Costa Gomesa7a595f2011-06-09 18:50:47 -03004001
Vinicius Costa Gomesbea710f2011-07-07 18:59:37 -03004002 ltk = hci_find_ltk(hdev, ev->ediv, ev->random);
4003 if (ltk == NULL)
4004 goto not_found;
4005
4006 memcpy(cp.ltk, ltk->val, sizeof(ltk->val));
Vinicius Costa Gomesa7a595f2011-06-09 18:50:47 -03004007 cp.handle = cpu_to_le16(conn->handle);
Vinicius Costa Gomesc9839a12012-02-02 21:08:01 -03004008
4009 if (ltk->authenticated)
4010 conn->sec_level = BT_SECURITY_HIGH;
Vinicius Costa Gomesa7a595f2011-06-09 18:50:47 -03004011
4012 hci_send_cmd(hdev, HCI_OP_LE_LTK_REPLY, sizeof(cp), &cp);
4013
Vinicius Costa Gomesc9839a12012-02-02 21:08:01 -03004014 if (ltk->type & HCI_SMP_STK) {
4015 list_del(&ltk->list);
4016 kfree(ltk);
4017 }
4018
Vinicius Costa Gomesa7a595f2011-06-09 18:50:47 -03004019 hci_dev_unlock(hdev);
Vinicius Costa Gomesbea710f2011-07-07 18:59:37 -03004020
4021 return;
4022
4023not_found:
4024 neg.handle = ev->handle;
4025 hci_send_cmd(hdev, HCI_OP_LE_LTK_NEG_REPLY, sizeof(neg), &neg);
4026 hci_dev_unlock(hdev);
Vinicius Costa Gomesa7a595f2011-06-09 18:50:47 -03004027}
4028
Gustavo Padovan6039aa72012-05-23 04:04:18 -03004029static void hci_le_meta_evt(struct hci_dev *hdev, struct sk_buff *skb)
Ville Tervofcd89c02011-02-10 22:38:47 -03004030{
4031 struct hci_ev_le_meta *le_ev = (void *) skb->data;
4032
4033 skb_pull(skb, sizeof(*le_ev));
4034
4035 switch (le_ev->subevent) {
4036 case HCI_EV_LE_CONN_COMPLETE:
4037 hci_le_conn_complete_evt(hdev, skb);
4038 break;
4039
Andre Guedes9aa04c92011-05-26 16:23:51 -03004040 case HCI_EV_LE_ADVERTISING_REPORT:
4041 hci_le_adv_report_evt(hdev, skb);
4042 break;
4043
Vinicius Costa Gomesa7a595f2011-06-09 18:50:47 -03004044 case HCI_EV_LE_LTK_REQ:
4045 hci_le_ltk_request_evt(hdev, skb);
4046 break;
4047
Ville Tervofcd89c02011-02-10 22:38:47 -03004048 default:
4049 break;
4050 }
4051}
4052
Andrei Emeltchenko9495b2e2012-09-27 17:26:22 +03004053static void hci_chan_selected_evt(struct hci_dev *hdev, struct sk_buff *skb)
4054{
4055 struct hci_ev_channel_selected *ev = (void *) skb->data;
4056 struct hci_conn *hcon;
4057
4058 BT_DBG("%s handle 0x%2.2x", hdev->name, ev->phy_handle);
4059
4060 skb_pull(skb, sizeof(*ev));
4061
4062 hcon = hci_conn_hash_lookup_handle(hdev, ev->phy_handle);
4063 if (!hcon)
4064 return;
4065
4066 amp_read_loc_assoc_final_data(hdev, hcon);
4067}
4068
Linus Torvalds1da177e2005-04-16 15:20:36 -07004069void hci_event_packet(struct hci_dev *hdev, struct sk_buff *skb)
4070{
Marcel Holtmanna9de9242007-10-20 13:33:56 +02004071 struct hci_event_hdr *hdr = (void *) skb->data;
4072 __u8 event = hdr->evt;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004073
4074 skb_pull(skb, HCI_EVENT_HDR_SIZE);
4075
Marcel Holtmanna9de9242007-10-20 13:33:56 +02004076 switch (event) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07004077 case HCI_EV_INQUIRY_COMPLETE:
4078 hci_inquiry_complete_evt(hdev, skb);
4079 break;
4080
4081 case HCI_EV_INQUIRY_RESULT:
4082 hci_inquiry_result_evt(hdev, skb);
4083 break;
4084
Marcel Holtmanna9de9242007-10-20 13:33:56 +02004085 case HCI_EV_CONN_COMPLETE:
4086 hci_conn_complete_evt(hdev, skb);
Marcel Holtmann21d9e302005-09-13 01:32:25 +02004087 break;
4088
Linus Torvalds1da177e2005-04-16 15:20:36 -07004089 case HCI_EV_CONN_REQUEST:
4090 hci_conn_request_evt(hdev, skb);
4091 break;
4092
Linus Torvalds1da177e2005-04-16 15:20:36 -07004093 case HCI_EV_DISCONN_COMPLETE:
4094 hci_disconn_complete_evt(hdev, skb);
4095 break;
4096
Linus Torvalds1da177e2005-04-16 15:20:36 -07004097 case HCI_EV_AUTH_COMPLETE:
4098 hci_auth_complete_evt(hdev, skb);
4099 break;
4100
Marcel Holtmanna9de9242007-10-20 13:33:56 +02004101 case HCI_EV_REMOTE_NAME:
4102 hci_remote_name_evt(hdev, skb);
4103 break;
4104
Linus Torvalds1da177e2005-04-16 15:20:36 -07004105 case HCI_EV_ENCRYPT_CHANGE:
4106 hci_encrypt_change_evt(hdev, skb);
4107 break;
4108
Marcel Holtmanna9de9242007-10-20 13:33:56 +02004109 case HCI_EV_CHANGE_LINK_KEY_COMPLETE:
4110 hci_change_link_key_complete_evt(hdev, skb);
4111 break;
4112
4113 case HCI_EV_REMOTE_FEATURES:
4114 hci_remote_features_evt(hdev, skb);
4115 break;
4116
4117 case HCI_EV_REMOTE_VERSION:
4118 hci_remote_version_evt(hdev, skb);
4119 break;
4120
4121 case HCI_EV_QOS_SETUP_COMPLETE:
4122 hci_qos_setup_complete_evt(hdev, skb);
4123 break;
4124
4125 case HCI_EV_CMD_COMPLETE:
4126 hci_cmd_complete_evt(hdev, skb);
4127 break;
4128
4129 case HCI_EV_CMD_STATUS:
4130 hci_cmd_status_evt(hdev, skb);
4131 break;
4132
4133 case HCI_EV_ROLE_CHANGE:
4134 hci_role_change_evt(hdev, skb);
4135 break;
4136
4137 case HCI_EV_NUM_COMP_PKTS:
4138 hci_num_comp_pkts_evt(hdev, skb);
4139 break;
4140
4141 case HCI_EV_MODE_CHANGE:
4142 hci_mode_change_evt(hdev, skb);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004143 break;
4144
4145 case HCI_EV_PIN_CODE_REQ:
4146 hci_pin_code_request_evt(hdev, skb);
4147 break;
4148
4149 case HCI_EV_LINK_KEY_REQ:
4150 hci_link_key_request_evt(hdev, skb);
4151 break;
4152
4153 case HCI_EV_LINK_KEY_NOTIFY:
4154 hci_link_key_notify_evt(hdev, skb);
4155 break;
4156
4157 case HCI_EV_CLOCK_OFFSET:
4158 hci_clock_offset_evt(hdev, skb);
4159 break;
4160
Marcel Holtmanna8746412008-07-14 20:13:46 +02004161 case HCI_EV_PKT_TYPE_CHANGE:
4162 hci_pkt_type_change_evt(hdev, skb);
4163 break;
4164
Marcel Holtmann85a1e932005-08-09 20:28:02 -07004165 case HCI_EV_PSCAN_REP_MODE:
4166 hci_pscan_rep_mode_evt(hdev, skb);
4167 break;
4168
Marcel Holtmanna9de9242007-10-20 13:33:56 +02004169 case HCI_EV_INQUIRY_RESULT_WITH_RSSI:
4170 hci_inquiry_result_with_rssi_evt(hdev, skb);
4171 break;
4172
4173 case HCI_EV_REMOTE_EXT_FEATURES:
4174 hci_remote_ext_features_evt(hdev, skb);
4175 break;
4176
4177 case HCI_EV_SYNC_CONN_COMPLETE:
4178 hci_sync_conn_complete_evt(hdev, skb);
4179 break;
4180
4181 case HCI_EV_SYNC_CONN_CHANGED:
4182 hci_sync_conn_changed_evt(hdev, skb);
4183 break;
4184
Marcel Holtmann04837f62006-07-03 10:02:33 +02004185 case HCI_EV_SNIFF_SUBRATE:
4186 hci_sniff_subrate_evt(hdev, skb);
4187 break;
4188
Marcel Holtmanna9de9242007-10-20 13:33:56 +02004189 case HCI_EV_EXTENDED_INQUIRY_RESULT:
4190 hci_extended_inquiry_result_evt(hdev, skb);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004191 break;
4192
Johan Hedberg1c2e0042012-06-08 23:31:13 +08004193 case HCI_EV_KEY_REFRESH_COMPLETE:
4194 hci_key_refresh_complete_evt(hdev, skb);
4195 break;
4196
Marcel Holtmann04936842008-07-14 20:13:48 +02004197 case HCI_EV_IO_CAPA_REQUEST:
4198 hci_io_capa_request_evt(hdev, skb);
4199 break;
4200
Johan Hedberg03b555e2011-01-04 15:40:05 +02004201 case HCI_EV_IO_CAPA_REPLY:
4202 hci_io_capa_reply_evt(hdev, skb);
4203 break;
4204
Johan Hedberga5c29682011-02-19 12:05:57 -03004205 case HCI_EV_USER_CONFIRM_REQUEST:
4206 hci_user_confirm_request_evt(hdev, skb);
4207 break;
4208
Brian Gix1143d452011-11-23 08:28:34 -08004209 case HCI_EV_USER_PASSKEY_REQUEST:
4210 hci_user_passkey_request_evt(hdev, skb);
4211 break;
4212
Johan Hedberg92a25252012-09-06 18:39:26 +03004213 case HCI_EV_USER_PASSKEY_NOTIFY:
4214 hci_user_passkey_notify_evt(hdev, skb);
4215 break;
4216
4217 case HCI_EV_KEYPRESS_NOTIFY:
4218 hci_keypress_notify_evt(hdev, skb);
4219 break;
4220
Marcel Holtmann04936842008-07-14 20:13:48 +02004221 case HCI_EV_SIMPLE_PAIR_COMPLETE:
4222 hci_simple_pair_complete_evt(hdev, skb);
4223 break;
4224
Marcel Holtmann41a96212008-07-14 20:13:48 +02004225 case HCI_EV_REMOTE_HOST_FEATURES:
4226 hci_remote_host_features_evt(hdev, skb);
4227 break;
4228
Ville Tervofcd89c02011-02-10 22:38:47 -03004229 case HCI_EV_LE_META:
4230 hci_le_meta_evt(hdev, skb);
4231 break;
4232
Andrei Emeltchenko9495b2e2012-09-27 17:26:22 +03004233 case HCI_EV_CHANNEL_SELECTED:
4234 hci_chan_selected_evt(hdev, skb);
4235 break;
4236
Szymon Janc2763eda2011-03-22 13:12:22 +01004237 case HCI_EV_REMOTE_OOB_DATA_REQUEST:
4238 hci_remote_oob_data_request_evt(hdev, skb);
4239 break;
4240
Andrei Emeltchenkod5e91192012-10-25 15:20:44 +03004241 case HCI_EV_PHY_LINK_COMPLETE:
4242 hci_phy_link_complete_evt(hdev, skb);
4243 break;
4244
Andrei Emeltchenko27695fb2012-10-25 15:20:45 +03004245 case HCI_EV_LOGICAL_LINK_COMPLETE:
4246 hci_loglink_complete_evt(hdev, skb);
4247 break;
4248
Andrei Emeltchenko606e2a12012-10-31 15:46:31 +02004249 case HCI_EV_DISCONN_LOGICAL_LINK_COMPLETE:
4250 hci_disconn_loglink_complete_evt(hdev, skb);
4251 break;
4252
Andrei Emeltchenko9eef6b32012-10-31 15:46:32 +02004253 case HCI_EV_DISCONN_PHY_LINK_COMPLETE:
4254 hci_disconn_phylink_complete_evt(hdev, skb);
4255 break;
4256
Andrei Emeltchenko25e89e92012-01-04 12:41:58 +02004257 case HCI_EV_NUM_COMP_BLOCKS:
4258 hci_num_comp_blocks_evt(hdev, skb);
4259 break;
4260
Marcel Holtmanna9de9242007-10-20 13:33:56 +02004261 default:
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +03004262 BT_DBG("%s event 0x%2.2x", hdev->name, event);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004263 break;
4264 }
4265
4266 kfree_skb(skb);
4267 hdev->stat.evt_rx++;
4268}