blob: 07c8c79a9fd17637512b457060f56afd380e54b0 [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 Hedberge1171e82012-10-19 20:57:45 +0300617}
618
Johan Hedbergd5859e22011-01-25 01:19:58 +0200619static void hci_setup(struct hci_dev *hdev)
620{
Andrei Emeltchenkoe61ef4992011-12-19 16:31:27 +0200621 if (hdev->dev_type != HCI_BREDR)
622 return;
623
Johan Hedberge1171e82012-10-19 20:57:45 +0300624 /* Read BD Address */
625 hci_send_cmd(hdev, HCI_OP_READ_BD_ADDR, 0, NULL);
626
627 if (lmp_bredr_capable(hdev))
Gustavo Padovan4611dfa2012-10-24 11:18:41 -0200628 bredr_setup(hdev);
Johan Hedberge1171e82012-10-19 20:57:45 +0300629
630 if (lmp_le_capable(hdev))
Gustavo Padovan4611dfa2012-10-24 11:18:41 -0200631 le_setup(hdev);
Johan Hedberge1171e82012-10-19 20:57:45 +0300632
Johan Hedbergd5859e22011-01-25 01:19:58 +0200633 hci_setup_event_mask(hdev);
634
Andrei Emeltchenkod095c1e2011-12-01 14:33:27 +0200635 if (hdev->hci_ver > BLUETOOTH_VER_1_1)
Johan Hedbergd5859e22011-01-25 01:19:58 +0200636 hci_send_cmd(hdev, HCI_OP_READ_LOCAL_COMMANDS, 0, NULL);
637
Gustavo Padovan6d3c7302012-05-24 03:36:37 -0300638 if (lmp_ssp_capable(hdev)) {
Johan Hedberg54d04db2012-02-22 15:47:48 +0200639 if (test_bit(HCI_SSP_ENABLED, &hdev->dev_flags)) {
640 u8 mode = 0x01;
641 hci_send_cmd(hdev, HCI_OP_WRITE_SSP_MODE,
Gustavo F. Padovan04124682012-03-08 01:25:00 -0300642 sizeof(mode), &mode);
Johan Hedberg54d04db2012-02-22 15:47:48 +0200643 } else {
644 struct hci_cp_write_eir cp;
645
646 memset(hdev->eir, 0, sizeof(hdev->eir));
647 memset(&cp, 0, sizeof(cp));
648
649 hci_send_cmd(hdev, HCI_OP_WRITE_EIR, sizeof(cp), &cp);
650 }
Johan Hedbergd5859e22011-01-25 01:19:58 +0200651 }
652
Johan Hedberg976eb202012-10-24 21:12:01 +0300653 if (lmp_inq_rssi_capable(hdev))
Johan Hedbergd5859e22011-01-25 01:19:58 +0200654 hci_setup_inquiry_mode(hdev);
655
Johan Hedberg976eb202012-10-24 21:12:01 +0300656 if (lmp_inq_tx_pwr_capable(hdev))
Johan Hedbergd5859e22011-01-25 01:19:58 +0200657 hci_send_cmd(hdev, HCI_OP_READ_INQ_RSP_TX_POWER, 0, NULL);
Andre Guedes971e3a42011-06-30 19:20:52 -0300658
Johan Hedberg976eb202012-10-24 21:12:01 +0300659 if (lmp_ext_feat_capable(hdev)) {
Andre Guedes971e3a42011-06-30 19:20:52 -0300660 struct hci_cp_read_local_ext_features cp;
661
662 cp.page = 0x01;
Gustavo F. Padovan04124682012-03-08 01:25:00 -0300663 hci_send_cmd(hdev, HCI_OP_READ_LOCAL_EXT_FEATURES, sizeof(cp),
664 &cp);
Andre Guedes971e3a42011-06-30 19:20:52 -0300665 }
Andre Guedese6100a22011-06-30 19:20:54 -0300666
Johan Hedberg47990ea2012-02-22 11:58:37 +0200667 if (test_bit(HCI_LINK_SECURITY, &hdev->dev_flags)) {
668 u8 enable = 1;
Gustavo F. Padovan04124682012-03-08 01:25:00 -0300669 hci_send_cmd(hdev, HCI_OP_WRITE_AUTH_ENABLE, sizeof(enable),
670 &enable);
Johan Hedberg47990ea2012-02-22 11:58:37 +0200671 }
Johan Hedbergd5859e22011-01-25 01:19:58 +0200672}
673
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200674static void hci_cc_read_local_version(struct hci_dev *hdev, struct sk_buff *skb)
675{
676 struct hci_rp_read_local_version *rp = (void *) skb->data;
677
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +0300678 BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200679
680 if (rp->status)
Andrei Emeltchenko28b8df72012-02-24 12:45:44 +0200681 goto done;
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200682
683 hdev->hci_ver = rp->hci_ver;
Marcel Holtmanne4e8e372008-07-14 20:13:47 +0200684 hdev->hci_rev = __le16_to_cpu(rp->hci_rev);
Johan Hedbergd5859e22011-01-25 01:19:58 +0200685 hdev->lmp_ver = rp->lmp_ver;
Marcel Holtmanne4e8e372008-07-14 20:13:47 +0200686 hdev->manufacturer = __le16_to_cpu(rp->manufacturer);
Johan Hedbergd5859e22011-01-25 01:19:58 +0200687 hdev->lmp_subver = __le16_to_cpu(rp->lmp_subver);
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200688
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +0300689 BT_DBG("%s manufacturer 0x%4.4x hci ver %d:%d", hdev->name,
Gustavo Padovan807deac2012-05-17 00:36:24 -0300690 hdev->manufacturer, hdev->hci_ver, hdev->hci_rev);
Johan Hedbergd5859e22011-01-25 01:19:58 +0200691
692 if (test_bit(HCI_INIT, &hdev->flags))
693 hci_setup(hdev);
Andrei Emeltchenko28b8df72012-02-24 12:45:44 +0200694
695done:
696 hci_req_complete(hdev, HCI_OP_READ_LOCAL_VERSION, rp->status);
Johan Hedbergd5859e22011-01-25 01:19:58 +0200697}
698
699static void hci_setup_link_policy(struct hci_dev *hdev)
700{
Andrei Emeltchenko035100c2012-03-12 15:59:32 +0200701 struct hci_cp_write_def_link_policy cp;
Johan Hedbergd5859e22011-01-25 01:19:58 +0200702 u16 link_policy = 0;
703
Andre Guedes9f92ebf2012-07-24 15:03:50 -0300704 if (lmp_rswitch_capable(hdev))
Johan Hedbergd5859e22011-01-25 01:19:58 +0200705 link_policy |= HCI_LP_RSWITCH;
Johan Hedberg976eb202012-10-24 21:12:01 +0300706 if (lmp_hold_capable(hdev))
Johan Hedbergd5859e22011-01-25 01:19:58 +0200707 link_policy |= HCI_LP_HOLD;
Andre Guedes6eded102012-07-24 15:03:51 -0300708 if (lmp_sniff_capable(hdev))
Johan Hedbergd5859e22011-01-25 01:19:58 +0200709 link_policy |= HCI_LP_SNIFF;
Johan Hedberg976eb202012-10-24 21:12:01 +0300710 if (lmp_park_capable(hdev))
Johan Hedbergd5859e22011-01-25 01:19:58 +0200711 link_policy |= HCI_LP_PARK;
712
Andrei Emeltchenko035100c2012-03-12 15:59:32 +0200713 cp.policy = cpu_to_le16(link_policy);
714 hci_send_cmd(hdev, HCI_OP_WRITE_DEF_LINK_POLICY, sizeof(cp), &cp);
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200715}
716
Gustavo Padovan8fc9ced2012-05-23 04:04:21 -0300717static void hci_cc_read_local_commands(struct hci_dev *hdev,
718 struct sk_buff *skb)
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200719{
720 struct hci_rp_read_local_commands *rp = (void *) skb->data;
721
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +0300722 BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200723
724 if (rp->status)
Johan Hedbergd5859e22011-01-25 01:19:58 +0200725 goto done;
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200726
727 memcpy(hdev->commands, rp->commands, sizeof(hdev->commands));
Johan Hedbergd5859e22011-01-25 01:19:58 +0200728
729 if (test_bit(HCI_INIT, &hdev->flags) && (hdev->commands[5] & 0x10))
730 hci_setup_link_policy(hdev);
731
732done:
733 hci_req_complete(hdev, HCI_OP_READ_LOCAL_COMMANDS, rp->status);
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200734}
735
Gustavo Padovan8fc9ced2012-05-23 04:04:21 -0300736static void hci_cc_read_local_features(struct hci_dev *hdev,
737 struct sk_buff *skb)
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200738{
739 struct hci_rp_read_local_features *rp = (void *) skb->data;
740
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +0300741 BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200742
743 if (rp->status)
744 return;
745
746 memcpy(hdev->features, rp->features, 8);
747
748 /* Adjust default settings according to features
749 * supported by device. */
750
751 if (hdev->features[0] & LMP_3SLOT)
752 hdev->pkt_type |= (HCI_DM3 | HCI_DH3);
753
754 if (hdev->features[0] & LMP_5SLOT)
755 hdev->pkt_type |= (HCI_DM5 | HCI_DH5);
756
757 if (hdev->features[1] & LMP_HV2) {
758 hdev->pkt_type |= (HCI_HV2);
759 hdev->esco_type |= (ESCO_HV2);
760 }
761
762 if (hdev->features[1] & LMP_HV3) {
763 hdev->pkt_type |= (HCI_HV3);
764 hdev->esco_type |= (ESCO_HV3);
765 }
766
Andre Guedes45db810f2012-07-24 15:03:49 -0300767 if (lmp_esco_capable(hdev))
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200768 hdev->esco_type |= (ESCO_EV3);
769
770 if (hdev->features[4] & LMP_EV4)
771 hdev->esco_type |= (ESCO_EV4);
772
773 if (hdev->features[4] & LMP_EV5)
774 hdev->esco_type |= (ESCO_EV5);
775
Marcel Holtmannefc76882009-02-06 09:13:37 +0100776 if (hdev->features[5] & LMP_EDR_ESCO_2M)
777 hdev->esco_type |= (ESCO_2EV3);
778
779 if (hdev->features[5] & LMP_EDR_ESCO_3M)
780 hdev->esco_type |= (ESCO_3EV3);
781
782 if (hdev->features[5] & LMP_EDR_3S_ESCO)
783 hdev->esco_type |= (ESCO_2EV5 | ESCO_3EV5);
784
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200785 BT_DBG("%s features 0x%.2x%.2x%.2x%.2x%.2x%.2x%.2x%.2x", hdev->name,
Gustavo Padovan807deac2012-05-17 00:36:24 -0300786 hdev->features[0], hdev->features[1],
787 hdev->features[2], hdev->features[3],
788 hdev->features[4], hdev->features[5],
789 hdev->features[6], hdev->features[7]);
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200790}
791
Johan Hedberg8f984df2012-02-28 01:07:22 +0200792static void hci_set_le_support(struct hci_dev *hdev)
793{
794 struct hci_cp_write_le_host_supported cp;
795
796 memset(&cp, 0, sizeof(cp));
797
Marcel Holtmann9d428202012-05-03 07:12:31 +0200798 if (test_bit(HCI_LE_ENABLED, &hdev->dev_flags)) {
Johan Hedberg8f984df2012-02-28 01:07:22 +0200799 cp.le = 1;
Gustavo Padovanffa88e02012-11-23 16:50:51 -0200800 cp.simul = lmp_le_br_capable(hdev);
Johan Hedberg8f984df2012-02-28 01:07:22 +0200801 }
802
Gustavo Padovanffa88e02012-11-23 16:50:51 -0200803 if (cp.le != lmp_host_le_capable(hdev))
Gustavo F. Padovan04124682012-03-08 01:25:00 -0300804 hci_send_cmd(hdev, HCI_OP_WRITE_LE_HOST_SUPPORTED, sizeof(cp),
805 &cp);
Johan Hedberg8f984df2012-02-28 01:07:22 +0200806}
807
Andre Guedes971e3a42011-06-30 19:20:52 -0300808static void hci_cc_read_local_ext_features(struct hci_dev *hdev,
Gustavo Padovan807deac2012-05-17 00:36:24 -0300809 struct sk_buff *skb)
Andre Guedes971e3a42011-06-30 19:20:52 -0300810{
811 struct hci_rp_read_local_ext_features *rp = (void *) skb->data;
812
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +0300813 BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
Andre Guedes971e3a42011-06-30 19:20:52 -0300814
815 if (rp->status)
Johan Hedberg8f984df2012-02-28 01:07:22 +0200816 goto done;
Andre Guedes971e3a42011-06-30 19:20:52 -0300817
Andre Guedesb5b32b62011-12-30 10:34:04 -0300818 switch (rp->page) {
819 case 0:
820 memcpy(hdev->features, rp->features, 8);
821 break;
822 case 1:
823 memcpy(hdev->host_features, rp->features, 8);
824 break;
825 }
Andre Guedes971e3a42011-06-30 19:20:52 -0300826
Andre Guedesc383ddc2012-07-24 15:03:47 -0300827 if (test_bit(HCI_INIT, &hdev->flags) && lmp_le_capable(hdev))
Johan Hedberg8f984df2012-02-28 01:07:22 +0200828 hci_set_le_support(hdev);
829
830done:
Andre Guedes971e3a42011-06-30 19:20:52 -0300831 hci_req_complete(hdev, HCI_OP_READ_LOCAL_EXT_FEATURES, rp->status);
832}
833
Andrei Emeltchenko1e89cff2011-11-24 14:52:02 +0200834static void hci_cc_read_flow_control_mode(struct hci_dev *hdev,
Gustavo Padovan807deac2012-05-17 00:36:24 -0300835 struct sk_buff *skb)
Andrei Emeltchenko1e89cff2011-11-24 14:52:02 +0200836{
837 struct hci_rp_read_flow_control_mode *rp = (void *) skb->data;
838
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +0300839 BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
Andrei Emeltchenko1e89cff2011-11-24 14:52:02 +0200840
841 if (rp->status)
842 return;
843
844 hdev->flow_ctl_mode = rp->mode;
845
846 hci_req_complete(hdev, HCI_OP_READ_FLOW_CONTROL_MODE, rp->status);
847}
848
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200849static void hci_cc_read_buffer_size(struct hci_dev *hdev, struct sk_buff *skb)
850{
851 struct hci_rp_read_buffer_size *rp = (void *) skb->data;
852
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +0300853 BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200854
855 if (rp->status)
856 return;
857
858 hdev->acl_mtu = __le16_to_cpu(rp->acl_mtu);
859 hdev->sco_mtu = rp->sco_mtu;
860 hdev->acl_pkts = __le16_to_cpu(rp->acl_max_pkt);
861 hdev->sco_pkts = __le16_to_cpu(rp->sco_max_pkt);
862
863 if (test_bit(HCI_QUIRK_FIXUP_BUFFER_SIZE, &hdev->quirks)) {
864 hdev->sco_mtu = 64;
865 hdev->sco_pkts = 8;
866 }
867
868 hdev->acl_cnt = hdev->acl_pkts;
869 hdev->sco_cnt = hdev->sco_pkts;
870
Gustavo Padovan807deac2012-05-17 00:36:24 -0300871 BT_DBG("%s acl mtu %d:%d sco mtu %d:%d", hdev->name, hdev->acl_mtu,
872 hdev->acl_pkts, hdev->sco_mtu, hdev->sco_pkts);
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200873}
874
875static void hci_cc_read_bd_addr(struct hci_dev *hdev, struct sk_buff *skb)
876{
877 struct hci_rp_read_bd_addr *rp = (void *) skb->data;
878
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +0300879 BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200880
881 if (!rp->status)
882 bacpy(&hdev->bdaddr, &rp->bdaddr);
883
Johan Hedberg23bb5762010-12-21 23:01:27 +0200884 hci_req_complete(hdev, HCI_OP_READ_BD_ADDR, rp->status);
885}
886
Andrei Emeltchenko350ee4c2011-12-07 15:56:51 +0200887static void hci_cc_read_data_block_size(struct hci_dev *hdev,
Gustavo Padovan807deac2012-05-17 00:36:24 -0300888 struct sk_buff *skb)
Andrei Emeltchenko350ee4c2011-12-07 15:56:51 +0200889{
890 struct hci_rp_read_data_block_size *rp = (void *) skb->data;
891
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +0300892 BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
Andrei Emeltchenko350ee4c2011-12-07 15:56:51 +0200893
894 if (rp->status)
895 return;
896
897 hdev->block_mtu = __le16_to_cpu(rp->max_acl_len);
898 hdev->block_len = __le16_to_cpu(rp->block_len);
899 hdev->num_blocks = __le16_to_cpu(rp->num_blocks);
900
901 hdev->block_cnt = hdev->num_blocks;
902
903 BT_DBG("%s blk mtu %d cnt %d len %d", hdev->name, hdev->block_mtu,
Gustavo Padovan807deac2012-05-17 00:36:24 -0300904 hdev->block_cnt, hdev->block_len);
Andrei Emeltchenko350ee4c2011-12-07 15:56:51 +0200905
906 hci_req_complete(hdev, HCI_OP_READ_DATA_BLOCK_SIZE, rp->status);
907}
908
Johan Hedberg23bb5762010-12-21 23:01:27 +0200909static void hci_cc_write_ca_timeout(struct hci_dev *hdev, struct sk_buff *skb)
910{
911 __u8 status = *((__u8 *) skb->data);
912
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +0300913 BT_DBG("%s status 0x%2.2x", hdev->name, status);
Johan Hedberg23bb5762010-12-21 23:01:27 +0200914
915 hci_req_complete(hdev, HCI_OP_WRITE_CA_TIMEOUT, status);
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200916}
917
Andrei Emeltchenko928abaa2011-10-12 10:53:57 +0300918static void hci_cc_read_local_amp_info(struct hci_dev *hdev,
Gustavo Padovan807deac2012-05-17 00:36:24 -0300919 struct sk_buff *skb)
Andrei Emeltchenko928abaa2011-10-12 10:53:57 +0300920{
921 struct hci_rp_read_local_amp_info *rp = (void *) skb->data;
922
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +0300923 BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
Andrei Emeltchenko928abaa2011-10-12 10:53:57 +0300924
925 if (rp->status)
Andrei Emeltchenko8e2a0d92012-09-27 17:26:08 +0300926 goto a2mp_rsp;
Andrei Emeltchenko928abaa2011-10-12 10:53:57 +0300927
928 hdev->amp_status = rp->amp_status;
929 hdev->amp_total_bw = __le32_to_cpu(rp->total_bw);
930 hdev->amp_max_bw = __le32_to_cpu(rp->max_bw);
931 hdev->amp_min_latency = __le32_to_cpu(rp->min_latency);
932 hdev->amp_max_pdu = __le32_to_cpu(rp->max_pdu);
933 hdev->amp_type = rp->amp_type;
934 hdev->amp_pal_cap = __le16_to_cpu(rp->pal_cap);
935 hdev->amp_assoc_size = __le16_to_cpu(rp->max_assoc_size);
936 hdev->amp_be_flush_to = __le32_to_cpu(rp->be_flush_to);
937 hdev->amp_max_flush_to = __le32_to_cpu(rp->max_flush_to);
938
939 hci_req_complete(hdev, HCI_OP_READ_LOCAL_AMP_INFO, rp->status);
Andrei Emeltchenko8e2a0d92012-09-27 17:26:08 +0300940
941a2mp_rsp:
942 a2mp_send_getinfo_rsp(hdev);
Andrei Emeltchenko928abaa2011-10-12 10:53:57 +0300943}
944
Andrei Emeltchenko903e4542012-09-27 17:26:09 +0300945static void hci_cc_read_local_amp_assoc(struct hci_dev *hdev,
946 struct sk_buff *skb)
947{
948 struct hci_rp_read_local_amp_assoc *rp = (void *) skb->data;
949 struct amp_assoc *assoc = &hdev->loc_assoc;
950 size_t rem_len, frag_len;
951
952 BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
953
954 if (rp->status)
955 goto a2mp_rsp;
956
957 frag_len = skb->len - sizeof(*rp);
958 rem_len = __le16_to_cpu(rp->rem_len);
959
960 if (rem_len > frag_len) {
Andrei Emeltchenko2e430be32012-09-28 14:44:23 +0300961 BT_DBG("frag_len %zu rem_len %zu", frag_len, rem_len);
Andrei Emeltchenko903e4542012-09-27 17:26:09 +0300962
963 memcpy(assoc->data + assoc->offset, rp->frag, frag_len);
964 assoc->offset += frag_len;
965
966 /* Read other fragments */
967 amp_read_loc_assoc_frag(hdev, rp->phy_handle);
968
969 return;
970 }
971
972 memcpy(assoc->data + assoc->offset, rp->frag, rem_len);
973 assoc->len = assoc->offset + rem_len;
974 assoc->offset = 0;
975
976a2mp_rsp:
977 /* Send A2MP Rsp when all fragments are received */
978 a2mp_send_getampassoc_rsp(hdev, rp->status);
Andrei Emeltchenko9495b2e2012-09-27 17:26:22 +0300979 a2mp_send_create_phy_link_req(hdev, rp->status);
Andrei Emeltchenko903e4542012-09-27 17:26:09 +0300980}
981
Johan Hedbergb0916ea2011-01-10 13:44:55 +0200982static void hci_cc_delete_stored_link_key(struct hci_dev *hdev,
Gustavo Padovan807deac2012-05-17 00:36:24 -0300983 struct sk_buff *skb)
Johan Hedbergb0916ea2011-01-10 13:44:55 +0200984{
985 __u8 status = *((__u8 *) skb->data);
986
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +0300987 BT_DBG("%s status 0x%2.2x", hdev->name, status);
Johan Hedbergb0916ea2011-01-10 13:44:55 +0200988
989 hci_req_complete(hdev, HCI_OP_DELETE_STORED_LINK_KEY, status);
990}
991
Johan Hedbergd5859e22011-01-25 01:19:58 +0200992static void hci_cc_set_event_mask(struct hci_dev *hdev, struct sk_buff *skb)
993{
994 __u8 status = *((__u8 *) skb->data);
995
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +0300996 BT_DBG("%s status 0x%2.2x", hdev->name, status);
Johan Hedbergd5859e22011-01-25 01:19:58 +0200997
998 hci_req_complete(hdev, HCI_OP_SET_EVENT_MASK, status);
999}
1000
1001static void hci_cc_write_inquiry_mode(struct hci_dev *hdev,
Gustavo Padovan807deac2012-05-17 00:36:24 -03001002 struct sk_buff *skb)
Johan Hedbergd5859e22011-01-25 01:19:58 +02001003{
1004 __u8 status = *((__u8 *) skb->data);
1005
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +03001006 BT_DBG("%s status 0x%2.2x", hdev->name, status);
Johan Hedbergd5859e22011-01-25 01:19:58 +02001007
1008 hci_req_complete(hdev, HCI_OP_WRITE_INQUIRY_MODE, status);
1009}
1010
1011static void hci_cc_read_inq_rsp_tx_power(struct hci_dev *hdev,
Gustavo Padovan807deac2012-05-17 00:36:24 -03001012 struct sk_buff *skb)
Johan Hedbergd5859e22011-01-25 01:19:58 +02001013{
Marcel Holtmann91c4e9b2012-03-11 19:27:21 -07001014 struct hci_rp_read_inq_rsp_tx_power *rp = (void *) skb->data;
Johan Hedbergd5859e22011-01-25 01:19:58 +02001015
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +03001016 BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
Johan Hedbergd5859e22011-01-25 01:19:58 +02001017
Marcel Holtmann91c4e9b2012-03-11 19:27:21 -07001018 if (!rp->status)
1019 hdev->inq_tx_power = rp->tx_power;
1020
1021 hci_req_complete(hdev, HCI_OP_READ_INQ_RSP_TX_POWER, rp->status);
Johan Hedbergd5859e22011-01-25 01:19:58 +02001022}
1023
1024static void hci_cc_set_event_flt(struct hci_dev *hdev, struct sk_buff *skb)
1025{
1026 __u8 status = *((__u8 *) skb->data);
1027
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +03001028 BT_DBG("%s status 0x%2.2x", hdev->name, status);
Johan Hedbergd5859e22011-01-25 01:19:58 +02001029
1030 hci_req_complete(hdev, HCI_OP_SET_EVENT_FLT, status);
1031}
1032
Johan Hedberg980e1a52011-01-22 06:10:07 +02001033static void hci_cc_pin_code_reply(struct hci_dev *hdev, struct sk_buff *skb)
1034{
1035 struct hci_rp_pin_code_reply *rp = (void *) skb->data;
1036 struct hci_cp_pin_code_reply *cp;
1037 struct hci_conn *conn;
1038
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +03001039 BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
Johan Hedberg980e1a52011-01-22 06:10:07 +02001040
Johan Hedberg56e5cb82011-11-08 20:40:16 +02001041 hci_dev_lock(hdev);
1042
Johan Hedberga8b2d5c2012-01-08 23:11:15 +02001043 if (test_bit(HCI_MGMT, &hdev->dev_flags))
Johan Hedberg744cf192011-11-08 20:40:14 +02001044 mgmt_pin_code_reply_complete(hdev, &rp->bdaddr, rp->status);
Johan Hedberg980e1a52011-01-22 06:10:07 +02001045
Mikel Astizfa1bd912012-08-09 09:52:29 +02001046 if (rp->status)
Johan Hedberg56e5cb82011-11-08 20:40:16 +02001047 goto unlock;
Johan Hedberg980e1a52011-01-22 06:10:07 +02001048
1049 cp = hci_sent_cmd_data(hdev, HCI_OP_PIN_CODE_REPLY);
1050 if (!cp)
Johan Hedberg56e5cb82011-11-08 20:40:16 +02001051 goto unlock;
Johan Hedberg980e1a52011-01-22 06:10:07 +02001052
1053 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &cp->bdaddr);
1054 if (conn)
1055 conn->pin_length = cp->pin_len;
Johan Hedberg56e5cb82011-11-08 20:40:16 +02001056
1057unlock:
1058 hci_dev_unlock(hdev);
Johan Hedberg980e1a52011-01-22 06:10:07 +02001059}
1060
1061static void hci_cc_pin_code_neg_reply(struct hci_dev *hdev, struct sk_buff *skb)
1062{
1063 struct hci_rp_pin_code_neg_reply *rp = (void *) skb->data;
1064
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +03001065 BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
Johan Hedberg980e1a52011-01-22 06:10:07 +02001066
Johan Hedberg56e5cb82011-11-08 20:40:16 +02001067 hci_dev_lock(hdev);
1068
Johan Hedberga8b2d5c2012-01-08 23:11:15 +02001069 if (test_bit(HCI_MGMT, &hdev->dev_flags))
Johan Hedberg744cf192011-11-08 20:40:14 +02001070 mgmt_pin_code_neg_reply_complete(hdev, &rp->bdaddr,
Gustavo Padovan807deac2012-05-17 00:36:24 -03001071 rp->status);
Johan Hedberg56e5cb82011-11-08 20:40:16 +02001072
1073 hci_dev_unlock(hdev);
Johan Hedberg980e1a52011-01-22 06:10:07 +02001074}
Johan Hedberg56e5cb82011-11-08 20:40:16 +02001075
Ville Tervo6ed58ec2011-02-10 22:38:48 -03001076static void hci_cc_le_read_buffer_size(struct hci_dev *hdev,
1077 struct sk_buff *skb)
1078{
1079 struct hci_rp_le_read_buffer_size *rp = (void *) skb->data;
1080
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +03001081 BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
Ville Tervo6ed58ec2011-02-10 22:38:48 -03001082
1083 if (rp->status)
1084 return;
1085
1086 hdev->le_mtu = __le16_to_cpu(rp->le_mtu);
1087 hdev->le_pkts = rp->le_max_pkt;
1088
1089 hdev->le_cnt = hdev->le_pkts;
1090
1091 BT_DBG("%s le mtu %d:%d", hdev->name, hdev->le_mtu, hdev->le_pkts);
1092
1093 hci_req_complete(hdev, HCI_OP_LE_READ_BUFFER_SIZE, rp->status);
1094}
Johan Hedberg980e1a52011-01-22 06:10:07 +02001095
Johan Hedberg60e77322013-01-22 14:01:59 +02001096static void hci_cc_le_read_local_features(struct hci_dev *hdev,
1097 struct sk_buff *skb)
1098{
1099 struct hci_rp_le_read_local_features *rp = (void *) skb->data;
1100
1101 BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
1102
1103 if (!rp->status)
1104 memcpy(hdev->le_features, rp->features, 8);
1105
1106 hci_req_complete(hdev, HCI_OP_LE_READ_LOCAL_FEATURES, rp->status);
1107}
1108
Johan Hedberg8fa19092012-10-19 20:57:49 +03001109static void hci_cc_le_read_adv_tx_power(struct hci_dev *hdev,
1110 struct sk_buff *skb)
1111{
1112 struct hci_rp_le_read_adv_tx_power *rp = (void *) skb->data;
1113
1114 BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
1115
Johan Hedberg3f0f5242012-11-08 01:23:00 +01001116 if (!rp->status) {
Johan Hedberg8fa19092012-10-19 20:57:49 +03001117 hdev->adv_tx_power = rp->tx_power;
Johan Hedberg3f0f5242012-11-08 01:23:00 +01001118 if (!test_bit(HCI_INIT, &hdev->flags))
1119 hci_update_ad(hdev);
1120 }
Johan Hedberg8fa19092012-10-19 20:57:49 +03001121
1122 hci_req_complete(hdev, HCI_OP_LE_READ_ADV_TX_POWER, rp->status);
1123}
1124
Johan Hedberge36b04c2012-10-19 20:57:47 +03001125static void hci_cc_le_set_event_mask(struct hci_dev *hdev, struct sk_buff *skb)
1126{
1127 __u8 status = *((__u8 *) skb->data);
1128
1129 BT_DBG("%s status 0x%2.2x", hdev->name, status);
1130
1131 hci_req_complete(hdev, HCI_OP_LE_SET_EVENT_MASK, status);
1132}
1133
Johan Hedberga5c29682011-02-19 12:05:57 -03001134static void hci_cc_user_confirm_reply(struct hci_dev *hdev, struct sk_buff *skb)
1135{
1136 struct hci_rp_user_confirm_reply *rp = (void *) skb->data;
1137
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +03001138 BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
Johan Hedberga5c29682011-02-19 12:05:57 -03001139
Johan Hedberg56e5cb82011-11-08 20:40:16 +02001140 hci_dev_lock(hdev);
1141
Johan Hedberga8b2d5c2012-01-08 23:11:15 +02001142 if (test_bit(HCI_MGMT, &hdev->dev_flags))
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001143 mgmt_user_confirm_reply_complete(hdev, &rp->bdaddr, ACL_LINK, 0,
1144 rp->status);
Johan Hedberg56e5cb82011-11-08 20:40:16 +02001145
1146 hci_dev_unlock(hdev);
Johan Hedberga5c29682011-02-19 12:05:57 -03001147}
1148
1149static void hci_cc_user_confirm_neg_reply(struct hci_dev *hdev,
Gustavo Padovan807deac2012-05-17 00:36:24 -03001150 struct sk_buff *skb)
Johan Hedberga5c29682011-02-19 12:05:57 -03001151{
1152 struct hci_rp_user_confirm_reply *rp = (void *) skb->data;
1153
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +03001154 BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
Johan Hedberga5c29682011-02-19 12:05:57 -03001155
Johan Hedberg56e5cb82011-11-08 20:40:16 +02001156 hci_dev_lock(hdev);
1157
Johan Hedberga8b2d5c2012-01-08 23:11:15 +02001158 if (test_bit(HCI_MGMT, &hdev->dev_flags))
Johan Hedberg744cf192011-11-08 20:40:14 +02001159 mgmt_user_confirm_neg_reply_complete(hdev, &rp->bdaddr,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001160 ACL_LINK, 0, rp->status);
Johan Hedberg56e5cb82011-11-08 20:40:16 +02001161
1162 hci_dev_unlock(hdev);
Johan Hedberga5c29682011-02-19 12:05:57 -03001163}
1164
Brian Gix1143d452011-11-23 08:28:34 -08001165static void hci_cc_user_passkey_reply(struct hci_dev *hdev, struct sk_buff *skb)
1166{
1167 struct hci_rp_user_confirm_reply *rp = (void *) skb->data;
1168
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +03001169 BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
Brian Gix1143d452011-11-23 08:28:34 -08001170
1171 hci_dev_lock(hdev);
1172
Johan Hedberga8b2d5c2012-01-08 23:11:15 +02001173 if (test_bit(HCI_MGMT, &hdev->dev_flags))
Johan Hedberg272d90d2012-02-09 15:26:12 +02001174 mgmt_user_passkey_reply_complete(hdev, &rp->bdaddr, ACL_LINK,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001175 0, rp->status);
Brian Gix1143d452011-11-23 08:28:34 -08001176
1177 hci_dev_unlock(hdev);
1178}
1179
1180static void hci_cc_user_passkey_neg_reply(struct hci_dev *hdev,
Gustavo Padovan807deac2012-05-17 00:36:24 -03001181 struct sk_buff *skb)
Brian Gix1143d452011-11-23 08:28:34 -08001182{
1183 struct hci_rp_user_confirm_reply *rp = (void *) skb->data;
1184
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +03001185 BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
Brian Gix1143d452011-11-23 08:28:34 -08001186
1187 hci_dev_lock(hdev);
1188
Johan Hedberga8b2d5c2012-01-08 23:11:15 +02001189 if (test_bit(HCI_MGMT, &hdev->dev_flags))
Brian Gix1143d452011-11-23 08:28:34 -08001190 mgmt_user_passkey_neg_reply_complete(hdev, &rp->bdaddr,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001191 ACL_LINK, 0, rp->status);
Brian Gix1143d452011-11-23 08:28:34 -08001192
1193 hci_dev_unlock(hdev);
1194}
1195
Szymon Jancc35938b2011-03-22 13:12:21 +01001196static void hci_cc_read_local_oob_data_reply(struct hci_dev *hdev,
Gustavo Padovan807deac2012-05-17 00:36:24 -03001197 struct sk_buff *skb)
Szymon Jancc35938b2011-03-22 13:12:21 +01001198{
1199 struct hci_rp_read_local_oob_data *rp = (void *) skb->data;
1200
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +03001201 BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
Szymon Jancc35938b2011-03-22 13:12:21 +01001202
Johan Hedberg56e5cb82011-11-08 20:40:16 +02001203 hci_dev_lock(hdev);
Johan Hedberg744cf192011-11-08 20:40:14 +02001204 mgmt_read_local_oob_data_reply_complete(hdev, rp->hash,
Szymon Jancc35938b2011-03-22 13:12:21 +01001205 rp->randomizer, rp->status);
Johan Hedberg56e5cb82011-11-08 20:40:16 +02001206 hci_dev_unlock(hdev);
Szymon Jancc35938b2011-03-22 13:12:21 +01001207}
1208
Johan Hedbergc1d5dc42012-11-08 01:23:01 +01001209static void hci_cc_le_set_adv_enable(struct hci_dev *hdev, struct sk_buff *skb)
1210{
1211 __u8 *sent, status = *((__u8 *) skb->data);
1212
1213 BT_DBG("%s status 0x%2.2x", hdev->name, status);
1214
1215 sent = hci_sent_cmd_data(hdev, HCI_OP_LE_SET_ADV_ENABLE);
1216 if (!sent)
1217 return;
1218
1219 hci_dev_lock(hdev);
1220
1221 if (!status) {
1222 if (*sent)
1223 set_bit(HCI_LE_PERIPHERAL, &hdev->dev_flags);
1224 else
1225 clear_bit(HCI_LE_PERIPHERAL, &hdev->dev_flags);
1226 }
1227
1228 hci_dev_unlock(hdev);
1229
1230 if (!test_bit(HCI_INIT, &hdev->flags))
1231 hci_update_ad(hdev);
1232
1233 hci_req_complete(hdev, HCI_OP_LE_SET_ADV_ENABLE, status);
1234}
1235
Andre Guedes07f7fa52011-12-02 21:13:31 +09001236static void hci_cc_le_set_scan_param(struct hci_dev *hdev, struct sk_buff *skb)
1237{
1238 __u8 status = *((__u8 *) skb->data);
1239
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +03001240 BT_DBG("%s status 0x%2.2x", hdev->name, status);
Andre Guedes7ba8b4b2012-02-03 17:47:59 -03001241
1242 hci_req_complete(hdev, HCI_OP_LE_SET_SCAN_PARAM, status);
Andre Guedes3fd24152012-02-03 17:48:01 -03001243
1244 if (status) {
1245 hci_dev_lock(hdev);
1246 mgmt_start_discovery_failed(hdev, status);
1247 hci_dev_unlock(hdev);
1248 return;
1249 }
Andre Guedes07f7fa52011-12-02 21:13:31 +09001250}
1251
Andre Guedeseb9d91f2011-05-26 16:23:52 -03001252static void hci_cc_le_set_scan_enable(struct hci_dev *hdev,
Gustavo Padovan807deac2012-05-17 00:36:24 -03001253 struct sk_buff *skb)
Andre Guedeseb9d91f2011-05-26 16:23:52 -03001254{
1255 struct hci_cp_le_set_scan_enable *cp;
1256 __u8 status = *((__u8 *) skb->data);
1257
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +03001258 BT_DBG("%s status 0x%2.2x", hdev->name, status);
Andre Guedeseb9d91f2011-05-26 16:23:52 -03001259
Andre Guedeseb9d91f2011-05-26 16:23:52 -03001260 cp = hci_sent_cmd_data(hdev, HCI_OP_LE_SET_SCAN_ENABLE);
1261 if (!cp)
1262 return;
1263
Andrei Emeltchenko68a8aea2011-12-19 16:14:18 +02001264 switch (cp->enable) {
1265 case LE_SCANNING_ENABLED:
Andre Guedes7ba8b4b2012-02-03 17:47:59 -03001266 hci_req_complete(hdev, HCI_OP_LE_SET_SCAN_ENABLE, status);
1267
Andre Guedes3fd24152012-02-03 17:48:01 -03001268 if (status) {
1269 hci_dev_lock(hdev);
1270 mgmt_start_discovery_failed(hdev, status);
1271 hci_dev_unlock(hdev);
Andre Guedes7ba8b4b2012-02-03 17:47:59 -03001272 return;
Andre Guedes3fd24152012-02-03 17:48:01 -03001273 }
Andre Guedes7ba8b4b2012-02-03 17:47:59 -03001274
Andre Guedesd23264a2011-11-25 20:53:38 -03001275 set_bit(HCI_LE_SCAN, &hdev->dev_flags);
1276
Andre Guedesa8f13c82011-09-09 18:56:24 -03001277 hci_dev_lock(hdev);
Andre Guedes343f9352012-02-17 20:39:37 -03001278 hci_discovery_set_state(hdev, DISCOVERY_FINDING);
Andre Guedesa8f13c82011-09-09 18:56:24 -03001279 hci_dev_unlock(hdev);
Andrei Emeltchenko68a8aea2011-12-19 16:14:18 +02001280 break;
1281
1282 case LE_SCANNING_DISABLED:
Andre Guedesc9ecc482012-03-15 16:52:08 -03001283 if (status) {
1284 hci_dev_lock(hdev);
1285 mgmt_stop_discovery_failed(hdev, status);
1286 hci_dev_unlock(hdev);
Andre Guedes7ba8b4b2012-02-03 17:47:59 -03001287 return;
Andre Guedesc9ecc482012-03-15 16:52:08 -03001288 }
Andre Guedes7ba8b4b2012-02-03 17:47:59 -03001289
Andre Guedesd23264a2011-11-25 20:53:38 -03001290 clear_bit(HCI_LE_SCAN, &hdev->dev_flags);
1291
Andre Guedesbc3dd332012-03-06 19:37:06 -03001292 if (hdev->discovery.type == DISCOV_TYPE_INTERLEAVED &&
1293 hdev->discovery.state == DISCOVERY_FINDING) {
Andre Guedes5e0452c2012-02-17 20:39:38 -03001294 mgmt_interleaved_discovery(hdev);
1295 } else {
1296 hci_dev_lock(hdev);
1297 hci_discovery_set_state(hdev, DISCOVERY_STOPPED);
1298 hci_dev_unlock(hdev);
1299 }
1300
Andrei Emeltchenko68a8aea2011-12-19 16:14:18 +02001301 break;
1302
1303 default:
1304 BT_ERR("Used reserved LE_Scan_Enable param %d", cp->enable);
1305 break;
Andre Guedes35815082011-05-26 16:23:53 -03001306 }
Andre Guedeseb9d91f2011-05-26 16:23:52 -03001307}
1308
Vinicius Costa Gomesa7a595f2011-06-09 18:50:47 -03001309static void hci_cc_le_ltk_reply(struct hci_dev *hdev, struct sk_buff *skb)
1310{
1311 struct hci_rp_le_ltk_reply *rp = (void *) skb->data;
1312
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +03001313 BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
Vinicius Costa Gomesa7a595f2011-06-09 18:50:47 -03001314
1315 if (rp->status)
1316 return;
1317
1318 hci_req_complete(hdev, HCI_OP_LE_LTK_REPLY, rp->status);
1319}
1320
1321static void hci_cc_le_ltk_neg_reply(struct hci_dev *hdev, struct sk_buff *skb)
1322{
1323 struct hci_rp_le_ltk_neg_reply *rp = (void *) skb->data;
1324
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +03001325 BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
Vinicius Costa Gomesa7a595f2011-06-09 18:50:47 -03001326
1327 if (rp->status)
1328 return;
1329
1330 hci_req_complete(hdev, HCI_OP_LE_LTK_NEG_REPLY, rp->status);
1331}
1332
Gustavo Padovan6039aa72012-05-23 04:04:18 -03001333static void hci_cc_write_le_host_supported(struct hci_dev *hdev,
1334 struct sk_buff *skb)
Andre Guedesf9b49302011-06-30 19:20:53 -03001335{
Johan Hedberg06199cf2012-02-22 16:37:11 +02001336 struct hci_cp_write_le_host_supported *sent;
Andre Guedesf9b49302011-06-30 19:20:53 -03001337 __u8 status = *((__u8 *) skb->data);
1338
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +03001339 BT_DBG("%s status 0x%2.2x", hdev->name, status);
Andre Guedesf9b49302011-06-30 19:20:53 -03001340
Johan Hedberg06199cf2012-02-22 16:37:11 +02001341 sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_LE_HOST_SUPPORTED);
Johan Hedberg8f984df2012-02-28 01:07:22 +02001342 if (!sent)
Andre Guedesf9b49302011-06-30 19:20:53 -03001343 return;
1344
Johan Hedberg8f984df2012-02-28 01:07:22 +02001345 if (!status) {
1346 if (sent->le)
1347 hdev->host_features[0] |= LMP_HOST_LE;
1348 else
1349 hdev->host_features[0] &= ~LMP_HOST_LE;
Johan Hedberg53b2caa2012-10-24 21:11:59 +03001350
1351 if (sent->simul)
1352 hdev->host_features[0] |= LMP_HOST_LE_BREDR;
1353 else
1354 hdev->host_features[0] &= ~LMP_HOST_LE_BREDR;
Johan Hedberg8f984df2012-02-28 01:07:22 +02001355 }
1356
1357 if (test_bit(HCI_MGMT, &hdev->dev_flags) &&
Gustavo Padovan807deac2012-05-17 00:36:24 -03001358 !test_bit(HCI_INIT, &hdev->flags))
Johan Hedberg8f984df2012-02-28 01:07:22 +02001359 mgmt_le_enable_complete(hdev, sent->le, status);
1360
1361 hci_req_complete(hdev, HCI_OP_WRITE_LE_HOST_SUPPORTED, status);
Andre Guedesf9b49302011-06-30 19:20:53 -03001362}
1363
Andrei Emeltchenko93c284e2012-09-27 17:26:20 +03001364static void hci_cc_write_remote_amp_assoc(struct hci_dev *hdev,
1365 struct sk_buff *skb)
1366{
1367 struct hci_rp_write_remote_amp_assoc *rp = (void *) skb->data;
1368
1369 BT_DBG("%s status 0x%2.2x phy_handle 0x%2.2x",
1370 hdev->name, rp->status, rp->phy_handle);
1371
1372 if (rp->status)
1373 return;
1374
1375 amp_write_rem_assoc_continue(hdev, rp->phy_handle);
1376}
1377
Gustavo Padovan6039aa72012-05-23 04:04:18 -03001378static void hci_cs_inquiry(struct hci_dev *hdev, __u8 status)
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001379{
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +03001380 BT_DBG("%s status 0x%2.2x", hdev->name, status);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001381
1382 if (status) {
Johan Hedberg23bb5762010-12-21 23:01:27 +02001383 hci_req_complete(hdev, HCI_OP_INQUIRY, status);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001384 hci_conn_check_pending(hdev);
Johan Hedberg56e5cb82011-11-08 20:40:16 +02001385 hci_dev_lock(hdev);
Johan Hedberga8b2d5c2012-01-08 23:11:15 +02001386 if (test_bit(HCI_MGMT, &hdev->dev_flags))
Andre Guedes7a135102011-11-09 17:14:25 -03001387 mgmt_start_discovery_failed(hdev, status);
Johan Hedberg56e5cb82011-11-08 20:40:16 +02001388 hci_dev_unlock(hdev);
Johan Hedberg314b2382011-04-27 10:29:57 -04001389 return;
1390 }
1391
Andre Guedes89352e72011-11-04 14:16:53 -03001392 set_bit(HCI_INQUIRY, &hdev->flags);
1393
Johan Hedberg56e5cb82011-11-08 20:40:16 +02001394 hci_dev_lock(hdev);
Andre Guedes343f9352012-02-17 20:39:37 -03001395 hci_discovery_set_state(hdev, DISCOVERY_FINDING);
Johan Hedberg56e5cb82011-11-08 20:40:16 +02001396 hci_dev_unlock(hdev);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001397}
1398
Gustavo Padovan6039aa72012-05-23 04:04:18 -03001399static void hci_cs_create_conn(struct hci_dev *hdev, __u8 status)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001400{
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001401 struct hci_cp_create_conn *cp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001402 struct hci_conn *conn;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001403
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +03001404 BT_DBG("%s status 0x%2.2x", hdev->name, status);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001405
1406 cp = hci_sent_cmd_data(hdev, HCI_OP_CREATE_CONN);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001407 if (!cp)
1408 return;
1409
1410 hci_dev_lock(hdev);
1411
1412 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &cp->bdaddr);
1413
Andrei Emeltchenko6ed93dc2012-09-25 12:49:43 +03001414 BT_DBG("%s bdaddr %pMR hcon %p", hdev->name, &cp->bdaddr, conn);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001415
1416 if (status) {
1417 if (conn && conn->state == BT_CONNECT) {
Marcel Holtmann4c67bc72006-10-15 17:30:56 +02001418 if (status != 0x0c || conn->attempt > 2) {
1419 conn->state = BT_CLOSED;
1420 hci_proto_connect_cfm(conn, status);
1421 hci_conn_del(conn);
1422 } else
1423 conn->state = BT_CONNECT2;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001424 }
1425 } else {
1426 if (!conn) {
1427 conn = hci_conn_add(hdev, ACL_LINK, &cp->bdaddr);
1428 if (conn) {
Johan Hedberga0c808b2012-01-16 09:49:58 +02001429 conn->out = true;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001430 conn->link_mode |= HCI_LM_MASTER;
1431 } else
Gustavo F. Padovan893ef972010-07-18 15:13:37 -03001432 BT_ERR("No memory for new connection");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001433 }
1434 }
1435
1436 hci_dev_unlock(hdev);
1437}
1438
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001439static void hci_cs_add_sco(struct hci_dev *hdev, __u8 status)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001440{
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001441 struct hci_cp_add_sco *cp;
1442 struct hci_conn *acl, *sco;
1443 __u16 handle;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001444
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +03001445 BT_DBG("%s status 0x%2.2x", hdev->name, status);
Marcel Holtmannb6a0dc82007-10-20 14:55:10 +02001446
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001447 if (!status)
1448 return;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001449
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001450 cp = hci_sent_cmd_data(hdev, HCI_OP_ADD_SCO);
1451 if (!cp)
1452 return;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001453
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001454 handle = __le16_to_cpu(cp->handle);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001455
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +03001456 BT_DBG("%s handle 0x%4.4x", hdev->name, handle);
Marcel Holtmann6bd57412006-11-18 22:14:22 +01001457
1458 hci_dev_lock(hdev);
1459
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001460 acl = hci_conn_hash_lookup_handle(hdev, handle);
Andrei Emeltchenko5a08ecc2011-01-11 17:20:20 +02001461 if (acl) {
1462 sco = acl->link;
1463 if (sco) {
1464 sco->state = BT_CLOSED;
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001465
Andrei Emeltchenko5a08ecc2011-01-11 17:20:20 +02001466 hci_proto_connect_cfm(sco, status);
1467 hci_conn_del(sco);
1468 }
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001469 }
Marcel Holtmann6bd57412006-11-18 22:14:22 +01001470
1471 hci_dev_unlock(hdev);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001472}
1473
Marcel Holtmannf8558552008-07-14 20:13:49 +02001474static void hci_cs_auth_requested(struct hci_dev *hdev, __u8 status)
1475{
1476 struct hci_cp_auth_requested *cp;
1477 struct hci_conn *conn;
1478
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +03001479 BT_DBG("%s status 0x%2.2x", hdev->name, status);
Marcel Holtmannf8558552008-07-14 20:13:49 +02001480
1481 if (!status)
1482 return;
1483
1484 cp = hci_sent_cmd_data(hdev, HCI_OP_AUTH_REQUESTED);
1485 if (!cp)
1486 return;
1487
1488 hci_dev_lock(hdev);
1489
1490 conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(cp->handle));
1491 if (conn) {
1492 if (conn->state == BT_CONFIG) {
1493 hci_proto_connect_cfm(conn, status);
1494 hci_conn_put(conn);
1495 }
1496 }
1497
1498 hci_dev_unlock(hdev);
1499}
1500
1501static void hci_cs_set_conn_encrypt(struct hci_dev *hdev, __u8 status)
1502{
1503 struct hci_cp_set_conn_encrypt *cp;
1504 struct hci_conn *conn;
1505
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +03001506 BT_DBG("%s status 0x%2.2x", hdev->name, status);
Marcel Holtmannf8558552008-07-14 20:13:49 +02001507
1508 if (!status)
1509 return;
1510
1511 cp = hci_sent_cmd_data(hdev, HCI_OP_SET_CONN_ENCRYPT);
1512 if (!cp)
1513 return;
1514
1515 hci_dev_lock(hdev);
1516
1517 conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(cp->handle));
1518 if (conn) {
1519 if (conn->state == BT_CONFIG) {
1520 hci_proto_connect_cfm(conn, status);
1521 hci_conn_put(conn);
1522 }
1523 }
1524
1525 hci_dev_unlock(hdev);
1526}
1527
Johan Hedberg127178d2010-11-18 22:22:29 +02001528static int hci_outgoing_auth_needed(struct hci_dev *hdev,
Gustavo Padovan807deac2012-05-17 00:36:24 -03001529 struct hci_conn *conn)
Johan Hedberg392599b2010-11-18 22:22:28 +02001530{
Johan Hedberg392599b2010-11-18 22:22:28 +02001531 if (conn->state != BT_CONFIG || !conn->out)
1532 return 0;
1533
Johan Hedberg765c2a92011-01-19 12:06:52 +05301534 if (conn->pending_sec_level == BT_SECURITY_SDP)
Johan Hedberg392599b2010-11-18 22:22:28 +02001535 return 0;
1536
1537 /* Only request authentication for SSP connections or non-SSP
Vinicius Costa Gomese9bf2bf2011-09-02 14:51:20 -03001538 * devices with sec_level HIGH or if MITM protection is requested */
Gustavo Padovan807deac2012-05-17 00:36:24 -03001539 if (!hci_conn_ssp_enabled(conn) && !(conn->auth_type & 0x01) &&
1540 conn->pending_sec_level != BT_SECURITY_HIGH)
Johan Hedberg392599b2010-11-18 22:22:28 +02001541 return 0;
1542
Johan Hedberg392599b2010-11-18 22:22:28 +02001543 return 1;
1544}
1545
Gustavo Padovan6039aa72012-05-23 04:04:18 -03001546static int hci_resolve_name(struct hci_dev *hdev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001547 struct inquiry_entry *e)
Johan Hedberg30dc78e2012-01-04 15:44:20 +02001548{
1549 struct hci_cp_remote_name_req cp;
1550
1551 memset(&cp, 0, sizeof(cp));
1552
1553 bacpy(&cp.bdaddr, &e->data.bdaddr);
1554 cp.pscan_rep_mode = e->data.pscan_rep_mode;
1555 cp.pscan_mode = e->data.pscan_mode;
1556 cp.clock_offset = e->data.clock_offset;
1557
1558 return hci_send_cmd(hdev, HCI_OP_REMOTE_NAME_REQ, sizeof(cp), &cp);
1559}
1560
Johan Hedbergb644ba32012-01-17 21:48:47 +02001561static bool hci_resolve_next_name(struct hci_dev *hdev)
Johan Hedberg30dc78e2012-01-04 15:44:20 +02001562{
1563 struct discovery_state *discov = &hdev->discovery;
1564 struct inquiry_entry *e;
1565
Johan Hedbergb644ba32012-01-17 21:48:47 +02001566 if (list_empty(&discov->resolve))
1567 return false;
1568
1569 e = hci_inquiry_cache_lookup_resolve(hdev, BDADDR_ANY, NAME_NEEDED);
Ram Malovanyc8100892012-07-19 10:26:09 +03001570 if (!e)
1571 return false;
1572
Johan Hedbergb644ba32012-01-17 21:48:47 +02001573 if (hci_resolve_name(hdev, e) == 0) {
1574 e->name_state = NAME_PENDING;
1575 return true;
1576 }
1577
1578 return false;
1579}
1580
1581static void hci_check_pending_name(struct hci_dev *hdev, struct hci_conn *conn,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001582 bdaddr_t *bdaddr, u8 *name, u8 name_len)
Johan Hedbergb644ba32012-01-17 21:48:47 +02001583{
1584 struct discovery_state *discov = &hdev->discovery;
1585 struct inquiry_entry *e;
1586
1587 if (conn && !test_and_set_bit(HCI_CONN_MGMT_CONNECTED, &conn->flags))
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001588 mgmt_device_connected(hdev, bdaddr, ACL_LINK, 0x00, 0, name,
1589 name_len, conn->dev_class);
Johan Hedbergb644ba32012-01-17 21:48:47 +02001590
1591 if (discov->state == DISCOVERY_STOPPED)
1592 return;
1593
Johan Hedberg30dc78e2012-01-04 15:44:20 +02001594 if (discov->state == DISCOVERY_STOPPING)
1595 goto discov_complete;
1596
1597 if (discov->state != DISCOVERY_RESOLVING)
1598 return;
1599
1600 e = hci_inquiry_cache_lookup_resolve(hdev, bdaddr, NAME_PENDING);
Ram Malovany7cc83802012-07-19 10:26:10 +03001601 /* If the device was not found in a list of found devices names of which
1602 * are pending. there is no need to continue resolving a next name as it
1603 * will be done upon receiving another Remote Name Request Complete
1604 * Event */
1605 if (!e)
1606 return;
1607
1608 list_del(&e->list);
1609 if (name) {
Johan Hedberg30dc78e2012-01-04 15:44:20 +02001610 e->name_state = NAME_KNOWN;
Ram Malovany7cc83802012-07-19 10:26:10 +03001611 mgmt_remote_name(hdev, bdaddr, ACL_LINK, 0x00,
1612 e->data.rssi, name, name_len);
Ram Malovanyc3e7c0d2012-07-19 10:26:11 +03001613 } else {
1614 e->name_state = NAME_NOT_KNOWN;
Johan Hedberg30dc78e2012-01-04 15:44:20 +02001615 }
1616
Johan Hedbergb644ba32012-01-17 21:48:47 +02001617 if (hci_resolve_next_name(hdev))
Johan Hedberg30dc78e2012-01-04 15:44:20 +02001618 return;
Johan Hedberg30dc78e2012-01-04 15:44:20 +02001619
1620discov_complete:
1621 hci_discovery_set_state(hdev, DISCOVERY_STOPPED);
1622}
1623
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001624static void hci_cs_remote_name_req(struct hci_dev *hdev, __u8 status)
1625{
Johan Hedberg127178d2010-11-18 22:22:29 +02001626 struct hci_cp_remote_name_req *cp;
1627 struct hci_conn *conn;
1628
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +03001629 BT_DBG("%s status 0x%2.2x", hdev->name, status);
Johan Hedberg127178d2010-11-18 22:22:29 +02001630
1631 /* If successful wait for the name req complete event before
1632 * checking for the need to do authentication */
1633 if (!status)
1634 return;
1635
1636 cp = hci_sent_cmd_data(hdev, HCI_OP_REMOTE_NAME_REQ);
1637 if (!cp)
1638 return;
1639
1640 hci_dev_lock(hdev);
1641
1642 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &cp->bdaddr);
Johan Hedbergb644ba32012-01-17 21:48:47 +02001643
1644 if (test_bit(HCI_MGMT, &hdev->dev_flags))
1645 hci_check_pending_name(hdev, conn, &cp->bdaddr, NULL, 0);
1646
Johan Hedberg79c6c702011-04-28 11:28:55 -07001647 if (!conn)
1648 goto unlock;
1649
1650 if (!hci_outgoing_auth_needed(hdev, conn))
1651 goto unlock;
1652
Johan Hedberg51a8efd2012-01-16 06:10:31 +02001653 if (!test_and_set_bit(HCI_CONN_AUTH_PEND, &conn->flags)) {
Johan Hedberg127178d2010-11-18 22:22:29 +02001654 struct hci_cp_auth_requested cp;
1655 cp.handle = __cpu_to_le16(conn->handle);
1656 hci_send_cmd(hdev, HCI_OP_AUTH_REQUESTED, sizeof(cp), &cp);
1657 }
1658
Johan Hedberg79c6c702011-04-28 11:28:55 -07001659unlock:
Johan Hedberg127178d2010-11-18 22:22:29 +02001660 hci_dev_unlock(hdev);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001661}
1662
Marcel Holtmann769be972008-07-14 20:13:49 +02001663static void hci_cs_read_remote_features(struct hci_dev *hdev, __u8 status)
1664{
1665 struct hci_cp_read_remote_features *cp;
1666 struct hci_conn *conn;
1667
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +03001668 BT_DBG("%s status 0x%2.2x", hdev->name, status);
Marcel Holtmann769be972008-07-14 20:13:49 +02001669
1670 if (!status)
1671 return;
1672
1673 cp = hci_sent_cmd_data(hdev, HCI_OP_READ_REMOTE_FEATURES);
1674 if (!cp)
1675 return;
1676
1677 hci_dev_lock(hdev);
1678
1679 conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(cp->handle));
1680 if (conn) {
1681 if (conn->state == BT_CONFIG) {
Marcel Holtmann769be972008-07-14 20:13:49 +02001682 hci_proto_connect_cfm(conn, status);
1683 hci_conn_put(conn);
1684 }
1685 }
1686
1687 hci_dev_unlock(hdev);
1688}
1689
1690static void hci_cs_read_remote_ext_features(struct hci_dev *hdev, __u8 status)
1691{
1692 struct hci_cp_read_remote_ext_features *cp;
1693 struct hci_conn *conn;
1694
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +03001695 BT_DBG("%s status 0x%2.2x", hdev->name, status);
Marcel Holtmann769be972008-07-14 20:13:49 +02001696
1697 if (!status)
1698 return;
1699
1700 cp = hci_sent_cmd_data(hdev, HCI_OP_READ_REMOTE_EXT_FEATURES);
1701 if (!cp)
1702 return;
1703
1704 hci_dev_lock(hdev);
1705
1706 conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(cp->handle));
1707 if (conn) {
1708 if (conn->state == BT_CONFIG) {
Marcel Holtmann769be972008-07-14 20:13:49 +02001709 hci_proto_connect_cfm(conn, status);
1710 hci_conn_put(conn);
1711 }
1712 }
1713
1714 hci_dev_unlock(hdev);
1715}
1716
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001717static void hci_cs_setup_sync_conn(struct hci_dev *hdev, __u8 status)
1718{
Marcel Holtmannb6a0dc82007-10-20 14:55:10 +02001719 struct hci_cp_setup_sync_conn *cp;
1720 struct hci_conn *acl, *sco;
1721 __u16 handle;
1722
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +03001723 BT_DBG("%s status 0x%2.2x", hdev->name, status);
Marcel Holtmannb6a0dc82007-10-20 14:55:10 +02001724
1725 if (!status)
1726 return;
1727
1728 cp = hci_sent_cmd_data(hdev, HCI_OP_SETUP_SYNC_CONN);
1729 if (!cp)
1730 return;
1731
1732 handle = __le16_to_cpu(cp->handle);
1733
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +03001734 BT_DBG("%s handle 0x%4.4x", hdev->name, handle);
Marcel Holtmannb6a0dc82007-10-20 14:55:10 +02001735
1736 hci_dev_lock(hdev);
1737
1738 acl = hci_conn_hash_lookup_handle(hdev, handle);
Andrei Emeltchenko5a08ecc2011-01-11 17:20:20 +02001739 if (acl) {
1740 sco = acl->link;
1741 if (sco) {
1742 sco->state = BT_CLOSED;
Marcel Holtmannb6a0dc82007-10-20 14:55:10 +02001743
Andrei Emeltchenko5a08ecc2011-01-11 17:20:20 +02001744 hci_proto_connect_cfm(sco, status);
1745 hci_conn_del(sco);
1746 }
Marcel Holtmannb6a0dc82007-10-20 14:55:10 +02001747 }
1748
1749 hci_dev_unlock(hdev);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001750}
1751
1752static void hci_cs_sniff_mode(struct hci_dev *hdev, __u8 status)
1753{
1754 struct hci_cp_sniff_mode *cp;
1755 struct hci_conn *conn;
1756
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +03001757 BT_DBG("%s status 0x%2.2x", hdev->name, status);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001758
1759 if (!status)
1760 return;
1761
1762 cp = hci_sent_cmd_data(hdev, HCI_OP_SNIFF_MODE);
1763 if (!cp)
1764 return;
1765
1766 hci_dev_lock(hdev);
1767
1768 conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(cp->handle));
Marcel Holtmanne73439d2010-07-26 10:06:00 -04001769 if (conn) {
Johan Hedberg51a8efd2012-01-16 06:10:31 +02001770 clear_bit(HCI_CONN_MODE_CHANGE_PEND, &conn->flags);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001771
Johan Hedberg51a8efd2012-01-16 06:10:31 +02001772 if (test_and_clear_bit(HCI_CONN_SCO_SETUP_PEND, &conn->flags))
Marcel Holtmanne73439d2010-07-26 10:06:00 -04001773 hci_sco_setup(conn, status);
1774 }
1775
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001776 hci_dev_unlock(hdev);
1777}
1778
1779static void hci_cs_exit_sniff_mode(struct hci_dev *hdev, __u8 status)
1780{
1781 struct hci_cp_exit_sniff_mode *cp;
1782 struct hci_conn *conn;
1783
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +03001784 BT_DBG("%s status 0x%2.2x", hdev->name, status);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001785
1786 if (!status)
1787 return;
1788
1789 cp = hci_sent_cmd_data(hdev, HCI_OP_EXIT_SNIFF_MODE);
1790 if (!cp)
1791 return;
1792
1793 hci_dev_lock(hdev);
1794
1795 conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(cp->handle));
Marcel Holtmanne73439d2010-07-26 10:06:00 -04001796 if (conn) {
Johan Hedberg51a8efd2012-01-16 06:10:31 +02001797 clear_bit(HCI_CONN_MODE_CHANGE_PEND, &conn->flags);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001798
Johan Hedberg51a8efd2012-01-16 06:10:31 +02001799 if (test_and_clear_bit(HCI_CONN_SCO_SETUP_PEND, &conn->flags))
Marcel Holtmanne73439d2010-07-26 10:06:00 -04001800 hci_sco_setup(conn, status);
1801 }
1802
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001803 hci_dev_unlock(hdev);
1804}
1805
Johan Hedberg88c3df12012-02-09 14:27:38 +02001806static void hci_cs_disconnect(struct hci_dev *hdev, u8 status)
1807{
1808 struct hci_cp_disconnect *cp;
1809 struct hci_conn *conn;
1810
1811 if (!status)
1812 return;
1813
1814 cp = hci_sent_cmd_data(hdev, HCI_OP_DISCONNECT);
1815 if (!cp)
1816 return;
1817
1818 hci_dev_lock(hdev);
1819
1820 conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(cp->handle));
1821 if (conn)
1822 mgmt_disconnect_failed(hdev, &conn->dst, conn->type,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001823 conn->dst_type, status);
Johan Hedberg88c3df12012-02-09 14:27:38 +02001824
1825 hci_dev_unlock(hdev);
1826}
1827
Ville Tervofcd89c02011-02-10 22:38:47 -03001828static void hci_cs_le_create_conn(struct hci_dev *hdev, __u8 status)
1829{
Ville Tervofcd89c02011-02-10 22:38:47 -03001830 struct hci_conn *conn;
1831
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +03001832 BT_DBG("%s status 0x%2.2x", hdev->name, status);
Ville Tervofcd89c02011-02-10 22:38:47 -03001833
Ville Tervofcd89c02011-02-10 22:38:47 -03001834 if (status) {
Andre Guedesf00a06a2012-07-27 15:10:13 -03001835 hci_dev_lock(hdev);
Ville Tervofcd89c02011-02-10 22:38:47 -03001836
Andre Guedes0c95ab72012-07-27 15:10:14 -03001837 conn = hci_conn_hash_lookup_state(hdev, LE_LINK, BT_CONNECT);
Andre Guedesf00a06a2012-07-27 15:10:13 -03001838 if (!conn) {
1839 hci_dev_unlock(hdev);
1840 return;
1841 }
1842
Andrei Emeltchenko6ed93dc2012-09-25 12:49:43 +03001843 BT_DBG("%s bdaddr %pMR conn %p", hdev->name, &conn->dst, conn);
Andre Guedesf00a06a2012-07-27 15:10:13 -03001844
1845 conn->state = BT_CLOSED;
Andre Guedes0c95ab72012-07-27 15:10:14 -03001846 mgmt_connect_failed(hdev, &conn->dst, conn->type,
Andre Guedesf00a06a2012-07-27 15:10:13 -03001847 conn->dst_type, status);
1848 hci_proto_connect_cfm(conn, status);
1849 hci_conn_del(conn);
1850
1851 hci_dev_unlock(hdev);
1852 }
Ville Tervofcd89c02011-02-10 22:38:47 -03001853}
1854
Vinicius Costa Gomesa7a595f2011-06-09 18:50:47 -03001855static void hci_cs_le_start_enc(struct hci_dev *hdev, u8 status)
1856{
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +03001857 BT_DBG("%s status 0x%2.2x", hdev->name, status);
Vinicius Costa Gomesa7a595f2011-06-09 18:50:47 -03001858}
1859
Andrei Emeltchenkoa02226d2012-09-27 17:26:19 +03001860static void hci_cs_create_phylink(struct hci_dev *hdev, u8 status)
1861{
Andrei Emeltchenko93c284e2012-09-27 17:26:20 +03001862 struct hci_cp_create_phy_link *cp;
1863
Andrei Emeltchenkoa02226d2012-09-27 17:26:19 +03001864 BT_DBG("%s status 0x%2.2x", hdev->name, status);
Andrei Emeltchenko93c284e2012-09-27 17:26:20 +03001865
Andrei Emeltchenko93c284e2012-09-27 17:26:20 +03001866 cp = hci_sent_cmd_data(hdev, HCI_OP_CREATE_PHY_LINK);
1867 if (!cp)
1868 return;
1869
Andrei Emeltchenkoe58917b2012-10-31 15:46:33 +02001870 hci_dev_lock(hdev);
1871
1872 if (status) {
1873 struct hci_conn *hcon;
1874
1875 hcon = hci_conn_hash_lookup_handle(hdev, cp->phy_handle);
1876 if (hcon)
1877 hci_conn_del(hcon);
1878 } else {
1879 amp_write_remote_assoc(hdev, cp->phy_handle);
1880 }
1881
1882 hci_dev_unlock(hdev);
Andrei Emeltchenkoa02226d2012-09-27 17:26:19 +03001883}
1884
Andrei Emeltchenko0b26ab92012-09-27 17:26:24 +03001885static void hci_cs_accept_phylink(struct hci_dev *hdev, u8 status)
1886{
1887 struct hci_cp_accept_phy_link *cp;
1888
1889 BT_DBG("%s status 0x%2.2x", hdev->name, status);
1890
1891 if (status)
1892 return;
1893
1894 cp = hci_sent_cmd_data(hdev, HCI_OP_ACCEPT_PHY_LINK);
1895 if (!cp)
1896 return;
1897
1898 amp_write_remote_assoc(hdev, cp->phy_handle);
1899}
1900
Andrei Emeltchenko5ce66b52012-10-31 15:46:30 +02001901static void hci_cs_create_logical_link(struct hci_dev *hdev, u8 status)
1902{
1903 BT_DBG("%s status 0x%2.2x", hdev->name, status);
1904}
1905
Gustavo Padovan6039aa72012-05-23 04:04:18 -03001906static void hci_inquiry_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001907{
1908 __u8 status = *((__u8 *) skb->data);
Johan Hedberg30dc78e2012-01-04 15:44:20 +02001909 struct discovery_state *discov = &hdev->discovery;
1910 struct inquiry_entry *e;
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001911
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +03001912 BT_DBG("%s status 0x%2.2x", hdev->name, status);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001913
Johan Hedberg23bb5762010-12-21 23:01:27 +02001914 hci_req_complete(hdev, HCI_OP_INQUIRY, status);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001915
1916 hci_conn_check_pending(hdev);
Andre Guedes89352e72011-11-04 14:16:53 -03001917
1918 if (!test_and_clear_bit(HCI_INQUIRY, &hdev->flags))
1919 return;
1920
Johan Hedberga8b2d5c2012-01-08 23:11:15 +02001921 if (!test_bit(HCI_MGMT, &hdev->dev_flags))
Johan Hedberg30dc78e2012-01-04 15:44:20 +02001922 return;
1923
Johan Hedberg56e5cb82011-11-08 20:40:16 +02001924 hci_dev_lock(hdev);
Johan Hedberg30dc78e2012-01-04 15:44:20 +02001925
Andre Guedes343f9352012-02-17 20:39:37 -03001926 if (discov->state != DISCOVERY_FINDING)
Johan Hedberg30dc78e2012-01-04 15:44:20 +02001927 goto unlock;
1928
1929 if (list_empty(&discov->resolve)) {
1930 hci_discovery_set_state(hdev, DISCOVERY_STOPPED);
1931 goto unlock;
1932 }
1933
1934 e = hci_inquiry_cache_lookup_resolve(hdev, BDADDR_ANY, NAME_NEEDED);
1935 if (e && hci_resolve_name(hdev, e) == 0) {
1936 e->name_state = NAME_PENDING;
1937 hci_discovery_set_state(hdev, DISCOVERY_RESOLVING);
1938 } else {
1939 hci_discovery_set_state(hdev, DISCOVERY_STOPPED);
1940 }
1941
1942unlock:
Johan Hedberg56e5cb82011-11-08 20:40:16 +02001943 hci_dev_unlock(hdev);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001944}
1945
Gustavo Padovan6039aa72012-05-23 04:04:18 -03001946static void hci_inquiry_result_evt(struct hci_dev *hdev, struct sk_buff *skb)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001947{
Marcel Holtmann45bb4bf2005-08-09 20:27:49 -07001948 struct inquiry_data data;
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001949 struct inquiry_info *info = (void *) (skb->data + 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001950 int num_rsp = *((__u8 *) skb->data);
1951
1952 BT_DBG("%s num_rsp %d", hdev->name, num_rsp);
1953
Marcel Holtmann45bb4bf2005-08-09 20:27:49 -07001954 if (!num_rsp)
1955 return;
1956
Andre Guedes1519cc12012-03-21 00:03:38 -03001957 if (test_bit(HCI_PERIODIC_INQ, &hdev->dev_flags))
1958 return;
1959
Linus Torvalds1da177e2005-04-16 15:20:36 -07001960 hci_dev_lock(hdev);
Marcel Holtmann45bb4bf2005-08-09 20:27:49 -07001961
Johan Hedberge17acd42011-03-30 23:57:16 +03001962 for (; num_rsp; num_rsp--, info++) {
Johan Hedberg388fc8f2012-02-23 00:38:59 +02001963 bool name_known, ssp;
Johan Hedberg31754052012-01-04 13:39:52 +02001964
Linus Torvalds1da177e2005-04-16 15:20:36 -07001965 bacpy(&data.bdaddr, &info->bdaddr);
1966 data.pscan_rep_mode = info->pscan_rep_mode;
1967 data.pscan_period_mode = info->pscan_period_mode;
1968 data.pscan_mode = info->pscan_mode;
1969 memcpy(data.dev_class, info->dev_class, 3);
1970 data.clock_offset = info->clock_offset;
1971 data.rssi = 0x00;
Marcel Holtmann41a96212008-07-14 20:13:48 +02001972 data.ssp_mode = 0x00;
Johan Hedberg31754052012-01-04 13:39:52 +02001973
Johan Hedberg388fc8f2012-02-23 00:38:59 +02001974 name_known = hci_inquiry_cache_update(hdev, &data, false, &ssp);
Johan Hedberg48264f02011-11-09 13:58:58 +02001975 mgmt_device_found(hdev, &info->bdaddr, ACL_LINK, 0x00,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001976 info->dev_class, 0, !name_known, ssp, NULL,
1977 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001978 }
Marcel Holtmann45bb4bf2005-08-09 20:27:49 -07001979
Linus Torvalds1da177e2005-04-16 15:20:36 -07001980 hci_dev_unlock(hdev);
1981}
1982
Gustavo Padovan6039aa72012-05-23 04:04:18 -03001983static void hci_conn_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001984{
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001985 struct hci_ev_conn_complete *ev = (void *) skb->data;
1986 struct hci_conn *conn;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001987
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001988 BT_DBG("%s", hdev->name);
Marcel Holtmann45bb4bf2005-08-09 20:27:49 -07001989
Linus Torvalds1da177e2005-04-16 15:20:36 -07001990 hci_dev_lock(hdev);
Marcel Holtmann45bb4bf2005-08-09 20:27:49 -07001991
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001992 conn = hci_conn_hash_lookup_ba(hdev, ev->link_type, &ev->bdaddr);
Marcel Holtmann94992372009-04-19 19:30:03 +02001993 if (!conn) {
1994 if (ev->link_type != SCO_LINK)
1995 goto unlock;
1996
1997 conn = hci_conn_hash_lookup_ba(hdev, ESCO_LINK, &ev->bdaddr);
1998 if (!conn)
1999 goto unlock;
2000
2001 conn->type = SCO_LINK;
2002 }
Marcel Holtmann45bb4bf2005-08-09 20:27:49 -07002003
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002004 if (!ev->status) {
2005 conn->handle = __le16_to_cpu(ev->handle);
Marcel Holtmann769be972008-07-14 20:13:49 +02002006
2007 if (conn->type == ACL_LINK) {
2008 conn->state = BT_CONFIG;
2009 hci_conn_hold(conn);
Szymon Janca9ea3ed2012-07-19 14:46:08 +02002010
2011 if (!conn->out && !hci_conn_ssp_enabled(conn) &&
2012 !hci_find_link_key(hdev, &ev->bdaddr))
2013 conn->disc_timeout = HCI_PAIRING_TIMEOUT;
2014 else
2015 conn->disc_timeout = HCI_DISCONN_TIMEOUT;
Marcel Holtmann769be972008-07-14 20:13:49 +02002016 } else
2017 conn->state = BT_CONNECTED;
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002018
Marcel Holtmann9eba32b2009-08-22 14:19:26 -07002019 hci_conn_hold_device(conn);
Marcel Holtmann7d0db0a2008-07-14 20:13:51 +02002020 hci_conn_add_sysfs(conn);
2021
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002022 if (test_bit(HCI_AUTH, &hdev->flags))
2023 conn->link_mode |= HCI_LM_AUTH;
2024
2025 if (test_bit(HCI_ENCRYPT, &hdev->flags))
2026 conn->link_mode |= HCI_LM_ENCRYPT;
2027
2028 /* Get remote features */
2029 if (conn->type == ACL_LINK) {
2030 struct hci_cp_read_remote_features cp;
2031 cp.handle = ev->handle;
Marcel Holtmann769be972008-07-14 20:13:49 +02002032 hci_send_cmd(hdev, HCI_OP_READ_REMOTE_FEATURES,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002033 sizeof(cp), &cp);
Marcel Holtmann45bb4bf2005-08-09 20:27:49 -07002034 }
Marcel Holtmann45bb4bf2005-08-09 20:27:49 -07002035
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002036 /* Set packet type for incoming connection */
Andrei Emeltchenkod095c1e2011-12-01 14:33:27 +02002037 if (!conn->out && hdev->hci_ver < BLUETOOTH_VER_2_0) {
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002038 struct hci_cp_change_conn_ptype cp;
2039 cp.handle = ev->handle;
Marcel Holtmanna8746412008-07-14 20:13:46 +02002040 cp.pkt_type = cpu_to_le16(conn->pkt_type);
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002041 hci_send_cmd(hdev, HCI_OP_CHANGE_CONN_PTYPE, sizeof(cp),
2042 &cp);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002043 }
Johan Hedberg17d5c042011-01-22 06:09:08 +02002044 } else {
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002045 conn->state = BT_CLOSED;
Johan Hedberg17d5c042011-01-22 06:09:08 +02002046 if (conn->type == ACL_LINK)
Johan Hedberg744cf192011-11-08 20:40:14 +02002047 mgmt_connect_failed(hdev, &ev->bdaddr, conn->type,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002048 conn->dst_type, ev->status);
Johan Hedberg17d5c042011-01-22 06:09:08 +02002049 }
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002050
Marcel Holtmanne73439d2010-07-26 10:06:00 -04002051 if (conn->type == ACL_LINK)
2052 hci_sco_setup(conn, ev->status);
Marcel Holtmann45bb4bf2005-08-09 20:27:49 -07002053
Marcel Holtmann769be972008-07-14 20:13:49 +02002054 if (ev->status) {
2055 hci_proto_connect_cfm(conn, ev->status);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002056 hci_conn_del(conn);
Marcel Holtmannc89b6e62009-01-15 21:57:03 +01002057 } else if (ev->link_type != ACL_LINK)
2058 hci_proto_connect_cfm(conn, ev->status);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002059
2060unlock:
Linus Torvalds1da177e2005-04-16 15:20:36 -07002061 hci_dev_unlock(hdev);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002062
2063 hci_conn_check_pending(hdev);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002064}
2065
Frédéric Dalleau20714bfe2012-11-21 10:51:12 +01002066void hci_conn_accept(struct hci_conn *conn, int mask)
2067{
2068 struct hci_dev *hdev = conn->hdev;
2069
2070 BT_DBG("conn %p", conn);
2071
2072 conn->state = BT_CONFIG;
2073
2074 if (!lmp_esco_capable(hdev)) {
2075 struct hci_cp_accept_conn_req cp;
2076
2077 bacpy(&cp.bdaddr, &conn->dst);
2078
2079 if (lmp_rswitch_capable(hdev) && (mask & HCI_LM_MASTER))
2080 cp.role = 0x00; /* Become master */
2081 else
2082 cp.role = 0x01; /* Remain slave */
2083
2084 hci_send_cmd(hdev, HCI_OP_ACCEPT_CONN_REQ, sizeof(cp), &cp);
2085 } else /* lmp_esco_capable(hdev)) */ {
2086 struct hci_cp_accept_sync_conn_req cp;
2087
2088 bacpy(&cp.bdaddr, &conn->dst);
2089 cp.pkt_type = cpu_to_le16(conn->pkt_type);
2090
2091 cp.tx_bandwidth = __constant_cpu_to_le32(0x00001f40);
2092 cp.rx_bandwidth = __constant_cpu_to_le32(0x00001f40);
2093 cp.max_latency = __constant_cpu_to_le16(0xffff);
2094 cp.content_format = cpu_to_le16(hdev->voice_setting);
2095 cp.retrans_effort = 0xff;
2096
2097 hci_send_cmd(hdev, HCI_OP_ACCEPT_SYNC_CONN_REQ,
2098 sizeof(cp), &cp);
2099 }
2100}
2101
Gustavo Padovan6039aa72012-05-23 04:04:18 -03002102static void hci_conn_request_evt(struct hci_dev *hdev, struct sk_buff *skb)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002103{
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002104 struct hci_ev_conn_request *ev = (void *) skb->data;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002105 int mask = hdev->link_mode;
Frédéric Dalleau20714bfe2012-11-21 10:51:12 +01002106 __u8 flags = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002107
Andrei Emeltchenko6ed93dc2012-09-25 12:49:43 +03002108 BT_DBG("%s bdaddr %pMR type 0x%x", hdev->name, &ev->bdaddr,
Gustavo Padovan807deac2012-05-17 00:36:24 -03002109 ev->link_type);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002110
Frédéric Dalleau20714bfe2012-11-21 10:51:12 +01002111 mask |= hci_proto_connect_ind(hdev, &ev->bdaddr, ev->link_type,
2112 &flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002113
Szymon Janc138d22e2011-02-17 16:44:23 +01002114 if ((mask & HCI_LM_ACCEPT) &&
Gustavo Padovan807deac2012-05-17 00:36:24 -03002115 !hci_blacklist_lookup(hdev, &ev->bdaddr)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002116 /* Connection accepted */
Marcel Holtmannc7bdd502008-07-14 20:13:47 +02002117 struct inquiry_entry *ie;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002118 struct hci_conn *conn;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002119
2120 hci_dev_lock(hdev);
Marcel Holtmannb6a0dc82007-10-20 14:55:10 +02002121
Andrei Emeltchenkocc11b9c2010-11-22 13:21:37 +02002122 ie = hci_inquiry_cache_lookup(hdev, &ev->bdaddr);
2123 if (ie)
Marcel Holtmannc7bdd502008-07-14 20:13:47 +02002124 memcpy(ie->data.dev_class, ev->dev_class, 3);
2125
Gustavo Padovan8fc9ced2012-05-23 04:04:21 -03002126 conn = hci_conn_hash_lookup_ba(hdev, ev->link_type,
2127 &ev->bdaddr);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002128 if (!conn) {
Andrei Emeltchenkocc11b9c2010-11-22 13:21:37 +02002129 conn = hci_conn_add(hdev, ev->link_type, &ev->bdaddr);
2130 if (!conn) {
Gustavo F. Padovan893ef972010-07-18 15:13:37 -03002131 BT_ERR("No memory for new connection");
Linus Torvalds1da177e2005-04-16 15:20:36 -07002132 hci_dev_unlock(hdev);
2133 return;
2134 }
2135 }
Marcel Holtmannb6a0dc82007-10-20 14:55:10 +02002136
Linus Torvalds1da177e2005-04-16 15:20:36 -07002137 memcpy(conn->dev_class, ev->dev_class, 3);
Marcel Holtmannb6a0dc82007-10-20 14:55:10 +02002138
Linus Torvalds1da177e2005-04-16 15:20:36 -07002139 hci_dev_unlock(hdev);
2140
Frédéric Dalleau20714bfe2012-11-21 10:51:12 +01002141 if (ev->link_type == ACL_LINK ||
2142 (!(flags & HCI_PROTO_DEFER) && !lmp_esco_capable(hdev))) {
Marcel Holtmannb6a0dc82007-10-20 14:55:10 +02002143 struct hci_cp_accept_conn_req cp;
Frédéric Dalleau20714bfe2012-11-21 10:51:12 +01002144 conn->state = BT_CONNECT;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002145
Marcel Holtmannb6a0dc82007-10-20 14:55:10 +02002146 bacpy(&cp.bdaddr, &ev->bdaddr);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002147
Marcel Holtmannb6a0dc82007-10-20 14:55:10 +02002148 if (lmp_rswitch_capable(hdev) && (mask & HCI_LM_MASTER))
2149 cp.role = 0x00; /* Become master */
2150 else
2151 cp.role = 0x01; /* Remain slave */
2152
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002153 hci_send_cmd(hdev, HCI_OP_ACCEPT_CONN_REQ, sizeof(cp),
2154 &cp);
Frédéric Dalleau20714bfe2012-11-21 10:51:12 +01002155 } else if (!(flags & HCI_PROTO_DEFER)) {
Marcel Holtmannb6a0dc82007-10-20 14:55:10 +02002156 struct hci_cp_accept_sync_conn_req cp;
Frédéric Dalleau20714bfe2012-11-21 10:51:12 +01002157 conn->state = BT_CONNECT;
Marcel Holtmannb6a0dc82007-10-20 14:55:10 +02002158
2159 bacpy(&cp.bdaddr, &ev->bdaddr);
Marcel Holtmanna8746412008-07-14 20:13:46 +02002160 cp.pkt_type = cpu_to_le16(conn->pkt_type);
Marcel Holtmannb6a0dc82007-10-20 14:55:10 +02002161
Andrei Emeltchenko82781e62012-05-25 11:38:27 +03002162 cp.tx_bandwidth = __constant_cpu_to_le32(0x00001f40);
2163 cp.rx_bandwidth = __constant_cpu_to_le32(0x00001f40);
2164 cp.max_latency = __constant_cpu_to_le16(0xffff);
Marcel Holtmannb6a0dc82007-10-20 14:55:10 +02002165 cp.content_format = cpu_to_le16(hdev->voice_setting);
2166 cp.retrans_effort = 0xff;
2167
2168 hci_send_cmd(hdev, HCI_OP_ACCEPT_SYNC_CONN_REQ,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002169 sizeof(cp), &cp);
Frédéric Dalleau20714bfe2012-11-21 10:51:12 +01002170 } else {
2171 conn->state = BT_CONNECT2;
2172 hci_proto_connect_cfm(conn, 0);
2173 hci_conn_put(conn);
Marcel Holtmannb6a0dc82007-10-20 14:55:10 +02002174 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002175 } else {
2176 /* Connection rejected */
2177 struct hci_cp_reject_conn_req cp;
2178
2179 bacpy(&cp.bdaddr, &ev->bdaddr);
Andrei Emeltchenko9f5a0d72011-11-07 14:20:25 +02002180 cp.reason = HCI_ERROR_REJ_BAD_ADDR;
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002181 hci_send_cmd(hdev, HCI_OP_REJECT_CONN_REQ, sizeof(cp), &cp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002182 }
2183}
2184
Mikel Astizf0d6a0e2012-08-09 09:52:30 +02002185static u8 hci_to_mgmt_reason(u8 err)
2186{
2187 switch (err) {
2188 case HCI_ERROR_CONNECTION_TIMEOUT:
2189 return MGMT_DEV_DISCONN_TIMEOUT;
2190 case HCI_ERROR_REMOTE_USER_TERM:
2191 case HCI_ERROR_REMOTE_LOW_RESOURCES:
2192 case HCI_ERROR_REMOTE_POWER_OFF:
2193 return MGMT_DEV_DISCONN_REMOTE;
2194 case HCI_ERROR_LOCAL_HOST_TERM:
2195 return MGMT_DEV_DISCONN_LOCAL_HOST;
2196 default:
2197 return MGMT_DEV_DISCONN_UNKNOWN;
2198 }
2199}
2200
Gustavo Padovan6039aa72012-05-23 04:04:18 -03002201static void hci_disconn_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002202{
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002203 struct hci_ev_disconn_complete *ev = (void *) skb->data;
Marcel Holtmann04837f62006-07-03 10:02:33 +02002204 struct hci_conn *conn;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002205
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +03002206 BT_DBG("%s status 0x%2.2x", hdev->name, ev->status);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002207
Linus Torvalds1da177e2005-04-16 15:20:36 -07002208 hci_dev_lock(hdev);
2209
Marcel Holtmann04837f62006-07-03 10:02:33 +02002210 conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
Johan Hedbergf7520542011-01-20 12:34:39 +02002211 if (!conn)
2212 goto unlock;
Marcel Holtmann7d0db0a2008-07-14 20:13:51 +02002213
Johan Hedberg37d9ef72011-11-10 15:54:39 +02002214 if (ev->status == 0)
2215 conn->state = BT_CLOSED;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002216
Johan Hedbergb644ba32012-01-17 21:48:47 +02002217 if (test_and_clear_bit(HCI_CONN_MGMT_CONNECTED, &conn->flags) &&
Gustavo Padovan807deac2012-05-17 00:36:24 -03002218 (conn->type == ACL_LINK || conn->type == LE_LINK)) {
Mikel Astizf0d6a0e2012-08-09 09:52:30 +02002219 if (ev->status) {
Johan Hedberg88c3df12012-02-09 14:27:38 +02002220 mgmt_disconnect_failed(hdev, &conn->dst, conn->type,
Gustavo Padovan807deac2012-05-17 00:36:24 -03002221 conn->dst_type, ev->status);
Mikel Astizf0d6a0e2012-08-09 09:52:30 +02002222 } else {
2223 u8 reason = hci_to_mgmt_reason(ev->reason);
2224
Johan Hedbergafc747a2012-01-15 18:11:07 +02002225 mgmt_device_disconnected(hdev, &conn->dst, conn->type,
Mikel Astizf0d6a0e2012-08-09 09:52:30 +02002226 conn->dst_type, reason);
2227 }
Johan Hedberg37d9ef72011-11-10 15:54:39 +02002228 }
Johan Hedbergf7520542011-01-20 12:34:39 +02002229
Johan Hedberg37d9ef72011-11-10 15:54:39 +02002230 if (ev->status == 0) {
Vishal Agarwal6ec5bca2012-04-16 14:44:44 +05302231 if (conn->type == ACL_LINK && conn->flush_key)
2232 hci_remove_link_key(hdev, &conn->dst);
Johan Hedberg37d9ef72011-11-10 15:54:39 +02002233 hci_proto_disconn_cfm(conn, ev->reason);
2234 hci_conn_del(conn);
2235 }
Johan Hedbergf7520542011-01-20 12:34:39 +02002236
2237unlock:
Linus Torvalds1da177e2005-04-16 15:20:36 -07002238 hci_dev_unlock(hdev);
2239}
2240
Gustavo Padovan6039aa72012-05-23 04:04:18 -03002241static void hci_auth_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002242{
2243 struct hci_ev_auth_complete *ev = (void *) skb->data;
2244 struct hci_conn *conn;
2245
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +03002246 BT_DBG("%s status 0x%2.2x", hdev->name, ev->status);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002247
2248 hci_dev_lock(hdev);
2249
2250 conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
Waldemar Rymarkiewiczd7556e22011-05-31 15:49:26 +02002251 if (!conn)
2252 goto unlock;
2253
2254 if (!ev->status) {
Johan Hedbergaa64a8b2012-01-18 21:33:12 +02002255 if (!hci_conn_ssp_enabled(conn) &&
Gustavo Padovan807deac2012-05-17 00:36:24 -03002256 test_bit(HCI_CONN_REAUTH_PEND, &conn->flags)) {
Waldemar Rymarkiewiczd7556e22011-05-31 15:49:26 +02002257 BT_INFO("re-auth of legacy device is not possible.");
Johan Hedberg2a611692011-02-19 12:06:00 -03002258 } else {
Waldemar Rymarkiewiczd7556e22011-05-31 15:49:26 +02002259 conn->link_mode |= HCI_LM_AUTH;
2260 conn->sec_level = conn->pending_sec_level;
Johan Hedberg2a611692011-02-19 12:06:00 -03002261 }
Waldemar Rymarkiewiczd7556e22011-05-31 15:49:26 +02002262 } else {
Johan Hedbergbab73cb2012-02-09 16:07:29 +02002263 mgmt_auth_failed(hdev, &conn->dst, conn->type, conn->dst_type,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002264 ev->status);
Waldemar Rymarkiewiczd7556e22011-05-31 15:49:26 +02002265 }
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002266
Johan Hedberg51a8efd2012-01-16 06:10:31 +02002267 clear_bit(HCI_CONN_AUTH_PEND, &conn->flags);
2268 clear_bit(HCI_CONN_REAUTH_PEND, &conn->flags);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002269
Waldemar Rymarkiewiczd7556e22011-05-31 15:49:26 +02002270 if (conn->state == BT_CONFIG) {
Johan Hedbergaa64a8b2012-01-18 21:33:12 +02002271 if (!ev->status && hci_conn_ssp_enabled(conn)) {
Waldemar Rymarkiewiczd7556e22011-05-31 15:49:26 +02002272 struct hci_cp_set_conn_encrypt cp;
2273 cp.handle = ev->handle;
2274 cp.encrypt = 0x01;
2275 hci_send_cmd(hdev, HCI_OP_SET_CONN_ENCRYPT, sizeof(cp),
Gustavo Padovan807deac2012-05-17 00:36:24 -03002276 &cp);
Marcel Holtmann052b30b2009-04-26 20:01:22 +02002277 } else {
Waldemar Rymarkiewiczd7556e22011-05-31 15:49:26 +02002278 conn->state = BT_CONNECTED;
2279 hci_proto_connect_cfm(conn, ev->status);
Marcel Holtmann052b30b2009-04-26 20:01:22 +02002280 hci_conn_put(conn);
2281 }
Waldemar Rymarkiewiczd7556e22011-05-31 15:49:26 +02002282 } else {
2283 hci_auth_cfm(conn, ev->status);
Marcel Holtmann052b30b2009-04-26 20:01:22 +02002284
Waldemar Rymarkiewiczd7556e22011-05-31 15:49:26 +02002285 hci_conn_hold(conn);
2286 conn->disc_timeout = HCI_DISCONN_TIMEOUT;
2287 hci_conn_put(conn);
2288 }
2289
Johan Hedberg51a8efd2012-01-16 06:10:31 +02002290 if (test_bit(HCI_CONN_ENCRYPT_PEND, &conn->flags)) {
Waldemar Rymarkiewiczd7556e22011-05-31 15:49:26 +02002291 if (!ev->status) {
2292 struct hci_cp_set_conn_encrypt cp;
2293 cp.handle = ev->handle;
2294 cp.encrypt = 0x01;
2295 hci_send_cmd(hdev, HCI_OP_SET_CONN_ENCRYPT, sizeof(cp),
Gustavo Padovan807deac2012-05-17 00:36:24 -03002296 &cp);
Waldemar Rymarkiewiczd7556e22011-05-31 15:49:26 +02002297 } else {
Johan Hedberg51a8efd2012-01-16 06:10:31 +02002298 clear_bit(HCI_CONN_ENCRYPT_PEND, &conn->flags);
Waldemar Rymarkiewiczd7556e22011-05-31 15:49:26 +02002299 hci_encrypt_cfm(conn, ev->status, 0x00);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002300 }
2301 }
2302
Waldemar Rymarkiewiczd7556e22011-05-31 15:49:26 +02002303unlock:
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002304 hci_dev_unlock(hdev);
2305}
2306
Gustavo Padovan6039aa72012-05-23 04:04:18 -03002307static void hci_remote_name_evt(struct hci_dev *hdev, struct sk_buff *skb)
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002308{
Johan Hedberg127178d2010-11-18 22:22:29 +02002309 struct hci_ev_remote_name *ev = (void *) skb->data;
2310 struct hci_conn *conn;
2311
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002312 BT_DBG("%s", hdev->name);
2313
2314 hci_conn_check_pending(hdev);
Johan Hedberg127178d2010-11-18 22:22:29 +02002315
2316 hci_dev_lock(hdev);
2317
2318 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
Johan Hedbergb644ba32012-01-17 21:48:47 +02002319
2320 if (!test_bit(HCI_MGMT, &hdev->dev_flags))
2321 goto check_auth;
2322
2323 if (ev->status == 0)
2324 hci_check_pending_name(hdev, conn, &ev->bdaddr, ev->name,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002325 strnlen(ev->name, HCI_MAX_NAME_LENGTH));
Johan Hedbergb644ba32012-01-17 21:48:47 +02002326 else
2327 hci_check_pending_name(hdev, conn, &ev->bdaddr, NULL, 0);
2328
2329check_auth:
Johan Hedberg79c6c702011-04-28 11:28:55 -07002330 if (!conn)
2331 goto unlock;
2332
2333 if (!hci_outgoing_auth_needed(hdev, conn))
2334 goto unlock;
2335
Johan Hedberg51a8efd2012-01-16 06:10:31 +02002336 if (!test_and_set_bit(HCI_CONN_AUTH_PEND, &conn->flags)) {
Johan Hedberg127178d2010-11-18 22:22:29 +02002337 struct hci_cp_auth_requested cp;
2338 cp.handle = __cpu_to_le16(conn->handle);
2339 hci_send_cmd(hdev, HCI_OP_AUTH_REQUESTED, sizeof(cp), &cp);
2340 }
2341
Johan Hedberg79c6c702011-04-28 11:28:55 -07002342unlock:
Johan Hedberg127178d2010-11-18 22:22:29 +02002343 hci_dev_unlock(hdev);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002344}
2345
Gustavo Padovan6039aa72012-05-23 04:04:18 -03002346static void hci_encrypt_change_evt(struct hci_dev *hdev, struct sk_buff *skb)
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002347{
2348 struct hci_ev_encrypt_change *ev = (void *) skb->data;
2349 struct hci_conn *conn;
2350
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +03002351 BT_DBG("%s status 0x%2.2x", hdev->name, ev->status);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002352
2353 hci_dev_lock(hdev);
2354
2355 conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
2356 if (conn) {
2357 if (!ev->status) {
Marcel Holtmannae293192008-07-14 20:13:45 +02002358 if (ev->encrypt) {
2359 /* Encryption implies authentication */
2360 conn->link_mode |= HCI_LM_AUTH;
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002361 conn->link_mode |= HCI_LM_ENCRYPT;
Vinicius Costa Gomesda85e5e2011-06-09 18:50:53 -03002362 conn->sec_level = conn->pending_sec_level;
Marcel Holtmannae293192008-07-14 20:13:45 +02002363 } else
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002364 conn->link_mode &= ~HCI_LM_ENCRYPT;
2365 }
2366
Johan Hedberg51a8efd2012-01-16 06:10:31 +02002367 clear_bit(HCI_CONN_ENCRYPT_PEND, &conn->flags);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002368
Gustavo Padovana7d77232012-05-13 03:20:07 -03002369 if (ev->status && conn->state == BT_CONNECTED) {
Gustavo Padovand839c812012-05-16 12:17:12 -03002370 hci_acl_disconn(conn, HCI_ERROR_AUTH_FAILURE);
Gustavo Padovana7d77232012-05-13 03:20:07 -03002371 hci_conn_put(conn);
2372 goto unlock;
2373 }
2374
Marcel Holtmannf8558552008-07-14 20:13:49 +02002375 if (conn->state == BT_CONFIG) {
2376 if (!ev->status)
2377 conn->state = BT_CONNECTED;
2378
2379 hci_proto_connect_cfm(conn, ev->status);
2380 hci_conn_put(conn);
2381 } else
2382 hci_encrypt_cfm(conn, ev->status, ev->encrypt);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002383 }
2384
Gustavo Padovana7d77232012-05-13 03:20:07 -03002385unlock:
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002386 hci_dev_unlock(hdev);
2387}
2388
Gustavo Padovan6039aa72012-05-23 04:04:18 -03002389static void hci_change_link_key_complete_evt(struct hci_dev *hdev,
2390 struct sk_buff *skb)
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002391{
2392 struct hci_ev_change_link_key_complete *ev = (void *) skb->data;
2393 struct hci_conn *conn;
2394
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +03002395 BT_DBG("%s status 0x%2.2x", hdev->name, ev->status);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002396
2397 hci_dev_lock(hdev);
2398
2399 conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
2400 if (conn) {
2401 if (!ev->status)
2402 conn->link_mode |= HCI_LM_SECURE;
2403
Johan Hedberg51a8efd2012-01-16 06:10:31 +02002404 clear_bit(HCI_CONN_AUTH_PEND, &conn->flags);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002405
2406 hci_key_change_cfm(conn, ev->status);
2407 }
2408
2409 hci_dev_unlock(hdev);
2410}
2411
Gustavo Padovan6039aa72012-05-23 04:04:18 -03002412static void hci_remote_features_evt(struct hci_dev *hdev,
2413 struct sk_buff *skb)
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002414{
2415 struct hci_ev_remote_features *ev = (void *) skb->data;
2416 struct hci_conn *conn;
2417
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +03002418 BT_DBG("%s status 0x%2.2x", hdev->name, ev->status);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002419
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002420 hci_dev_lock(hdev);
2421
2422 conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
Johan Hedbergccd556f2010-11-10 17:11:51 +02002423 if (!conn)
2424 goto unlock;
Marcel Holtmann769be972008-07-14 20:13:49 +02002425
Johan Hedbergccd556f2010-11-10 17:11:51 +02002426 if (!ev->status)
2427 memcpy(conn->features, ev->features, 8);
2428
2429 if (conn->state != BT_CONFIG)
2430 goto unlock;
2431
2432 if (!ev->status && lmp_ssp_capable(hdev) && lmp_ssp_capable(conn)) {
2433 struct hci_cp_read_remote_ext_features cp;
2434 cp.handle = ev->handle;
2435 cp.page = 0x01;
2436 hci_send_cmd(hdev, HCI_OP_READ_REMOTE_EXT_FEATURES,
Gustavo Padovan807deac2012-05-17 00:36:24 -03002437 sizeof(cp), &cp);
Johan Hedberg392599b2010-11-18 22:22:28 +02002438 goto unlock;
2439 }
2440
Johan Hedberg671267b2012-05-12 16:11:50 -03002441 if (!ev->status && !test_bit(HCI_CONN_MGMT_CONNECTED, &conn->flags)) {
Johan Hedberg127178d2010-11-18 22:22:29 +02002442 struct hci_cp_remote_name_req cp;
2443 memset(&cp, 0, sizeof(cp));
2444 bacpy(&cp.bdaddr, &conn->dst);
2445 cp.pscan_rep_mode = 0x02;
2446 hci_send_cmd(hdev, HCI_OP_REMOTE_NAME_REQ, sizeof(cp), &cp);
Johan Hedbergb644ba32012-01-17 21:48:47 +02002447 } else if (!test_and_set_bit(HCI_CONN_MGMT_CONNECTED, &conn->flags))
2448 mgmt_device_connected(hdev, &conn->dst, conn->type,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002449 conn->dst_type, 0, NULL, 0,
2450 conn->dev_class);
Johan Hedberg392599b2010-11-18 22:22:28 +02002451
Johan Hedberg127178d2010-11-18 22:22:29 +02002452 if (!hci_outgoing_auth_needed(hdev, conn)) {
Johan Hedbergccd556f2010-11-10 17:11:51 +02002453 conn->state = BT_CONNECTED;
2454 hci_proto_connect_cfm(conn, ev->status);
2455 hci_conn_put(conn);
Marcel Holtmann769be972008-07-14 20:13:49 +02002456 }
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002457
Johan Hedbergccd556f2010-11-10 17:11:51 +02002458unlock:
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002459 hci_dev_unlock(hdev);
2460}
2461
Gustavo Padovan6039aa72012-05-23 04:04:18 -03002462static void hci_remote_version_evt(struct hci_dev *hdev, struct sk_buff *skb)
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002463{
2464 BT_DBG("%s", hdev->name);
2465}
2466
Gustavo Padovan6039aa72012-05-23 04:04:18 -03002467static void hci_qos_setup_complete_evt(struct hci_dev *hdev,
2468 struct sk_buff *skb)
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002469{
2470 BT_DBG("%s", hdev->name);
2471}
2472
Gustavo Padovan6039aa72012-05-23 04:04:18 -03002473static void hci_cmd_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002474{
2475 struct hci_ev_cmd_complete *ev = (void *) skb->data;
2476 __u16 opcode;
2477
2478 skb_pull(skb, sizeof(*ev));
2479
2480 opcode = __le16_to_cpu(ev->opcode);
2481
2482 switch (opcode) {
2483 case HCI_OP_INQUIRY_CANCEL:
2484 hci_cc_inquiry_cancel(hdev, skb);
2485 break;
2486
Andre Guedes4d934832012-03-21 00:03:35 -03002487 case HCI_OP_PERIODIC_INQ:
2488 hci_cc_periodic_inq(hdev, skb);
2489 break;
2490
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002491 case HCI_OP_EXIT_PERIODIC_INQ:
2492 hci_cc_exit_periodic_inq(hdev, skb);
2493 break;
2494
2495 case HCI_OP_REMOTE_NAME_REQ_CANCEL:
2496 hci_cc_remote_name_req_cancel(hdev, skb);
2497 break;
2498
2499 case HCI_OP_ROLE_DISCOVERY:
2500 hci_cc_role_discovery(hdev, skb);
2501 break;
2502
Marcel Holtmanne4e8e372008-07-14 20:13:47 +02002503 case HCI_OP_READ_LINK_POLICY:
2504 hci_cc_read_link_policy(hdev, skb);
2505 break;
2506
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002507 case HCI_OP_WRITE_LINK_POLICY:
2508 hci_cc_write_link_policy(hdev, skb);
2509 break;
2510
Marcel Holtmanne4e8e372008-07-14 20:13:47 +02002511 case HCI_OP_READ_DEF_LINK_POLICY:
2512 hci_cc_read_def_link_policy(hdev, skb);
2513 break;
2514
2515 case HCI_OP_WRITE_DEF_LINK_POLICY:
2516 hci_cc_write_def_link_policy(hdev, skb);
2517 break;
2518
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002519 case HCI_OP_RESET:
2520 hci_cc_reset(hdev, skb);
2521 break;
2522
2523 case HCI_OP_WRITE_LOCAL_NAME:
2524 hci_cc_write_local_name(hdev, skb);
2525 break;
2526
2527 case HCI_OP_READ_LOCAL_NAME:
2528 hci_cc_read_local_name(hdev, skb);
2529 break;
2530
2531 case HCI_OP_WRITE_AUTH_ENABLE:
2532 hci_cc_write_auth_enable(hdev, skb);
2533 break;
2534
2535 case HCI_OP_WRITE_ENCRYPT_MODE:
2536 hci_cc_write_encrypt_mode(hdev, skb);
2537 break;
2538
2539 case HCI_OP_WRITE_SCAN_ENABLE:
2540 hci_cc_write_scan_enable(hdev, skb);
2541 break;
2542
2543 case HCI_OP_READ_CLASS_OF_DEV:
2544 hci_cc_read_class_of_dev(hdev, skb);
2545 break;
2546
2547 case HCI_OP_WRITE_CLASS_OF_DEV:
2548 hci_cc_write_class_of_dev(hdev, skb);
2549 break;
2550
2551 case HCI_OP_READ_VOICE_SETTING:
2552 hci_cc_read_voice_setting(hdev, skb);
2553 break;
2554
2555 case HCI_OP_WRITE_VOICE_SETTING:
2556 hci_cc_write_voice_setting(hdev, skb);
2557 break;
2558
2559 case HCI_OP_HOST_BUFFER_SIZE:
2560 hci_cc_host_buffer_size(hdev, skb);
2561 break;
2562
Marcel Holtmann333140b2008-07-14 20:13:48 +02002563 case HCI_OP_WRITE_SSP_MODE:
2564 hci_cc_write_ssp_mode(hdev, skb);
2565 break;
2566
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002567 case HCI_OP_READ_LOCAL_VERSION:
2568 hci_cc_read_local_version(hdev, skb);
2569 break;
2570
2571 case HCI_OP_READ_LOCAL_COMMANDS:
2572 hci_cc_read_local_commands(hdev, skb);
2573 break;
2574
2575 case HCI_OP_READ_LOCAL_FEATURES:
2576 hci_cc_read_local_features(hdev, skb);
2577 break;
2578
Andre Guedes971e3a42011-06-30 19:20:52 -03002579 case HCI_OP_READ_LOCAL_EXT_FEATURES:
2580 hci_cc_read_local_ext_features(hdev, skb);
2581 break;
2582
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002583 case HCI_OP_READ_BUFFER_SIZE:
2584 hci_cc_read_buffer_size(hdev, skb);
2585 break;
2586
2587 case HCI_OP_READ_BD_ADDR:
2588 hci_cc_read_bd_addr(hdev, skb);
2589 break;
2590
Andrei Emeltchenko350ee4c2011-12-07 15:56:51 +02002591 case HCI_OP_READ_DATA_BLOCK_SIZE:
2592 hci_cc_read_data_block_size(hdev, skb);
2593 break;
2594
Johan Hedberg23bb5762010-12-21 23:01:27 +02002595 case HCI_OP_WRITE_CA_TIMEOUT:
2596 hci_cc_write_ca_timeout(hdev, skb);
2597 break;
2598
Andrei Emeltchenko1e89cff2011-11-24 14:52:02 +02002599 case HCI_OP_READ_FLOW_CONTROL_MODE:
2600 hci_cc_read_flow_control_mode(hdev, skb);
2601 break;
2602
Andrei Emeltchenko928abaa2011-10-12 10:53:57 +03002603 case HCI_OP_READ_LOCAL_AMP_INFO:
2604 hci_cc_read_local_amp_info(hdev, skb);
2605 break;
2606
Andrei Emeltchenko903e4542012-09-27 17:26:09 +03002607 case HCI_OP_READ_LOCAL_AMP_ASSOC:
2608 hci_cc_read_local_amp_assoc(hdev, skb);
2609 break;
2610
Johan Hedbergb0916ea2011-01-10 13:44:55 +02002611 case HCI_OP_DELETE_STORED_LINK_KEY:
2612 hci_cc_delete_stored_link_key(hdev, skb);
2613 break;
2614
Johan Hedbergd5859e22011-01-25 01:19:58 +02002615 case HCI_OP_SET_EVENT_MASK:
2616 hci_cc_set_event_mask(hdev, skb);
2617 break;
2618
2619 case HCI_OP_WRITE_INQUIRY_MODE:
2620 hci_cc_write_inquiry_mode(hdev, skb);
2621 break;
2622
2623 case HCI_OP_READ_INQ_RSP_TX_POWER:
2624 hci_cc_read_inq_rsp_tx_power(hdev, skb);
2625 break;
2626
2627 case HCI_OP_SET_EVENT_FLT:
2628 hci_cc_set_event_flt(hdev, skb);
2629 break;
2630
Johan Hedberg980e1a52011-01-22 06:10:07 +02002631 case HCI_OP_PIN_CODE_REPLY:
2632 hci_cc_pin_code_reply(hdev, skb);
2633 break;
2634
2635 case HCI_OP_PIN_CODE_NEG_REPLY:
2636 hci_cc_pin_code_neg_reply(hdev, skb);
2637 break;
2638
Szymon Jancc35938b2011-03-22 13:12:21 +01002639 case HCI_OP_READ_LOCAL_OOB_DATA:
2640 hci_cc_read_local_oob_data_reply(hdev, skb);
2641 break;
2642
Ville Tervo6ed58ec2011-02-10 22:38:48 -03002643 case HCI_OP_LE_READ_BUFFER_SIZE:
2644 hci_cc_le_read_buffer_size(hdev, skb);
2645 break;
2646
Johan Hedberg60e77322013-01-22 14:01:59 +02002647 case HCI_OP_LE_READ_LOCAL_FEATURES:
2648 hci_cc_le_read_local_features(hdev, skb);
2649 break;
2650
Johan Hedberg8fa19092012-10-19 20:57:49 +03002651 case HCI_OP_LE_READ_ADV_TX_POWER:
2652 hci_cc_le_read_adv_tx_power(hdev, skb);
2653 break;
2654
Johan Hedberge36b04c2012-10-19 20:57:47 +03002655 case HCI_OP_LE_SET_EVENT_MASK:
2656 hci_cc_le_set_event_mask(hdev, skb);
2657 break;
2658
Johan Hedberga5c29682011-02-19 12:05:57 -03002659 case HCI_OP_USER_CONFIRM_REPLY:
2660 hci_cc_user_confirm_reply(hdev, skb);
2661 break;
2662
2663 case HCI_OP_USER_CONFIRM_NEG_REPLY:
2664 hci_cc_user_confirm_neg_reply(hdev, skb);
2665 break;
2666
Brian Gix1143d452011-11-23 08:28:34 -08002667 case HCI_OP_USER_PASSKEY_REPLY:
2668 hci_cc_user_passkey_reply(hdev, skb);
2669 break;
2670
2671 case HCI_OP_USER_PASSKEY_NEG_REPLY:
2672 hci_cc_user_passkey_neg_reply(hdev, skb);
Szymon Janc16cde992012-04-13 12:32:42 +02002673 break;
Andre Guedes07f7fa52011-12-02 21:13:31 +09002674
2675 case HCI_OP_LE_SET_SCAN_PARAM:
2676 hci_cc_le_set_scan_param(hdev, skb);
Brian Gix1143d452011-11-23 08:28:34 -08002677 break;
2678
Johan Hedbergc1d5dc42012-11-08 01:23:01 +01002679 case HCI_OP_LE_SET_ADV_ENABLE:
2680 hci_cc_le_set_adv_enable(hdev, skb);
2681 break;
2682
Andre Guedeseb9d91f2011-05-26 16:23:52 -03002683 case HCI_OP_LE_SET_SCAN_ENABLE:
2684 hci_cc_le_set_scan_enable(hdev, skb);
2685 break;
2686
Vinicius Costa Gomesa7a595f2011-06-09 18:50:47 -03002687 case HCI_OP_LE_LTK_REPLY:
2688 hci_cc_le_ltk_reply(hdev, skb);
2689 break;
2690
2691 case HCI_OP_LE_LTK_NEG_REPLY:
2692 hci_cc_le_ltk_neg_reply(hdev, skb);
2693 break;
2694
Andre Guedesf9b49302011-06-30 19:20:53 -03002695 case HCI_OP_WRITE_LE_HOST_SUPPORTED:
2696 hci_cc_write_le_host_supported(hdev, skb);
2697 break;
2698
Andrei Emeltchenko93c284e2012-09-27 17:26:20 +03002699 case HCI_OP_WRITE_REMOTE_AMP_ASSOC:
2700 hci_cc_write_remote_amp_assoc(hdev, skb);
2701 break;
2702
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002703 default:
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +03002704 BT_DBG("%s opcode 0x%4.4x", hdev->name, opcode);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002705 break;
2706 }
2707
Ville Tervo6bd32322011-02-16 16:32:41 +02002708 if (ev->opcode != HCI_OP_NOP)
2709 del_timer(&hdev->cmd_timer);
2710
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002711 if (ev->ncmd) {
2712 atomic_set(&hdev->cmd_cnt, 1);
2713 if (!skb_queue_empty(&hdev->cmd_q))
Gustavo F. Padovanc347b762011-12-14 23:53:47 -02002714 queue_work(hdev->workqueue, &hdev->cmd_work);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002715 }
2716}
2717
Gustavo Padovan6039aa72012-05-23 04:04:18 -03002718static void hci_cmd_status_evt(struct hci_dev *hdev, struct sk_buff *skb)
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002719{
2720 struct hci_ev_cmd_status *ev = (void *) skb->data;
2721 __u16 opcode;
2722
2723 skb_pull(skb, sizeof(*ev));
2724
2725 opcode = __le16_to_cpu(ev->opcode);
2726
2727 switch (opcode) {
2728 case HCI_OP_INQUIRY:
2729 hci_cs_inquiry(hdev, ev->status);
2730 break;
2731
2732 case HCI_OP_CREATE_CONN:
2733 hci_cs_create_conn(hdev, ev->status);
2734 break;
2735
2736 case HCI_OP_ADD_SCO:
2737 hci_cs_add_sco(hdev, ev->status);
2738 break;
2739
Marcel Holtmannf8558552008-07-14 20:13:49 +02002740 case HCI_OP_AUTH_REQUESTED:
2741 hci_cs_auth_requested(hdev, ev->status);
2742 break;
2743
2744 case HCI_OP_SET_CONN_ENCRYPT:
2745 hci_cs_set_conn_encrypt(hdev, ev->status);
2746 break;
2747
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002748 case HCI_OP_REMOTE_NAME_REQ:
2749 hci_cs_remote_name_req(hdev, ev->status);
2750 break;
2751
Marcel Holtmann769be972008-07-14 20:13:49 +02002752 case HCI_OP_READ_REMOTE_FEATURES:
2753 hci_cs_read_remote_features(hdev, ev->status);
2754 break;
2755
2756 case HCI_OP_READ_REMOTE_EXT_FEATURES:
2757 hci_cs_read_remote_ext_features(hdev, ev->status);
2758 break;
2759
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002760 case HCI_OP_SETUP_SYNC_CONN:
2761 hci_cs_setup_sync_conn(hdev, ev->status);
2762 break;
2763
2764 case HCI_OP_SNIFF_MODE:
2765 hci_cs_sniff_mode(hdev, ev->status);
2766 break;
2767
2768 case HCI_OP_EXIT_SNIFF_MODE:
2769 hci_cs_exit_sniff_mode(hdev, ev->status);
2770 break;
2771
Johan Hedberg8962ee72011-01-20 12:40:27 +02002772 case HCI_OP_DISCONNECT:
Johan Hedberg88c3df12012-02-09 14:27:38 +02002773 hci_cs_disconnect(hdev, ev->status);
Johan Hedberg8962ee72011-01-20 12:40:27 +02002774 break;
2775
Ville Tervofcd89c02011-02-10 22:38:47 -03002776 case HCI_OP_LE_CREATE_CONN:
2777 hci_cs_le_create_conn(hdev, ev->status);
2778 break;
2779
Vinicius Costa Gomesa7a595f2011-06-09 18:50:47 -03002780 case HCI_OP_LE_START_ENC:
2781 hci_cs_le_start_enc(hdev, ev->status);
2782 break;
2783
Andrei Emeltchenkoa02226d2012-09-27 17:26:19 +03002784 case HCI_OP_CREATE_PHY_LINK:
2785 hci_cs_create_phylink(hdev, ev->status);
2786 break;
2787
Andrei Emeltchenko0b26ab92012-09-27 17:26:24 +03002788 case HCI_OP_ACCEPT_PHY_LINK:
2789 hci_cs_accept_phylink(hdev, ev->status);
2790 break;
2791
Andrei Emeltchenko5ce66b52012-10-31 15:46:30 +02002792 case HCI_OP_CREATE_LOGICAL_LINK:
2793 hci_cs_create_logical_link(hdev, ev->status);
2794 break;
2795
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002796 default:
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +03002797 BT_DBG("%s opcode 0x%4.4x", hdev->name, opcode);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002798 break;
2799 }
2800
Ville Tervo6bd32322011-02-16 16:32:41 +02002801 if (ev->opcode != HCI_OP_NOP)
2802 del_timer(&hdev->cmd_timer);
2803
Gustavo F. Padovan10572132011-03-16 15:36:29 -03002804 if (ev->ncmd && !test_bit(HCI_RESET, &hdev->flags)) {
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002805 atomic_set(&hdev->cmd_cnt, 1);
2806 if (!skb_queue_empty(&hdev->cmd_q))
Gustavo F. Padovanc347b762011-12-14 23:53:47 -02002807 queue_work(hdev->workqueue, &hdev->cmd_work);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002808 }
2809}
2810
Gustavo Padovan6039aa72012-05-23 04:04:18 -03002811static void hci_role_change_evt(struct hci_dev *hdev, struct sk_buff *skb)
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002812{
2813 struct hci_ev_role_change *ev = (void *) skb->data;
2814 struct hci_conn *conn;
2815
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +03002816 BT_DBG("%s status 0x%2.2x", hdev->name, ev->status);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002817
2818 hci_dev_lock(hdev);
2819
2820 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
2821 if (conn) {
2822 if (!ev->status) {
2823 if (ev->role)
2824 conn->link_mode &= ~HCI_LM_MASTER;
2825 else
2826 conn->link_mode |= HCI_LM_MASTER;
2827 }
2828
Johan Hedberg51a8efd2012-01-16 06:10:31 +02002829 clear_bit(HCI_CONN_RSWITCH_PEND, &conn->flags);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002830
2831 hci_role_switch_cfm(conn, ev->status, ev->role);
2832 }
2833
2834 hci_dev_unlock(hdev);
2835}
2836
Gustavo Padovan6039aa72012-05-23 04:04:18 -03002837static void hci_num_comp_pkts_evt(struct hci_dev *hdev, struct sk_buff *skb)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002838{
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002839 struct hci_ev_num_comp_pkts *ev = (void *) skb->data;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002840 int i;
2841
Andrei Emeltchenko32ac5b92011-12-19 16:31:29 +02002842 if (hdev->flow_ctl_mode != HCI_FLOW_CTL_MODE_PACKET_BASED) {
2843 BT_ERR("Wrong event for mode %d", hdev->flow_ctl_mode);
2844 return;
2845 }
2846
Andrei Emeltchenkoc5993de2011-12-30 12:07:47 +02002847 if (skb->len < sizeof(*ev) || skb->len < sizeof(*ev) +
Gustavo Padovan807deac2012-05-17 00:36:24 -03002848 ev->num_hndl * sizeof(struct hci_comp_pkts_info)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002849 BT_DBG("%s bad parameters", hdev->name);
2850 return;
2851 }
2852
Andrei Emeltchenkoc5993de2011-12-30 12:07:47 +02002853 BT_DBG("%s num_hndl %d", hdev->name, ev->num_hndl);
2854
Andrei Emeltchenko613a1c02011-12-19 16:31:30 +02002855 for (i = 0; i < ev->num_hndl; i++) {
2856 struct hci_comp_pkts_info *info = &ev->handles[i];
Linus Torvalds1da177e2005-04-16 15:20:36 -07002857 struct hci_conn *conn;
2858 __u16 handle, count;
2859
Andrei Emeltchenko613a1c02011-12-19 16:31:30 +02002860 handle = __le16_to_cpu(info->handle);
2861 count = __le16_to_cpu(info->count);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002862
2863 conn = hci_conn_hash_lookup_handle(hdev, handle);
Andrei Emeltchenkof4280912011-12-07 15:56:52 +02002864 if (!conn)
2865 continue;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002866
Andrei Emeltchenkof4280912011-12-07 15:56:52 +02002867 conn->sent -= count;
2868
2869 switch (conn->type) {
2870 case ACL_LINK:
2871 hdev->acl_cnt += count;
2872 if (hdev->acl_cnt > hdev->acl_pkts)
2873 hdev->acl_cnt = hdev->acl_pkts;
2874 break;
2875
2876 case LE_LINK:
2877 if (hdev->le_pkts) {
2878 hdev->le_cnt += count;
2879 if (hdev->le_cnt > hdev->le_pkts)
2880 hdev->le_cnt = hdev->le_pkts;
2881 } else {
Andrei Emeltchenko70f230202010-12-01 16:58:25 +02002882 hdev->acl_cnt += count;
2883 if (hdev->acl_cnt > hdev->acl_pkts)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002884 hdev->acl_cnt = hdev->acl_pkts;
2885 }
Andrei Emeltchenkof4280912011-12-07 15:56:52 +02002886 break;
2887
2888 case SCO_LINK:
2889 hdev->sco_cnt += count;
2890 if (hdev->sco_cnt > hdev->sco_pkts)
2891 hdev->sco_cnt = hdev->sco_pkts;
2892 break;
2893
2894 default:
2895 BT_ERR("Unknown type %d conn %p", conn->type, conn);
2896 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002897 }
2898 }
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002899
Gustavo F. Padovan3eff45e2011-12-15 00:50:02 -02002900 queue_work(hdev->workqueue, &hdev->tx_work);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002901}
2902
Andrei Emeltchenko76ef7cf2012-10-10 17:38:29 +03002903static struct hci_conn *__hci_conn_lookup_handle(struct hci_dev *hdev,
2904 __u16 handle)
2905{
2906 struct hci_chan *chan;
2907
2908 switch (hdev->dev_type) {
2909 case HCI_BREDR:
2910 return hci_conn_hash_lookup_handle(hdev, handle);
2911 case HCI_AMP:
2912 chan = hci_chan_lookup_handle(hdev, handle);
2913 if (chan)
2914 return chan->conn;
2915 break;
2916 default:
2917 BT_ERR("%s unknown dev_type %d", hdev->name, hdev->dev_type);
2918 break;
2919 }
2920
2921 return NULL;
2922}
2923
Gustavo Padovan6039aa72012-05-23 04:04:18 -03002924static void hci_num_comp_blocks_evt(struct hci_dev *hdev, struct sk_buff *skb)
Andrei Emeltchenko25e89e92012-01-04 12:41:58 +02002925{
2926 struct hci_ev_num_comp_blocks *ev = (void *) skb->data;
2927 int i;
2928
2929 if (hdev->flow_ctl_mode != HCI_FLOW_CTL_MODE_BLOCK_BASED) {
2930 BT_ERR("Wrong event for mode %d", hdev->flow_ctl_mode);
2931 return;
2932 }
2933
2934 if (skb->len < sizeof(*ev) || skb->len < sizeof(*ev) +
Gustavo Padovan807deac2012-05-17 00:36:24 -03002935 ev->num_hndl * sizeof(struct hci_comp_blocks_info)) {
Andrei Emeltchenko25e89e92012-01-04 12:41:58 +02002936 BT_DBG("%s bad parameters", hdev->name);
2937 return;
2938 }
2939
2940 BT_DBG("%s num_blocks %d num_hndl %d", hdev->name, ev->num_blocks,
Gustavo Padovan807deac2012-05-17 00:36:24 -03002941 ev->num_hndl);
Andrei Emeltchenko25e89e92012-01-04 12:41:58 +02002942
2943 for (i = 0; i < ev->num_hndl; i++) {
2944 struct hci_comp_blocks_info *info = &ev->handles[i];
Andrei Emeltchenko76ef7cf2012-10-10 17:38:29 +03002945 struct hci_conn *conn = NULL;
Andrei Emeltchenko25e89e92012-01-04 12:41:58 +02002946 __u16 handle, block_count;
2947
2948 handle = __le16_to_cpu(info->handle);
2949 block_count = __le16_to_cpu(info->blocks);
2950
Andrei Emeltchenko76ef7cf2012-10-10 17:38:29 +03002951 conn = __hci_conn_lookup_handle(hdev, handle);
Andrei Emeltchenko25e89e92012-01-04 12:41:58 +02002952 if (!conn)
2953 continue;
2954
2955 conn->sent -= block_count;
2956
2957 switch (conn->type) {
2958 case ACL_LINK:
Andrei Emeltchenkobd1eb662012-10-10 17:38:30 +03002959 case AMP_LINK:
Andrei Emeltchenko25e89e92012-01-04 12:41:58 +02002960 hdev->block_cnt += block_count;
2961 if (hdev->block_cnt > hdev->num_blocks)
2962 hdev->block_cnt = hdev->num_blocks;
2963 break;
2964
2965 default:
2966 BT_ERR("Unknown type %d conn %p", conn->type, conn);
2967 break;
2968 }
2969 }
2970
2971 queue_work(hdev->workqueue, &hdev->tx_work);
2972}
2973
Gustavo Padovan6039aa72012-05-23 04:04:18 -03002974static void hci_mode_change_evt(struct hci_dev *hdev, struct sk_buff *skb)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002975{
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002976 struct hci_ev_mode_change *ev = (void *) skb->data;
Marcel Holtmann04837f62006-07-03 10:02:33 +02002977 struct hci_conn *conn;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002978
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +03002979 BT_DBG("%s status 0x%2.2x", hdev->name, ev->status);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002980
2981 hci_dev_lock(hdev);
2982
Marcel Holtmann04837f62006-07-03 10:02:33 +02002983 conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
2984 if (conn) {
2985 conn->mode = ev->mode;
2986 conn->interval = __le16_to_cpu(ev->interval);
2987
Gustavo Padovan8fc9ced2012-05-23 04:04:21 -03002988 if (!test_and_clear_bit(HCI_CONN_MODE_CHANGE_PEND,
2989 &conn->flags)) {
Marcel Holtmann04837f62006-07-03 10:02:33 +02002990 if (conn->mode == HCI_CM_ACTIVE)
Johan Hedberg58a681e2012-01-16 06:47:28 +02002991 set_bit(HCI_CONN_POWER_SAVE, &conn->flags);
Marcel Holtmann04837f62006-07-03 10:02:33 +02002992 else
Johan Hedberg58a681e2012-01-16 06:47:28 +02002993 clear_bit(HCI_CONN_POWER_SAVE, &conn->flags);
Marcel Holtmann04837f62006-07-03 10:02:33 +02002994 }
Marcel Holtmanne73439d2010-07-26 10:06:00 -04002995
Johan Hedberg51a8efd2012-01-16 06:10:31 +02002996 if (test_and_clear_bit(HCI_CONN_SCO_SETUP_PEND, &conn->flags))
Marcel Holtmanne73439d2010-07-26 10:06:00 -04002997 hci_sco_setup(conn, ev->status);
Marcel Holtmann04837f62006-07-03 10:02:33 +02002998 }
2999
3000 hci_dev_unlock(hdev);
3001}
3002
Gustavo Padovan6039aa72012-05-23 04:04:18 -03003003static void hci_pin_code_request_evt(struct hci_dev *hdev, struct sk_buff *skb)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003004{
Marcel Holtmann052b30b2009-04-26 20:01:22 +02003005 struct hci_ev_pin_code_req *ev = (void *) skb->data;
3006 struct hci_conn *conn;
3007
Marcel Holtmanna9de9242007-10-20 13:33:56 +02003008 BT_DBG("%s", hdev->name);
Marcel Holtmann052b30b2009-04-26 20:01:22 +02003009
3010 hci_dev_lock(hdev);
3011
3012 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
Waldemar Rymarkiewiczb6f98042011-09-23 10:01:30 +02003013 if (!conn)
3014 goto unlock;
3015
3016 if (conn->state == BT_CONNECTED) {
Marcel Holtmann052b30b2009-04-26 20:01:22 +02003017 hci_conn_hold(conn);
3018 conn->disc_timeout = HCI_PAIRING_TIMEOUT;
3019 hci_conn_put(conn);
3020 }
3021
Johan Hedberga8b2d5c2012-01-08 23:11:15 +02003022 if (!test_bit(HCI_PAIRABLE, &hdev->dev_flags))
Johan Hedberg03b555e2011-01-04 15:40:05 +02003023 hci_send_cmd(hdev, HCI_OP_PIN_CODE_NEG_REPLY,
Gustavo Padovan807deac2012-05-17 00:36:24 -03003024 sizeof(ev->bdaddr), &ev->bdaddr);
Johan Hedberga8b2d5c2012-01-08 23:11:15 +02003025 else if (test_bit(HCI_MGMT, &hdev->dev_flags)) {
Waldemar Rymarkiewicza770bb52011-04-28 12:07:59 +02003026 u8 secure;
3027
3028 if (conn->pending_sec_level == BT_SECURITY_HIGH)
3029 secure = 1;
3030 else
3031 secure = 0;
3032
Johan Hedberg744cf192011-11-08 20:40:14 +02003033 mgmt_pin_code_request(hdev, &ev->bdaddr, secure);
Waldemar Rymarkiewicza770bb52011-04-28 12:07:59 +02003034 }
Johan Hedberg980e1a52011-01-22 06:10:07 +02003035
Waldemar Rymarkiewiczb6f98042011-09-23 10:01:30 +02003036unlock:
Marcel Holtmann052b30b2009-04-26 20:01:22 +02003037 hci_dev_unlock(hdev);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003038}
3039
Gustavo Padovan6039aa72012-05-23 04:04:18 -03003040static void hci_link_key_request_evt(struct hci_dev *hdev, struct sk_buff *skb)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003041{
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02003042 struct hci_ev_link_key_req *ev = (void *) skb->data;
3043 struct hci_cp_link_key_reply cp;
3044 struct hci_conn *conn;
3045 struct link_key *key;
3046
Marcel Holtmanna9de9242007-10-20 13:33:56 +02003047 BT_DBG("%s", hdev->name);
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02003048
Johan Hedberga8b2d5c2012-01-08 23:11:15 +02003049 if (!test_bit(HCI_LINK_KEYS, &hdev->dev_flags))
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02003050 return;
3051
3052 hci_dev_lock(hdev);
3053
3054 key = hci_find_link_key(hdev, &ev->bdaddr);
3055 if (!key) {
Andrei Emeltchenko6ed93dc2012-09-25 12:49:43 +03003056 BT_DBG("%s link key not found for %pMR", hdev->name,
3057 &ev->bdaddr);
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02003058 goto not_found;
3059 }
3060
Andrei Emeltchenko6ed93dc2012-09-25 12:49:43 +03003061 BT_DBG("%s found key type %u for %pMR", hdev->name, key->type,
3062 &ev->bdaddr);
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02003063
Johan Hedberga8b2d5c2012-01-08 23:11:15 +02003064 if (!test_bit(HCI_DEBUG_KEYS, &hdev->dev_flags) &&
Gustavo Padovan807deac2012-05-17 00:36:24 -03003065 key->type == HCI_LK_DEBUG_COMBINATION) {
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02003066 BT_DBG("%s ignoring debug key", hdev->name);
3067 goto not_found;
3068 }
3069
3070 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
Waldemar Rymarkiewicz60b83f52011-04-28 12:07:56 +02003071 if (conn) {
3072 if (key->type == HCI_LK_UNAUTH_COMBINATION &&
Gustavo Padovan807deac2012-05-17 00:36:24 -03003073 conn->auth_type != 0xff && (conn->auth_type & 0x01)) {
Waldemar Rymarkiewicz60b83f52011-04-28 12:07:56 +02003074 BT_DBG("%s ignoring unauthenticated key", hdev->name);
3075 goto not_found;
3076 }
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02003077
Waldemar Rymarkiewicz60b83f52011-04-28 12:07:56 +02003078 if (key->type == HCI_LK_COMBINATION && key->pin_len < 16 &&
Gustavo Padovan807deac2012-05-17 00:36:24 -03003079 conn->pending_sec_level == BT_SECURITY_HIGH) {
Gustavo Padovan8fc9ced2012-05-23 04:04:21 -03003080 BT_DBG("%s ignoring key unauthenticated for high security",
3081 hdev->name);
Waldemar Rymarkiewicz60b83f52011-04-28 12:07:56 +02003082 goto not_found;
3083 }
3084
3085 conn->key_type = key->type;
3086 conn->pin_length = key->pin_len;
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02003087 }
3088
3089 bacpy(&cp.bdaddr, &ev->bdaddr);
Andrei Emeltchenko9b3b4462012-05-23 11:31:20 +03003090 memcpy(cp.link_key, key->val, HCI_LINK_KEY_SIZE);
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02003091
3092 hci_send_cmd(hdev, HCI_OP_LINK_KEY_REPLY, sizeof(cp), &cp);
3093
3094 hci_dev_unlock(hdev);
3095
3096 return;
3097
3098not_found:
3099 hci_send_cmd(hdev, HCI_OP_LINK_KEY_NEG_REPLY, 6, &ev->bdaddr);
3100 hci_dev_unlock(hdev);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003101}
3102
Gustavo Padovan6039aa72012-05-23 04:04:18 -03003103static void hci_link_key_notify_evt(struct hci_dev *hdev, struct sk_buff *skb)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003104{
Marcel Holtmann052b30b2009-04-26 20:01:22 +02003105 struct hci_ev_link_key_notify *ev = (void *) skb->data;
3106 struct hci_conn *conn;
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02003107 u8 pin_len = 0;
Marcel Holtmann052b30b2009-04-26 20:01:22 +02003108
Marcel Holtmanna9de9242007-10-20 13:33:56 +02003109 BT_DBG("%s", hdev->name);
Marcel Holtmann052b30b2009-04-26 20:01:22 +02003110
3111 hci_dev_lock(hdev);
3112
3113 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
3114 if (conn) {
3115 hci_conn_hold(conn);
3116 conn->disc_timeout = HCI_DISCONN_TIMEOUT;
Johan Hedberg980e1a52011-01-22 06:10:07 +02003117 pin_len = conn->pin_length;
Waldemar Rymarkiewicz13d39312011-04-28 12:07:55 +02003118
3119 if (ev->key_type != HCI_LK_CHANGED_COMBINATION)
3120 conn->key_type = ev->key_type;
3121
Marcel Holtmann052b30b2009-04-26 20:01:22 +02003122 hci_conn_put(conn);
3123 }
3124
Johan Hedberga8b2d5c2012-01-08 23:11:15 +02003125 if (test_bit(HCI_LINK_KEYS, &hdev->dev_flags))
Johan Hedbergd25e28a2011-04-28 11:28:59 -07003126 hci_add_link_key(hdev, conn, 1, &ev->bdaddr, ev->link_key,
Gustavo Padovan807deac2012-05-17 00:36:24 -03003127 ev->key_type, pin_len);
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02003128
Marcel Holtmann052b30b2009-04-26 20:01:22 +02003129 hci_dev_unlock(hdev);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003130}
3131
Gustavo Padovan6039aa72012-05-23 04:04:18 -03003132static void hci_clock_offset_evt(struct hci_dev *hdev, struct sk_buff *skb)
Marcel Holtmann04837f62006-07-03 10:02:33 +02003133{
Marcel Holtmanna9de9242007-10-20 13:33:56 +02003134 struct hci_ev_clock_offset *ev = (void *) skb->data;
Marcel Holtmann04837f62006-07-03 10:02:33 +02003135 struct hci_conn *conn;
3136
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +03003137 BT_DBG("%s status 0x%2.2x", hdev->name, ev->status);
Marcel Holtmann04837f62006-07-03 10:02:33 +02003138
3139 hci_dev_lock(hdev);
3140
3141 conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
Linus Torvalds1da177e2005-04-16 15:20:36 -07003142 if (conn && !ev->status) {
3143 struct inquiry_entry *ie;
3144
Andrei Emeltchenkocc11b9c2010-11-22 13:21:37 +02003145 ie = hci_inquiry_cache_lookup(hdev, &conn->dst);
3146 if (ie) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003147 ie->data.clock_offset = ev->clock_offset;
3148 ie->timestamp = jiffies;
3149 }
3150 }
3151
3152 hci_dev_unlock(hdev);
3153}
3154
Gustavo Padovan6039aa72012-05-23 04:04:18 -03003155static void hci_pkt_type_change_evt(struct hci_dev *hdev, struct sk_buff *skb)
Marcel Holtmanna8746412008-07-14 20:13:46 +02003156{
3157 struct hci_ev_pkt_type_change *ev = (void *) skb->data;
3158 struct hci_conn *conn;
3159
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +03003160 BT_DBG("%s status 0x%2.2x", hdev->name, ev->status);
Marcel Holtmanna8746412008-07-14 20:13:46 +02003161
3162 hci_dev_lock(hdev);
3163
3164 conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
3165 if (conn && !ev->status)
3166 conn->pkt_type = __le16_to_cpu(ev->pkt_type);
3167
3168 hci_dev_unlock(hdev);
3169}
3170
Gustavo Padovan6039aa72012-05-23 04:04:18 -03003171static void hci_pscan_rep_mode_evt(struct hci_dev *hdev, struct sk_buff *skb)
Marcel Holtmann85a1e932005-08-09 20:28:02 -07003172{
Marcel Holtmanna9de9242007-10-20 13:33:56 +02003173 struct hci_ev_pscan_rep_mode *ev = (void *) skb->data;
Marcel Holtmann85a1e932005-08-09 20:28:02 -07003174 struct inquiry_entry *ie;
3175
3176 BT_DBG("%s", hdev->name);
3177
3178 hci_dev_lock(hdev);
3179
Andrei Emeltchenkocc11b9c2010-11-22 13:21:37 +02003180 ie = hci_inquiry_cache_lookup(hdev, &ev->bdaddr);
3181 if (ie) {
Marcel Holtmann85a1e932005-08-09 20:28:02 -07003182 ie->data.pscan_rep_mode = ev->pscan_rep_mode;
3183 ie->timestamp = jiffies;
3184 }
3185
3186 hci_dev_unlock(hdev);
3187}
3188
Gustavo Padovan6039aa72012-05-23 04:04:18 -03003189static void hci_inquiry_result_with_rssi_evt(struct hci_dev *hdev,
3190 struct sk_buff *skb)
Marcel Holtmanna9de9242007-10-20 13:33:56 +02003191{
3192 struct inquiry_data data;
3193 int num_rsp = *((__u8 *) skb->data);
Johan Hedberg388fc8f2012-02-23 00:38:59 +02003194 bool name_known, ssp;
Marcel Holtmanna9de9242007-10-20 13:33:56 +02003195
3196 BT_DBG("%s num_rsp %d", hdev->name, num_rsp);
3197
3198 if (!num_rsp)
3199 return;
3200
Andre Guedes1519cc12012-03-21 00:03:38 -03003201 if (test_bit(HCI_PERIODIC_INQ, &hdev->dev_flags))
3202 return;
3203
Marcel Holtmanna9de9242007-10-20 13:33:56 +02003204 hci_dev_lock(hdev);
3205
3206 if ((skb->len - 1) / num_rsp != sizeof(struct inquiry_info_with_rssi)) {
Szymon Janc138d22e2011-02-17 16:44:23 +01003207 struct inquiry_info_with_rssi_and_pscan_mode *info;
3208 info = (void *) (skb->data + 1);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02003209
Johan Hedberge17acd42011-03-30 23:57:16 +03003210 for (; num_rsp; num_rsp--, info++) {
Marcel Holtmanna9de9242007-10-20 13:33:56 +02003211 bacpy(&data.bdaddr, &info->bdaddr);
3212 data.pscan_rep_mode = info->pscan_rep_mode;
3213 data.pscan_period_mode = info->pscan_period_mode;
3214 data.pscan_mode = info->pscan_mode;
3215 memcpy(data.dev_class, info->dev_class, 3);
3216 data.clock_offset = info->clock_offset;
3217 data.rssi = info->rssi;
Marcel Holtmann41a96212008-07-14 20:13:48 +02003218 data.ssp_mode = 0x00;
Johan Hedberg31754052012-01-04 13:39:52 +02003219
3220 name_known = hci_inquiry_cache_update(hdev, &data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003221 false, &ssp);
Johan Hedberg48264f02011-11-09 13:58:58 +02003222 mgmt_device_found(hdev, &info->bdaddr, ACL_LINK, 0x00,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003223 info->dev_class, info->rssi,
3224 !name_known, ssp, NULL, 0);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02003225 }
3226 } else {
3227 struct inquiry_info_with_rssi *info = (void *) (skb->data + 1);
3228
Johan Hedberge17acd42011-03-30 23:57:16 +03003229 for (; num_rsp; num_rsp--, info++) {
Marcel Holtmanna9de9242007-10-20 13:33:56 +02003230 bacpy(&data.bdaddr, &info->bdaddr);
3231 data.pscan_rep_mode = info->pscan_rep_mode;
3232 data.pscan_period_mode = info->pscan_period_mode;
3233 data.pscan_mode = 0x00;
3234 memcpy(data.dev_class, info->dev_class, 3);
3235 data.clock_offset = info->clock_offset;
3236 data.rssi = info->rssi;
Marcel Holtmann41a96212008-07-14 20:13:48 +02003237 data.ssp_mode = 0x00;
Johan Hedberg31754052012-01-04 13:39:52 +02003238 name_known = hci_inquiry_cache_update(hdev, &data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003239 false, &ssp);
Johan Hedberg48264f02011-11-09 13:58:58 +02003240 mgmt_device_found(hdev, &info->bdaddr, ACL_LINK, 0x00,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003241 info->dev_class, info->rssi,
3242 !name_known, ssp, NULL, 0);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02003243 }
3244 }
3245
3246 hci_dev_unlock(hdev);
3247}
3248
Gustavo Padovan6039aa72012-05-23 04:04:18 -03003249static void hci_remote_ext_features_evt(struct hci_dev *hdev,
3250 struct sk_buff *skb)
Marcel Holtmanna9de9242007-10-20 13:33:56 +02003251{
Marcel Holtmann41a96212008-07-14 20:13:48 +02003252 struct hci_ev_remote_ext_features *ev = (void *) skb->data;
3253 struct hci_conn *conn;
3254
Marcel Holtmanna9de9242007-10-20 13:33:56 +02003255 BT_DBG("%s", hdev->name);
Marcel Holtmann41a96212008-07-14 20:13:48 +02003256
Marcel Holtmann41a96212008-07-14 20:13:48 +02003257 hci_dev_lock(hdev);
3258
3259 conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
Johan Hedbergccd556f2010-11-10 17:11:51 +02003260 if (!conn)
3261 goto unlock;
Marcel Holtmann41a96212008-07-14 20:13:48 +02003262
Johan Hedbergccd556f2010-11-10 17:11:51 +02003263 if (!ev->status && ev->page == 0x01) {
3264 struct inquiry_entry *ie;
Marcel Holtmann41a96212008-07-14 20:13:48 +02003265
Andrei Emeltchenkocc11b9c2010-11-22 13:21:37 +02003266 ie = hci_inquiry_cache_lookup(hdev, &conn->dst);
3267 if (ie)
Johan Hedberg02b7cc62012-02-28 02:28:43 +02003268 ie->data.ssp_mode = (ev->features[0] & LMP_HOST_SSP);
Marcel Holtmann769be972008-07-14 20:13:49 +02003269
Johan Hedberg02b7cc62012-02-28 02:28:43 +02003270 if (ev->features[0] & LMP_HOST_SSP)
Johan Hedberg58a681e2012-01-16 06:47:28 +02003271 set_bit(HCI_CONN_SSP_ENABLED, &conn->flags);
Marcel Holtmann41a96212008-07-14 20:13:48 +02003272 }
3273
Johan Hedbergccd556f2010-11-10 17:11:51 +02003274 if (conn->state != BT_CONFIG)
3275 goto unlock;
3276
Johan Hedberg671267b2012-05-12 16:11:50 -03003277 if (!ev->status && !test_bit(HCI_CONN_MGMT_CONNECTED, &conn->flags)) {
Johan Hedberg127178d2010-11-18 22:22:29 +02003278 struct hci_cp_remote_name_req cp;
3279 memset(&cp, 0, sizeof(cp));
3280 bacpy(&cp.bdaddr, &conn->dst);
3281 cp.pscan_rep_mode = 0x02;
3282 hci_send_cmd(hdev, HCI_OP_REMOTE_NAME_REQ, sizeof(cp), &cp);
Johan Hedbergb644ba32012-01-17 21:48:47 +02003283 } else if (!test_and_set_bit(HCI_CONN_MGMT_CONNECTED, &conn->flags))
3284 mgmt_device_connected(hdev, &conn->dst, conn->type,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003285 conn->dst_type, 0, NULL, 0,
3286 conn->dev_class);
Johan Hedberg392599b2010-11-18 22:22:28 +02003287
Johan Hedberg127178d2010-11-18 22:22:29 +02003288 if (!hci_outgoing_auth_needed(hdev, conn)) {
Johan Hedbergccd556f2010-11-10 17:11:51 +02003289 conn->state = BT_CONNECTED;
3290 hci_proto_connect_cfm(conn, ev->status);
3291 hci_conn_put(conn);
3292 }
3293
3294unlock:
Marcel Holtmann41a96212008-07-14 20:13:48 +02003295 hci_dev_unlock(hdev);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02003296}
3297
Gustavo Padovan6039aa72012-05-23 04:04:18 -03003298static void hci_sync_conn_complete_evt(struct hci_dev *hdev,
3299 struct sk_buff *skb)
Marcel Holtmanna9de9242007-10-20 13:33:56 +02003300{
Marcel Holtmannb6a0dc82007-10-20 14:55:10 +02003301 struct hci_ev_sync_conn_complete *ev = (void *) skb->data;
3302 struct hci_conn *conn;
3303
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +03003304 BT_DBG("%s status 0x%2.2x", hdev->name, ev->status);
Marcel Holtmannb6a0dc82007-10-20 14:55:10 +02003305
3306 hci_dev_lock(hdev);
3307
3308 conn = hci_conn_hash_lookup_ba(hdev, ev->link_type, &ev->bdaddr);
Marcel Holtmann9dc0a3a2008-07-14 20:13:46 +02003309 if (!conn) {
3310 if (ev->link_type == ESCO_LINK)
3311 goto unlock;
3312
3313 conn = hci_conn_hash_lookup_ba(hdev, ESCO_LINK, &ev->bdaddr);
3314 if (!conn)
3315 goto unlock;
3316
3317 conn->type = SCO_LINK;
3318 }
Marcel Holtmannb6a0dc82007-10-20 14:55:10 +02003319
Marcel Holtmann732547f2009-04-19 19:14:14 +02003320 switch (ev->status) {
3321 case 0x00:
Marcel Holtmannb6a0dc82007-10-20 14:55:10 +02003322 conn->handle = __le16_to_cpu(ev->handle);
3323 conn->state = BT_CONNECTED;
Marcel Holtmann7d0db0a2008-07-14 20:13:51 +02003324
Marcel Holtmann9eba32b2009-08-22 14:19:26 -07003325 hci_conn_hold_device(conn);
Marcel Holtmann7d0db0a2008-07-14 20:13:51 +02003326 hci_conn_add_sysfs(conn);
Marcel Holtmann732547f2009-04-19 19:14:14 +02003327 break;
3328
Stephen Coe705e5712010-02-16 11:29:44 -05003329 case 0x11: /* Unsupported Feature or Parameter Value */
Marcel Holtmann732547f2009-04-19 19:14:14 +02003330 case 0x1c: /* SCO interval rejected */
Nick Pelly1038a002010-02-03 11:42:26 -08003331 case 0x1a: /* Unsupported Remote Feature */
Marcel Holtmann732547f2009-04-19 19:14:14 +02003332 case 0x1f: /* Unspecified error */
3333 if (conn->out && conn->attempt < 2) {
3334 conn->pkt_type = (hdev->esco_type & SCO_ESCO_MASK) |
3335 (hdev->esco_type & EDR_ESCO_MASK);
3336 hci_setup_sync(conn, conn->link->handle);
3337 goto unlock;
3338 }
3339 /* fall through */
3340
3341 default:
Marcel Holtmannb6a0dc82007-10-20 14:55:10 +02003342 conn->state = BT_CLOSED;
Marcel Holtmann732547f2009-04-19 19:14:14 +02003343 break;
3344 }
Marcel Holtmannb6a0dc82007-10-20 14:55:10 +02003345
3346 hci_proto_connect_cfm(conn, ev->status);
3347 if (ev->status)
3348 hci_conn_del(conn);
3349
3350unlock:
3351 hci_dev_unlock(hdev);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02003352}
3353
Gustavo Padovan6039aa72012-05-23 04:04:18 -03003354static void hci_sync_conn_changed_evt(struct hci_dev *hdev, struct sk_buff *skb)
Marcel Holtmanna9de9242007-10-20 13:33:56 +02003355{
3356 BT_DBG("%s", hdev->name);
3357}
3358
Gustavo Padovan6039aa72012-05-23 04:04:18 -03003359static void hci_sniff_subrate_evt(struct hci_dev *hdev, struct sk_buff *skb)
Marcel Holtmann04837f62006-07-03 10:02:33 +02003360{
Marcel Holtmanna9de9242007-10-20 13:33:56 +02003361 struct hci_ev_sniff_subrate *ev = (void *) skb->data;
Marcel Holtmann04837f62006-07-03 10:02:33 +02003362
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +03003363 BT_DBG("%s status 0x%2.2x", hdev->name, ev->status);
Marcel Holtmann04837f62006-07-03 10:02:33 +02003364}
3365
Gustavo Padovan6039aa72012-05-23 04:04:18 -03003366static void hci_extended_inquiry_result_evt(struct hci_dev *hdev,
3367 struct sk_buff *skb)
Marcel Holtmanna9de9242007-10-20 13:33:56 +02003368{
3369 struct inquiry_data data;
3370 struct extended_inquiry_info *info = (void *) (skb->data + 1);
3371 int num_rsp = *((__u8 *) skb->data);
Vishal Agarwal9d939d92012-04-26 19:19:56 +05303372 size_t eir_len;
Marcel Holtmanna9de9242007-10-20 13:33:56 +02003373
3374 BT_DBG("%s num_rsp %d", hdev->name, num_rsp);
3375
3376 if (!num_rsp)
3377 return;
3378
Andre Guedes1519cc12012-03-21 00:03:38 -03003379 if (test_bit(HCI_PERIODIC_INQ, &hdev->dev_flags))
3380 return;
3381
Marcel Holtmanna9de9242007-10-20 13:33:56 +02003382 hci_dev_lock(hdev);
3383
Johan Hedberge17acd42011-03-30 23:57:16 +03003384 for (; num_rsp; num_rsp--, info++) {
Johan Hedberg388fc8f2012-02-23 00:38:59 +02003385 bool name_known, ssp;
Johan Hedberg561aafb2012-01-04 13:31:59 +02003386
Marcel Holtmanna9de9242007-10-20 13:33:56 +02003387 bacpy(&data.bdaddr, &info->bdaddr);
Szymon Janc138d22e2011-02-17 16:44:23 +01003388 data.pscan_rep_mode = info->pscan_rep_mode;
3389 data.pscan_period_mode = info->pscan_period_mode;
3390 data.pscan_mode = 0x00;
Marcel Holtmanna9de9242007-10-20 13:33:56 +02003391 memcpy(data.dev_class, info->dev_class, 3);
Szymon Janc138d22e2011-02-17 16:44:23 +01003392 data.clock_offset = info->clock_offset;
3393 data.rssi = info->rssi;
Marcel Holtmann41a96212008-07-14 20:13:48 +02003394 data.ssp_mode = 0x01;
Johan Hedberg561aafb2012-01-04 13:31:59 +02003395
Johan Hedberga8b2d5c2012-01-08 23:11:15 +02003396 if (test_bit(HCI_MGMT, &hdev->dev_flags))
Johan Hedberg4ddb1932012-01-15 20:04:43 +02003397 name_known = eir_has_data_type(info->data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003398 sizeof(info->data),
3399 EIR_NAME_COMPLETE);
Johan Hedberg561aafb2012-01-04 13:31:59 +02003400 else
3401 name_known = true;
3402
Johan Hedberg388fc8f2012-02-23 00:38:59 +02003403 name_known = hci_inquiry_cache_update(hdev, &data, name_known,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003404 &ssp);
Vishal Agarwal9d939d92012-04-26 19:19:56 +05303405 eir_len = eir_get_length(info->data, sizeof(info->data));
Johan Hedberg48264f02011-11-09 13:58:58 +02003406 mgmt_device_found(hdev, &info->bdaddr, ACL_LINK, 0x00,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003407 info->dev_class, info->rssi, !name_known,
Vishal Agarwal9d939d92012-04-26 19:19:56 +05303408 ssp, info->data, eir_len);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02003409 }
3410
3411 hci_dev_unlock(hdev);
3412}
3413
Johan Hedberg1c2e0042012-06-08 23:31:13 +08003414static void hci_key_refresh_complete_evt(struct hci_dev *hdev,
3415 struct sk_buff *skb)
3416{
3417 struct hci_ev_key_refresh_complete *ev = (void *) skb->data;
3418 struct hci_conn *conn;
3419
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +03003420 BT_DBG("%s status 0x%2.2x handle 0x%4.4x", hdev->name, ev->status,
Johan Hedberg1c2e0042012-06-08 23:31:13 +08003421 __le16_to_cpu(ev->handle));
3422
3423 hci_dev_lock(hdev);
3424
3425 conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
3426 if (!conn)
3427 goto unlock;
3428
3429 if (!ev->status)
3430 conn->sec_level = conn->pending_sec_level;
3431
3432 clear_bit(HCI_CONN_ENCRYPT_PEND, &conn->flags);
3433
3434 if (ev->status && conn->state == BT_CONNECTED) {
3435 hci_acl_disconn(conn, HCI_ERROR_AUTH_FAILURE);
3436 hci_conn_put(conn);
3437 goto unlock;
3438 }
3439
3440 if (conn->state == BT_CONFIG) {
3441 if (!ev->status)
3442 conn->state = BT_CONNECTED;
3443
3444 hci_proto_connect_cfm(conn, ev->status);
3445 hci_conn_put(conn);
3446 } else {
3447 hci_auth_cfm(conn, ev->status);
3448
3449 hci_conn_hold(conn);
3450 conn->disc_timeout = HCI_DISCONN_TIMEOUT;
3451 hci_conn_put(conn);
3452 }
3453
3454unlock:
3455 hci_dev_unlock(hdev);
3456}
3457
Gustavo Padovan6039aa72012-05-23 04:04:18 -03003458static u8 hci_get_auth_req(struct hci_conn *conn)
Johan Hedberg17fa4b92011-01-25 13:28:33 +02003459{
3460 /* If remote requests dedicated bonding follow that lead */
3461 if (conn->remote_auth == 0x02 || conn->remote_auth == 0x03) {
3462 /* If both remote and local IO capabilities allow MITM
3463 * protection then require it, otherwise don't */
3464 if (conn->remote_cap == 0x03 || conn->io_capability == 0x03)
3465 return 0x02;
3466 else
3467 return 0x03;
3468 }
3469
3470 /* If remote requests no-bonding follow that lead */
3471 if (conn->remote_auth == 0x00 || conn->remote_auth == 0x01)
Waldemar Rymarkiewicz58797bf2011-04-28 12:07:58 +02003472 return conn->remote_auth | (conn->auth_type & 0x01);
Johan Hedberg17fa4b92011-01-25 13:28:33 +02003473
3474 return conn->auth_type;
3475}
3476
Gustavo Padovan6039aa72012-05-23 04:04:18 -03003477static void hci_io_capa_request_evt(struct hci_dev *hdev, struct sk_buff *skb)
Marcel Holtmann04936842008-07-14 20:13:48 +02003478{
3479 struct hci_ev_io_capa_request *ev = (void *) skb->data;
3480 struct hci_conn *conn;
3481
3482 BT_DBG("%s", hdev->name);
3483
3484 hci_dev_lock(hdev);
3485
3486 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
Johan Hedberg03b555e2011-01-04 15:40:05 +02003487 if (!conn)
3488 goto unlock;
Marcel Holtmann04936842008-07-14 20:13:48 +02003489
Johan Hedberg03b555e2011-01-04 15:40:05 +02003490 hci_conn_hold(conn);
3491
Johan Hedberga8b2d5c2012-01-08 23:11:15 +02003492 if (!test_bit(HCI_MGMT, &hdev->dev_flags))
Johan Hedberg03b555e2011-01-04 15:40:05 +02003493 goto unlock;
3494
Johan Hedberga8b2d5c2012-01-08 23:11:15 +02003495 if (test_bit(HCI_PAIRABLE, &hdev->dev_flags) ||
Gustavo Padovan807deac2012-05-17 00:36:24 -03003496 (conn->remote_auth & ~0x01) == HCI_AT_NO_BONDING) {
Johan Hedberg17fa4b92011-01-25 13:28:33 +02003497 struct hci_cp_io_capability_reply cp;
3498
3499 bacpy(&cp.bdaddr, &ev->bdaddr);
Hemant Gupta7a7f1e72012-01-16 13:34:29 +05303500 /* Change the IO capability from KeyboardDisplay
3501 * to DisplayYesNo as it is not supported by BT spec. */
3502 cp.capability = (conn->io_capability == 0x04) ?
3503 0x01 : conn->io_capability;
Johan Hedberg7cbc9bd2011-04-28 11:29:04 -07003504 conn->auth_type = hci_get_auth_req(conn);
3505 cp.authentication = conn->auth_type;
Johan Hedberg17fa4b92011-01-25 13:28:33 +02003506
Gustavo Padovan8fc9ced2012-05-23 04:04:21 -03003507 if (hci_find_remote_oob_data(hdev, &conn->dst) &&
3508 (conn->out || test_bit(HCI_CONN_REMOTE_OOB, &conn->flags)))
Szymon Jancce85ee12011-03-22 13:12:23 +01003509 cp.oob_data = 0x01;
3510 else
3511 cp.oob_data = 0x00;
3512
Johan Hedberg17fa4b92011-01-25 13:28:33 +02003513 hci_send_cmd(hdev, HCI_OP_IO_CAPABILITY_REPLY,
Gustavo Padovan807deac2012-05-17 00:36:24 -03003514 sizeof(cp), &cp);
Johan Hedberg03b555e2011-01-04 15:40:05 +02003515 } else {
3516 struct hci_cp_io_capability_neg_reply cp;
3517
3518 bacpy(&cp.bdaddr, &ev->bdaddr);
Andrei Emeltchenko9f5a0d72011-11-07 14:20:25 +02003519 cp.reason = HCI_ERROR_PAIRING_NOT_ALLOWED;
Johan Hedberg03b555e2011-01-04 15:40:05 +02003520
3521 hci_send_cmd(hdev, HCI_OP_IO_CAPABILITY_NEG_REPLY,
Gustavo Padovan807deac2012-05-17 00:36:24 -03003522 sizeof(cp), &cp);
Johan Hedberg03b555e2011-01-04 15:40:05 +02003523 }
3524
3525unlock:
3526 hci_dev_unlock(hdev);
3527}
3528
Gustavo Padovan6039aa72012-05-23 04:04:18 -03003529static void hci_io_capa_reply_evt(struct hci_dev *hdev, struct sk_buff *skb)
Johan Hedberg03b555e2011-01-04 15:40:05 +02003530{
3531 struct hci_ev_io_capa_reply *ev = (void *) skb->data;
3532 struct hci_conn *conn;
3533
3534 BT_DBG("%s", hdev->name);
3535
3536 hci_dev_lock(hdev);
3537
3538 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
3539 if (!conn)
3540 goto unlock;
3541
Johan Hedberg03b555e2011-01-04 15:40:05 +02003542 conn->remote_cap = ev->capability;
Johan Hedberg03b555e2011-01-04 15:40:05 +02003543 conn->remote_auth = ev->authentication;
Johan Hedberg58a681e2012-01-16 06:47:28 +02003544 if (ev->oob_data)
3545 set_bit(HCI_CONN_REMOTE_OOB, &conn->flags);
Johan Hedberg03b555e2011-01-04 15:40:05 +02003546
3547unlock:
Marcel Holtmann04936842008-07-14 20:13:48 +02003548 hci_dev_unlock(hdev);
3549}
3550
Gustavo Padovan6039aa72012-05-23 04:04:18 -03003551static void hci_user_confirm_request_evt(struct hci_dev *hdev,
3552 struct sk_buff *skb)
Johan Hedberga5c29682011-02-19 12:05:57 -03003553{
3554 struct hci_ev_user_confirm_req *ev = (void *) skb->data;
Johan Hedberg55bc1a32011-04-28 11:28:56 -07003555 int loc_mitm, rem_mitm, confirm_hint = 0;
Johan Hedberg7a828902011-04-28 11:28:53 -07003556 struct hci_conn *conn;
Johan Hedberga5c29682011-02-19 12:05:57 -03003557
3558 BT_DBG("%s", hdev->name);
3559
3560 hci_dev_lock(hdev);
3561
Johan Hedberga8b2d5c2012-01-08 23:11:15 +02003562 if (!test_bit(HCI_MGMT, &hdev->dev_flags))
Johan Hedberg7a828902011-04-28 11:28:53 -07003563 goto unlock;
Johan Hedberga5c29682011-02-19 12:05:57 -03003564
Johan Hedberg7a828902011-04-28 11:28:53 -07003565 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
3566 if (!conn)
3567 goto unlock;
3568
3569 loc_mitm = (conn->auth_type & 0x01);
3570 rem_mitm = (conn->remote_auth & 0x01);
3571
3572 /* If we require MITM but the remote device can't provide that
3573 * (it has NoInputNoOutput) then reject the confirmation
3574 * request. The only exception is when we're dedicated bonding
3575 * initiators (connect_cfm_cb set) since then we always have the MITM
3576 * bit set. */
3577 if (!conn->connect_cfm_cb && loc_mitm && conn->remote_cap == 0x03) {
3578 BT_DBG("Rejecting request: remote device can't provide MITM");
3579 hci_send_cmd(hdev, HCI_OP_USER_CONFIRM_NEG_REPLY,
Gustavo Padovan807deac2012-05-17 00:36:24 -03003580 sizeof(ev->bdaddr), &ev->bdaddr);
Johan Hedberg7a828902011-04-28 11:28:53 -07003581 goto unlock;
3582 }
3583
3584 /* If no side requires MITM protection; auto-accept */
3585 if ((!loc_mitm || conn->remote_cap == 0x03) &&
Gustavo Padovan807deac2012-05-17 00:36:24 -03003586 (!rem_mitm || conn->io_capability == 0x03)) {
Johan Hedberg55bc1a32011-04-28 11:28:56 -07003587
3588 /* If we're not the initiators request authorization to
3589 * proceed from user space (mgmt_user_confirm with
3590 * confirm_hint set to 1). */
Johan Hedberg51a8efd2012-01-16 06:10:31 +02003591 if (!test_bit(HCI_CONN_AUTH_PEND, &conn->flags)) {
Johan Hedberg55bc1a32011-04-28 11:28:56 -07003592 BT_DBG("Confirming auto-accept as acceptor");
3593 confirm_hint = 1;
3594 goto confirm;
3595 }
3596
Johan Hedberg9f616562011-04-28 11:28:54 -07003597 BT_DBG("Auto-accept of user confirmation with %ums delay",
Gustavo Padovan807deac2012-05-17 00:36:24 -03003598 hdev->auto_accept_delay);
Johan Hedberg9f616562011-04-28 11:28:54 -07003599
3600 if (hdev->auto_accept_delay > 0) {
3601 int delay = msecs_to_jiffies(hdev->auto_accept_delay);
3602 mod_timer(&conn->auto_accept_timer, jiffies + delay);
3603 goto unlock;
3604 }
3605
Johan Hedberg7a828902011-04-28 11:28:53 -07003606 hci_send_cmd(hdev, HCI_OP_USER_CONFIRM_REPLY,
Gustavo Padovan807deac2012-05-17 00:36:24 -03003607 sizeof(ev->bdaddr), &ev->bdaddr);
Johan Hedberg7a828902011-04-28 11:28:53 -07003608 goto unlock;
3609 }
3610
Johan Hedberg55bc1a32011-04-28 11:28:56 -07003611confirm:
Johan Hedberg272d90d2012-02-09 15:26:12 +02003612 mgmt_user_confirm_request(hdev, &ev->bdaddr, ACL_LINK, 0, ev->passkey,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003613 confirm_hint);
Johan Hedberg7a828902011-04-28 11:28:53 -07003614
3615unlock:
Johan Hedberga5c29682011-02-19 12:05:57 -03003616 hci_dev_unlock(hdev);
3617}
3618
Gustavo Padovan6039aa72012-05-23 04:04:18 -03003619static void hci_user_passkey_request_evt(struct hci_dev *hdev,
3620 struct sk_buff *skb)
Brian Gix1143d452011-11-23 08:28:34 -08003621{
3622 struct hci_ev_user_passkey_req *ev = (void *) skb->data;
3623
3624 BT_DBG("%s", hdev->name);
3625
Johan Hedberga8b2d5c2012-01-08 23:11:15 +02003626 if (test_bit(HCI_MGMT, &hdev->dev_flags))
Johan Hedberg272d90d2012-02-09 15:26:12 +02003627 mgmt_user_passkey_request(hdev, &ev->bdaddr, ACL_LINK, 0);
Brian Gix1143d452011-11-23 08:28:34 -08003628}
3629
Johan Hedberg92a25252012-09-06 18:39:26 +03003630static void hci_user_passkey_notify_evt(struct hci_dev *hdev,
3631 struct sk_buff *skb)
3632{
3633 struct hci_ev_user_passkey_notify *ev = (void *) skb->data;
3634 struct hci_conn *conn;
3635
3636 BT_DBG("%s", hdev->name);
3637
3638 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
3639 if (!conn)
3640 return;
3641
3642 conn->passkey_notify = __le32_to_cpu(ev->passkey);
3643 conn->passkey_entered = 0;
3644
3645 if (test_bit(HCI_MGMT, &hdev->dev_flags))
3646 mgmt_user_passkey_notify(hdev, &conn->dst, conn->type,
3647 conn->dst_type, conn->passkey_notify,
3648 conn->passkey_entered);
3649}
3650
3651static void hci_keypress_notify_evt(struct hci_dev *hdev, struct sk_buff *skb)
3652{
3653 struct hci_ev_keypress_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 switch (ev->type) {
3663 case HCI_KEYPRESS_STARTED:
3664 conn->passkey_entered = 0;
3665 return;
3666
3667 case HCI_KEYPRESS_ENTERED:
3668 conn->passkey_entered++;
3669 break;
3670
3671 case HCI_KEYPRESS_ERASED:
3672 conn->passkey_entered--;
3673 break;
3674
3675 case HCI_KEYPRESS_CLEARED:
3676 conn->passkey_entered = 0;
3677 break;
3678
3679 case HCI_KEYPRESS_COMPLETED:
3680 return;
3681 }
3682
3683 if (test_bit(HCI_MGMT, &hdev->dev_flags))
3684 mgmt_user_passkey_notify(hdev, &conn->dst, conn->type,
3685 conn->dst_type, conn->passkey_notify,
3686 conn->passkey_entered);
3687}
3688
Gustavo Padovan6039aa72012-05-23 04:04:18 -03003689static void hci_simple_pair_complete_evt(struct hci_dev *hdev,
3690 struct sk_buff *skb)
Marcel Holtmann04936842008-07-14 20:13:48 +02003691{
3692 struct hci_ev_simple_pair_complete *ev = (void *) skb->data;
3693 struct hci_conn *conn;
3694
3695 BT_DBG("%s", hdev->name);
3696
3697 hci_dev_lock(hdev);
3698
3699 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
Johan Hedberg2a611692011-02-19 12:06:00 -03003700 if (!conn)
3701 goto unlock;
Marcel Holtmann04936842008-07-14 20:13:48 +02003702
Johan Hedberg2a611692011-02-19 12:06:00 -03003703 /* To avoid duplicate auth_failed events to user space we check
3704 * the HCI_CONN_AUTH_PEND flag which will be set if we
3705 * initiated the authentication. A traditional auth_complete
3706 * event gets always produced as initiator and is also mapped to
3707 * the mgmt_auth_failed event */
Mikel Astizfa1bd912012-08-09 09:52:29 +02003708 if (!test_bit(HCI_CONN_AUTH_PEND, &conn->flags) && ev->status)
Johan Hedbergbab73cb2012-02-09 16:07:29 +02003709 mgmt_auth_failed(hdev, &conn->dst, conn->type, conn->dst_type,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003710 ev->status);
Johan Hedberg2a611692011-02-19 12:06:00 -03003711
3712 hci_conn_put(conn);
3713
3714unlock:
Marcel Holtmann04936842008-07-14 20:13:48 +02003715 hci_dev_unlock(hdev);
3716}
3717
Gustavo Padovan6039aa72012-05-23 04:04:18 -03003718static void hci_remote_host_features_evt(struct hci_dev *hdev,
3719 struct sk_buff *skb)
Marcel Holtmann41a96212008-07-14 20:13:48 +02003720{
3721 struct hci_ev_remote_host_features *ev = (void *) skb->data;
3722 struct inquiry_entry *ie;
3723
3724 BT_DBG("%s", hdev->name);
3725
3726 hci_dev_lock(hdev);
3727
Andrei Emeltchenkocc11b9c2010-11-22 13:21:37 +02003728 ie = hci_inquiry_cache_lookup(hdev, &ev->bdaddr);
3729 if (ie)
Johan Hedberg02b7cc62012-02-28 02:28:43 +02003730 ie->data.ssp_mode = (ev->features[0] & LMP_HOST_SSP);
Marcel Holtmann41a96212008-07-14 20:13:48 +02003731
3732 hci_dev_unlock(hdev);
3733}
3734
Gustavo Padovan6039aa72012-05-23 04:04:18 -03003735static void hci_remote_oob_data_request_evt(struct hci_dev *hdev,
3736 struct sk_buff *skb)
Szymon Janc2763eda2011-03-22 13:12:22 +01003737{
3738 struct hci_ev_remote_oob_data_request *ev = (void *) skb->data;
3739 struct oob_data *data;
3740
3741 BT_DBG("%s", hdev->name);
3742
3743 hci_dev_lock(hdev);
3744
Johan Hedberga8b2d5c2012-01-08 23:11:15 +02003745 if (!test_bit(HCI_MGMT, &hdev->dev_flags))
Szymon Jance1ba1f12011-04-06 13:01:59 +02003746 goto unlock;
3747
Szymon Janc2763eda2011-03-22 13:12:22 +01003748 data = hci_find_remote_oob_data(hdev, &ev->bdaddr);
3749 if (data) {
3750 struct hci_cp_remote_oob_data_reply cp;
3751
3752 bacpy(&cp.bdaddr, &ev->bdaddr);
3753 memcpy(cp.hash, data->hash, sizeof(cp.hash));
3754 memcpy(cp.randomizer, data->randomizer, sizeof(cp.randomizer));
3755
3756 hci_send_cmd(hdev, HCI_OP_REMOTE_OOB_DATA_REPLY, sizeof(cp),
Gustavo Padovan807deac2012-05-17 00:36:24 -03003757 &cp);
Szymon Janc2763eda2011-03-22 13:12:22 +01003758 } else {
3759 struct hci_cp_remote_oob_data_neg_reply cp;
3760
3761 bacpy(&cp.bdaddr, &ev->bdaddr);
3762 hci_send_cmd(hdev, HCI_OP_REMOTE_OOB_DATA_NEG_REPLY, sizeof(cp),
Gustavo Padovan807deac2012-05-17 00:36:24 -03003763 &cp);
Szymon Janc2763eda2011-03-22 13:12:22 +01003764 }
3765
Szymon Jance1ba1f12011-04-06 13:01:59 +02003766unlock:
Szymon Janc2763eda2011-03-22 13:12:22 +01003767 hci_dev_unlock(hdev);
3768}
3769
Andrei Emeltchenkod5e91192012-10-25 15:20:44 +03003770static void hci_phy_link_complete_evt(struct hci_dev *hdev,
3771 struct sk_buff *skb)
3772{
3773 struct hci_ev_phy_link_complete *ev = (void *) skb->data;
3774 struct hci_conn *hcon, *bredr_hcon;
3775
3776 BT_DBG("%s handle 0x%2.2x status 0x%2.2x", hdev->name, ev->phy_handle,
3777 ev->status);
3778
3779 hci_dev_lock(hdev);
3780
3781 hcon = hci_conn_hash_lookup_handle(hdev, ev->phy_handle);
3782 if (!hcon) {
3783 hci_dev_unlock(hdev);
3784 return;
3785 }
3786
3787 if (ev->status) {
3788 hci_conn_del(hcon);
3789 hci_dev_unlock(hdev);
3790 return;
3791 }
3792
3793 bredr_hcon = hcon->amp_mgr->l2cap_conn->hcon;
3794
3795 hcon->state = BT_CONNECTED;
3796 bacpy(&hcon->dst, &bredr_hcon->dst);
3797
3798 hci_conn_hold(hcon);
3799 hcon->disc_timeout = HCI_DISCONN_TIMEOUT;
3800 hci_conn_put(hcon);
3801
3802 hci_conn_hold_device(hcon);
3803 hci_conn_add_sysfs(hcon);
3804
Andrei Emeltchenkocf70ff22012-10-31 15:46:36 +02003805 amp_physical_cfm(bredr_hcon, hcon);
3806
Andrei Emeltchenkod5e91192012-10-25 15:20:44 +03003807 hci_dev_unlock(hdev);
Andrei Emeltchenkod5e91192012-10-25 15:20:44 +03003808}
3809
Andrei Emeltchenko27695fb2012-10-25 15:20:45 +03003810static void hci_loglink_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
3811{
3812 struct hci_ev_logical_link_complete *ev = (void *) skb->data;
3813 struct hci_conn *hcon;
3814 struct hci_chan *hchan;
3815 struct amp_mgr *mgr;
3816
3817 BT_DBG("%s log_handle 0x%4.4x phy_handle 0x%2.2x status 0x%2.2x",
3818 hdev->name, le16_to_cpu(ev->handle), ev->phy_handle,
3819 ev->status);
3820
3821 hcon = hci_conn_hash_lookup_handle(hdev, ev->phy_handle);
3822 if (!hcon)
3823 return;
3824
3825 /* Create AMP hchan */
3826 hchan = hci_chan_create(hcon);
3827 if (!hchan)
3828 return;
3829
3830 hchan->handle = le16_to_cpu(ev->handle);
3831
3832 BT_DBG("hcon %p mgr %p hchan %p", hcon, hcon->amp_mgr, hchan);
3833
3834 mgr = hcon->amp_mgr;
3835 if (mgr && mgr->bredr_chan) {
3836 struct l2cap_chan *bredr_chan = mgr->bredr_chan;
3837
3838 l2cap_chan_lock(bredr_chan);
3839
3840 bredr_chan->conn->mtu = hdev->block_mtu;
3841 l2cap_logical_cfm(bredr_chan, hchan, 0);
3842 hci_conn_hold(hcon);
3843
3844 l2cap_chan_unlock(bredr_chan);
3845 }
3846}
3847
Andrei Emeltchenko606e2a12012-10-31 15:46:31 +02003848static void hci_disconn_loglink_complete_evt(struct hci_dev *hdev,
3849 struct sk_buff *skb)
3850{
3851 struct hci_ev_disconn_logical_link_complete *ev = (void *) skb->data;
3852 struct hci_chan *hchan;
3853
3854 BT_DBG("%s log handle 0x%4.4x status 0x%2.2x", hdev->name,
3855 le16_to_cpu(ev->handle), ev->status);
3856
3857 if (ev->status)
3858 return;
3859
3860 hci_dev_lock(hdev);
3861
3862 hchan = hci_chan_lookup_handle(hdev, le16_to_cpu(ev->handle));
3863 if (!hchan)
3864 goto unlock;
3865
3866 amp_destroy_logical_link(hchan, ev->reason);
3867
3868unlock:
3869 hci_dev_unlock(hdev);
3870}
3871
Andrei Emeltchenko9eef6b32012-10-31 15:46:32 +02003872static void hci_disconn_phylink_complete_evt(struct hci_dev *hdev,
3873 struct sk_buff *skb)
3874{
3875 struct hci_ev_disconn_phy_link_complete *ev = (void *) skb->data;
3876 struct hci_conn *hcon;
3877
3878 BT_DBG("%s status 0x%2.2x", hdev->name, ev->status);
3879
3880 if (ev->status)
3881 return;
3882
3883 hci_dev_lock(hdev);
3884
3885 hcon = hci_conn_hash_lookup_handle(hdev, ev->phy_handle);
3886 if (hcon) {
3887 hcon->state = BT_CLOSED;
3888 hci_conn_del(hcon);
3889 }
3890
3891 hci_dev_unlock(hdev);
3892}
3893
Gustavo Padovan6039aa72012-05-23 04:04:18 -03003894static void hci_le_conn_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
Ville Tervofcd89c02011-02-10 22:38:47 -03003895{
3896 struct hci_ev_le_conn_complete *ev = (void *) skb->data;
3897 struct hci_conn *conn;
3898
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +03003899 BT_DBG("%s status 0x%2.2x", hdev->name, ev->status);
Ville Tervofcd89c02011-02-10 22:38:47 -03003900
3901 hci_dev_lock(hdev);
3902
Andre Guedesb47a09b2012-07-27 15:10:15 -03003903 conn = hci_conn_hash_lookup_state(hdev, LE_LINK, BT_CONNECT);
Ville Tervob62f3282011-02-10 22:38:50 -03003904 if (!conn) {
3905 conn = hci_conn_add(hdev, LE_LINK, &ev->bdaddr);
3906 if (!conn) {
3907 BT_ERR("No memory for new connection");
Andre Guedes230fd162012-07-27 15:10:10 -03003908 goto unlock;
Ville Tervob62f3282011-02-10 22:38:50 -03003909 }
Andre Guedes29b79882011-05-31 14:20:54 -03003910
3911 conn->dst_type = ev->bdaddr_type;
Andre Guedesb9b343d2012-07-27 15:10:11 -03003912
3913 if (ev->role == LE_CONN_ROLE_MASTER) {
3914 conn->out = true;
3915 conn->link_mode |= HCI_LM_MASTER;
3916 }
Ville Tervob62f3282011-02-10 22:38:50 -03003917 }
Ville Tervofcd89c02011-02-10 22:38:47 -03003918
Andre Guedescd17dec2012-07-27 15:10:16 -03003919 if (ev->status) {
3920 mgmt_connect_failed(hdev, &conn->dst, conn->type,
3921 conn->dst_type, ev->status);
3922 hci_proto_connect_cfm(conn, ev->status);
3923 conn->state = BT_CLOSED;
3924 hci_conn_del(conn);
3925 goto unlock;
3926 }
3927
Johan Hedbergb644ba32012-01-17 21:48:47 +02003928 if (!test_and_set_bit(HCI_CONN_MGMT_CONNECTED, &conn->flags))
3929 mgmt_device_connected(hdev, &ev->bdaddr, conn->type,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003930 conn->dst_type, 0, NULL, 0, NULL);
Vinicius Costa Gomes83bc71b2011-05-06 18:41:43 -03003931
Vinicius Costa Gomes7b5c0d52011-06-09 18:50:50 -03003932 conn->sec_level = BT_SECURITY_LOW;
Ville Tervofcd89c02011-02-10 22:38:47 -03003933 conn->handle = __le16_to_cpu(ev->handle);
3934 conn->state = BT_CONNECTED;
3935
3936 hci_conn_hold_device(conn);
3937 hci_conn_add_sysfs(conn);
3938
3939 hci_proto_connect_cfm(conn, ev->status);
3940
3941unlock:
3942 hci_dev_unlock(hdev);
3943}
3944
Gustavo Padovan6039aa72012-05-23 04:04:18 -03003945static void hci_le_adv_report_evt(struct hci_dev *hdev, struct sk_buff *skb)
Andre Guedes9aa04c92011-05-26 16:23:51 -03003946{
Andre Guedese95beb42011-09-26 20:48:35 -03003947 u8 num_reports = skb->data[0];
3948 void *ptr = &skb->data[1];
Andre Guedes3c9e9192012-01-10 18:20:50 -03003949 s8 rssi;
Andre Guedes9aa04c92011-05-26 16:23:51 -03003950
3951 hci_dev_lock(hdev);
3952
Andre Guedese95beb42011-09-26 20:48:35 -03003953 while (num_reports--) {
3954 struct hci_ev_le_advertising_info *ev = ptr;
Andre Guedes9aa04c92011-05-26 16:23:51 -03003955
Andre Guedes3c9e9192012-01-10 18:20:50 -03003956 rssi = ev->data[ev->length];
3957 mgmt_device_found(hdev, &ev->bdaddr, LE_LINK, ev->bdaddr_type,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003958 NULL, rssi, 0, 1, ev->data, ev->length);
Andre Guedes3c9e9192012-01-10 18:20:50 -03003959
Andre Guedese95beb42011-09-26 20:48:35 -03003960 ptr += sizeof(*ev) + ev->length + 1;
Andre Guedes9aa04c92011-05-26 16:23:51 -03003961 }
3962
3963 hci_dev_unlock(hdev);
3964}
3965
Gustavo Padovan6039aa72012-05-23 04:04:18 -03003966static void hci_le_ltk_request_evt(struct hci_dev *hdev, struct sk_buff *skb)
Vinicius Costa Gomesa7a595f2011-06-09 18:50:47 -03003967{
3968 struct hci_ev_le_ltk_req *ev = (void *) skb->data;
3969 struct hci_cp_le_ltk_reply cp;
Vinicius Costa Gomesbea710f2011-07-07 18:59:37 -03003970 struct hci_cp_le_ltk_neg_reply neg;
Vinicius Costa Gomesa7a595f2011-06-09 18:50:47 -03003971 struct hci_conn *conn;
Vinicius Costa Gomesc9839a12012-02-02 21:08:01 -03003972 struct smp_ltk *ltk;
Vinicius Costa Gomesa7a595f2011-06-09 18:50:47 -03003973
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +03003974 BT_DBG("%s handle 0x%4.4x", hdev->name, __le16_to_cpu(ev->handle));
Vinicius Costa Gomesa7a595f2011-06-09 18:50:47 -03003975
3976 hci_dev_lock(hdev);
3977
3978 conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
Vinicius Costa Gomesbea710f2011-07-07 18:59:37 -03003979 if (conn == NULL)
3980 goto not_found;
Vinicius Costa Gomesa7a595f2011-06-09 18:50:47 -03003981
Vinicius Costa Gomesbea710f2011-07-07 18:59:37 -03003982 ltk = hci_find_ltk(hdev, ev->ediv, ev->random);
3983 if (ltk == NULL)
3984 goto not_found;
3985
3986 memcpy(cp.ltk, ltk->val, sizeof(ltk->val));
Vinicius Costa Gomesa7a595f2011-06-09 18:50:47 -03003987 cp.handle = cpu_to_le16(conn->handle);
Vinicius Costa Gomesc9839a12012-02-02 21:08:01 -03003988
3989 if (ltk->authenticated)
3990 conn->sec_level = BT_SECURITY_HIGH;
Vinicius Costa Gomesa7a595f2011-06-09 18:50:47 -03003991
3992 hci_send_cmd(hdev, HCI_OP_LE_LTK_REPLY, sizeof(cp), &cp);
3993
Vinicius Costa Gomesc9839a12012-02-02 21:08:01 -03003994 if (ltk->type & HCI_SMP_STK) {
3995 list_del(&ltk->list);
3996 kfree(ltk);
3997 }
3998
Vinicius Costa Gomesa7a595f2011-06-09 18:50:47 -03003999 hci_dev_unlock(hdev);
Vinicius Costa Gomesbea710f2011-07-07 18:59:37 -03004000
4001 return;
4002
4003not_found:
4004 neg.handle = ev->handle;
4005 hci_send_cmd(hdev, HCI_OP_LE_LTK_NEG_REPLY, sizeof(neg), &neg);
4006 hci_dev_unlock(hdev);
Vinicius Costa Gomesa7a595f2011-06-09 18:50:47 -03004007}
4008
Gustavo Padovan6039aa72012-05-23 04:04:18 -03004009static void hci_le_meta_evt(struct hci_dev *hdev, struct sk_buff *skb)
Ville Tervofcd89c02011-02-10 22:38:47 -03004010{
4011 struct hci_ev_le_meta *le_ev = (void *) skb->data;
4012
4013 skb_pull(skb, sizeof(*le_ev));
4014
4015 switch (le_ev->subevent) {
4016 case HCI_EV_LE_CONN_COMPLETE:
4017 hci_le_conn_complete_evt(hdev, skb);
4018 break;
4019
Andre Guedes9aa04c92011-05-26 16:23:51 -03004020 case HCI_EV_LE_ADVERTISING_REPORT:
4021 hci_le_adv_report_evt(hdev, skb);
4022 break;
4023
Vinicius Costa Gomesa7a595f2011-06-09 18:50:47 -03004024 case HCI_EV_LE_LTK_REQ:
4025 hci_le_ltk_request_evt(hdev, skb);
4026 break;
4027
Ville Tervofcd89c02011-02-10 22:38:47 -03004028 default:
4029 break;
4030 }
4031}
4032
Andrei Emeltchenko9495b2e2012-09-27 17:26:22 +03004033static void hci_chan_selected_evt(struct hci_dev *hdev, struct sk_buff *skb)
4034{
4035 struct hci_ev_channel_selected *ev = (void *) skb->data;
4036 struct hci_conn *hcon;
4037
4038 BT_DBG("%s handle 0x%2.2x", hdev->name, ev->phy_handle);
4039
4040 skb_pull(skb, sizeof(*ev));
4041
4042 hcon = hci_conn_hash_lookup_handle(hdev, ev->phy_handle);
4043 if (!hcon)
4044 return;
4045
4046 amp_read_loc_assoc_final_data(hdev, hcon);
4047}
4048
Linus Torvalds1da177e2005-04-16 15:20:36 -07004049void hci_event_packet(struct hci_dev *hdev, struct sk_buff *skb)
4050{
Marcel Holtmanna9de9242007-10-20 13:33:56 +02004051 struct hci_event_hdr *hdr = (void *) skb->data;
4052 __u8 event = hdr->evt;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004053
4054 skb_pull(skb, HCI_EVENT_HDR_SIZE);
4055
Marcel Holtmanna9de9242007-10-20 13:33:56 +02004056 switch (event) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07004057 case HCI_EV_INQUIRY_COMPLETE:
4058 hci_inquiry_complete_evt(hdev, skb);
4059 break;
4060
4061 case HCI_EV_INQUIRY_RESULT:
4062 hci_inquiry_result_evt(hdev, skb);
4063 break;
4064
Marcel Holtmanna9de9242007-10-20 13:33:56 +02004065 case HCI_EV_CONN_COMPLETE:
4066 hci_conn_complete_evt(hdev, skb);
Marcel Holtmann21d9e302005-09-13 01:32:25 +02004067 break;
4068
Linus Torvalds1da177e2005-04-16 15:20:36 -07004069 case HCI_EV_CONN_REQUEST:
4070 hci_conn_request_evt(hdev, skb);
4071 break;
4072
Linus Torvalds1da177e2005-04-16 15:20:36 -07004073 case HCI_EV_DISCONN_COMPLETE:
4074 hci_disconn_complete_evt(hdev, skb);
4075 break;
4076
Linus Torvalds1da177e2005-04-16 15:20:36 -07004077 case HCI_EV_AUTH_COMPLETE:
4078 hci_auth_complete_evt(hdev, skb);
4079 break;
4080
Marcel Holtmanna9de9242007-10-20 13:33:56 +02004081 case HCI_EV_REMOTE_NAME:
4082 hci_remote_name_evt(hdev, skb);
4083 break;
4084
Linus Torvalds1da177e2005-04-16 15:20:36 -07004085 case HCI_EV_ENCRYPT_CHANGE:
4086 hci_encrypt_change_evt(hdev, skb);
4087 break;
4088
Marcel Holtmanna9de9242007-10-20 13:33:56 +02004089 case HCI_EV_CHANGE_LINK_KEY_COMPLETE:
4090 hci_change_link_key_complete_evt(hdev, skb);
4091 break;
4092
4093 case HCI_EV_REMOTE_FEATURES:
4094 hci_remote_features_evt(hdev, skb);
4095 break;
4096
4097 case HCI_EV_REMOTE_VERSION:
4098 hci_remote_version_evt(hdev, skb);
4099 break;
4100
4101 case HCI_EV_QOS_SETUP_COMPLETE:
4102 hci_qos_setup_complete_evt(hdev, skb);
4103 break;
4104
4105 case HCI_EV_CMD_COMPLETE:
4106 hci_cmd_complete_evt(hdev, skb);
4107 break;
4108
4109 case HCI_EV_CMD_STATUS:
4110 hci_cmd_status_evt(hdev, skb);
4111 break;
4112
4113 case HCI_EV_ROLE_CHANGE:
4114 hci_role_change_evt(hdev, skb);
4115 break;
4116
4117 case HCI_EV_NUM_COMP_PKTS:
4118 hci_num_comp_pkts_evt(hdev, skb);
4119 break;
4120
4121 case HCI_EV_MODE_CHANGE:
4122 hci_mode_change_evt(hdev, skb);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004123 break;
4124
4125 case HCI_EV_PIN_CODE_REQ:
4126 hci_pin_code_request_evt(hdev, skb);
4127 break;
4128
4129 case HCI_EV_LINK_KEY_REQ:
4130 hci_link_key_request_evt(hdev, skb);
4131 break;
4132
4133 case HCI_EV_LINK_KEY_NOTIFY:
4134 hci_link_key_notify_evt(hdev, skb);
4135 break;
4136
4137 case HCI_EV_CLOCK_OFFSET:
4138 hci_clock_offset_evt(hdev, skb);
4139 break;
4140
Marcel Holtmanna8746412008-07-14 20:13:46 +02004141 case HCI_EV_PKT_TYPE_CHANGE:
4142 hci_pkt_type_change_evt(hdev, skb);
4143 break;
4144
Marcel Holtmann85a1e932005-08-09 20:28:02 -07004145 case HCI_EV_PSCAN_REP_MODE:
4146 hci_pscan_rep_mode_evt(hdev, skb);
4147 break;
4148
Marcel Holtmanna9de9242007-10-20 13:33:56 +02004149 case HCI_EV_INQUIRY_RESULT_WITH_RSSI:
4150 hci_inquiry_result_with_rssi_evt(hdev, skb);
4151 break;
4152
4153 case HCI_EV_REMOTE_EXT_FEATURES:
4154 hci_remote_ext_features_evt(hdev, skb);
4155 break;
4156
4157 case HCI_EV_SYNC_CONN_COMPLETE:
4158 hci_sync_conn_complete_evt(hdev, skb);
4159 break;
4160
4161 case HCI_EV_SYNC_CONN_CHANGED:
4162 hci_sync_conn_changed_evt(hdev, skb);
4163 break;
4164
Marcel Holtmann04837f62006-07-03 10:02:33 +02004165 case HCI_EV_SNIFF_SUBRATE:
4166 hci_sniff_subrate_evt(hdev, skb);
4167 break;
4168
Marcel Holtmanna9de9242007-10-20 13:33:56 +02004169 case HCI_EV_EXTENDED_INQUIRY_RESULT:
4170 hci_extended_inquiry_result_evt(hdev, skb);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004171 break;
4172
Johan Hedberg1c2e0042012-06-08 23:31:13 +08004173 case HCI_EV_KEY_REFRESH_COMPLETE:
4174 hci_key_refresh_complete_evt(hdev, skb);
4175 break;
4176
Marcel Holtmann04936842008-07-14 20:13:48 +02004177 case HCI_EV_IO_CAPA_REQUEST:
4178 hci_io_capa_request_evt(hdev, skb);
4179 break;
4180
Johan Hedberg03b555e2011-01-04 15:40:05 +02004181 case HCI_EV_IO_CAPA_REPLY:
4182 hci_io_capa_reply_evt(hdev, skb);
4183 break;
4184
Johan Hedberga5c29682011-02-19 12:05:57 -03004185 case HCI_EV_USER_CONFIRM_REQUEST:
4186 hci_user_confirm_request_evt(hdev, skb);
4187 break;
4188
Brian Gix1143d452011-11-23 08:28:34 -08004189 case HCI_EV_USER_PASSKEY_REQUEST:
4190 hci_user_passkey_request_evt(hdev, skb);
4191 break;
4192
Johan Hedberg92a25252012-09-06 18:39:26 +03004193 case HCI_EV_USER_PASSKEY_NOTIFY:
4194 hci_user_passkey_notify_evt(hdev, skb);
4195 break;
4196
4197 case HCI_EV_KEYPRESS_NOTIFY:
4198 hci_keypress_notify_evt(hdev, skb);
4199 break;
4200
Marcel Holtmann04936842008-07-14 20:13:48 +02004201 case HCI_EV_SIMPLE_PAIR_COMPLETE:
4202 hci_simple_pair_complete_evt(hdev, skb);
4203 break;
4204
Marcel Holtmann41a96212008-07-14 20:13:48 +02004205 case HCI_EV_REMOTE_HOST_FEATURES:
4206 hci_remote_host_features_evt(hdev, skb);
4207 break;
4208
Ville Tervofcd89c02011-02-10 22:38:47 -03004209 case HCI_EV_LE_META:
4210 hci_le_meta_evt(hdev, skb);
4211 break;
4212
Andrei Emeltchenko9495b2e2012-09-27 17:26:22 +03004213 case HCI_EV_CHANNEL_SELECTED:
4214 hci_chan_selected_evt(hdev, skb);
4215 break;
4216
Szymon Janc2763eda2011-03-22 13:12:22 +01004217 case HCI_EV_REMOTE_OOB_DATA_REQUEST:
4218 hci_remote_oob_data_request_evt(hdev, skb);
4219 break;
4220
Andrei Emeltchenkod5e91192012-10-25 15:20:44 +03004221 case HCI_EV_PHY_LINK_COMPLETE:
4222 hci_phy_link_complete_evt(hdev, skb);
4223 break;
4224
Andrei Emeltchenko27695fb2012-10-25 15:20:45 +03004225 case HCI_EV_LOGICAL_LINK_COMPLETE:
4226 hci_loglink_complete_evt(hdev, skb);
4227 break;
4228
Andrei Emeltchenko606e2a12012-10-31 15:46:31 +02004229 case HCI_EV_DISCONN_LOGICAL_LINK_COMPLETE:
4230 hci_disconn_loglink_complete_evt(hdev, skb);
4231 break;
4232
Andrei Emeltchenko9eef6b32012-10-31 15:46:32 +02004233 case HCI_EV_DISCONN_PHY_LINK_COMPLETE:
4234 hci_disconn_phylink_complete_evt(hdev, skb);
4235 break;
4236
Andrei Emeltchenko25e89e92012-01-04 12:41:58 +02004237 case HCI_EV_NUM_COMP_BLOCKS:
4238 hci_num_comp_blocks_evt(hdev, skb);
4239 break;
4240
Marcel Holtmanna9de9242007-10-20 13:33:56 +02004241 default:
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +03004242 BT_DBG("%s event 0x%2.2x", hdev->name, event);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004243 break;
4244 }
4245
4246 kfree_skb(skb);
4247 hdev->stat.evt_rx++;
4248}