blob: eb45774165f4ff4bcecec416841eca8b241ff585 [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
Gustavo Padovan8c520a52012-05-23 04:04:22 -030027#include <linux/export.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070028#include <asm/unaligned.h>
29
30#include <net/bluetooth/bluetooth.h>
31#include <net/bluetooth/hci_core.h>
Mikel Astizf0d6a0e2012-08-09 09:52:30 +020032#include <net/bluetooth/mgmt.h>
Andrei Emeltchenko8e2a0d92012-09-27 17:26:08 +030033#include <net/bluetooth/a2mp.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;
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200205}
206
207static void hci_cc_write_local_name(struct hci_dev *hdev, struct sk_buff *skb)
208{
209 __u8 status = *((__u8 *) skb->data);
210 void *sent;
211
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +0300212 BT_DBG("%s status 0x%2.2x", hdev->name, status);
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200213
214 sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_LOCAL_NAME);
215 if (!sent)
216 return;
217
Johan Hedberg56e5cb82011-11-08 20:40:16 +0200218 hci_dev_lock(hdev);
219
Johan Hedbergf51d5b22012-02-22 18:17:32 +0200220 if (test_bit(HCI_MGMT, &hdev->dev_flags))
221 mgmt_set_local_name_complete(hdev, sent, status);
Johan Hedberg28cc7bd2012-02-22 21:06:55 +0200222 else if (!status)
223 memcpy(hdev->dev_name, sent, HCI_MAX_NAME_LENGTH);
Johan Hedbergf51d5b22012-02-22 18:17:32 +0200224
Johan Hedberg56e5cb82011-11-08 20:40:16 +0200225 hci_dev_unlock(hdev);
Johan Hedberg3159d382012-02-24 13:47:56 +0200226
227 hci_req_complete(hdev, HCI_OP_WRITE_LOCAL_NAME, status);
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200228}
229
230static void hci_cc_read_local_name(struct hci_dev *hdev, struct sk_buff *skb)
231{
232 struct hci_rp_read_local_name *rp = (void *) skb->data;
233
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +0300234 BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200235
236 if (rp->status)
237 return;
238
Johan Hedbergdb99b5f2012-02-22 20:14:22 +0200239 if (test_bit(HCI_SETUP, &hdev->dev_flags))
240 memcpy(hdev->dev_name, rp->name, HCI_MAX_NAME_LENGTH);
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200241}
242
243static void hci_cc_write_auth_enable(struct hci_dev *hdev, struct sk_buff *skb)
244{
245 __u8 status = *((__u8 *) skb->data);
246 void *sent;
247
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +0300248 BT_DBG("%s status 0x%2.2x", hdev->name, status);
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200249
250 sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_AUTH_ENABLE);
251 if (!sent)
252 return;
253
254 if (!status) {
255 __u8 param = *((__u8 *) sent);
256
257 if (param == AUTH_ENABLED)
258 set_bit(HCI_AUTH, &hdev->flags);
259 else
260 clear_bit(HCI_AUTH, &hdev->flags);
261 }
262
Johan Hedberg33ef95e2012-02-16 23:56:27 +0200263 if (test_bit(HCI_MGMT, &hdev->dev_flags))
264 mgmt_auth_enable_complete(hdev, status);
265
Johan Hedberg23bb5762010-12-21 23:01:27 +0200266 hci_req_complete(hdev, HCI_OP_WRITE_AUTH_ENABLE, status);
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200267}
268
269static void hci_cc_write_encrypt_mode(struct hci_dev *hdev, struct sk_buff *skb)
270{
271 __u8 status = *((__u8 *) skb->data);
272 void *sent;
273
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +0300274 BT_DBG("%s status 0x%2.2x", hdev->name, status);
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200275
276 sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_ENCRYPT_MODE);
277 if (!sent)
278 return;
279
280 if (!status) {
281 __u8 param = *((__u8 *) sent);
282
283 if (param)
284 set_bit(HCI_ENCRYPT, &hdev->flags);
285 else
286 clear_bit(HCI_ENCRYPT, &hdev->flags);
287 }
288
Johan Hedberg23bb5762010-12-21 23:01:27 +0200289 hci_req_complete(hdev, HCI_OP_WRITE_ENCRYPT_MODE, status);
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200290}
291
292static void hci_cc_write_scan_enable(struct hci_dev *hdev, struct sk_buff *skb)
293{
Johan Hedberg36f7fc72011-11-04 00:17:45 +0200294 __u8 param, status = *((__u8 *) skb->data);
295 int old_pscan, old_iscan;
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200296 void *sent;
297
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +0300298 BT_DBG("%s status 0x%2.2x", hdev->name, status);
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200299
300 sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_SCAN_ENABLE);
301 if (!sent)
302 return;
303
Johan Hedberg36f7fc72011-11-04 00:17:45 +0200304 param = *((__u8 *) sent);
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200305
Johan Hedberg56e5cb82011-11-08 20:40:16 +0200306 hci_dev_lock(hdev);
307
Mikel Astizfa1bd912012-08-09 09:52:29 +0200308 if (status) {
Johan Hedberg744cf192011-11-08 20:40:14 +0200309 mgmt_write_scan_failed(hdev, param, status);
Johan Hedberg2d7cee52011-11-07 22:16:03 +0200310 hdev->discov_timeout = 0;
311 goto done;
312 }
313
Johan Hedberg36f7fc72011-11-04 00:17:45 +0200314 old_pscan = test_and_clear_bit(HCI_PSCAN, &hdev->flags);
315 old_iscan = test_and_clear_bit(HCI_ISCAN, &hdev->flags);
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200316
Johan Hedberg36f7fc72011-11-04 00:17:45 +0200317 if (param & SCAN_INQUIRY) {
318 set_bit(HCI_ISCAN, &hdev->flags);
319 if (!old_iscan)
Johan Hedberg744cf192011-11-08 20:40:14 +0200320 mgmt_discoverable(hdev, 1);
Johan Hedberg16ab91a2011-11-07 22:16:02 +0200321 if (hdev->discov_timeout > 0) {
322 int to = msecs_to_jiffies(hdev->discov_timeout * 1000);
323 queue_delayed_work(hdev->workqueue, &hdev->discov_off,
Gustavo Padovan807deac2012-05-17 00:36:24 -0300324 to);
Johan Hedberg16ab91a2011-11-07 22:16:02 +0200325 }
Johan Hedberg36f7fc72011-11-04 00:17:45 +0200326 } else if (old_iscan)
Johan Hedberg744cf192011-11-08 20:40:14 +0200327 mgmt_discoverable(hdev, 0);
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200328
Johan Hedberg36f7fc72011-11-04 00:17:45 +0200329 if (param & SCAN_PAGE) {
330 set_bit(HCI_PSCAN, &hdev->flags);
331 if (!old_pscan)
Johan Hedberg744cf192011-11-08 20:40:14 +0200332 mgmt_connectable(hdev, 1);
Johan Hedberg36f7fc72011-11-04 00:17:45 +0200333 } else if (old_pscan)
Johan Hedberg744cf192011-11-08 20:40:14 +0200334 mgmt_connectable(hdev, 0);
Johan Hedberg36f7fc72011-11-04 00:17:45 +0200335
336done:
Johan Hedberg56e5cb82011-11-08 20:40:16 +0200337 hci_dev_unlock(hdev);
Johan Hedberg23bb5762010-12-21 23:01:27 +0200338 hci_req_complete(hdev, HCI_OP_WRITE_SCAN_ENABLE, status);
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200339}
340
341static void hci_cc_read_class_of_dev(struct hci_dev *hdev, struct sk_buff *skb)
342{
343 struct hci_rp_read_class_of_dev *rp = (void *) skb->data;
344
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +0300345 BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200346
347 if (rp->status)
348 return;
349
350 memcpy(hdev->dev_class, rp->dev_class, 3);
351
352 BT_DBG("%s class 0x%.2x%.2x%.2x", hdev->name,
Gustavo Padovan807deac2012-05-17 00:36:24 -0300353 hdev->dev_class[2], hdev->dev_class[1], hdev->dev_class[0]);
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200354}
355
356static void hci_cc_write_class_of_dev(struct hci_dev *hdev, struct sk_buff *skb)
357{
358 __u8 status = *((__u8 *) skb->data);
359 void *sent;
360
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +0300361 BT_DBG("%s status 0x%2.2x", hdev->name, status);
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200362
363 sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_CLASS_OF_DEV);
364 if (!sent)
365 return;
366
Marcel Holtmann7f9a9032012-02-22 18:38:01 +0100367 hci_dev_lock(hdev);
368
369 if (status == 0)
370 memcpy(hdev->dev_class, sent, 3);
371
372 if (test_bit(HCI_MGMT, &hdev->dev_flags))
373 mgmt_set_class_of_dev_complete(hdev, sent, status);
374
375 hci_dev_unlock(hdev);
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200376}
377
378static void hci_cc_read_voice_setting(struct hci_dev *hdev, struct sk_buff *skb)
379{
380 struct hci_rp_read_voice_setting *rp = (void *) skb->data;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700381 __u16 setting;
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200382
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +0300383 BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200384
385 if (rp->status)
386 return;
387
388 setting = __le16_to_cpu(rp->voice_setting);
389
Marcel Holtmannf383f272008-07-14 20:13:47 +0200390 if (hdev->voice_setting == setting)
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200391 return;
392
393 hdev->voice_setting = setting;
394
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +0300395 BT_DBG("%s voice setting 0x%4.4x", hdev->name, setting);
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200396
Gustavo F. Padovan3c547112011-12-14 22:58:44 -0200397 if (hdev->notify)
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200398 hdev->notify(hdev, HCI_NOTIFY_VOICE_SETTING);
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200399}
400
Gustavo Padovan8fc9ced2012-05-23 04:04:21 -0300401static void hci_cc_write_voice_setting(struct hci_dev *hdev,
402 struct sk_buff *skb)
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200403{
404 __u8 status = *((__u8 *) skb->data);
Marcel Holtmannf383f272008-07-14 20:13:47 +0200405 __u16 setting;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700406 void *sent;
407
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +0300408 BT_DBG("%s status 0x%2.2x", hdev->name, status);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700409
Marcel Holtmannf383f272008-07-14 20:13:47 +0200410 if (status)
411 return;
412
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200413 sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_VOICE_SETTING);
414 if (!sent)
415 return;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700416
Marcel Holtmannf383f272008-07-14 20:13:47 +0200417 setting = get_unaligned_le16(sent);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700418
Marcel Holtmannf383f272008-07-14 20:13:47 +0200419 if (hdev->voice_setting == setting)
420 return;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700421
Marcel Holtmannf383f272008-07-14 20:13:47 +0200422 hdev->voice_setting = setting;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700423
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +0300424 BT_DBG("%s voice setting 0x%4.4x", hdev->name, setting);
Marcel Holtmannf383f272008-07-14 20:13:47 +0200425
Gustavo F. Padovan3c547112011-12-14 22:58:44 -0200426 if (hdev->notify)
Marcel Holtmannf383f272008-07-14 20:13:47 +0200427 hdev->notify(hdev, HCI_NOTIFY_VOICE_SETTING);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700428}
429
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200430static void hci_cc_host_buffer_size(struct hci_dev *hdev, struct sk_buff *skb)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700431{
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200432 __u8 status = *((__u8 *) skb->data);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700433
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +0300434 BT_DBG("%s status 0x%2.2x", hdev->name, status);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700435
Johan Hedberg23bb5762010-12-21 23:01:27 +0200436 hci_req_complete(hdev, HCI_OP_HOST_BUFFER_SIZE, status);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700437}
438
Marcel Holtmann333140b2008-07-14 20:13:48 +0200439static void hci_cc_write_ssp_mode(struct hci_dev *hdev, struct sk_buff *skb)
440{
441 __u8 status = *((__u8 *) skb->data);
442 void *sent;
443
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +0300444 BT_DBG("%s status 0x%2.2x", hdev->name, status);
Marcel Holtmann333140b2008-07-14 20:13:48 +0200445
Marcel Holtmann333140b2008-07-14 20:13:48 +0200446 sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_SSP_MODE);
447 if (!sent)
448 return;
449
Johan Hedberged2c4ee2012-02-17 00:56:28 +0200450 if (test_bit(HCI_MGMT, &hdev->dev_flags))
Johan Hedbergc0ecddc2012-02-22 12:38:31 +0200451 mgmt_ssp_enable_complete(hdev, *((u8 *) sent), status);
452 else if (!status) {
453 if (*((u8 *) sent))
454 set_bit(HCI_SSP_ENABLED, &hdev->dev_flags);
455 else
456 clear_bit(HCI_SSP_ENABLED, &hdev->dev_flags);
457 }
Marcel Holtmann333140b2008-07-14 20:13:48 +0200458}
459
Johan Hedbergd5859e22011-01-25 01:19:58 +0200460static u8 hci_get_inquiry_mode(struct hci_dev *hdev)
461{
462 if (hdev->features[6] & LMP_EXT_INQ)
463 return 2;
464
465 if (hdev->features[3] & LMP_RSSI_INQ)
466 return 1;
467
468 if (hdev->manufacturer == 11 && hdev->hci_rev == 0x00 &&
Gustavo Padovan807deac2012-05-17 00:36:24 -0300469 hdev->lmp_subver == 0x0757)
Johan Hedbergd5859e22011-01-25 01:19:58 +0200470 return 1;
471
472 if (hdev->manufacturer == 15) {
473 if (hdev->hci_rev == 0x03 && hdev->lmp_subver == 0x6963)
474 return 1;
475 if (hdev->hci_rev == 0x09 && hdev->lmp_subver == 0x6963)
476 return 1;
477 if (hdev->hci_rev == 0x00 && hdev->lmp_subver == 0x6965)
478 return 1;
479 }
480
481 if (hdev->manufacturer == 31 && hdev->hci_rev == 0x2005 &&
Gustavo Padovan807deac2012-05-17 00:36:24 -0300482 hdev->lmp_subver == 0x1805)
Johan Hedbergd5859e22011-01-25 01:19:58 +0200483 return 1;
484
485 return 0;
486}
487
488static void hci_setup_inquiry_mode(struct hci_dev *hdev)
489{
490 u8 mode;
491
492 mode = hci_get_inquiry_mode(hdev);
493
494 hci_send_cmd(hdev, HCI_OP_WRITE_INQUIRY_MODE, 1, &mode);
495}
496
497static void hci_setup_event_mask(struct hci_dev *hdev)
498{
499 /* The second byte is 0xff instead of 0x9f (two reserved bits
500 * disabled) since a Broadcom 1.2 dongle doesn't respond to the
501 * command otherwise */
502 u8 events[8] = { 0xff, 0xff, 0xfb, 0xff, 0x00, 0x00, 0x00, 0x00 };
503
Ville Tervo6de6c182011-05-27 11:16:21 +0300504 /* CSR 1.1 dongles does not accept any bitfield so don't try to set
505 * any event mask for pre 1.2 devices */
Andrei Emeltchenko5a13b092011-12-01 14:33:28 +0200506 if (hdev->hci_ver < BLUETOOTH_VER_1_2)
Ville Tervo6de6c182011-05-27 11:16:21 +0300507 return;
508
509 events[4] |= 0x01; /* Flow Specification Complete */
510 events[4] |= 0x02; /* Inquiry Result with RSSI */
511 events[4] |= 0x04; /* Read Remote Extended Features Complete */
512 events[5] |= 0x08; /* Synchronous Connection Complete */
513 events[5] |= 0x10; /* Synchronous Connection Changed */
Johan Hedbergd5859e22011-01-25 01:19:58 +0200514
515 if (hdev->features[3] & LMP_RSSI_INQ)
Johan Hedberga24299e2012-04-26 09:47:46 +0300516 events[4] |= 0x02; /* Inquiry Result with RSSI */
Johan Hedbergd5859e22011-01-25 01:19:58 +0200517
Andre Guedes999dcd12012-07-24 15:03:52 -0300518 if (lmp_sniffsubr_capable(hdev))
Johan Hedbergd5859e22011-01-25 01:19:58 +0200519 events[5] |= 0x20; /* Sniff Subrating */
520
521 if (hdev->features[5] & LMP_PAUSE_ENC)
522 events[5] |= 0x80; /* Encryption Key Refresh Complete */
523
524 if (hdev->features[6] & LMP_EXT_INQ)
525 events[5] |= 0x40; /* Extended Inquiry Result */
526
Andre Guedesc58e8102012-07-24 15:03:53 -0300527 if (lmp_no_flush_capable(hdev))
Johan Hedbergd5859e22011-01-25 01:19:58 +0200528 events[7] |= 0x01; /* Enhanced Flush Complete */
529
530 if (hdev->features[7] & LMP_LSTO)
531 events[6] |= 0x80; /* Link Supervision Timeout Changed */
532
Andre Guedes9a1a1992012-07-24 15:03:48 -0300533 if (lmp_ssp_capable(hdev)) {
Johan Hedbergd5859e22011-01-25 01:19:58 +0200534 events[6] |= 0x01; /* IO Capability Request */
535 events[6] |= 0x02; /* IO Capability Response */
536 events[6] |= 0x04; /* User Confirmation Request */
537 events[6] |= 0x08; /* User Passkey Request */
538 events[6] |= 0x10; /* Remote OOB Data Request */
539 events[6] |= 0x20; /* Simple Pairing Complete */
540 events[7] |= 0x04; /* User Passkey Notification */
541 events[7] |= 0x08; /* Keypress Notification */
542 events[7] |= 0x10; /* Remote Host Supported
543 * Features Notification */
544 }
545
Andre Guedesc383ddc2012-07-24 15:03:47 -0300546 if (lmp_le_capable(hdev))
Johan Hedbergd5859e22011-01-25 01:19:58 +0200547 events[7] |= 0x20; /* LE Meta-Event */
548
549 hci_send_cmd(hdev, HCI_OP_SET_EVENT_MASK, sizeof(events), events);
550}
551
552static void hci_setup(struct hci_dev *hdev)
553{
Andrei Emeltchenkoe61ef492011-12-19 16:31:27 +0200554 if (hdev->dev_type != HCI_BREDR)
555 return;
556
Johan Hedbergd5859e22011-01-25 01:19:58 +0200557 hci_setup_event_mask(hdev);
558
Andrei Emeltchenkod095c1e2011-12-01 14:33:27 +0200559 if (hdev->hci_ver > BLUETOOTH_VER_1_1)
Johan Hedbergd5859e22011-01-25 01:19:58 +0200560 hci_send_cmd(hdev, HCI_OP_READ_LOCAL_COMMANDS, 0, NULL);
561
Gustavo Padovan6d3c7302012-05-24 03:36:37 -0300562 if (lmp_ssp_capable(hdev)) {
Johan Hedberg54d04db2012-02-22 15:47:48 +0200563 if (test_bit(HCI_SSP_ENABLED, &hdev->dev_flags)) {
564 u8 mode = 0x01;
565 hci_send_cmd(hdev, HCI_OP_WRITE_SSP_MODE,
Gustavo F. Padovan04124682012-03-08 01:25:00 -0300566 sizeof(mode), &mode);
Johan Hedberg54d04db2012-02-22 15:47:48 +0200567 } else {
568 struct hci_cp_write_eir cp;
569
570 memset(hdev->eir, 0, sizeof(hdev->eir));
571 memset(&cp, 0, sizeof(cp));
572
573 hci_send_cmd(hdev, HCI_OP_WRITE_EIR, sizeof(cp), &cp);
574 }
Johan Hedbergd5859e22011-01-25 01:19:58 +0200575 }
576
577 if (hdev->features[3] & LMP_RSSI_INQ)
578 hci_setup_inquiry_mode(hdev);
579
580 if (hdev->features[7] & LMP_INQ_TX_PWR)
581 hci_send_cmd(hdev, HCI_OP_READ_INQ_RSP_TX_POWER, 0, NULL);
Andre Guedes971e3a42011-06-30 19:20:52 -0300582
583 if (hdev->features[7] & LMP_EXTFEATURES) {
584 struct hci_cp_read_local_ext_features cp;
585
586 cp.page = 0x01;
Gustavo F. Padovan04124682012-03-08 01:25:00 -0300587 hci_send_cmd(hdev, HCI_OP_READ_LOCAL_EXT_FEATURES, sizeof(cp),
588 &cp);
Andre Guedes971e3a42011-06-30 19:20:52 -0300589 }
Andre Guedese6100a22011-06-30 19:20:54 -0300590
Johan Hedberg47990ea2012-02-22 11:58:37 +0200591 if (test_bit(HCI_LINK_SECURITY, &hdev->dev_flags)) {
592 u8 enable = 1;
Gustavo F. Padovan04124682012-03-08 01:25:00 -0300593 hci_send_cmd(hdev, HCI_OP_WRITE_AUTH_ENABLE, sizeof(enable),
594 &enable);
Johan Hedberg47990ea2012-02-22 11:58:37 +0200595 }
Johan Hedbergd5859e22011-01-25 01:19:58 +0200596}
597
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200598static void hci_cc_read_local_version(struct hci_dev *hdev, struct sk_buff *skb)
599{
600 struct hci_rp_read_local_version *rp = (void *) skb->data;
601
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +0300602 BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200603
604 if (rp->status)
Andrei Emeltchenko28b8df72012-02-24 12:45:44 +0200605 goto done;
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200606
607 hdev->hci_ver = rp->hci_ver;
Marcel Holtmanne4e8e372008-07-14 20:13:47 +0200608 hdev->hci_rev = __le16_to_cpu(rp->hci_rev);
Johan Hedbergd5859e22011-01-25 01:19:58 +0200609 hdev->lmp_ver = rp->lmp_ver;
Marcel Holtmanne4e8e372008-07-14 20:13:47 +0200610 hdev->manufacturer = __le16_to_cpu(rp->manufacturer);
Johan Hedbergd5859e22011-01-25 01:19:58 +0200611 hdev->lmp_subver = __le16_to_cpu(rp->lmp_subver);
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200612
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +0300613 BT_DBG("%s manufacturer 0x%4.4x hci ver %d:%d", hdev->name,
Gustavo Padovan807deac2012-05-17 00:36:24 -0300614 hdev->manufacturer, hdev->hci_ver, hdev->hci_rev);
Johan Hedbergd5859e22011-01-25 01:19:58 +0200615
616 if (test_bit(HCI_INIT, &hdev->flags))
617 hci_setup(hdev);
Andrei Emeltchenko28b8df72012-02-24 12:45:44 +0200618
619done:
620 hci_req_complete(hdev, HCI_OP_READ_LOCAL_VERSION, rp->status);
Johan Hedbergd5859e22011-01-25 01:19:58 +0200621}
622
623static void hci_setup_link_policy(struct hci_dev *hdev)
624{
Andrei Emeltchenko035100c2012-03-12 15:59:32 +0200625 struct hci_cp_write_def_link_policy cp;
Johan Hedbergd5859e22011-01-25 01:19:58 +0200626 u16 link_policy = 0;
627
Andre Guedes9f92ebf2012-07-24 15:03:50 -0300628 if (lmp_rswitch_capable(hdev))
Johan Hedbergd5859e22011-01-25 01:19:58 +0200629 link_policy |= HCI_LP_RSWITCH;
630 if (hdev->features[0] & LMP_HOLD)
631 link_policy |= HCI_LP_HOLD;
Andre Guedes6eded102012-07-24 15:03:51 -0300632 if (lmp_sniff_capable(hdev))
Johan Hedbergd5859e22011-01-25 01:19:58 +0200633 link_policy |= HCI_LP_SNIFF;
634 if (hdev->features[1] & LMP_PARK)
635 link_policy |= HCI_LP_PARK;
636
Andrei Emeltchenko035100c2012-03-12 15:59:32 +0200637 cp.policy = cpu_to_le16(link_policy);
638 hci_send_cmd(hdev, HCI_OP_WRITE_DEF_LINK_POLICY, sizeof(cp), &cp);
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200639}
640
Gustavo Padovan8fc9ced2012-05-23 04:04:21 -0300641static void hci_cc_read_local_commands(struct hci_dev *hdev,
642 struct sk_buff *skb)
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200643{
644 struct hci_rp_read_local_commands *rp = (void *) skb->data;
645
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +0300646 BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200647
648 if (rp->status)
Johan Hedbergd5859e22011-01-25 01:19:58 +0200649 goto done;
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200650
651 memcpy(hdev->commands, rp->commands, sizeof(hdev->commands));
Johan Hedbergd5859e22011-01-25 01:19:58 +0200652
653 if (test_bit(HCI_INIT, &hdev->flags) && (hdev->commands[5] & 0x10))
654 hci_setup_link_policy(hdev);
655
656done:
657 hci_req_complete(hdev, HCI_OP_READ_LOCAL_COMMANDS, rp->status);
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200658}
659
Gustavo Padovan8fc9ced2012-05-23 04:04:21 -0300660static void hci_cc_read_local_features(struct hci_dev *hdev,
661 struct sk_buff *skb)
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200662{
663 struct hci_rp_read_local_features *rp = (void *) skb->data;
664
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +0300665 BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200666
667 if (rp->status)
668 return;
669
670 memcpy(hdev->features, rp->features, 8);
671
672 /* Adjust default settings according to features
673 * supported by device. */
674
675 if (hdev->features[0] & LMP_3SLOT)
676 hdev->pkt_type |= (HCI_DM3 | HCI_DH3);
677
678 if (hdev->features[0] & LMP_5SLOT)
679 hdev->pkt_type |= (HCI_DM5 | HCI_DH5);
680
681 if (hdev->features[1] & LMP_HV2) {
682 hdev->pkt_type |= (HCI_HV2);
683 hdev->esco_type |= (ESCO_HV2);
684 }
685
686 if (hdev->features[1] & LMP_HV3) {
687 hdev->pkt_type |= (HCI_HV3);
688 hdev->esco_type |= (ESCO_HV3);
689 }
690
Andre Guedes45db810f2012-07-24 15:03:49 -0300691 if (lmp_esco_capable(hdev))
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200692 hdev->esco_type |= (ESCO_EV3);
693
694 if (hdev->features[4] & LMP_EV4)
695 hdev->esco_type |= (ESCO_EV4);
696
697 if (hdev->features[4] & LMP_EV5)
698 hdev->esco_type |= (ESCO_EV5);
699
Marcel Holtmannefc76882009-02-06 09:13:37 +0100700 if (hdev->features[5] & LMP_EDR_ESCO_2M)
701 hdev->esco_type |= (ESCO_2EV3);
702
703 if (hdev->features[5] & LMP_EDR_ESCO_3M)
704 hdev->esco_type |= (ESCO_3EV3);
705
706 if (hdev->features[5] & LMP_EDR_3S_ESCO)
707 hdev->esco_type |= (ESCO_2EV5 | ESCO_3EV5);
708
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200709 BT_DBG("%s features 0x%.2x%.2x%.2x%.2x%.2x%.2x%.2x%.2x", hdev->name,
Gustavo Padovan807deac2012-05-17 00:36:24 -0300710 hdev->features[0], hdev->features[1],
711 hdev->features[2], hdev->features[3],
712 hdev->features[4], hdev->features[5],
713 hdev->features[6], hdev->features[7]);
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200714}
715
Johan Hedberg8f984df2012-02-28 01:07:22 +0200716static void hci_set_le_support(struct hci_dev *hdev)
717{
718 struct hci_cp_write_le_host_supported cp;
719
720 memset(&cp, 0, sizeof(cp));
721
Marcel Holtmann9d428202012-05-03 07:12:31 +0200722 if (test_bit(HCI_LE_ENABLED, &hdev->dev_flags)) {
Johan Hedberg8f984df2012-02-28 01:07:22 +0200723 cp.le = 1;
724 cp.simul = !!(hdev->features[6] & LMP_SIMUL_LE_BR);
725 }
726
727 if (cp.le != !!(hdev->host_features[0] & LMP_HOST_LE))
Gustavo F. Padovan04124682012-03-08 01:25:00 -0300728 hci_send_cmd(hdev, HCI_OP_WRITE_LE_HOST_SUPPORTED, sizeof(cp),
729 &cp);
Johan Hedberg8f984df2012-02-28 01:07:22 +0200730}
731
Andre Guedes971e3a42011-06-30 19:20:52 -0300732static void hci_cc_read_local_ext_features(struct hci_dev *hdev,
Gustavo Padovan807deac2012-05-17 00:36:24 -0300733 struct sk_buff *skb)
Andre Guedes971e3a42011-06-30 19:20:52 -0300734{
735 struct hci_rp_read_local_ext_features *rp = (void *) skb->data;
736
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +0300737 BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
Andre Guedes971e3a42011-06-30 19:20:52 -0300738
739 if (rp->status)
Johan Hedberg8f984df2012-02-28 01:07:22 +0200740 goto done;
Andre Guedes971e3a42011-06-30 19:20:52 -0300741
Andre Guedesb5b32b62011-12-30 10:34:04 -0300742 switch (rp->page) {
743 case 0:
744 memcpy(hdev->features, rp->features, 8);
745 break;
746 case 1:
747 memcpy(hdev->host_features, rp->features, 8);
748 break;
749 }
Andre Guedes971e3a42011-06-30 19:20:52 -0300750
Andre Guedesc383ddc2012-07-24 15:03:47 -0300751 if (test_bit(HCI_INIT, &hdev->flags) && lmp_le_capable(hdev))
Johan Hedberg8f984df2012-02-28 01:07:22 +0200752 hci_set_le_support(hdev);
753
754done:
Andre Guedes971e3a42011-06-30 19:20:52 -0300755 hci_req_complete(hdev, HCI_OP_READ_LOCAL_EXT_FEATURES, rp->status);
756}
757
Andrei Emeltchenko1e89cff2011-11-24 14:52:02 +0200758static void hci_cc_read_flow_control_mode(struct hci_dev *hdev,
Gustavo Padovan807deac2012-05-17 00:36:24 -0300759 struct sk_buff *skb)
Andrei Emeltchenko1e89cff2011-11-24 14:52:02 +0200760{
761 struct hci_rp_read_flow_control_mode *rp = (void *) skb->data;
762
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +0300763 BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
Andrei Emeltchenko1e89cff2011-11-24 14:52:02 +0200764
765 if (rp->status)
766 return;
767
768 hdev->flow_ctl_mode = rp->mode;
769
770 hci_req_complete(hdev, HCI_OP_READ_FLOW_CONTROL_MODE, rp->status);
771}
772
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200773static void hci_cc_read_buffer_size(struct hci_dev *hdev, struct sk_buff *skb)
774{
775 struct hci_rp_read_buffer_size *rp = (void *) skb->data;
776
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +0300777 BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200778
779 if (rp->status)
780 return;
781
782 hdev->acl_mtu = __le16_to_cpu(rp->acl_mtu);
783 hdev->sco_mtu = rp->sco_mtu;
784 hdev->acl_pkts = __le16_to_cpu(rp->acl_max_pkt);
785 hdev->sco_pkts = __le16_to_cpu(rp->sco_max_pkt);
786
787 if (test_bit(HCI_QUIRK_FIXUP_BUFFER_SIZE, &hdev->quirks)) {
788 hdev->sco_mtu = 64;
789 hdev->sco_pkts = 8;
790 }
791
792 hdev->acl_cnt = hdev->acl_pkts;
793 hdev->sco_cnt = hdev->sco_pkts;
794
Gustavo Padovan807deac2012-05-17 00:36:24 -0300795 BT_DBG("%s acl mtu %d:%d sco mtu %d:%d", hdev->name, hdev->acl_mtu,
796 hdev->acl_pkts, hdev->sco_mtu, hdev->sco_pkts);
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200797}
798
799static void hci_cc_read_bd_addr(struct hci_dev *hdev, struct sk_buff *skb)
800{
801 struct hci_rp_read_bd_addr *rp = (void *) skb->data;
802
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +0300803 BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200804
805 if (!rp->status)
806 bacpy(&hdev->bdaddr, &rp->bdaddr);
807
Johan Hedberg23bb5762010-12-21 23:01:27 +0200808 hci_req_complete(hdev, HCI_OP_READ_BD_ADDR, rp->status);
809}
810
Andrei Emeltchenko350ee4c2011-12-07 15:56:51 +0200811static void hci_cc_read_data_block_size(struct hci_dev *hdev,
Gustavo Padovan807deac2012-05-17 00:36:24 -0300812 struct sk_buff *skb)
Andrei Emeltchenko350ee4c2011-12-07 15:56:51 +0200813{
814 struct hci_rp_read_data_block_size *rp = (void *) skb->data;
815
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +0300816 BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
Andrei Emeltchenko350ee4c2011-12-07 15:56:51 +0200817
818 if (rp->status)
819 return;
820
821 hdev->block_mtu = __le16_to_cpu(rp->max_acl_len);
822 hdev->block_len = __le16_to_cpu(rp->block_len);
823 hdev->num_blocks = __le16_to_cpu(rp->num_blocks);
824
825 hdev->block_cnt = hdev->num_blocks;
826
827 BT_DBG("%s blk mtu %d cnt %d len %d", hdev->name, hdev->block_mtu,
Gustavo Padovan807deac2012-05-17 00:36:24 -0300828 hdev->block_cnt, hdev->block_len);
Andrei Emeltchenko350ee4c2011-12-07 15:56:51 +0200829
830 hci_req_complete(hdev, HCI_OP_READ_DATA_BLOCK_SIZE, rp->status);
831}
832
Johan Hedberg23bb5762010-12-21 23:01:27 +0200833static void hci_cc_write_ca_timeout(struct hci_dev *hdev, struct sk_buff *skb)
834{
835 __u8 status = *((__u8 *) skb->data);
836
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +0300837 BT_DBG("%s status 0x%2.2x", hdev->name, status);
Johan Hedberg23bb5762010-12-21 23:01:27 +0200838
839 hci_req_complete(hdev, HCI_OP_WRITE_CA_TIMEOUT, status);
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200840}
841
Andrei Emeltchenko928abaa2011-10-12 10:53:57 +0300842static void hci_cc_read_local_amp_info(struct hci_dev *hdev,
Gustavo Padovan807deac2012-05-17 00:36:24 -0300843 struct sk_buff *skb)
Andrei Emeltchenko928abaa2011-10-12 10:53:57 +0300844{
845 struct hci_rp_read_local_amp_info *rp = (void *) skb->data;
846
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +0300847 BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
Andrei Emeltchenko928abaa2011-10-12 10:53:57 +0300848
849 if (rp->status)
Andrei Emeltchenko8e2a0d92012-09-27 17:26:08 +0300850 goto a2mp_rsp;
Andrei Emeltchenko928abaa2011-10-12 10:53:57 +0300851
852 hdev->amp_status = rp->amp_status;
853 hdev->amp_total_bw = __le32_to_cpu(rp->total_bw);
854 hdev->amp_max_bw = __le32_to_cpu(rp->max_bw);
855 hdev->amp_min_latency = __le32_to_cpu(rp->min_latency);
856 hdev->amp_max_pdu = __le32_to_cpu(rp->max_pdu);
857 hdev->amp_type = rp->amp_type;
858 hdev->amp_pal_cap = __le16_to_cpu(rp->pal_cap);
859 hdev->amp_assoc_size = __le16_to_cpu(rp->max_assoc_size);
860 hdev->amp_be_flush_to = __le32_to_cpu(rp->be_flush_to);
861 hdev->amp_max_flush_to = __le32_to_cpu(rp->max_flush_to);
862
863 hci_req_complete(hdev, HCI_OP_READ_LOCAL_AMP_INFO, rp->status);
Andrei Emeltchenko8e2a0d92012-09-27 17:26:08 +0300864
865a2mp_rsp:
866 a2mp_send_getinfo_rsp(hdev);
Andrei Emeltchenko928abaa2011-10-12 10:53:57 +0300867}
868
Johan Hedbergb0916ea2011-01-10 13:44:55 +0200869static void hci_cc_delete_stored_link_key(struct hci_dev *hdev,
Gustavo Padovan807deac2012-05-17 00:36:24 -0300870 struct sk_buff *skb)
Johan Hedbergb0916ea2011-01-10 13:44:55 +0200871{
872 __u8 status = *((__u8 *) skb->data);
873
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +0300874 BT_DBG("%s status 0x%2.2x", hdev->name, status);
Johan Hedbergb0916ea2011-01-10 13:44:55 +0200875
876 hci_req_complete(hdev, HCI_OP_DELETE_STORED_LINK_KEY, status);
877}
878
Johan Hedbergd5859e22011-01-25 01:19:58 +0200879static void hci_cc_set_event_mask(struct hci_dev *hdev, struct sk_buff *skb)
880{
881 __u8 status = *((__u8 *) skb->data);
882
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +0300883 BT_DBG("%s status 0x%2.2x", hdev->name, status);
Johan Hedbergd5859e22011-01-25 01:19:58 +0200884
885 hci_req_complete(hdev, HCI_OP_SET_EVENT_MASK, status);
886}
887
888static void hci_cc_write_inquiry_mode(struct hci_dev *hdev,
Gustavo Padovan807deac2012-05-17 00:36:24 -0300889 struct sk_buff *skb)
Johan Hedbergd5859e22011-01-25 01:19:58 +0200890{
891 __u8 status = *((__u8 *) skb->data);
892
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +0300893 BT_DBG("%s status 0x%2.2x", hdev->name, status);
Johan Hedbergd5859e22011-01-25 01:19:58 +0200894
895 hci_req_complete(hdev, HCI_OP_WRITE_INQUIRY_MODE, status);
896}
897
898static void hci_cc_read_inq_rsp_tx_power(struct hci_dev *hdev,
Gustavo Padovan807deac2012-05-17 00:36:24 -0300899 struct sk_buff *skb)
Johan Hedbergd5859e22011-01-25 01:19:58 +0200900{
Marcel Holtmann91c4e9b2012-03-11 19:27:21 -0700901 struct hci_rp_read_inq_rsp_tx_power *rp = (void *) skb->data;
Johan Hedbergd5859e22011-01-25 01:19:58 +0200902
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +0300903 BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
Johan Hedbergd5859e22011-01-25 01:19:58 +0200904
Marcel Holtmann91c4e9b2012-03-11 19:27:21 -0700905 if (!rp->status)
906 hdev->inq_tx_power = rp->tx_power;
907
908 hci_req_complete(hdev, HCI_OP_READ_INQ_RSP_TX_POWER, rp->status);
Johan Hedbergd5859e22011-01-25 01:19:58 +0200909}
910
911static void hci_cc_set_event_flt(struct hci_dev *hdev, struct sk_buff *skb)
912{
913 __u8 status = *((__u8 *) skb->data);
914
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +0300915 BT_DBG("%s status 0x%2.2x", hdev->name, status);
Johan Hedbergd5859e22011-01-25 01:19:58 +0200916
917 hci_req_complete(hdev, HCI_OP_SET_EVENT_FLT, status);
918}
919
Johan Hedberg980e1a52011-01-22 06:10:07 +0200920static void hci_cc_pin_code_reply(struct hci_dev *hdev, struct sk_buff *skb)
921{
922 struct hci_rp_pin_code_reply *rp = (void *) skb->data;
923 struct hci_cp_pin_code_reply *cp;
924 struct hci_conn *conn;
925
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +0300926 BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
Johan Hedberg980e1a52011-01-22 06:10:07 +0200927
Johan Hedberg56e5cb82011-11-08 20:40:16 +0200928 hci_dev_lock(hdev);
929
Johan Hedberga8b2d5c2012-01-08 23:11:15 +0200930 if (test_bit(HCI_MGMT, &hdev->dev_flags))
Johan Hedberg744cf192011-11-08 20:40:14 +0200931 mgmt_pin_code_reply_complete(hdev, &rp->bdaddr, rp->status);
Johan Hedberg980e1a52011-01-22 06:10:07 +0200932
Mikel Astizfa1bd912012-08-09 09:52:29 +0200933 if (rp->status)
Johan Hedberg56e5cb82011-11-08 20:40:16 +0200934 goto unlock;
Johan Hedberg980e1a52011-01-22 06:10:07 +0200935
936 cp = hci_sent_cmd_data(hdev, HCI_OP_PIN_CODE_REPLY);
937 if (!cp)
Johan Hedberg56e5cb82011-11-08 20:40:16 +0200938 goto unlock;
Johan Hedberg980e1a52011-01-22 06:10:07 +0200939
940 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &cp->bdaddr);
941 if (conn)
942 conn->pin_length = cp->pin_len;
Johan Hedberg56e5cb82011-11-08 20:40:16 +0200943
944unlock:
945 hci_dev_unlock(hdev);
Johan Hedberg980e1a52011-01-22 06:10:07 +0200946}
947
948static void hci_cc_pin_code_neg_reply(struct hci_dev *hdev, struct sk_buff *skb)
949{
950 struct hci_rp_pin_code_neg_reply *rp = (void *) skb->data;
951
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +0300952 BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
Johan Hedberg980e1a52011-01-22 06:10:07 +0200953
Johan Hedberg56e5cb82011-11-08 20:40:16 +0200954 hci_dev_lock(hdev);
955
Johan Hedberga8b2d5c2012-01-08 23:11:15 +0200956 if (test_bit(HCI_MGMT, &hdev->dev_flags))
Johan Hedberg744cf192011-11-08 20:40:14 +0200957 mgmt_pin_code_neg_reply_complete(hdev, &rp->bdaddr,
Gustavo Padovan807deac2012-05-17 00:36:24 -0300958 rp->status);
Johan Hedberg56e5cb82011-11-08 20:40:16 +0200959
960 hci_dev_unlock(hdev);
Johan Hedberg980e1a52011-01-22 06:10:07 +0200961}
Johan Hedberg56e5cb82011-11-08 20:40:16 +0200962
Ville Tervo6ed58ec2011-02-10 22:38:48 -0300963static void hci_cc_le_read_buffer_size(struct hci_dev *hdev,
964 struct sk_buff *skb)
965{
966 struct hci_rp_le_read_buffer_size *rp = (void *) skb->data;
967
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +0300968 BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
Ville Tervo6ed58ec2011-02-10 22:38:48 -0300969
970 if (rp->status)
971 return;
972
973 hdev->le_mtu = __le16_to_cpu(rp->le_mtu);
974 hdev->le_pkts = rp->le_max_pkt;
975
976 hdev->le_cnt = hdev->le_pkts;
977
978 BT_DBG("%s le mtu %d:%d", hdev->name, hdev->le_mtu, hdev->le_pkts);
979
980 hci_req_complete(hdev, HCI_OP_LE_READ_BUFFER_SIZE, rp->status);
981}
Johan Hedberg980e1a52011-01-22 06:10:07 +0200982
Johan Hedberga5c29682011-02-19 12:05:57 -0300983static void hci_cc_user_confirm_reply(struct hci_dev *hdev, struct sk_buff *skb)
984{
985 struct hci_rp_user_confirm_reply *rp = (void *) skb->data;
986
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +0300987 BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
Johan Hedberga5c29682011-02-19 12:05:57 -0300988
Johan Hedberg56e5cb82011-11-08 20:40:16 +0200989 hci_dev_lock(hdev);
990
Johan Hedberga8b2d5c2012-01-08 23:11:15 +0200991 if (test_bit(HCI_MGMT, &hdev->dev_flags))
Gustavo F. Padovan04124682012-03-08 01:25:00 -0300992 mgmt_user_confirm_reply_complete(hdev, &rp->bdaddr, ACL_LINK, 0,
993 rp->status);
Johan Hedberg56e5cb82011-11-08 20:40:16 +0200994
995 hci_dev_unlock(hdev);
Johan Hedberga5c29682011-02-19 12:05:57 -0300996}
997
998static void hci_cc_user_confirm_neg_reply(struct hci_dev *hdev,
Gustavo Padovan807deac2012-05-17 00:36:24 -0300999 struct sk_buff *skb)
Johan Hedberga5c29682011-02-19 12:05:57 -03001000{
1001 struct hci_rp_user_confirm_reply *rp = (void *) skb->data;
1002
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +03001003 BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
Johan Hedberga5c29682011-02-19 12:05:57 -03001004
Johan Hedberg56e5cb82011-11-08 20:40:16 +02001005 hci_dev_lock(hdev);
1006
Johan Hedberga8b2d5c2012-01-08 23:11:15 +02001007 if (test_bit(HCI_MGMT, &hdev->dev_flags))
Johan Hedberg744cf192011-11-08 20:40:14 +02001008 mgmt_user_confirm_neg_reply_complete(hdev, &rp->bdaddr,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001009 ACL_LINK, 0, rp->status);
Johan Hedberg56e5cb82011-11-08 20:40:16 +02001010
1011 hci_dev_unlock(hdev);
Johan Hedberga5c29682011-02-19 12:05:57 -03001012}
1013
Brian Gix1143d452011-11-23 08:28:34 -08001014static void hci_cc_user_passkey_reply(struct hci_dev *hdev, struct sk_buff *skb)
1015{
1016 struct hci_rp_user_confirm_reply *rp = (void *) skb->data;
1017
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +03001018 BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
Brian Gix1143d452011-11-23 08:28:34 -08001019
1020 hci_dev_lock(hdev);
1021
Johan Hedberga8b2d5c2012-01-08 23:11:15 +02001022 if (test_bit(HCI_MGMT, &hdev->dev_flags))
Johan Hedberg272d90d2012-02-09 15:26:12 +02001023 mgmt_user_passkey_reply_complete(hdev, &rp->bdaddr, ACL_LINK,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001024 0, rp->status);
Brian Gix1143d452011-11-23 08:28:34 -08001025
1026 hci_dev_unlock(hdev);
1027}
1028
1029static void hci_cc_user_passkey_neg_reply(struct hci_dev *hdev,
Gustavo Padovan807deac2012-05-17 00:36:24 -03001030 struct sk_buff *skb)
Brian Gix1143d452011-11-23 08:28:34 -08001031{
1032 struct hci_rp_user_confirm_reply *rp = (void *) skb->data;
1033
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +03001034 BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
Brian Gix1143d452011-11-23 08:28:34 -08001035
1036 hci_dev_lock(hdev);
1037
Johan Hedberga8b2d5c2012-01-08 23:11:15 +02001038 if (test_bit(HCI_MGMT, &hdev->dev_flags))
Brian Gix1143d452011-11-23 08:28:34 -08001039 mgmt_user_passkey_neg_reply_complete(hdev, &rp->bdaddr,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001040 ACL_LINK, 0, rp->status);
Brian Gix1143d452011-11-23 08:28:34 -08001041
1042 hci_dev_unlock(hdev);
1043}
1044
Szymon Jancc35938b2011-03-22 13:12:21 +01001045static void hci_cc_read_local_oob_data_reply(struct hci_dev *hdev,
Gustavo Padovan807deac2012-05-17 00:36:24 -03001046 struct sk_buff *skb)
Szymon Jancc35938b2011-03-22 13:12:21 +01001047{
1048 struct hci_rp_read_local_oob_data *rp = (void *) skb->data;
1049
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +03001050 BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
Szymon Jancc35938b2011-03-22 13:12:21 +01001051
Johan Hedberg56e5cb82011-11-08 20:40:16 +02001052 hci_dev_lock(hdev);
Johan Hedberg744cf192011-11-08 20:40:14 +02001053 mgmt_read_local_oob_data_reply_complete(hdev, rp->hash,
Szymon Jancc35938b2011-03-22 13:12:21 +01001054 rp->randomizer, rp->status);
Johan Hedberg56e5cb82011-11-08 20:40:16 +02001055 hci_dev_unlock(hdev);
Szymon Jancc35938b2011-03-22 13:12:21 +01001056}
1057
Andre Guedes07f7fa52011-12-02 21:13:31 +09001058static void hci_cc_le_set_scan_param(struct hci_dev *hdev, struct sk_buff *skb)
1059{
1060 __u8 status = *((__u8 *) skb->data);
1061
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +03001062 BT_DBG("%s status 0x%2.2x", hdev->name, status);
Andre Guedes7ba8b4b2012-02-03 17:47:59 -03001063
1064 hci_req_complete(hdev, HCI_OP_LE_SET_SCAN_PARAM, status);
Andre Guedes3fd24152012-02-03 17:48:01 -03001065
1066 if (status) {
1067 hci_dev_lock(hdev);
1068 mgmt_start_discovery_failed(hdev, status);
1069 hci_dev_unlock(hdev);
1070 return;
1071 }
Andre Guedes07f7fa52011-12-02 21:13:31 +09001072}
1073
Andre Guedeseb9d91f2011-05-26 16:23:52 -03001074static void hci_cc_le_set_scan_enable(struct hci_dev *hdev,
Gustavo Padovan807deac2012-05-17 00:36:24 -03001075 struct sk_buff *skb)
Andre Guedeseb9d91f2011-05-26 16:23:52 -03001076{
1077 struct hci_cp_le_set_scan_enable *cp;
1078 __u8 status = *((__u8 *) skb->data);
1079
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +03001080 BT_DBG("%s status 0x%2.2x", hdev->name, status);
Andre Guedeseb9d91f2011-05-26 16:23:52 -03001081
Andre Guedeseb9d91f2011-05-26 16:23:52 -03001082 cp = hci_sent_cmd_data(hdev, HCI_OP_LE_SET_SCAN_ENABLE);
1083 if (!cp)
1084 return;
1085
Andrei Emeltchenko68a8aea2011-12-19 16:14:18 +02001086 switch (cp->enable) {
1087 case LE_SCANNING_ENABLED:
Andre Guedes7ba8b4b2012-02-03 17:47:59 -03001088 hci_req_complete(hdev, HCI_OP_LE_SET_SCAN_ENABLE, status);
1089
Andre Guedes3fd24152012-02-03 17:48:01 -03001090 if (status) {
1091 hci_dev_lock(hdev);
1092 mgmt_start_discovery_failed(hdev, status);
1093 hci_dev_unlock(hdev);
Andre Guedes7ba8b4b2012-02-03 17:47:59 -03001094 return;
Andre Guedes3fd24152012-02-03 17:48:01 -03001095 }
Andre Guedes7ba8b4b2012-02-03 17:47:59 -03001096
Andre Guedesd23264a2011-11-25 20:53:38 -03001097 set_bit(HCI_LE_SCAN, &hdev->dev_flags);
1098
Andre Guedesa8f13c82011-09-09 18:56:24 -03001099 hci_dev_lock(hdev);
Andre Guedes343f9352012-02-17 20:39:37 -03001100 hci_discovery_set_state(hdev, DISCOVERY_FINDING);
Andre Guedesa8f13c82011-09-09 18:56:24 -03001101 hci_dev_unlock(hdev);
Andrei Emeltchenko68a8aea2011-12-19 16:14:18 +02001102 break;
1103
1104 case LE_SCANNING_DISABLED:
Andre Guedesc9ecc482012-03-15 16:52:08 -03001105 if (status) {
1106 hci_dev_lock(hdev);
1107 mgmt_stop_discovery_failed(hdev, status);
1108 hci_dev_unlock(hdev);
Andre Guedes7ba8b4b2012-02-03 17:47:59 -03001109 return;
Andre Guedesc9ecc482012-03-15 16:52:08 -03001110 }
Andre Guedes7ba8b4b2012-02-03 17:47:59 -03001111
Andre Guedesd23264a2011-11-25 20:53:38 -03001112 clear_bit(HCI_LE_SCAN, &hdev->dev_flags);
1113
Andre Guedesbc3dd332012-03-06 19:37:06 -03001114 if (hdev->discovery.type == DISCOV_TYPE_INTERLEAVED &&
1115 hdev->discovery.state == DISCOVERY_FINDING) {
Andre Guedes5e0452c2012-02-17 20:39:38 -03001116 mgmt_interleaved_discovery(hdev);
1117 } else {
1118 hci_dev_lock(hdev);
1119 hci_discovery_set_state(hdev, DISCOVERY_STOPPED);
1120 hci_dev_unlock(hdev);
1121 }
1122
Andrei Emeltchenko68a8aea2011-12-19 16:14:18 +02001123 break;
1124
1125 default:
1126 BT_ERR("Used reserved LE_Scan_Enable param %d", cp->enable);
1127 break;
Andre Guedes35815082011-05-26 16:23:53 -03001128 }
Andre Guedeseb9d91f2011-05-26 16:23:52 -03001129}
1130
Vinicius Costa Gomesa7a595f2011-06-09 18:50:47 -03001131static void hci_cc_le_ltk_reply(struct hci_dev *hdev, struct sk_buff *skb)
1132{
1133 struct hci_rp_le_ltk_reply *rp = (void *) skb->data;
1134
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +03001135 BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
Vinicius Costa Gomesa7a595f2011-06-09 18:50:47 -03001136
1137 if (rp->status)
1138 return;
1139
1140 hci_req_complete(hdev, HCI_OP_LE_LTK_REPLY, rp->status);
1141}
1142
1143static void hci_cc_le_ltk_neg_reply(struct hci_dev *hdev, struct sk_buff *skb)
1144{
1145 struct hci_rp_le_ltk_neg_reply *rp = (void *) skb->data;
1146
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +03001147 BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
Vinicius Costa Gomesa7a595f2011-06-09 18:50:47 -03001148
1149 if (rp->status)
1150 return;
1151
1152 hci_req_complete(hdev, HCI_OP_LE_LTK_NEG_REPLY, rp->status);
1153}
1154
Gustavo Padovan6039aa732012-05-23 04:04:18 -03001155static void hci_cc_write_le_host_supported(struct hci_dev *hdev,
1156 struct sk_buff *skb)
Andre Guedesf9b49302011-06-30 19:20:53 -03001157{
Johan Hedberg06199cf2012-02-22 16:37:11 +02001158 struct hci_cp_write_le_host_supported *sent;
Andre Guedesf9b49302011-06-30 19:20:53 -03001159 __u8 status = *((__u8 *) skb->data);
1160
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +03001161 BT_DBG("%s status 0x%2.2x", hdev->name, status);
Andre Guedesf9b49302011-06-30 19:20:53 -03001162
Johan Hedberg06199cf2012-02-22 16:37:11 +02001163 sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_LE_HOST_SUPPORTED);
Johan Hedberg8f984df2012-02-28 01:07:22 +02001164 if (!sent)
Andre Guedesf9b49302011-06-30 19:20:53 -03001165 return;
1166
Johan Hedberg8f984df2012-02-28 01:07:22 +02001167 if (!status) {
1168 if (sent->le)
1169 hdev->host_features[0] |= LMP_HOST_LE;
1170 else
1171 hdev->host_features[0] &= ~LMP_HOST_LE;
1172 }
1173
1174 if (test_bit(HCI_MGMT, &hdev->dev_flags) &&
Gustavo Padovan807deac2012-05-17 00:36:24 -03001175 !test_bit(HCI_INIT, &hdev->flags))
Johan Hedberg8f984df2012-02-28 01:07:22 +02001176 mgmt_le_enable_complete(hdev, sent->le, status);
1177
1178 hci_req_complete(hdev, HCI_OP_WRITE_LE_HOST_SUPPORTED, status);
Andre Guedesf9b49302011-06-30 19:20:53 -03001179}
1180
Gustavo Padovan6039aa732012-05-23 04:04:18 -03001181static void hci_cs_inquiry(struct hci_dev *hdev, __u8 status)
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001182{
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +03001183 BT_DBG("%s status 0x%2.2x", hdev->name, status);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001184
1185 if (status) {
Johan Hedberg23bb5762010-12-21 23:01:27 +02001186 hci_req_complete(hdev, HCI_OP_INQUIRY, status);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001187 hci_conn_check_pending(hdev);
Johan Hedberg56e5cb82011-11-08 20:40:16 +02001188 hci_dev_lock(hdev);
Johan Hedberga8b2d5c2012-01-08 23:11:15 +02001189 if (test_bit(HCI_MGMT, &hdev->dev_flags))
Andre Guedes7a135102011-11-09 17:14:25 -03001190 mgmt_start_discovery_failed(hdev, status);
Johan Hedberg56e5cb82011-11-08 20:40:16 +02001191 hci_dev_unlock(hdev);
Johan Hedberg314b2382011-04-27 10:29:57 -04001192 return;
1193 }
1194
Andre Guedes89352e72011-11-04 14:16:53 -03001195 set_bit(HCI_INQUIRY, &hdev->flags);
1196
Johan Hedberg56e5cb82011-11-08 20:40:16 +02001197 hci_dev_lock(hdev);
Andre Guedes343f9352012-02-17 20:39:37 -03001198 hci_discovery_set_state(hdev, DISCOVERY_FINDING);
Johan Hedberg56e5cb82011-11-08 20:40:16 +02001199 hci_dev_unlock(hdev);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001200}
1201
Gustavo Padovan6039aa732012-05-23 04:04:18 -03001202static void hci_cs_create_conn(struct hci_dev *hdev, __u8 status)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001203{
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001204 struct hci_cp_create_conn *cp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001205 struct hci_conn *conn;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001206
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +03001207 BT_DBG("%s status 0x%2.2x", hdev->name, status);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001208
1209 cp = hci_sent_cmd_data(hdev, HCI_OP_CREATE_CONN);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001210 if (!cp)
1211 return;
1212
1213 hci_dev_lock(hdev);
1214
1215 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &cp->bdaddr);
1216
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +03001217 BT_DBG("%s bdaddr %s hcon %p", hdev->name, batostr(&cp->bdaddr), conn);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001218
1219 if (status) {
1220 if (conn && conn->state == BT_CONNECT) {
Marcel Holtmann4c67bc72006-10-15 17:30:56 +02001221 if (status != 0x0c || conn->attempt > 2) {
1222 conn->state = BT_CLOSED;
1223 hci_proto_connect_cfm(conn, status);
1224 hci_conn_del(conn);
1225 } else
1226 conn->state = BT_CONNECT2;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001227 }
1228 } else {
1229 if (!conn) {
1230 conn = hci_conn_add(hdev, ACL_LINK, &cp->bdaddr);
1231 if (conn) {
Johan Hedberga0c808b2012-01-16 09:49:58 +02001232 conn->out = true;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001233 conn->link_mode |= HCI_LM_MASTER;
1234 } else
Gustavo F. Padovan893ef972010-07-18 15:13:37 -03001235 BT_ERR("No memory for new connection");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001236 }
1237 }
1238
1239 hci_dev_unlock(hdev);
1240}
1241
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001242static void hci_cs_add_sco(struct hci_dev *hdev, __u8 status)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001243{
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001244 struct hci_cp_add_sco *cp;
1245 struct hci_conn *acl, *sco;
1246 __u16 handle;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001247
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +03001248 BT_DBG("%s status 0x%2.2x", hdev->name, status);
Marcel Holtmannb6a0dc82007-10-20 14:55:10 +02001249
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001250 if (!status)
1251 return;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001252
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001253 cp = hci_sent_cmd_data(hdev, HCI_OP_ADD_SCO);
1254 if (!cp)
1255 return;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001256
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001257 handle = __le16_to_cpu(cp->handle);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001258
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +03001259 BT_DBG("%s handle 0x%4.4x", hdev->name, handle);
Marcel Holtmann6bd57412006-11-18 22:14:22 +01001260
1261 hci_dev_lock(hdev);
1262
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001263 acl = hci_conn_hash_lookup_handle(hdev, handle);
Andrei Emeltchenko5a08ecc2011-01-11 17:20:20 +02001264 if (acl) {
1265 sco = acl->link;
1266 if (sco) {
1267 sco->state = BT_CLOSED;
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001268
Andrei Emeltchenko5a08ecc2011-01-11 17:20:20 +02001269 hci_proto_connect_cfm(sco, status);
1270 hci_conn_del(sco);
1271 }
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001272 }
Marcel Holtmann6bd57412006-11-18 22:14:22 +01001273
1274 hci_dev_unlock(hdev);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001275}
1276
Marcel Holtmannf8558552008-07-14 20:13:49 +02001277static void hci_cs_auth_requested(struct hci_dev *hdev, __u8 status)
1278{
1279 struct hci_cp_auth_requested *cp;
1280 struct hci_conn *conn;
1281
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +03001282 BT_DBG("%s status 0x%2.2x", hdev->name, status);
Marcel Holtmannf8558552008-07-14 20:13:49 +02001283
1284 if (!status)
1285 return;
1286
1287 cp = hci_sent_cmd_data(hdev, HCI_OP_AUTH_REQUESTED);
1288 if (!cp)
1289 return;
1290
1291 hci_dev_lock(hdev);
1292
1293 conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(cp->handle));
1294 if (conn) {
1295 if (conn->state == BT_CONFIG) {
1296 hci_proto_connect_cfm(conn, status);
1297 hci_conn_put(conn);
1298 }
1299 }
1300
1301 hci_dev_unlock(hdev);
1302}
1303
1304static void hci_cs_set_conn_encrypt(struct hci_dev *hdev, __u8 status)
1305{
1306 struct hci_cp_set_conn_encrypt *cp;
1307 struct hci_conn *conn;
1308
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +03001309 BT_DBG("%s status 0x%2.2x", hdev->name, status);
Marcel Holtmannf8558552008-07-14 20:13:49 +02001310
1311 if (!status)
1312 return;
1313
1314 cp = hci_sent_cmd_data(hdev, HCI_OP_SET_CONN_ENCRYPT);
1315 if (!cp)
1316 return;
1317
1318 hci_dev_lock(hdev);
1319
1320 conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(cp->handle));
1321 if (conn) {
1322 if (conn->state == BT_CONFIG) {
1323 hci_proto_connect_cfm(conn, status);
1324 hci_conn_put(conn);
1325 }
1326 }
1327
1328 hci_dev_unlock(hdev);
1329}
1330
Johan Hedberg127178d2010-11-18 22:22:29 +02001331static int hci_outgoing_auth_needed(struct hci_dev *hdev,
Gustavo Padovan807deac2012-05-17 00:36:24 -03001332 struct hci_conn *conn)
Johan Hedberg392599b2010-11-18 22:22:28 +02001333{
Johan Hedberg392599b2010-11-18 22:22:28 +02001334 if (conn->state != BT_CONFIG || !conn->out)
1335 return 0;
1336
Johan Hedberg765c2a92011-01-19 12:06:52 +05301337 if (conn->pending_sec_level == BT_SECURITY_SDP)
Johan Hedberg392599b2010-11-18 22:22:28 +02001338 return 0;
1339
1340 /* Only request authentication for SSP connections or non-SSP
Vinicius Costa Gomese9bf2bf2011-09-02 14:51:20 -03001341 * devices with sec_level HIGH or if MITM protection is requested */
Gustavo Padovan807deac2012-05-17 00:36:24 -03001342 if (!hci_conn_ssp_enabled(conn) && !(conn->auth_type & 0x01) &&
1343 conn->pending_sec_level != BT_SECURITY_HIGH)
Johan Hedberg392599b2010-11-18 22:22:28 +02001344 return 0;
1345
Johan Hedberg392599b2010-11-18 22:22:28 +02001346 return 1;
1347}
1348
Gustavo Padovan6039aa732012-05-23 04:04:18 -03001349static int hci_resolve_name(struct hci_dev *hdev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001350 struct inquiry_entry *e)
Johan Hedberg30dc78e2012-01-04 15:44:20 +02001351{
1352 struct hci_cp_remote_name_req cp;
1353
1354 memset(&cp, 0, sizeof(cp));
1355
1356 bacpy(&cp.bdaddr, &e->data.bdaddr);
1357 cp.pscan_rep_mode = e->data.pscan_rep_mode;
1358 cp.pscan_mode = e->data.pscan_mode;
1359 cp.clock_offset = e->data.clock_offset;
1360
1361 return hci_send_cmd(hdev, HCI_OP_REMOTE_NAME_REQ, sizeof(cp), &cp);
1362}
1363
Johan Hedbergb644ba32012-01-17 21:48:47 +02001364static bool hci_resolve_next_name(struct hci_dev *hdev)
Johan Hedberg30dc78e2012-01-04 15:44:20 +02001365{
1366 struct discovery_state *discov = &hdev->discovery;
1367 struct inquiry_entry *e;
1368
Johan Hedbergb644ba32012-01-17 21:48:47 +02001369 if (list_empty(&discov->resolve))
1370 return false;
1371
1372 e = hci_inquiry_cache_lookup_resolve(hdev, BDADDR_ANY, NAME_NEEDED);
Ram Malovanyc8100892012-07-19 10:26:09 +03001373 if (!e)
1374 return false;
1375
Johan Hedbergb644ba32012-01-17 21:48:47 +02001376 if (hci_resolve_name(hdev, e) == 0) {
1377 e->name_state = NAME_PENDING;
1378 return true;
1379 }
1380
1381 return false;
1382}
1383
1384static void hci_check_pending_name(struct hci_dev *hdev, struct hci_conn *conn,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001385 bdaddr_t *bdaddr, u8 *name, u8 name_len)
Johan Hedbergb644ba32012-01-17 21:48:47 +02001386{
1387 struct discovery_state *discov = &hdev->discovery;
1388 struct inquiry_entry *e;
1389
1390 if (conn && !test_and_set_bit(HCI_CONN_MGMT_CONNECTED, &conn->flags))
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001391 mgmt_device_connected(hdev, bdaddr, ACL_LINK, 0x00, 0, name,
1392 name_len, conn->dev_class);
Johan Hedbergb644ba32012-01-17 21:48:47 +02001393
1394 if (discov->state == DISCOVERY_STOPPED)
1395 return;
1396
Johan Hedberg30dc78e2012-01-04 15:44:20 +02001397 if (discov->state == DISCOVERY_STOPPING)
1398 goto discov_complete;
1399
1400 if (discov->state != DISCOVERY_RESOLVING)
1401 return;
1402
1403 e = hci_inquiry_cache_lookup_resolve(hdev, bdaddr, NAME_PENDING);
Ram Malovany7cc83802012-07-19 10:26:10 +03001404 /* If the device was not found in a list of found devices names of which
1405 * are pending. there is no need to continue resolving a next name as it
1406 * will be done upon receiving another Remote Name Request Complete
1407 * Event */
1408 if (!e)
1409 return;
1410
1411 list_del(&e->list);
1412 if (name) {
Johan Hedberg30dc78e2012-01-04 15:44:20 +02001413 e->name_state = NAME_KNOWN;
Ram Malovany7cc83802012-07-19 10:26:10 +03001414 mgmt_remote_name(hdev, bdaddr, ACL_LINK, 0x00,
1415 e->data.rssi, name, name_len);
Ram Malovanyc3e7c0d2012-07-19 10:26:11 +03001416 } else {
1417 e->name_state = NAME_NOT_KNOWN;
Johan Hedberg30dc78e2012-01-04 15:44:20 +02001418 }
1419
Johan Hedbergb644ba32012-01-17 21:48:47 +02001420 if (hci_resolve_next_name(hdev))
Johan Hedberg30dc78e2012-01-04 15:44:20 +02001421 return;
Johan Hedberg30dc78e2012-01-04 15:44:20 +02001422
1423discov_complete:
1424 hci_discovery_set_state(hdev, DISCOVERY_STOPPED);
1425}
1426
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001427static void hci_cs_remote_name_req(struct hci_dev *hdev, __u8 status)
1428{
Johan Hedberg127178d2010-11-18 22:22:29 +02001429 struct hci_cp_remote_name_req *cp;
1430 struct hci_conn *conn;
1431
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +03001432 BT_DBG("%s status 0x%2.2x", hdev->name, status);
Johan Hedberg127178d2010-11-18 22:22:29 +02001433
1434 /* If successful wait for the name req complete event before
1435 * checking for the need to do authentication */
1436 if (!status)
1437 return;
1438
1439 cp = hci_sent_cmd_data(hdev, HCI_OP_REMOTE_NAME_REQ);
1440 if (!cp)
1441 return;
1442
1443 hci_dev_lock(hdev);
1444
1445 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &cp->bdaddr);
Johan Hedbergb644ba32012-01-17 21:48:47 +02001446
1447 if (test_bit(HCI_MGMT, &hdev->dev_flags))
1448 hci_check_pending_name(hdev, conn, &cp->bdaddr, NULL, 0);
1449
Johan Hedberg79c6c702011-04-28 11:28:55 -07001450 if (!conn)
1451 goto unlock;
1452
1453 if (!hci_outgoing_auth_needed(hdev, conn))
1454 goto unlock;
1455
Johan Hedberg51a8efd2012-01-16 06:10:31 +02001456 if (!test_and_set_bit(HCI_CONN_AUTH_PEND, &conn->flags)) {
Johan Hedberg127178d2010-11-18 22:22:29 +02001457 struct hci_cp_auth_requested cp;
1458 cp.handle = __cpu_to_le16(conn->handle);
1459 hci_send_cmd(hdev, HCI_OP_AUTH_REQUESTED, sizeof(cp), &cp);
1460 }
1461
Johan Hedberg79c6c702011-04-28 11:28:55 -07001462unlock:
Johan Hedberg127178d2010-11-18 22:22:29 +02001463 hci_dev_unlock(hdev);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001464}
1465
Marcel Holtmann769be972008-07-14 20:13:49 +02001466static void hci_cs_read_remote_features(struct hci_dev *hdev, __u8 status)
1467{
1468 struct hci_cp_read_remote_features *cp;
1469 struct hci_conn *conn;
1470
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +03001471 BT_DBG("%s status 0x%2.2x", hdev->name, status);
Marcel Holtmann769be972008-07-14 20:13:49 +02001472
1473 if (!status)
1474 return;
1475
1476 cp = hci_sent_cmd_data(hdev, HCI_OP_READ_REMOTE_FEATURES);
1477 if (!cp)
1478 return;
1479
1480 hci_dev_lock(hdev);
1481
1482 conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(cp->handle));
1483 if (conn) {
1484 if (conn->state == BT_CONFIG) {
Marcel Holtmann769be972008-07-14 20:13:49 +02001485 hci_proto_connect_cfm(conn, status);
1486 hci_conn_put(conn);
1487 }
1488 }
1489
1490 hci_dev_unlock(hdev);
1491}
1492
1493static void hci_cs_read_remote_ext_features(struct hci_dev *hdev, __u8 status)
1494{
1495 struct hci_cp_read_remote_ext_features *cp;
1496 struct hci_conn *conn;
1497
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +03001498 BT_DBG("%s status 0x%2.2x", hdev->name, status);
Marcel Holtmann769be972008-07-14 20:13:49 +02001499
1500 if (!status)
1501 return;
1502
1503 cp = hci_sent_cmd_data(hdev, HCI_OP_READ_REMOTE_EXT_FEATURES);
1504 if (!cp)
1505 return;
1506
1507 hci_dev_lock(hdev);
1508
1509 conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(cp->handle));
1510 if (conn) {
1511 if (conn->state == BT_CONFIG) {
Marcel Holtmann769be972008-07-14 20:13:49 +02001512 hci_proto_connect_cfm(conn, status);
1513 hci_conn_put(conn);
1514 }
1515 }
1516
1517 hci_dev_unlock(hdev);
1518}
1519
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001520static void hci_cs_setup_sync_conn(struct hci_dev *hdev, __u8 status)
1521{
Marcel Holtmannb6a0dc82007-10-20 14:55:10 +02001522 struct hci_cp_setup_sync_conn *cp;
1523 struct hci_conn *acl, *sco;
1524 __u16 handle;
1525
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +03001526 BT_DBG("%s status 0x%2.2x", hdev->name, status);
Marcel Holtmannb6a0dc82007-10-20 14:55:10 +02001527
1528 if (!status)
1529 return;
1530
1531 cp = hci_sent_cmd_data(hdev, HCI_OP_SETUP_SYNC_CONN);
1532 if (!cp)
1533 return;
1534
1535 handle = __le16_to_cpu(cp->handle);
1536
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +03001537 BT_DBG("%s handle 0x%4.4x", hdev->name, handle);
Marcel Holtmannb6a0dc82007-10-20 14:55:10 +02001538
1539 hci_dev_lock(hdev);
1540
1541 acl = hci_conn_hash_lookup_handle(hdev, handle);
Andrei Emeltchenko5a08ecc2011-01-11 17:20:20 +02001542 if (acl) {
1543 sco = acl->link;
1544 if (sco) {
1545 sco->state = BT_CLOSED;
Marcel Holtmannb6a0dc82007-10-20 14:55:10 +02001546
Andrei Emeltchenko5a08ecc2011-01-11 17:20:20 +02001547 hci_proto_connect_cfm(sco, status);
1548 hci_conn_del(sco);
1549 }
Marcel Holtmannb6a0dc82007-10-20 14:55:10 +02001550 }
1551
1552 hci_dev_unlock(hdev);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001553}
1554
1555static void hci_cs_sniff_mode(struct hci_dev *hdev, __u8 status)
1556{
1557 struct hci_cp_sniff_mode *cp;
1558 struct hci_conn *conn;
1559
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +03001560 BT_DBG("%s status 0x%2.2x", hdev->name, status);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001561
1562 if (!status)
1563 return;
1564
1565 cp = hci_sent_cmd_data(hdev, HCI_OP_SNIFF_MODE);
1566 if (!cp)
1567 return;
1568
1569 hci_dev_lock(hdev);
1570
1571 conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(cp->handle));
Marcel Holtmanne73439d2010-07-26 10:06:00 -04001572 if (conn) {
Johan Hedberg51a8efd2012-01-16 06:10:31 +02001573 clear_bit(HCI_CONN_MODE_CHANGE_PEND, &conn->flags);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001574
Johan Hedberg51a8efd2012-01-16 06:10:31 +02001575 if (test_and_clear_bit(HCI_CONN_SCO_SETUP_PEND, &conn->flags))
Marcel Holtmanne73439d2010-07-26 10:06:00 -04001576 hci_sco_setup(conn, status);
1577 }
1578
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001579 hci_dev_unlock(hdev);
1580}
1581
1582static void hci_cs_exit_sniff_mode(struct hci_dev *hdev, __u8 status)
1583{
1584 struct hci_cp_exit_sniff_mode *cp;
1585 struct hci_conn *conn;
1586
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +03001587 BT_DBG("%s status 0x%2.2x", hdev->name, status);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001588
1589 if (!status)
1590 return;
1591
1592 cp = hci_sent_cmd_data(hdev, HCI_OP_EXIT_SNIFF_MODE);
1593 if (!cp)
1594 return;
1595
1596 hci_dev_lock(hdev);
1597
1598 conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(cp->handle));
Marcel Holtmanne73439d2010-07-26 10:06:00 -04001599 if (conn) {
Johan Hedberg51a8efd2012-01-16 06:10:31 +02001600 clear_bit(HCI_CONN_MODE_CHANGE_PEND, &conn->flags);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001601
Johan Hedberg51a8efd2012-01-16 06:10:31 +02001602 if (test_and_clear_bit(HCI_CONN_SCO_SETUP_PEND, &conn->flags))
Marcel Holtmanne73439d2010-07-26 10:06:00 -04001603 hci_sco_setup(conn, status);
1604 }
1605
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001606 hci_dev_unlock(hdev);
1607}
1608
Johan Hedberg88c3df12012-02-09 14:27:38 +02001609static void hci_cs_disconnect(struct hci_dev *hdev, u8 status)
1610{
1611 struct hci_cp_disconnect *cp;
1612 struct hci_conn *conn;
1613
1614 if (!status)
1615 return;
1616
1617 cp = hci_sent_cmd_data(hdev, HCI_OP_DISCONNECT);
1618 if (!cp)
1619 return;
1620
1621 hci_dev_lock(hdev);
1622
1623 conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(cp->handle));
1624 if (conn)
1625 mgmt_disconnect_failed(hdev, &conn->dst, conn->type,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001626 conn->dst_type, status);
Johan Hedberg88c3df12012-02-09 14:27:38 +02001627
1628 hci_dev_unlock(hdev);
1629}
1630
Ville Tervofcd89c02011-02-10 22:38:47 -03001631static void hci_cs_le_create_conn(struct hci_dev *hdev, __u8 status)
1632{
Ville Tervofcd89c02011-02-10 22:38:47 -03001633 struct hci_conn *conn;
1634
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +03001635 BT_DBG("%s status 0x%2.2x", hdev->name, status);
Ville Tervofcd89c02011-02-10 22:38:47 -03001636
Ville Tervofcd89c02011-02-10 22:38:47 -03001637 if (status) {
Andre Guedesf00a06a2012-07-27 15:10:13 -03001638 hci_dev_lock(hdev);
Ville Tervofcd89c02011-02-10 22:38:47 -03001639
Andre Guedes0c95ab72012-07-27 15:10:14 -03001640 conn = hci_conn_hash_lookup_state(hdev, LE_LINK, BT_CONNECT);
Andre Guedesf00a06a2012-07-27 15:10:13 -03001641 if (!conn) {
1642 hci_dev_unlock(hdev);
1643 return;
1644 }
1645
Andre Guedes0c95ab72012-07-27 15:10:14 -03001646 BT_DBG("%s bdaddr %s conn %p", hdev->name, batostr(&conn->dst),
Andre Guedesf00a06a2012-07-27 15:10:13 -03001647 conn);
1648
1649 conn->state = BT_CLOSED;
Andre Guedes0c95ab72012-07-27 15:10:14 -03001650 mgmt_connect_failed(hdev, &conn->dst, conn->type,
Andre Guedesf00a06a2012-07-27 15:10:13 -03001651 conn->dst_type, status);
1652 hci_proto_connect_cfm(conn, status);
1653 hci_conn_del(conn);
1654
1655 hci_dev_unlock(hdev);
1656 }
Ville Tervofcd89c02011-02-10 22:38:47 -03001657}
1658
Vinicius Costa Gomesa7a595f2011-06-09 18:50:47 -03001659static void hci_cs_le_start_enc(struct hci_dev *hdev, u8 status)
1660{
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +03001661 BT_DBG("%s status 0x%2.2x", hdev->name, status);
Vinicius Costa Gomesa7a595f2011-06-09 18:50:47 -03001662}
1663
Gustavo Padovan6039aa732012-05-23 04:04:18 -03001664static void hci_inquiry_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001665{
1666 __u8 status = *((__u8 *) skb->data);
Johan Hedberg30dc78e2012-01-04 15:44:20 +02001667 struct discovery_state *discov = &hdev->discovery;
1668 struct inquiry_entry *e;
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001669
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +03001670 BT_DBG("%s status 0x%2.2x", hdev->name, status);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001671
Johan Hedberg23bb5762010-12-21 23:01:27 +02001672 hci_req_complete(hdev, HCI_OP_INQUIRY, status);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001673
1674 hci_conn_check_pending(hdev);
Andre Guedes89352e72011-11-04 14:16:53 -03001675
1676 if (!test_and_clear_bit(HCI_INQUIRY, &hdev->flags))
1677 return;
1678
Johan Hedberga8b2d5c2012-01-08 23:11:15 +02001679 if (!test_bit(HCI_MGMT, &hdev->dev_flags))
Johan Hedberg30dc78e2012-01-04 15:44:20 +02001680 return;
1681
Johan Hedberg56e5cb82011-11-08 20:40:16 +02001682 hci_dev_lock(hdev);
Johan Hedberg30dc78e2012-01-04 15:44:20 +02001683
Andre Guedes343f9352012-02-17 20:39:37 -03001684 if (discov->state != DISCOVERY_FINDING)
Johan Hedberg30dc78e2012-01-04 15:44:20 +02001685 goto unlock;
1686
1687 if (list_empty(&discov->resolve)) {
1688 hci_discovery_set_state(hdev, DISCOVERY_STOPPED);
1689 goto unlock;
1690 }
1691
1692 e = hci_inquiry_cache_lookup_resolve(hdev, BDADDR_ANY, NAME_NEEDED);
1693 if (e && hci_resolve_name(hdev, e) == 0) {
1694 e->name_state = NAME_PENDING;
1695 hci_discovery_set_state(hdev, DISCOVERY_RESOLVING);
1696 } else {
1697 hci_discovery_set_state(hdev, DISCOVERY_STOPPED);
1698 }
1699
1700unlock:
Johan Hedberg56e5cb82011-11-08 20:40:16 +02001701 hci_dev_unlock(hdev);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001702}
1703
Gustavo Padovan6039aa732012-05-23 04:04:18 -03001704static void hci_inquiry_result_evt(struct hci_dev *hdev, struct sk_buff *skb)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001705{
Marcel Holtmann45bb4bf2005-08-09 20:27:49 -07001706 struct inquiry_data data;
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001707 struct inquiry_info *info = (void *) (skb->data + 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001708 int num_rsp = *((__u8 *) skb->data);
1709
1710 BT_DBG("%s num_rsp %d", hdev->name, num_rsp);
1711
Marcel Holtmann45bb4bf2005-08-09 20:27:49 -07001712 if (!num_rsp)
1713 return;
1714
Andre Guedes1519cc12012-03-21 00:03:38 -03001715 if (test_bit(HCI_PERIODIC_INQ, &hdev->dev_flags))
1716 return;
1717
Linus Torvalds1da177e2005-04-16 15:20:36 -07001718 hci_dev_lock(hdev);
Marcel Holtmann45bb4bf2005-08-09 20:27:49 -07001719
Johan Hedberge17acd42011-03-30 23:57:16 +03001720 for (; num_rsp; num_rsp--, info++) {
Johan Hedberg388fc8f2012-02-23 00:38:59 +02001721 bool name_known, ssp;
Johan Hedberg31754052012-01-04 13:39:52 +02001722
Linus Torvalds1da177e2005-04-16 15:20:36 -07001723 bacpy(&data.bdaddr, &info->bdaddr);
1724 data.pscan_rep_mode = info->pscan_rep_mode;
1725 data.pscan_period_mode = info->pscan_period_mode;
1726 data.pscan_mode = info->pscan_mode;
1727 memcpy(data.dev_class, info->dev_class, 3);
1728 data.clock_offset = info->clock_offset;
1729 data.rssi = 0x00;
Marcel Holtmann41a96212008-07-14 20:13:48 +02001730 data.ssp_mode = 0x00;
Johan Hedberg31754052012-01-04 13:39:52 +02001731
Johan Hedberg388fc8f2012-02-23 00:38:59 +02001732 name_known = hci_inquiry_cache_update(hdev, &data, false, &ssp);
Johan Hedberg48264f02011-11-09 13:58:58 +02001733 mgmt_device_found(hdev, &info->bdaddr, ACL_LINK, 0x00,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001734 info->dev_class, 0, !name_known, ssp, NULL,
1735 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001736 }
Marcel Holtmann45bb4bf2005-08-09 20:27:49 -07001737
Linus Torvalds1da177e2005-04-16 15:20:36 -07001738 hci_dev_unlock(hdev);
1739}
1740
Gustavo Padovan6039aa732012-05-23 04:04:18 -03001741static void hci_conn_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001742{
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001743 struct hci_ev_conn_complete *ev = (void *) skb->data;
1744 struct hci_conn *conn;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001745
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001746 BT_DBG("%s", hdev->name);
Marcel Holtmann45bb4bf2005-08-09 20:27:49 -07001747
Linus Torvalds1da177e2005-04-16 15:20:36 -07001748 hci_dev_lock(hdev);
Marcel Holtmann45bb4bf2005-08-09 20:27:49 -07001749
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001750 conn = hci_conn_hash_lookup_ba(hdev, ev->link_type, &ev->bdaddr);
Marcel Holtmann94992372009-04-19 19:30:03 +02001751 if (!conn) {
1752 if (ev->link_type != SCO_LINK)
1753 goto unlock;
1754
1755 conn = hci_conn_hash_lookup_ba(hdev, ESCO_LINK, &ev->bdaddr);
1756 if (!conn)
1757 goto unlock;
1758
1759 conn->type = SCO_LINK;
1760 }
Marcel Holtmann45bb4bf2005-08-09 20:27:49 -07001761
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001762 if (!ev->status) {
1763 conn->handle = __le16_to_cpu(ev->handle);
Marcel Holtmann769be972008-07-14 20:13:49 +02001764
1765 if (conn->type == ACL_LINK) {
1766 conn->state = BT_CONFIG;
1767 hci_conn_hold(conn);
Szymon Janca9ea3ed2012-07-19 14:46:08 +02001768
1769 if (!conn->out && !hci_conn_ssp_enabled(conn) &&
1770 !hci_find_link_key(hdev, &ev->bdaddr))
1771 conn->disc_timeout = HCI_PAIRING_TIMEOUT;
1772 else
1773 conn->disc_timeout = HCI_DISCONN_TIMEOUT;
Marcel Holtmann769be972008-07-14 20:13:49 +02001774 } else
1775 conn->state = BT_CONNECTED;
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001776
Marcel Holtmann9eba32b2009-08-22 14:19:26 -07001777 hci_conn_hold_device(conn);
Marcel Holtmann7d0db0a2008-07-14 20:13:51 +02001778 hci_conn_add_sysfs(conn);
1779
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001780 if (test_bit(HCI_AUTH, &hdev->flags))
1781 conn->link_mode |= HCI_LM_AUTH;
1782
1783 if (test_bit(HCI_ENCRYPT, &hdev->flags))
1784 conn->link_mode |= HCI_LM_ENCRYPT;
1785
1786 /* Get remote features */
1787 if (conn->type == ACL_LINK) {
1788 struct hci_cp_read_remote_features cp;
1789 cp.handle = ev->handle;
Marcel Holtmann769be972008-07-14 20:13:49 +02001790 hci_send_cmd(hdev, HCI_OP_READ_REMOTE_FEATURES,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001791 sizeof(cp), &cp);
Marcel Holtmann45bb4bf2005-08-09 20:27:49 -07001792 }
Marcel Holtmann45bb4bf2005-08-09 20:27:49 -07001793
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001794 /* Set packet type for incoming connection */
Andrei Emeltchenkod095c1e2011-12-01 14:33:27 +02001795 if (!conn->out && hdev->hci_ver < BLUETOOTH_VER_2_0) {
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001796 struct hci_cp_change_conn_ptype cp;
1797 cp.handle = ev->handle;
Marcel Holtmanna8746412008-07-14 20:13:46 +02001798 cp.pkt_type = cpu_to_le16(conn->pkt_type);
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001799 hci_send_cmd(hdev, HCI_OP_CHANGE_CONN_PTYPE, sizeof(cp),
1800 &cp);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001801 }
Johan Hedberg17d5c042011-01-22 06:09:08 +02001802 } else {
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001803 conn->state = BT_CLOSED;
Johan Hedberg17d5c042011-01-22 06:09:08 +02001804 if (conn->type == ACL_LINK)
Johan Hedberg744cf192011-11-08 20:40:14 +02001805 mgmt_connect_failed(hdev, &ev->bdaddr, conn->type,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001806 conn->dst_type, ev->status);
Johan Hedberg17d5c042011-01-22 06:09:08 +02001807 }
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001808
Marcel Holtmanne73439d2010-07-26 10:06:00 -04001809 if (conn->type == ACL_LINK)
1810 hci_sco_setup(conn, ev->status);
Marcel Holtmann45bb4bf2005-08-09 20:27:49 -07001811
Marcel Holtmann769be972008-07-14 20:13:49 +02001812 if (ev->status) {
1813 hci_proto_connect_cfm(conn, ev->status);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001814 hci_conn_del(conn);
Marcel Holtmannc89b6e62009-01-15 21:57:03 +01001815 } else if (ev->link_type != ACL_LINK)
1816 hci_proto_connect_cfm(conn, ev->status);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001817
1818unlock:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001819 hci_dev_unlock(hdev);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001820
1821 hci_conn_check_pending(hdev);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001822}
1823
Gustavo Padovan6039aa732012-05-23 04:04:18 -03001824static void hci_conn_request_evt(struct hci_dev *hdev, struct sk_buff *skb)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001825{
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001826 struct hci_ev_conn_request *ev = (void *) skb->data;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001827 int mask = hdev->link_mode;
1828
Gustavo Padovan807deac2012-05-17 00:36:24 -03001829 BT_DBG("%s bdaddr %s type 0x%x", hdev->name, batostr(&ev->bdaddr),
1830 ev->link_type);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001831
1832 mask |= hci_proto_connect_ind(hdev, &ev->bdaddr, ev->link_type);
1833
Szymon Janc138d22e2011-02-17 16:44:23 +01001834 if ((mask & HCI_LM_ACCEPT) &&
Gustavo Padovan807deac2012-05-17 00:36:24 -03001835 !hci_blacklist_lookup(hdev, &ev->bdaddr)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001836 /* Connection accepted */
Marcel Holtmannc7bdd502008-07-14 20:13:47 +02001837 struct inquiry_entry *ie;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001838 struct hci_conn *conn;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001839
1840 hci_dev_lock(hdev);
Marcel Holtmannb6a0dc82007-10-20 14:55:10 +02001841
Andrei Emeltchenkocc11b9c2010-11-22 13:21:37 +02001842 ie = hci_inquiry_cache_lookup(hdev, &ev->bdaddr);
1843 if (ie)
Marcel Holtmannc7bdd502008-07-14 20:13:47 +02001844 memcpy(ie->data.dev_class, ev->dev_class, 3);
1845
Gustavo Padovan8fc9ced2012-05-23 04:04:21 -03001846 conn = hci_conn_hash_lookup_ba(hdev, ev->link_type,
1847 &ev->bdaddr);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001848 if (!conn) {
Andrei Emeltchenkocc11b9c2010-11-22 13:21:37 +02001849 conn = hci_conn_add(hdev, ev->link_type, &ev->bdaddr);
1850 if (!conn) {
Gustavo F. Padovan893ef972010-07-18 15:13:37 -03001851 BT_ERR("No memory for new connection");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001852 hci_dev_unlock(hdev);
1853 return;
1854 }
1855 }
Marcel Holtmannb6a0dc82007-10-20 14:55:10 +02001856
Linus Torvalds1da177e2005-04-16 15:20:36 -07001857 memcpy(conn->dev_class, ev->dev_class, 3);
1858 conn->state = BT_CONNECT;
Marcel Holtmannb6a0dc82007-10-20 14:55:10 +02001859
Linus Torvalds1da177e2005-04-16 15:20:36 -07001860 hci_dev_unlock(hdev);
1861
Marcel Holtmannb6a0dc82007-10-20 14:55:10 +02001862 if (ev->link_type == ACL_LINK || !lmp_esco_capable(hdev)) {
1863 struct hci_cp_accept_conn_req cp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001864
Marcel Holtmannb6a0dc82007-10-20 14:55:10 +02001865 bacpy(&cp.bdaddr, &ev->bdaddr);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001866
Marcel Holtmannb6a0dc82007-10-20 14:55:10 +02001867 if (lmp_rswitch_capable(hdev) && (mask & HCI_LM_MASTER))
1868 cp.role = 0x00; /* Become master */
1869 else
1870 cp.role = 0x01; /* Remain slave */
1871
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001872 hci_send_cmd(hdev, HCI_OP_ACCEPT_CONN_REQ, sizeof(cp),
1873 &cp);
Marcel Holtmannb6a0dc82007-10-20 14:55:10 +02001874 } else {
1875 struct hci_cp_accept_sync_conn_req cp;
1876
1877 bacpy(&cp.bdaddr, &ev->bdaddr);
Marcel Holtmanna8746412008-07-14 20:13:46 +02001878 cp.pkt_type = cpu_to_le16(conn->pkt_type);
Marcel Holtmannb6a0dc82007-10-20 14:55:10 +02001879
Andrei Emeltchenko82781e62012-05-25 11:38:27 +03001880 cp.tx_bandwidth = __constant_cpu_to_le32(0x00001f40);
1881 cp.rx_bandwidth = __constant_cpu_to_le32(0x00001f40);
1882 cp.max_latency = __constant_cpu_to_le16(0xffff);
Marcel Holtmannb6a0dc82007-10-20 14:55:10 +02001883 cp.content_format = cpu_to_le16(hdev->voice_setting);
1884 cp.retrans_effort = 0xff;
1885
1886 hci_send_cmd(hdev, HCI_OP_ACCEPT_SYNC_CONN_REQ,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001887 sizeof(cp), &cp);
Marcel Holtmannb6a0dc82007-10-20 14:55:10 +02001888 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001889 } else {
1890 /* Connection rejected */
1891 struct hci_cp_reject_conn_req cp;
1892
1893 bacpy(&cp.bdaddr, &ev->bdaddr);
Andrei Emeltchenko9f5a0d72011-11-07 14:20:25 +02001894 cp.reason = HCI_ERROR_REJ_BAD_ADDR;
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001895 hci_send_cmd(hdev, HCI_OP_REJECT_CONN_REQ, sizeof(cp), &cp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001896 }
1897}
1898
Mikel Astizf0d6a0e2012-08-09 09:52:30 +02001899static u8 hci_to_mgmt_reason(u8 err)
1900{
1901 switch (err) {
1902 case HCI_ERROR_CONNECTION_TIMEOUT:
1903 return MGMT_DEV_DISCONN_TIMEOUT;
1904 case HCI_ERROR_REMOTE_USER_TERM:
1905 case HCI_ERROR_REMOTE_LOW_RESOURCES:
1906 case HCI_ERROR_REMOTE_POWER_OFF:
1907 return MGMT_DEV_DISCONN_REMOTE;
1908 case HCI_ERROR_LOCAL_HOST_TERM:
1909 return MGMT_DEV_DISCONN_LOCAL_HOST;
1910 default:
1911 return MGMT_DEV_DISCONN_UNKNOWN;
1912 }
1913}
1914
Gustavo Padovan6039aa732012-05-23 04:04:18 -03001915static void hci_disconn_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001916{
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001917 struct hci_ev_disconn_complete *ev = (void *) skb->data;
Marcel Holtmann04837f62006-07-03 10:02:33 +02001918 struct hci_conn *conn;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001919
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +03001920 BT_DBG("%s status 0x%2.2x", hdev->name, ev->status);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001921
Linus Torvalds1da177e2005-04-16 15:20:36 -07001922 hci_dev_lock(hdev);
1923
Marcel Holtmann04837f62006-07-03 10:02:33 +02001924 conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
Johan Hedbergf7520542011-01-20 12:34:39 +02001925 if (!conn)
1926 goto unlock;
Marcel Holtmann7d0db0a2008-07-14 20:13:51 +02001927
Johan Hedberg37d9ef72011-11-10 15:54:39 +02001928 if (ev->status == 0)
1929 conn->state = BT_CLOSED;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001930
Johan Hedbergb644ba32012-01-17 21:48:47 +02001931 if (test_and_clear_bit(HCI_CONN_MGMT_CONNECTED, &conn->flags) &&
Gustavo Padovan807deac2012-05-17 00:36:24 -03001932 (conn->type == ACL_LINK || conn->type == LE_LINK)) {
Mikel Astizf0d6a0e2012-08-09 09:52:30 +02001933 if (ev->status) {
Johan Hedberg88c3df12012-02-09 14:27:38 +02001934 mgmt_disconnect_failed(hdev, &conn->dst, conn->type,
Gustavo Padovan807deac2012-05-17 00:36:24 -03001935 conn->dst_type, ev->status);
Mikel Astizf0d6a0e2012-08-09 09:52:30 +02001936 } else {
1937 u8 reason = hci_to_mgmt_reason(ev->reason);
1938
Johan Hedbergafc747a2012-01-15 18:11:07 +02001939 mgmt_device_disconnected(hdev, &conn->dst, conn->type,
Mikel Astizf0d6a0e2012-08-09 09:52:30 +02001940 conn->dst_type, reason);
1941 }
Johan Hedberg37d9ef72011-11-10 15:54:39 +02001942 }
Johan Hedbergf7520542011-01-20 12:34:39 +02001943
Johan Hedberg37d9ef72011-11-10 15:54:39 +02001944 if (ev->status == 0) {
Vishal Agarwal6ec5bca2012-04-16 14:44:44 +05301945 if (conn->type == ACL_LINK && conn->flush_key)
1946 hci_remove_link_key(hdev, &conn->dst);
Johan Hedberg37d9ef72011-11-10 15:54:39 +02001947 hci_proto_disconn_cfm(conn, ev->reason);
1948 hci_conn_del(conn);
1949 }
Johan Hedbergf7520542011-01-20 12:34:39 +02001950
1951unlock:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001952 hci_dev_unlock(hdev);
1953}
1954
Gustavo Padovan6039aa732012-05-23 04:04:18 -03001955static void hci_auth_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001956{
1957 struct hci_ev_auth_complete *ev = (void *) skb->data;
1958 struct hci_conn *conn;
1959
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +03001960 BT_DBG("%s status 0x%2.2x", hdev->name, ev->status);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001961
1962 hci_dev_lock(hdev);
1963
1964 conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
Waldemar Rymarkiewiczd7556e22011-05-31 15:49:26 +02001965 if (!conn)
1966 goto unlock;
1967
1968 if (!ev->status) {
Johan Hedbergaa64a8b2012-01-18 21:33:12 +02001969 if (!hci_conn_ssp_enabled(conn) &&
Gustavo Padovan807deac2012-05-17 00:36:24 -03001970 test_bit(HCI_CONN_REAUTH_PEND, &conn->flags)) {
Waldemar Rymarkiewiczd7556e22011-05-31 15:49:26 +02001971 BT_INFO("re-auth of legacy device is not possible.");
Johan Hedberg2a611692011-02-19 12:06:00 -03001972 } else {
Waldemar Rymarkiewiczd7556e22011-05-31 15:49:26 +02001973 conn->link_mode |= HCI_LM_AUTH;
1974 conn->sec_level = conn->pending_sec_level;
Johan Hedberg2a611692011-02-19 12:06:00 -03001975 }
Waldemar Rymarkiewiczd7556e22011-05-31 15:49:26 +02001976 } else {
Johan Hedbergbab73cb2012-02-09 16:07:29 +02001977 mgmt_auth_failed(hdev, &conn->dst, conn->type, conn->dst_type,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001978 ev->status);
Waldemar Rymarkiewiczd7556e22011-05-31 15:49:26 +02001979 }
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001980
Johan Hedberg51a8efd2012-01-16 06:10:31 +02001981 clear_bit(HCI_CONN_AUTH_PEND, &conn->flags);
1982 clear_bit(HCI_CONN_REAUTH_PEND, &conn->flags);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001983
Waldemar Rymarkiewiczd7556e22011-05-31 15:49:26 +02001984 if (conn->state == BT_CONFIG) {
Johan Hedbergaa64a8b2012-01-18 21:33:12 +02001985 if (!ev->status && hci_conn_ssp_enabled(conn)) {
Waldemar Rymarkiewiczd7556e22011-05-31 15:49:26 +02001986 struct hci_cp_set_conn_encrypt cp;
1987 cp.handle = ev->handle;
1988 cp.encrypt = 0x01;
1989 hci_send_cmd(hdev, HCI_OP_SET_CONN_ENCRYPT, sizeof(cp),
Gustavo Padovan807deac2012-05-17 00:36:24 -03001990 &cp);
Marcel Holtmann052b30b2009-04-26 20:01:22 +02001991 } else {
Waldemar Rymarkiewiczd7556e22011-05-31 15:49:26 +02001992 conn->state = BT_CONNECTED;
1993 hci_proto_connect_cfm(conn, ev->status);
Marcel Holtmann052b30b2009-04-26 20:01:22 +02001994 hci_conn_put(conn);
1995 }
Waldemar Rymarkiewiczd7556e22011-05-31 15:49:26 +02001996 } else {
1997 hci_auth_cfm(conn, ev->status);
Marcel Holtmann052b30b2009-04-26 20:01:22 +02001998
Waldemar Rymarkiewiczd7556e22011-05-31 15:49:26 +02001999 hci_conn_hold(conn);
2000 conn->disc_timeout = HCI_DISCONN_TIMEOUT;
2001 hci_conn_put(conn);
2002 }
2003
Johan Hedberg51a8efd2012-01-16 06:10:31 +02002004 if (test_bit(HCI_CONN_ENCRYPT_PEND, &conn->flags)) {
Waldemar Rymarkiewiczd7556e22011-05-31 15:49:26 +02002005 if (!ev->status) {
2006 struct hci_cp_set_conn_encrypt cp;
2007 cp.handle = ev->handle;
2008 cp.encrypt = 0x01;
2009 hci_send_cmd(hdev, HCI_OP_SET_CONN_ENCRYPT, sizeof(cp),
Gustavo Padovan807deac2012-05-17 00:36:24 -03002010 &cp);
Waldemar Rymarkiewiczd7556e22011-05-31 15:49:26 +02002011 } else {
Johan Hedberg51a8efd2012-01-16 06:10:31 +02002012 clear_bit(HCI_CONN_ENCRYPT_PEND, &conn->flags);
Waldemar Rymarkiewiczd7556e22011-05-31 15:49:26 +02002013 hci_encrypt_cfm(conn, ev->status, 0x00);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002014 }
2015 }
2016
Waldemar Rymarkiewiczd7556e22011-05-31 15:49:26 +02002017unlock:
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002018 hci_dev_unlock(hdev);
2019}
2020
Gustavo Padovan6039aa732012-05-23 04:04:18 -03002021static void hci_remote_name_evt(struct hci_dev *hdev, struct sk_buff *skb)
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002022{
Johan Hedberg127178d2010-11-18 22:22:29 +02002023 struct hci_ev_remote_name *ev = (void *) skb->data;
2024 struct hci_conn *conn;
2025
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002026 BT_DBG("%s", hdev->name);
2027
2028 hci_conn_check_pending(hdev);
Johan Hedberg127178d2010-11-18 22:22:29 +02002029
2030 hci_dev_lock(hdev);
2031
2032 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
Johan Hedbergb644ba32012-01-17 21:48:47 +02002033
2034 if (!test_bit(HCI_MGMT, &hdev->dev_flags))
2035 goto check_auth;
2036
2037 if (ev->status == 0)
2038 hci_check_pending_name(hdev, conn, &ev->bdaddr, ev->name,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002039 strnlen(ev->name, HCI_MAX_NAME_LENGTH));
Johan Hedbergb644ba32012-01-17 21:48:47 +02002040 else
2041 hci_check_pending_name(hdev, conn, &ev->bdaddr, NULL, 0);
2042
2043check_auth:
Johan Hedberg79c6c702011-04-28 11:28:55 -07002044 if (!conn)
2045 goto unlock;
2046
2047 if (!hci_outgoing_auth_needed(hdev, conn))
2048 goto unlock;
2049
Johan Hedberg51a8efd2012-01-16 06:10:31 +02002050 if (!test_and_set_bit(HCI_CONN_AUTH_PEND, &conn->flags)) {
Johan Hedberg127178d2010-11-18 22:22:29 +02002051 struct hci_cp_auth_requested cp;
2052 cp.handle = __cpu_to_le16(conn->handle);
2053 hci_send_cmd(hdev, HCI_OP_AUTH_REQUESTED, sizeof(cp), &cp);
2054 }
2055
Johan Hedberg79c6c702011-04-28 11:28:55 -07002056unlock:
Johan Hedberg127178d2010-11-18 22:22:29 +02002057 hci_dev_unlock(hdev);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002058}
2059
Gustavo Padovan6039aa732012-05-23 04:04:18 -03002060static void hci_encrypt_change_evt(struct hci_dev *hdev, struct sk_buff *skb)
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002061{
2062 struct hci_ev_encrypt_change *ev = (void *) skb->data;
2063 struct hci_conn *conn;
2064
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +03002065 BT_DBG("%s status 0x%2.2x", hdev->name, ev->status);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002066
2067 hci_dev_lock(hdev);
2068
2069 conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
2070 if (conn) {
2071 if (!ev->status) {
Marcel Holtmannae293192008-07-14 20:13:45 +02002072 if (ev->encrypt) {
2073 /* Encryption implies authentication */
2074 conn->link_mode |= HCI_LM_AUTH;
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002075 conn->link_mode |= HCI_LM_ENCRYPT;
Vinicius Costa Gomesda85e5e2011-06-09 18:50:53 -03002076 conn->sec_level = conn->pending_sec_level;
Marcel Holtmannae293192008-07-14 20:13:45 +02002077 } else
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002078 conn->link_mode &= ~HCI_LM_ENCRYPT;
2079 }
2080
Johan Hedberg51a8efd2012-01-16 06:10:31 +02002081 clear_bit(HCI_CONN_ENCRYPT_PEND, &conn->flags);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002082
Gustavo Padovana7d77232012-05-13 03:20:07 -03002083 if (ev->status && conn->state == BT_CONNECTED) {
Gustavo Padovand839c812012-05-16 12:17:12 -03002084 hci_acl_disconn(conn, HCI_ERROR_AUTH_FAILURE);
Gustavo Padovana7d77232012-05-13 03:20:07 -03002085 hci_conn_put(conn);
2086 goto unlock;
2087 }
2088
Marcel Holtmannf8558552008-07-14 20:13:49 +02002089 if (conn->state == BT_CONFIG) {
2090 if (!ev->status)
2091 conn->state = BT_CONNECTED;
2092
2093 hci_proto_connect_cfm(conn, ev->status);
2094 hci_conn_put(conn);
2095 } else
2096 hci_encrypt_cfm(conn, ev->status, ev->encrypt);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002097 }
2098
Gustavo Padovana7d77232012-05-13 03:20:07 -03002099unlock:
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002100 hci_dev_unlock(hdev);
2101}
2102
Gustavo Padovan6039aa732012-05-23 04:04:18 -03002103static void hci_change_link_key_complete_evt(struct hci_dev *hdev,
2104 struct sk_buff *skb)
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002105{
2106 struct hci_ev_change_link_key_complete *ev = (void *) skb->data;
2107 struct hci_conn *conn;
2108
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +03002109 BT_DBG("%s status 0x%2.2x", hdev->name, ev->status);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002110
2111 hci_dev_lock(hdev);
2112
2113 conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
2114 if (conn) {
2115 if (!ev->status)
2116 conn->link_mode |= HCI_LM_SECURE;
2117
Johan Hedberg51a8efd2012-01-16 06:10:31 +02002118 clear_bit(HCI_CONN_AUTH_PEND, &conn->flags);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002119
2120 hci_key_change_cfm(conn, ev->status);
2121 }
2122
2123 hci_dev_unlock(hdev);
2124}
2125
Gustavo Padovan6039aa732012-05-23 04:04:18 -03002126static void hci_remote_features_evt(struct hci_dev *hdev,
2127 struct sk_buff *skb)
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002128{
2129 struct hci_ev_remote_features *ev = (void *) skb->data;
2130 struct hci_conn *conn;
2131
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +03002132 BT_DBG("%s status 0x%2.2x", hdev->name, ev->status);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002133
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002134 hci_dev_lock(hdev);
2135
2136 conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
Johan Hedbergccd556f2010-11-10 17:11:51 +02002137 if (!conn)
2138 goto unlock;
Marcel Holtmann769be972008-07-14 20:13:49 +02002139
Johan Hedbergccd556f2010-11-10 17:11:51 +02002140 if (!ev->status)
2141 memcpy(conn->features, ev->features, 8);
2142
2143 if (conn->state != BT_CONFIG)
2144 goto unlock;
2145
2146 if (!ev->status && lmp_ssp_capable(hdev) && lmp_ssp_capable(conn)) {
2147 struct hci_cp_read_remote_ext_features cp;
2148 cp.handle = ev->handle;
2149 cp.page = 0x01;
2150 hci_send_cmd(hdev, HCI_OP_READ_REMOTE_EXT_FEATURES,
Gustavo Padovan807deac2012-05-17 00:36:24 -03002151 sizeof(cp), &cp);
Johan Hedberg392599b2010-11-18 22:22:28 +02002152 goto unlock;
2153 }
2154
Johan Hedberg671267b2012-05-12 16:11:50 -03002155 if (!ev->status && !test_bit(HCI_CONN_MGMT_CONNECTED, &conn->flags)) {
Johan Hedberg127178d2010-11-18 22:22:29 +02002156 struct hci_cp_remote_name_req cp;
2157 memset(&cp, 0, sizeof(cp));
2158 bacpy(&cp.bdaddr, &conn->dst);
2159 cp.pscan_rep_mode = 0x02;
2160 hci_send_cmd(hdev, HCI_OP_REMOTE_NAME_REQ, sizeof(cp), &cp);
Johan Hedbergb644ba32012-01-17 21:48:47 +02002161 } else if (!test_and_set_bit(HCI_CONN_MGMT_CONNECTED, &conn->flags))
2162 mgmt_device_connected(hdev, &conn->dst, conn->type,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002163 conn->dst_type, 0, NULL, 0,
2164 conn->dev_class);
Johan Hedberg392599b2010-11-18 22:22:28 +02002165
Johan Hedberg127178d2010-11-18 22:22:29 +02002166 if (!hci_outgoing_auth_needed(hdev, conn)) {
Johan Hedbergccd556f2010-11-10 17:11:51 +02002167 conn->state = BT_CONNECTED;
2168 hci_proto_connect_cfm(conn, ev->status);
2169 hci_conn_put(conn);
Marcel Holtmann769be972008-07-14 20:13:49 +02002170 }
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002171
Johan Hedbergccd556f2010-11-10 17:11:51 +02002172unlock:
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002173 hci_dev_unlock(hdev);
2174}
2175
Gustavo Padovan6039aa732012-05-23 04:04:18 -03002176static void hci_remote_version_evt(struct hci_dev *hdev, struct sk_buff *skb)
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002177{
2178 BT_DBG("%s", hdev->name);
2179}
2180
Gustavo Padovan6039aa732012-05-23 04:04:18 -03002181static void hci_qos_setup_complete_evt(struct hci_dev *hdev,
2182 struct sk_buff *skb)
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002183{
2184 BT_DBG("%s", hdev->name);
2185}
2186
Gustavo Padovan6039aa732012-05-23 04:04:18 -03002187static void hci_cmd_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002188{
2189 struct hci_ev_cmd_complete *ev = (void *) skb->data;
2190 __u16 opcode;
2191
2192 skb_pull(skb, sizeof(*ev));
2193
2194 opcode = __le16_to_cpu(ev->opcode);
2195
2196 switch (opcode) {
2197 case HCI_OP_INQUIRY_CANCEL:
2198 hci_cc_inquiry_cancel(hdev, skb);
2199 break;
2200
Andre Guedes4d934832012-03-21 00:03:35 -03002201 case HCI_OP_PERIODIC_INQ:
2202 hci_cc_periodic_inq(hdev, skb);
2203 break;
2204
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002205 case HCI_OP_EXIT_PERIODIC_INQ:
2206 hci_cc_exit_periodic_inq(hdev, skb);
2207 break;
2208
2209 case HCI_OP_REMOTE_NAME_REQ_CANCEL:
2210 hci_cc_remote_name_req_cancel(hdev, skb);
2211 break;
2212
2213 case HCI_OP_ROLE_DISCOVERY:
2214 hci_cc_role_discovery(hdev, skb);
2215 break;
2216
Marcel Holtmanne4e8e372008-07-14 20:13:47 +02002217 case HCI_OP_READ_LINK_POLICY:
2218 hci_cc_read_link_policy(hdev, skb);
2219 break;
2220
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002221 case HCI_OP_WRITE_LINK_POLICY:
2222 hci_cc_write_link_policy(hdev, skb);
2223 break;
2224
Marcel Holtmanne4e8e372008-07-14 20:13:47 +02002225 case HCI_OP_READ_DEF_LINK_POLICY:
2226 hci_cc_read_def_link_policy(hdev, skb);
2227 break;
2228
2229 case HCI_OP_WRITE_DEF_LINK_POLICY:
2230 hci_cc_write_def_link_policy(hdev, skb);
2231 break;
2232
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002233 case HCI_OP_RESET:
2234 hci_cc_reset(hdev, skb);
2235 break;
2236
2237 case HCI_OP_WRITE_LOCAL_NAME:
2238 hci_cc_write_local_name(hdev, skb);
2239 break;
2240
2241 case HCI_OP_READ_LOCAL_NAME:
2242 hci_cc_read_local_name(hdev, skb);
2243 break;
2244
2245 case HCI_OP_WRITE_AUTH_ENABLE:
2246 hci_cc_write_auth_enable(hdev, skb);
2247 break;
2248
2249 case HCI_OP_WRITE_ENCRYPT_MODE:
2250 hci_cc_write_encrypt_mode(hdev, skb);
2251 break;
2252
2253 case HCI_OP_WRITE_SCAN_ENABLE:
2254 hci_cc_write_scan_enable(hdev, skb);
2255 break;
2256
2257 case HCI_OP_READ_CLASS_OF_DEV:
2258 hci_cc_read_class_of_dev(hdev, skb);
2259 break;
2260
2261 case HCI_OP_WRITE_CLASS_OF_DEV:
2262 hci_cc_write_class_of_dev(hdev, skb);
2263 break;
2264
2265 case HCI_OP_READ_VOICE_SETTING:
2266 hci_cc_read_voice_setting(hdev, skb);
2267 break;
2268
2269 case HCI_OP_WRITE_VOICE_SETTING:
2270 hci_cc_write_voice_setting(hdev, skb);
2271 break;
2272
2273 case HCI_OP_HOST_BUFFER_SIZE:
2274 hci_cc_host_buffer_size(hdev, skb);
2275 break;
2276
Marcel Holtmann333140b2008-07-14 20:13:48 +02002277 case HCI_OP_WRITE_SSP_MODE:
2278 hci_cc_write_ssp_mode(hdev, skb);
2279 break;
2280
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002281 case HCI_OP_READ_LOCAL_VERSION:
2282 hci_cc_read_local_version(hdev, skb);
2283 break;
2284
2285 case HCI_OP_READ_LOCAL_COMMANDS:
2286 hci_cc_read_local_commands(hdev, skb);
2287 break;
2288
2289 case HCI_OP_READ_LOCAL_FEATURES:
2290 hci_cc_read_local_features(hdev, skb);
2291 break;
2292
Andre Guedes971e3a42011-06-30 19:20:52 -03002293 case HCI_OP_READ_LOCAL_EXT_FEATURES:
2294 hci_cc_read_local_ext_features(hdev, skb);
2295 break;
2296
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002297 case HCI_OP_READ_BUFFER_SIZE:
2298 hci_cc_read_buffer_size(hdev, skb);
2299 break;
2300
2301 case HCI_OP_READ_BD_ADDR:
2302 hci_cc_read_bd_addr(hdev, skb);
2303 break;
2304
Andrei Emeltchenko350ee4c2011-12-07 15:56:51 +02002305 case HCI_OP_READ_DATA_BLOCK_SIZE:
2306 hci_cc_read_data_block_size(hdev, skb);
2307 break;
2308
Johan Hedberg23bb5762010-12-21 23:01:27 +02002309 case HCI_OP_WRITE_CA_TIMEOUT:
2310 hci_cc_write_ca_timeout(hdev, skb);
2311 break;
2312
Andrei Emeltchenko1e89cff2011-11-24 14:52:02 +02002313 case HCI_OP_READ_FLOW_CONTROL_MODE:
2314 hci_cc_read_flow_control_mode(hdev, skb);
2315 break;
2316
Andrei Emeltchenko928abaa2011-10-12 10:53:57 +03002317 case HCI_OP_READ_LOCAL_AMP_INFO:
2318 hci_cc_read_local_amp_info(hdev, skb);
2319 break;
2320
Johan Hedbergb0916ea2011-01-10 13:44:55 +02002321 case HCI_OP_DELETE_STORED_LINK_KEY:
2322 hci_cc_delete_stored_link_key(hdev, skb);
2323 break;
2324
Johan Hedbergd5859e22011-01-25 01:19:58 +02002325 case HCI_OP_SET_EVENT_MASK:
2326 hci_cc_set_event_mask(hdev, skb);
2327 break;
2328
2329 case HCI_OP_WRITE_INQUIRY_MODE:
2330 hci_cc_write_inquiry_mode(hdev, skb);
2331 break;
2332
2333 case HCI_OP_READ_INQ_RSP_TX_POWER:
2334 hci_cc_read_inq_rsp_tx_power(hdev, skb);
2335 break;
2336
2337 case HCI_OP_SET_EVENT_FLT:
2338 hci_cc_set_event_flt(hdev, skb);
2339 break;
2340
Johan Hedberg980e1a52011-01-22 06:10:07 +02002341 case HCI_OP_PIN_CODE_REPLY:
2342 hci_cc_pin_code_reply(hdev, skb);
2343 break;
2344
2345 case HCI_OP_PIN_CODE_NEG_REPLY:
2346 hci_cc_pin_code_neg_reply(hdev, skb);
2347 break;
2348
Szymon Jancc35938b2011-03-22 13:12:21 +01002349 case HCI_OP_READ_LOCAL_OOB_DATA:
2350 hci_cc_read_local_oob_data_reply(hdev, skb);
2351 break;
2352
Ville Tervo6ed58ec2011-02-10 22:38:48 -03002353 case HCI_OP_LE_READ_BUFFER_SIZE:
2354 hci_cc_le_read_buffer_size(hdev, skb);
2355 break;
2356
Johan Hedberga5c29682011-02-19 12:05:57 -03002357 case HCI_OP_USER_CONFIRM_REPLY:
2358 hci_cc_user_confirm_reply(hdev, skb);
2359 break;
2360
2361 case HCI_OP_USER_CONFIRM_NEG_REPLY:
2362 hci_cc_user_confirm_neg_reply(hdev, skb);
2363 break;
2364
Brian Gix1143d452011-11-23 08:28:34 -08002365 case HCI_OP_USER_PASSKEY_REPLY:
2366 hci_cc_user_passkey_reply(hdev, skb);
2367 break;
2368
2369 case HCI_OP_USER_PASSKEY_NEG_REPLY:
2370 hci_cc_user_passkey_neg_reply(hdev, skb);
Szymon Janc16cde992012-04-13 12:32:42 +02002371 break;
Andre Guedes07f7fa52011-12-02 21:13:31 +09002372
2373 case HCI_OP_LE_SET_SCAN_PARAM:
2374 hci_cc_le_set_scan_param(hdev, skb);
Brian Gix1143d452011-11-23 08:28:34 -08002375 break;
2376
Andre Guedeseb9d91f2011-05-26 16:23:52 -03002377 case HCI_OP_LE_SET_SCAN_ENABLE:
2378 hci_cc_le_set_scan_enable(hdev, skb);
2379 break;
2380
Vinicius Costa Gomesa7a595f2011-06-09 18:50:47 -03002381 case HCI_OP_LE_LTK_REPLY:
2382 hci_cc_le_ltk_reply(hdev, skb);
2383 break;
2384
2385 case HCI_OP_LE_LTK_NEG_REPLY:
2386 hci_cc_le_ltk_neg_reply(hdev, skb);
2387 break;
2388
Andre Guedesf9b49302011-06-30 19:20:53 -03002389 case HCI_OP_WRITE_LE_HOST_SUPPORTED:
2390 hci_cc_write_le_host_supported(hdev, skb);
2391 break;
2392
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002393 default:
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +03002394 BT_DBG("%s opcode 0x%4.4x", hdev->name, opcode);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002395 break;
2396 }
2397
Ville Tervo6bd32322011-02-16 16:32:41 +02002398 if (ev->opcode != HCI_OP_NOP)
2399 del_timer(&hdev->cmd_timer);
2400
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002401 if (ev->ncmd) {
2402 atomic_set(&hdev->cmd_cnt, 1);
2403 if (!skb_queue_empty(&hdev->cmd_q))
Gustavo F. Padovanc347b762011-12-14 23:53:47 -02002404 queue_work(hdev->workqueue, &hdev->cmd_work);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002405 }
2406}
2407
Gustavo Padovan6039aa732012-05-23 04:04:18 -03002408static void hci_cmd_status_evt(struct hci_dev *hdev, struct sk_buff *skb)
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002409{
2410 struct hci_ev_cmd_status *ev = (void *) skb->data;
2411 __u16 opcode;
2412
2413 skb_pull(skb, sizeof(*ev));
2414
2415 opcode = __le16_to_cpu(ev->opcode);
2416
2417 switch (opcode) {
2418 case HCI_OP_INQUIRY:
2419 hci_cs_inquiry(hdev, ev->status);
2420 break;
2421
2422 case HCI_OP_CREATE_CONN:
2423 hci_cs_create_conn(hdev, ev->status);
2424 break;
2425
2426 case HCI_OP_ADD_SCO:
2427 hci_cs_add_sco(hdev, ev->status);
2428 break;
2429
Marcel Holtmannf8558552008-07-14 20:13:49 +02002430 case HCI_OP_AUTH_REQUESTED:
2431 hci_cs_auth_requested(hdev, ev->status);
2432 break;
2433
2434 case HCI_OP_SET_CONN_ENCRYPT:
2435 hci_cs_set_conn_encrypt(hdev, ev->status);
2436 break;
2437
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002438 case HCI_OP_REMOTE_NAME_REQ:
2439 hci_cs_remote_name_req(hdev, ev->status);
2440 break;
2441
Marcel Holtmann769be972008-07-14 20:13:49 +02002442 case HCI_OP_READ_REMOTE_FEATURES:
2443 hci_cs_read_remote_features(hdev, ev->status);
2444 break;
2445
2446 case HCI_OP_READ_REMOTE_EXT_FEATURES:
2447 hci_cs_read_remote_ext_features(hdev, ev->status);
2448 break;
2449
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002450 case HCI_OP_SETUP_SYNC_CONN:
2451 hci_cs_setup_sync_conn(hdev, ev->status);
2452 break;
2453
2454 case HCI_OP_SNIFF_MODE:
2455 hci_cs_sniff_mode(hdev, ev->status);
2456 break;
2457
2458 case HCI_OP_EXIT_SNIFF_MODE:
2459 hci_cs_exit_sniff_mode(hdev, ev->status);
2460 break;
2461
Johan Hedberg8962ee72011-01-20 12:40:27 +02002462 case HCI_OP_DISCONNECT:
Johan Hedberg88c3df12012-02-09 14:27:38 +02002463 hci_cs_disconnect(hdev, ev->status);
Johan Hedberg8962ee72011-01-20 12:40:27 +02002464 break;
2465
Ville Tervofcd89c02011-02-10 22:38:47 -03002466 case HCI_OP_LE_CREATE_CONN:
2467 hci_cs_le_create_conn(hdev, ev->status);
2468 break;
2469
Vinicius Costa Gomesa7a595f2011-06-09 18:50:47 -03002470 case HCI_OP_LE_START_ENC:
2471 hci_cs_le_start_enc(hdev, ev->status);
2472 break;
2473
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002474 default:
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +03002475 BT_DBG("%s opcode 0x%4.4x", hdev->name, opcode);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002476 break;
2477 }
2478
Ville Tervo6bd32322011-02-16 16:32:41 +02002479 if (ev->opcode != HCI_OP_NOP)
2480 del_timer(&hdev->cmd_timer);
2481
Gustavo F. Padovan10572132011-03-16 15:36:29 -03002482 if (ev->ncmd && !test_bit(HCI_RESET, &hdev->flags)) {
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002483 atomic_set(&hdev->cmd_cnt, 1);
2484 if (!skb_queue_empty(&hdev->cmd_q))
Gustavo F. Padovanc347b762011-12-14 23:53:47 -02002485 queue_work(hdev->workqueue, &hdev->cmd_work);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002486 }
2487}
2488
Gustavo Padovan6039aa732012-05-23 04:04:18 -03002489static void hci_role_change_evt(struct hci_dev *hdev, struct sk_buff *skb)
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002490{
2491 struct hci_ev_role_change *ev = (void *) skb->data;
2492 struct hci_conn *conn;
2493
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +03002494 BT_DBG("%s status 0x%2.2x", hdev->name, ev->status);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002495
2496 hci_dev_lock(hdev);
2497
2498 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
2499 if (conn) {
2500 if (!ev->status) {
2501 if (ev->role)
2502 conn->link_mode &= ~HCI_LM_MASTER;
2503 else
2504 conn->link_mode |= HCI_LM_MASTER;
2505 }
2506
Johan Hedberg51a8efd2012-01-16 06:10:31 +02002507 clear_bit(HCI_CONN_RSWITCH_PEND, &conn->flags);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002508
2509 hci_role_switch_cfm(conn, ev->status, ev->role);
2510 }
2511
2512 hci_dev_unlock(hdev);
2513}
2514
Gustavo Padovan6039aa732012-05-23 04:04:18 -03002515static void hci_num_comp_pkts_evt(struct hci_dev *hdev, struct sk_buff *skb)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002516{
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002517 struct hci_ev_num_comp_pkts *ev = (void *) skb->data;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002518 int i;
2519
Andrei Emeltchenko32ac5b92011-12-19 16:31:29 +02002520 if (hdev->flow_ctl_mode != HCI_FLOW_CTL_MODE_PACKET_BASED) {
2521 BT_ERR("Wrong event for mode %d", hdev->flow_ctl_mode);
2522 return;
2523 }
2524
Andrei Emeltchenkoc5993de2011-12-30 12:07:47 +02002525 if (skb->len < sizeof(*ev) || skb->len < sizeof(*ev) +
Gustavo Padovan807deac2012-05-17 00:36:24 -03002526 ev->num_hndl * sizeof(struct hci_comp_pkts_info)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002527 BT_DBG("%s bad parameters", hdev->name);
2528 return;
2529 }
2530
Andrei Emeltchenkoc5993de2011-12-30 12:07:47 +02002531 BT_DBG("%s num_hndl %d", hdev->name, ev->num_hndl);
2532
Andrei Emeltchenko613a1c02011-12-19 16:31:30 +02002533 for (i = 0; i < ev->num_hndl; i++) {
2534 struct hci_comp_pkts_info *info = &ev->handles[i];
Linus Torvalds1da177e2005-04-16 15:20:36 -07002535 struct hci_conn *conn;
2536 __u16 handle, count;
2537
Andrei Emeltchenko613a1c02011-12-19 16:31:30 +02002538 handle = __le16_to_cpu(info->handle);
2539 count = __le16_to_cpu(info->count);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002540
2541 conn = hci_conn_hash_lookup_handle(hdev, handle);
Andrei Emeltchenkof4280912011-12-07 15:56:52 +02002542 if (!conn)
2543 continue;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002544
Andrei Emeltchenkof4280912011-12-07 15:56:52 +02002545 conn->sent -= count;
2546
2547 switch (conn->type) {
2548 case ACL_LINK:
2549 hdev->acl_cnt += count;
2550 if (hdev->acl_cnt > hdev->acl_pkts)
2551 hdev->acl_cnt = hdev->acl_pkts;
2552 break;
2553
2554 case LE_LINK:
2555 if (hdev->le_pkts) {
2556 hdev->le_cnt += count;
2557 if (hdev->le_cnt > hdev->le_pkts)
2558 hdev->le_cnt = hdev->le_pkts;
2559 } else {
Andrei Emeltchenko70f230202010-12-01 16:58:25 +02002560 hdev->acl_cnt += count;
2561 if (hdev->acl_cnt > hdev->acl_pkts)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002562 hdev->acl_cnt = hdev->acl_pkts;
2563 }
Andrei Emeltchenkof4280912011-12-07 15:56:52 +02002564 break;
2565
2566 case SCO_LINK:
2567 hdev->sco_cnt += count;
2568 if (hdev->sco_cnt > hdev->sco_pkts)
2569 hdev->sco_cnt = hdev->sco_pkts;
2570 break;
2571
2572 default:
2573 BT_ERR("Unknown type %d conn %p", conn->type, conn);
2574 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002575 }
2576 }
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002577
Gustavo F. Padovan3eff45e2011-12-15 00:50:02 -02002578 queue_work(hdev->workqueue, &hdev->tx_work);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002579}
2580
Gustavo Padovan6039aa732012-05-23 04:04:18 -03002581static void hci_num_comp_blocks_evt(struct hci_dev *hdev, struct sk_buff *skb)
Andrei Emeltchenko25e89e92012-01-04 12:41:58 +02002582{
2583 struct hci_ev_num_comp_blocks *ev = (void *) skb->data;
2584 int i;
2585
2586 if (hdev->flow_ctl_mode != HCI_FLOW_CTL_MODE_BLOCK_BASED) {
2587 BT_ERR("Wrong event for mode %d", hdev->flow_ctl_mode);
2588 return;
2589 }
2590
2591 if (skb->len < sizeof(*ev) || skb->len < sizeof(*ev) +
Gustavo Padovan807deac2012-05-17 00:36:24 -03002592 ev->num_hndl * sizeof(struct hci_comp_blocks_info)) {
Andrei Emeltchenko25e89e92012-01-04 12:41:58 +02002593 BT_DBG("%s bad parameters", hdev->name);
2594 return;
2595 }
2596
2597 BT_DBG("%s num_blocks %d num_hndl %d", hdev->name, ev->num_blocks,
Gustavo Padovan807deac2012-05-17 00:36:24 -03002598 ev->num_hndl);
Andrei Emeltchenko25e89e92012-01-04 12:41:58 +02002599
2600 for (i = 0; i < ev->num_hndl; i++) {
2601 struct hci_comp_blocks_info *info = &ev->handles[i];
2602 struct hci_conn *conn;
2603 __u16 handle, block_count;
2604
2605 handle = __le16_to_cpu(info->handle);
2606 block_count = __le16_to_cpu(info->blocks);
2607
2608 conn = hci_conn_hash_lookup_handle(hdev, handle);
2609 if (!conn)
2610 continue;
2611
2612 conn->sent -= block_count;
2613
2614 switch (conn->type) {
2615 case ACL_LINK:
2616 hdev->block_cnt += block_count;
2617 if (hdev->block_cnt > hdev->num_blocks)
2618 hdev->block_cnt = hdev->num_blocks;
2619 break;
2620
2621 default:
2622 BT_ERR("Unknown type %d conn %p", conn->type, conn);
2623 break;
2624 }
2625 }
2626
2627 queue_work(hdev->workqueue, &hdev->tx_work);
2628}
2629
Gustavo Padovan6039aa732012-05-23 04:04:18 -03002630static void hci_mode_change_evt(struct hci_dev *hdev, struct sk_buff *skb)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002631{
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002632 struct hci_ev_mode_change *ev = (void *) skb->data;
Marcel Holtmann04837f62006-07-03 10:02:33 +02002633 struct hci_conn *conn;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002634
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +03002635 BT_DBG("%s status 0x%2.2x", hdev->name, ev->status);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002636
2637 hci_dev_lock(hdev);
2638
Marcel Holtmann04837f62006-07-03 10:02:33 +02002639 conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
2640 if (conn) {
2641 conn->mode = ev->mode;
2642 conn->interval = __le16_to_cpu(ev->interval);
2643
Gustavo Padovan8fc9ced2012-05-23 04:04:21 -03002644 if (!test_and_clear_bit(HCI_CONN_MODE_CHANGE_PEND,
2645 &conn->flags)) {
Marcel Holtmann04837f62006-07-03 10:02:33 +02002646 if (conn->mode == HCI_CM_ACTIVE)
Johan Hedberg58a681e2012-01-16 06:47:28 +02002647 set_bit(HCI_CONN_POWER_SAVE, &conn->flags);
Marcel Holtmann04837f62006-07-03 10:02:33 +02002648 else
Johan Hedberg58a681e2012-01-16 06:47:28 +02002649 clear_bit(HCI_CONN_POWER_SAVE, &conn->flags);
Marcel Holtmann04837f62006-07-03 10:02:33 +02002650 }
Marcel Holtmanne73439d2010-07-26 10:06:00 -04002651
Johan Hedberg51a8efd2012-01-16 06:10:31 +02002652 if (test_and_clear_bit(HCI_CONN_SCO_SETUP_PEND, &conn->flags))
Marcel Holtmanne73439d2010-07-26 10:06:00 -04002653 hci_sco_setup(conn, ev->status);
Marcel Holtmann04837f62006-07-03 10:02:33 +02002654 }
2655
2656 hci_dev_unlock(hdev);
2657}
2658
Gustavo Padovan6039aa732012-05-23 04:04:18 -03002659static void hci_pin_code_request_evt(struct hci_dev *hdev, struct sk_buff *skb)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002660{
Marcel Holtmann052b30b2009-04-26 20:01:22 +02002661 struct hci_ev_pin_code_req *ev = (void *) skb->data;
2662 struct hci_conn *conn;
2663
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002664 BT_DBG("%s", hdev->name);
Marcel Holtmann052b30b2009-04-26 20:01:22 +02002665
2666 hci_dev_lock(hdev);
2667
2668 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
Waldemar Rymarkiewiczb6f98042011-09-23 10:01:30 +02002669 if (!conn)
2670 goto unlock;
2671
2672 if (conn->state == BT_CONNECTED) {
Marcel Holtmann052b30b2009-04-26 20:01:22 +02002673 hci_conn_hold(conn);
2674 conn->disc_timeout = HCI_PAIRING_TIMEOUT;
2675 hci_conn_put(conn);
2676 }
2677
Johan Hedberga8b2d5c2012-01-08 23:11:15 +02002678 if (!test_bit(HCI_PAIRABLE, &hdev->dev_flags))
Johan Hedberg03b555e2011-01-04 15:40:05 +02002679 hci_send_cmd(hdev, HCI_OP_PIN_CODE_NEG_REPLY,
Gustavo Padovan807deac2012-05-17 00:36:24 -03002680 sizeof(ev->bdaddr), &ev->bdaddr);
Johan Hedberga8b2d5c2012-01-08 23:11:15 +02002681 else if (test_bit(HCI_MGMT, &hdev->dev_flags)) {
Waldemar Rymarkiewicza770bb52011-04-28 12:07:59 +02002682 u8 secure;
2683
2684 if (conn->pending_sec_level == BT_SECURITY_HIGH)
2685 secure = 1;
2686 else
2687 secure = 0;
2688
Johan Hedberg744cf192011-11-08 20:40:14 +02002689 mgmt_pin_code_request(hdev, &ev->bdaddr, secure);
Waldemar Rymarkiewicza770bb52011-04-28 12:07:59 +02002690 }
Johan Hedberg980e1a52011-01-22 06:10:07 +02002691
Waldemar Rymarkiewiczb6f98042011-09-23 10:01:30 +02002692unlock:
Marcel Holtmann052b30b2009-04-26 20:01:22 +02002693 hci_dev_unlock(hdev);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002694}
2695
Gustavo Padovan6039aa732012-05-23 04:04:18 -03002696static void hci_link_key_request_evt(struct hci_dev *hdev, struct sk_buff *skb)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002697{
Johan Hedberg55ed8ca2011-01-17 14:41:05 +02002698 struct hci_ev_link_key_req *ev = (void *) skb->data;
2699 struct hci_cp_link_key_reply cp;
2700 struct hci_conn *conn;
2701 struct link_key *key;
2702
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002703 BT_DBG("%s", hdev->name);
Johan Hedberg55ed8ca2011-01-17 14:41:05 +02002704
Johan Hedberga8b2d5c2012-01-08 23:11:15 +02002705 if (!test_bit(HCI_LINK_KEYS, &hdev->dev_flags))
Johan Hedberg55ed8ca2011-01-17 14:41:05 +02002706 return;
2707
2708 hci_dev_lock(hdev);
2709
2710 key = hci_find_link_key(hdev, &ev->bdaddr);
2711 if (!key) {
2712 BT_DBG("%s link key not found for %s", hdev->name,
Gustavo Padovan807deac2012-05-17 00:36:24 -03002713 batostr(&ev->bdaddr));
Johan Hedberg55ed8ca2011-01-17 14:41:05 +02002714 goto not_found;
2715 }
2716
2717 BT_DBG("%s found key type %u for %s", hdev->name, key->type,
Gustavo Padovan807deac2012-05-17 00:36:24 -03002718 batostr(&ev->bdaddr));
Johan Hedberg55ed8ca2011-01-17 14:41:05 +02002719
Johan Hedberga8b2d5c2012-01-08 23:11:15 +02002720 if (!test_bit(HCI_DEBUG_KEYS, &hdev->dev_flags) &&
Gustavo Padovan807deac2012-05-17 00:36:24 -03002721 key->type == HCI_LK_DEBUG_COMBINATION) {
Johan Hedberg55ed8ca2011-01-17 14:41:05 +02002722 BT_DBG("%s ignoring debug key", hdev->name);
2723 goto not_found;
2724 }
2725
2726 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
Waldemar Rymarkiewicz60b83f52011-04-28 12:07:56 +02002727 if (conn) {
2728 if (key->type == HCI_LK_UNAUTH_COMBINATION &&
Gustavo Padovan807deac2012-05-17 00:36:24 -03002729 conn->auth_type != 0xff && (conn->auth_type & 0x01)) {
Waldemar Rymarkiewicz60b83f52011-04-28 12:07:56 +02002730 BT_DBG("%s ignoring unauthenticated key", hdev->name);
2731 goto not_found;
2732 }
Johan Hedberg55ed8ca2011-01-17 14:41:05 +02002733
Waldemar Rymarkiewicz60b83f52011-04-28 12:07:56 +02002734 if (key->type == HCI_LK_COMBINATION && key->pin_len < 16 &&
Gustavo Padovan807deac2012-05-17 00:36:24 -03002735 conn->pending_sec_level == BT_SECURITY_HIGH) {
Gustavo Padovan8fc9ced2012-05-23 04:04:21 -03002736 BT_DBG("%s ignoring key unauthenticated for high security",
2737 hdev->name);
Waldemar Rymarkiewicz60b83f52011-04-28 12:07:56 +02002738 goto not_found;
2739 }
2740
2741 conn->key_type = key->type;
2742 conn->pin_length = key->pin_len;
Johan Hedberg55ed8ca2011-01-17 14:41:05 +02002743 }
2744
2745 bacpy(&cp.bdaddr, &ev->bdaddr);
Andrei Emeltchenko9b3b4462012-05-23 11:31:20 +03002746 memcpy(cp.link_key, key->val, HCI_LINK_KEY_SIZE);
Johan Hedberg55ed8ca2011-01-17 14:41:05 +02002747
2748 hci_send_cmd(hdev, HCI_OP_LINK_KEY_REPLY, sizeof(cp), &cp);
2749
2750 hci_dev_unlock(hdev);
2751
2752 return;
2753
2754not_found:
2755 hci_send_cmd(hdev, HCI_OP_LINK_KEY_NEG_REPLY, 6, &ev->bdaddr);
2756 hci_dev_unlock(hdev);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002757}
2758
Gustavo Padovan6039aa732012-05-23 04:04:18 -03002759static void hci_link_key_notify_evt(struct hci_dev *hdev, struct sk_buff *skb)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002760{
Marcel Holtmann052b30b2009-04-26 20:01:22 +02002761 struct hci_ev_link_key_notify *ev = (void *) skb->data;
2762 struct hci_conn *conn;
Johan Hedberg55ed8ca2011-01-17 14:41:05 +02002763 u8 pin_len = 0;
Marcel Holtmann052b30b2009-04-26 20:01:22 +02002764
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002765 BT_DBG("%s", hdev->name);
Marcel Holtmann052b30b2009-04-26 20:01:22 +02002766
2767 hci_dev_lock(hdev);
2768
2769 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
2770 if (conn) {
2771 hci_conn_hold(conn);
2772 conn->disc_timeout = HCI_DISCONN_TIMEOUT;
Johan Hedberg980e1a52011-01-22 06:10:07 +02002773 pin_len = conn->pin_length;
Waldemar Rymarkiewicz13d39312011-04-28 12:07:55 +02002774
2775 if (ev->key_type != HCI_LK_CHANGED_COMBINATION)
2776 conn->key_type = ev->key_type;
2777
Marcel Holtmann052b30b2009-04-26 20:01:22 +02002778 hci_conn_put(conn);
2779 }
2780
Johan Hedberga8b2d5c2012-01-08 23:11:15 +02002781 if (test_bit(HCI_LINK_KEYS, &hdev->dev_flags))
Johan Hedbergd25e28a2011-04-28 11:28:59 -07002782 hci_add_link_key(hdev, conn, 1, &ev->bdaddr, ev->link_key,
Gustavo Padovan807deac2012-05-17 00:36:24 -03002783 ev->key_type, pin_len);
Johan Hedberg55ed8ca2011-01-17 14:41:05 +02002784
Marcel Holtmann052b30b2009-04-26 20:01:22 +02002785 hci_dev_unlock(hdev);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002786}
2787
Gustavo Padovan6039aa732012-05-23 04:04:18 -03002788static void hci_clock_offset_evt(struct hci_dev *hdev, struct sk_buff *skb)
Marcel Holtmann04837f62006-07-03 10:02:33 +02002789{
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002790 struct hci_ev_clock_offset *ev = (void *) skb->data;
Marcel Holtmann04837f62006-07-03 10:02:33 +02002791 struct hci_conn *conn;
2792
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +03002793 BT_DBG("%s status 0x%2.2x", hdev->name, ev->status);
Marcel Holtmann04837f62006-07-03 10:02:33 +02002794
2795 hci_dev_lock(hdev);
2796
2797 conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
Linus Torvalds1da177e2005-04-16 15:20:36 -07002798 if (conn && !ev->status) {
2799 struct inquiry_entry *ie;
2800
Andrei Emeltchenkocc11b9c2010-11-22 13:21:37 +02002801 ie = hci_inquiry_cache_lookup(hdev, &conn->dst);
2802 if (ie) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002803 ie->data.clock_offset = ev->clock_offset;
2804 ie->timestamp = jiffies;
2805 }
2806 }
2807
2808 hci_dev_unlock(hdev);
2809}
2810
Gustavo Padovan6039aa732012-05-23 04:04:18 -03002811static void hci_pkt_type_change_evt(struct hci_dev *hdev, struct sk_buff *skb)
Marcel Holtmanna8746412008-07-14 20:13:46 +02002812{
2813 struct hci_ev_pkt_type_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 Holtmanna8746412008-07-14 20:13:46 +02002817
2818 hci_dev_lock(hdev);
2819
2820 conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
2821 if (conn && !ev->status)
2822 conn->pkt_type = __le16_to_cpu(ev->pkt_type);
2823
2824 hci_dev_unlock(hdev);
2825}
2826
Gustavo Padovan6039aa732012-05-23 04:04:18 -03002827static void hci_pscan_rep_mode_evt(struct hci_dev *hdev, struct sk_buff *skb)
Marcel Holtmann85a1e932005-08-09 20:28:02 -07002828{
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002829 struct hci_ev_pscan_rep_mode *ev = (void *) skb->data;
Marcel Holtmann85a1e932005-08-09 20:28:02 -07002830 struct inquiry_entry *ie;
2831
2832 BT_DBG("%s", hdev->name);
2833
2834 hci_dev_lock(hdev);
2835
Andrei Emeltchenkocc11b9c2010-11-22 13:21:37 +02002836 ie = hci_inquiry_cache_lookup(hdev, &ev->bdaddr);
2837 if (ie) {
Marcel Holtmann85a1e932005-08-09 20:28:02 -07002838 ie->data.pscan_rep_mode = ev->pscan_rep_mode;
2839 ie->timestamp = jiffies;
2840 }
2841
2842 hci_dev_unlock(hdev);
2843}
2844
Gustavo Padovan6039aa732012-05-23 04:04:18 -03002845static void hci_inquiry_result_with_rssi_evt(struct hci_dev *hdev,
2846 struct sk_buff *skb)
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002847{
2848 struct inquiry_data data;
2849 int num_rsp = *((__u8 *) skb->data);
Johan Hedberg388fc8f2012-02-23 00:38:59 +02002850 bool name_known, ssp;
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002851
2852 BT_DBG("%s num_rsp %d", hdev->name, num_rsp);
2853
2854 if (!num_rsp)
2855 return;
2856
Andre Guedes1519cc12012-03-21 00:03:38 -03002857 if (test_bit(HCI_PERIODIC_INQ, &hdev->dev_flags))
2858 return;
2859
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002860 hci_dev_lock(hdev);
2861
2862 if ((skb->len - 1) / num_rsp != sizeof(struct inquiry_info_with_rssi)) {
Szymon Janc138d22e2011-02-17 16:44:23 +01002863 struct inquiry_info_with_rssi_and_pscan_mode *info;
2864 info = (void *) (skb->data + 1);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002865
Johan Hedberge17acd42011-03-30 23:57:16 +03002866 for (; num_rsp; num_rsp--, info++) {
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002867 bacpy(&data.bdaddr, &info->bdaddr);
2868 data.pscan_rep_mode = info->pscan_rep_mode;
2869 data.pscan_period_mode = info->pscan_period_mode;
2870 data.pscan_mode = info->pscan_mode;
2871 memcpy(data.dev_class, info->dev_class, 3);
2872 data.clock_offset = info->clock_offset;
2873 data.rssi = info->rssi;
Marcel Holtmann41a96212008-07-14 20:13:48 +02002874 data.ssp_mode = 0x00;
Johan Hedberg31754052012-01-04 13:39:52 +02002875
2876 name_known = hci_inquiry_cache_update(hdev, &data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002877 false, &ssp);
Johan Hedberg48264f02011-11-09 13:58:58 +02002878 mgmt_device_found(hdev, &info->bdaddr, ACL_LINK, 0x00,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002879 info->dev_class, info->rssi,
2880 !name_known, ssp, NULL, 0);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002881 }
2882 } else {
2883 struct inquiry_info_with_rssi *info = (void *) (skb->data + 1);
2884
Johan Hedberge17acd42011-03-30 23:57:16 +03002885 for (; num_rsp; num_rsp--, info++) {
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002886 bacpy(&data.bdaddr, &info->bdaddr);
2887 data.pscan_rep_mode = info->pscan_rep_mode;
2888 data.pscan_period_mode = info->pscan_period_mode;
2889 data.pscan_mode = 0x00;
2890 memcpy(data.dev_class, info->dev_class, 3);
2891 data.clock_offset = info->clock_offset;
2892 data.rssi = info->rssi;
Marcel Holtmann41a96212008-07-14 20:13:48 +02002893 data.ssp_mode = 0x00;
Johan Hedberg31754052012-01-04 13:39:52 +02002894 name_known = hci_inquiry_cache_update(hdev, &data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002895 false, &ssp);
Johan Hedberg48264f02011-11-09 13:58:58 +02002896 mgmt_device_found(hdev, &info->bdaddr, ACL_LINK, 0x00,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002897 info->dev_class, info->rssi,
2898 !name_known, ssp, NULL, 0);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002899 }
2900 }
2901
2902 hci_dev_unlock(hdev);
2903}
2904
Gustavo Padovan6039aa732012-05-23 04:04:18 -03002905static void hci_remote_ext_features_evt(struct hci_dev *hdev,
2906 struct sk_buff *skb)
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002907{
Marcel Holtmann41a96212008-07-14 20:13:48 +02002908 struct hci_ev_remote_ext_features *ev = (void *) skb->data;
2909 struct hci_conn *conn;
2910
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002911 BT_DBG("%s", hdev->name);
Marcel Holtmann41a96212008-07-14 20:13:48 +02002912
Marcel Holtmann41a96212008-07-14 20:13:48 +02002913 hci_dev_lock(hdev);
2914
2915 conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
Johan Hedbergccd556f2010-11-10 17:11:51 +02002916 if (!conn)
2917 goto unlock;
Marcel Holtmann41a96212008-07-14 20:13:48 +02002918
Johan Hedbergccd556f2010-11-10 17:11:51 +02002919 if (!ev->status && ev->page == 0x01) {
2920 struct inquiry_entry *ie;
Marcel Holtmann41a96212008-07-14 20:13:48 +02002921
Andrei Emeltchenkocc11b9c2010-11-22 13:21:37 +02002922 ie = hci_inquiry_cache_lookup(hdev, &conn->dst);
2923 if (ie)
Johan Hedberg02b7cc62012-02-28 02:28:43 +02002924 ie->data.ssp_mode = (ev->features[0] & LMP_HOST_SSP);
Marcel Holtmann769be972008-07-14 20:13:49 +02002925
Johan Hedberg02b7cc62012-02-28 02:28:43 +02002926 if (ev->features[0] & LMP_HOST_SSP)
Johan Hedberg58a681e2012-01-16 06:47:28 +02002927 set_bit(HCI_CONN_SSP_ENABLED, &conn->flags);
Marcel Holtmann41a96212008-07-14 20:13:48 +02002928 }
2929
Johan Hedbergccd556f2010-11-10 17:11:51 +02002930 if (conn->state != BT_CONFIG)
2931 goto unlock;
2932
Johan Hedberg671267b2012-05-12 16:11:50 -03002933 if (!ev->status && !test_bit(HCI_CONN_MGMT_CONNECTED, &conn->flags)) {
Johan Hedberg127178d2010-11-18 22:22:29 +02002934 struct hci_cp_remote_name_req cp;
2935 memset(&cp, 0, sizeof(cp));
2936 bacpy(&cp.bdaddr, &conn->dst);
2937 cp.pscan_rep_mode = 0x02;
2938 hci_send_cmd(hdev, HCI_OP_REMOTE_NAME_REQ, sizeof(cp), &cp);
Johan Hedbergb644ba32012-01-17 21:48:47 +02002939 } else if (!test_and_set_bit(HCI_CONN_MGMT_CONNECTED, &conn->flags))
2940 mgmt_device_connected(hdev, &conn->dst, conn->type,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002941 conn->dst_type, 0, NULL, 0,
2942 conn->dev_class);
Johan Hedberg392599b2010-11-18 22:22:28 +02002943
Johan Hedberg127178d2010-11-18 22:22:29 +02002944 if (!hci_outgoing_auth_needed(hdev, conn)) {
Johan Hedbergccd556f2010-11-10 17:11:51 +02002945 conn->state = BT_CONNECTED;
2946 hci_proto_connect_cfm(conn, ev->status);
2947 hci_conn_put(conn);
2948 }
2949
2950unlock:
Marcel Holtmann41a96212008-07-14 20:13:48 +02002951 hci_dev_unlock(hdev);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002952}
2953
Gustavo Padovan6039aa732012-05-23 04:04:18 -03002954static void hci_sync_conn_complete_evt(struct hci_dev *hdev,
2955 struct sk_buff *skb)
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002956{
Marcel Holtmannb6a0dc82007-10-20 14:55:10 +02002957 struct hci_ev_sync_conn_complete *ev = (void *) skb->data;
2958 struct hci_conn *conn;
2959
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +03002960 BT_DBG("%s status 0x%2.2x", hdev->name, ev->status);
Marcel Holtmannb6a0dc82007-10-20 14:55:10 +02002961
2962 hci_dev_lock(hdev);
2963
2964 conn = hci_conn_hash_lookup_ba(hdev, ev->link_type, &ev->bdaddr);
Marcel Holtmann9dc0a3a2008-07-14 20:13:46 +02002965 if (!conn) {
2966 if (ev->link_type == ESCO_LINK)
2967 goto unlock;
2968
2969 conn = hci_conn_hash_lookup_ba(hdev, ESCO_LINK, &ev->bdaddr);
2970 if (!conn)
2971 goto unlock;
2972
2973 conn->type = SCO_LINK;
2974 }
Marcel Holtmannb6a0dc82007-10-20 14:55:10 +02002975
Marcel Holtmann732547f2009-04-19 19:14:14 +02002976 switch (ev->status) {
2977 case 0x00:
Marcel Holtmannb6a0dc82007-10-20 14:55:10 +02002978 conn->handle = __le16_to_cpu(ev->handle);
2979 conn->state = BT_CONNECTED;
Marcel Holtmann7d0db0a2008-07-14 20:13:51 +02002980
Marcel Holtmann9eba32b2009-08-22 14:19:26 -07002981 hci_conn_hold_device(conn);
Marcel Holtmann7d0db0a2008-07-14 20:13:51 +02002982 hci_conn_add_sysfs(conn);
Marcel Holtmann732547f2009-04-19 19:14:14 +02002983 break;
2984
Stephen Coe705e5712010-02-16 11:29:44 -05002985 case 0x11: /* Unsupported Feature or Parameter Value */
Marcel Holtmann732547f2009-04-19 19:14:14 +02002986 case 0x1c: /* SCO interval rejected */
Nick Pelly1038a002010-02-03 11:42:26 -08002987 case 0x1a: /* Unsupported Remote Feature */
Marcel Holtmann732547f2009-04-19 19:14:14 +02002988 case 0x1f: /* Unspecified error */
2989 if (conn->out && conn->attempt < 2) {
2990 conn->pkt_type = (hdev->esco_type & SCO_ESCO_MASK) |
2991 (hdev->esco_type & EDR_ESCO_MASK);
2992 hci_setup_sync(conn, conn->link->handle);
2993 goto unlock;
2994 }
2995 /* fall through */
2996
2997 default:
Marcel Holtmannb6a0dc82007-10-20 14:55:10 +02002998 conn->state = BT_CLOSED;
Marcel Holtmann732547f2009-04-19 19:14:14 +02002999 break;
3000 }
Marcel Holtmannb6a0dc82007-10-20 14:55:10 +02003001
3002 hci_proto_connect_cfm(conn, ev->status);
3003 if (ev->status)
3004 hci_conn_del(conn);
3005
3006unlock:
3007 hci_dev_unlock(hdev);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02003008}
3009
Gustavo Padovan6039aa732012-05-23 04:04:18 -03003010static void hci_sync_conn_changed_evt(struct hci_dev *hdev, struct sk_buff *skb)
Marcel Holtmanna9de9242007-10-20 13:33:56 +02003011{
3012 BT_DBG("%s", hdev->name);
3013}
3014
Gustavo Padovan6039aa732012-05-23 04:04:18 -03003015static void hci_sniff_subrate_evt(struct hci_dev *hdev, struct sk_buff *skb)
Marcel Holtmann04837f62006-07-03 10:02:33 +02003016{
Marcel Holtmanna9de9242007-10-20 13:33:56 +02003017 struct hci_ev_sniff_subrate *ev = (void *) skb->data;
Marcel Holtmann04837f62006-07-03 10:02:33 +02003018
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +03003019 BT_DBG("%s status 0x%2.2x", hdev->name, ev->status);
Marcel Holtmann04837f62006-07-03 10:02:33 +02003020}
3021
Gustavo Padovan6039aa732012-05-23 04:04:18 -03003022static void hci_extended_inquiry_result_evt(struct hci_dev *hdev,
3023 struct sk_buff *skb)
Marcel Holtmanna9de9242007-10-20 13:33:56 +02003024{
3025 struct inquiry_data data;
3026 struct extended_inquiry_info *info = (void *) (skb->data + 1);
3027 int num_rsp = *((__u8 *) skb->data);
Vishal Agarwal9d939d92012-04-26 19:19:56 +05303028 size_t eir_len;
Marcel Holtmanna9de9242007-10-20 13:33:56 +02003029
3030 BT_DBG("%s num_rsp %d", hdev->name, num_rsp);
3031
3032 if (!num_rsp)
3033 return;
3034
Andre Guedes1519cc12012-03-21 00:03:38 -03003035 if (test_bit(HCI_PERIODIC_INQ, &hdev->dev_flags))
3036 return;
3037
Marcel Holtmanna9de9242007-10-20 13:33:56 +02003038 hci_dev_lock(hdev);
3039
Johan Hedberge17acd42011-03-30 23:57:16 +03003040 for (; num_rsp; num_rsp--, info++) {
Johan Hedberg388fc8f2012-02-23 00:38:59 +02003041 bool name_known, ssp;
Johan Hedberg561aafb2012-01-04 13:31:59 +02003042
Marcel Holtmanna9de9242007-10-20 13:33:56 +02003043 bacpy(&data.bdaddr, &info->bdaddr);
Szymon Janc138d22e2011-02-17 16:44:23 +01003044 data.pscan_rep_mode = info->pscan_rep_mode;
3045 data.pscan_period_mode = info->pscan_period_mode;
3046 data.pscan_mode = 0x00;
Marcel Holtmanna9de9242007-10-20 13:33:56 +02003047 memcpy(data.dev_class, info->dev_class, 3);
Szymon Janc138d22e2011-02-17 16:44:23 +01003048 data.clock_offset = info->clock_offset;
3049 data.rssi = info->rssi;
Marcel Holtmann41a96212008-07-14 20:13:48 +02003050 data.ssp_mode = 0x01;
Johan Hedberg561aafb2012-01-04 13:31:59 +02003051
Johan Hedberga8b2d5c2012-01-08 23:11:15 +02003052 if (test_bit(HCI_MGMT, &hdev->dev_flags))
Johan Hedberg4ddb1932012-01-15 20:04:43 +02003053 name_known = eir_has_data_type(info->data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003054 sizeof(info->data),
3055 EIR_NAME_COMPLETE);
Johan Hedberg561aafb2012-01-04 13:31:59 +02003056 else
3057 name_known = true;
3058
Johan Hedberg388fc8f2012-02-23 00:38:59 +02003059 name_known = hci_inquiry_cache_update(hdev, &data, name_known,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003060 &ssp);
Vishal Agarwal9d939d92012-04-26 19:19:56 +05303061 eir_len = eir_get_length(info->data, sizeof(info->data));
Johan Hedberg48264f02011-11-09 13:58:58 +02003062 mgmt_device_found(hdev, &info->bdaddr, ACL_LINK, 0x00,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003063 info->dev_class, info->rssi, !name_known,
Vishal Agarwal9d939d92012-04-26 19:19:56 +05303064 ssp, info->data, eir_len);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02003065 }
3066
3067 hci_dev_unlock(hdev);
3068}
3069
Johan Hedberg1c2e0042012-06-08 23:31:13 +08003070static void hci_key_refresh_complete_evt(struct hci_dev *hdev,
3071 struct sk_buff *skb)
3072{
3073 struct hci_ev_key_refresh_complete *ev = (void *) skb->data;
3074 struct hci_conn *conn;
3075
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +03003076 BT_DBG("%s status 0x%2.2x handle 0x%4.4x", hdev->name, ev->status,
Johan Hedberg1c2e0042012-06-08 23:31:13 +08003077 __le16_to_cpu(ev->handle));
3078
3079 hci_dev_lock(hdev);
3080
3081 conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
3082 if (!conn)
3083 goto unlock;
3084
3085 if (!ev->status)
3086 conn->sec_level = conn->pending_sec_level;
3087
3088 clear_bit(HCI_CONN_ENCRYPT_PEND, &conn->flags);
3089
3090 if (ev->status && conn->state == BT_CONNECTED) {
3091 hci_acl_disconn(conn, HCI_ERROR_AUTH_FAILURE);
3092 hci_conn_put(conn);
3093 goto unlock;
3094 }
3095
3096 if (conn->state == BT_CONFIG) {
3097 if (!ev->status)
3098 conn->state = BT_CONNECTED;
3099
3100 hci_proto_connect_cfm(conn, ev->status);
3101 hci_conn_put(conn);
3102 } else {
3103 hci_auth_cfm(conn, ev->status);
3104
3105 hci_conn_hold(conn);
3106 conn->disc_timeout = HCI_DISCONN_TIMEOUT;
3107 hci_conn_put(conn);
3108 }
3109
3110unlock:
3111 hci_dev_unlock(hdev);
3112}
3113
Gustavo Padovan6039aa732012-05-23 04:04:18 -03003114static u8 hci_get_auth_req(struct hci_conn *conn)
Johan Hedberg17fa4b92011-01-25 13:28:33 +02003115{
3116 /* If remote requests dedicated bonding follow that lead */
3117 if (conn->remote_auth == 0x02 || conn->remote_auth == 0x03) {
3118 /* If both remote and local IO capabilities allow MITM
3119 * protection then require it, otherwise don't */
3120 if (conn->remote_cap == 0x03 || conn->io_capability == 0x03)
3121 return 0x02;
3122 else
3123 return 0x03;
3124 }
3125
3126 /* If remote requests no-bonding follow that lead */
3127 if (conn->remote_auth == 0x00 || conn->remote_auth == 0x01)
Waldemar Rymarkiewicz58797bf2011-04-28 12:07:58 +02003128 return conn->remote_auth | (conn->auth_type & 0x01);
Johan Hedberg17fa4b92011-01-25 13:28:33 +02003129
3130 return conn->auth_type;
3131}
3132
Gustavo Padovan6039aa732012-05-23 04:04:18 -03003133static void hci_io_capa_request_evt(struct hci_dev *hdev, struct sk_buff *skb)
Marcel Holtmann04936842008-07-14 20:13:48 +02003134{
3135 struct hci_ev_io_capa_request *ev = (void *) skb->data;
3136 struct hci_conn *conn;
3137
3138 BT_DBG("%s", hdev->name);
3139
3140 hci_dev_lock(hdev);
3141
3142 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
Johan Hedberg03b555e2011-01-04 15:40:05 +02003143 if (!conn)
3144 goto unlock;
Marcel Holtmann04936842008-07-14 20:13:48 +02003145
Johan Hedberg03b555e2011-01-04 15:40:05 +02003146 hci_conn_hold(conn);
3147
Johan Hedberga8b2d5c2012-01-08 23:11:15 +02003148 if (!test_bit(HCI_MGMT, &hdev->dev_flags))
Johan Hedberg03b555e2011-01-04 15:40:05 +02003149 goto unlock;
3150
Johan Hedberga8b2d5c2012-01-08 23:11:15 +02003151 if (test_bit(HCI_PAIRABLE, &hdev->dev_flags) ||
Gustavo Padovan807deac2012-05-17 00:36:24 -03003152 (conn->remote_auth & ~0x01) == HCI_AT_NO_BONDING) {
Johan Hedberg17fa4b92011-01-25 13:28:33 +02003153 struct hci_cp_io_capability_reply cp;
3154
3155 bacpy(&cp.bdaddr, &ev->bdaddr);
Hemant Gupta7a7f1e72012-01-16 13:34:29 +05303156 /* Change the IO capability from KeyboardDisplay
3157 * to DisplayYesNo as it is not supported by BT spec. */
3158 cp.capability = (conn->io_capability == 0x04) ?
3159 0x01 : conn->io_capability;
Johan Hedberg7cbc9bd2011-04-28 11:29:04 -07003160 conn->auth_type = hci_get_auth_req(conn);
3161 cp.authentication = conn->auth_type;
Johan Hedberg17fa4b92011-01-25 13:28:33 +02003162
Gustavo Padovan8fc9ced2012-05-23 04:04:21 -03003163 if (hci_find_remote_oob_data(hdev, &conn->dst) &&
3164 (conn->out || test_bit(HCI_CONN_REMOTE_OOB, &conn->flags)))
Szymon Jancce85ee12011-03-22 13:12:23 +01003165 cp.oob_data = 0x01;
3166 else
3167 cp.oob_data = 0x00;
3168
Johan Hedberg17fa4b92011-01-25 13:28:33 +02003169 hci_send_cmd(hdev, HCI_OP_IO_CAPABILITY_REPLY,
Gustavo Padovan807deac2012-05-17 00:36:24 -03003170 sizeof(cp), &cp);
Johan Hedberg03b555e2011-01-04 15:40:05 +02003171 } else {
3172 struct hci_cp_io_capability_neg_reply cp;
3173
3174 bacpy(&cp.bdaddr, &ev->bdaddr);
Andrei Emeltchenko9f5a0d72011-11-07 14:20:25 +02003175 cp.reason = HCI_ERROR_PAIRING_NOT_ALLOWED;
Johan Hedberg03b555e2011-01-04 15:40:05 +02003176
3177 hci_send_cmd(hdev, HCI_OP_IO_CAPABILITY_NEG_REPLY,
Gustavo Padovan807deac2012-05-17 00:36:24 -03003178 sizeof(cp), &cp);
Johan Hedberg03b555e2011-01-04 15:40:05 +02003179 }
3180
3181unlock:
3182 hci_dev_unlock(hdev);
3183}
3184
Gustavo Padovan6039aa732012-05-23 04:04:18 -03003185static void hci_io_capa_reply_evt(struct hci_dev *hdev, struct sk_buff *skb)
Johan Hedberg03b555e2011-01-04 15:40:05 +02003186{
3187 struct hci_ev_io_capa_reply *ev = (void *) skb->data;
3188 struct hci_conn *conn;
3189
3190 BT_DBG("%s", hdev->name);
3191
3192 hci_dev_lock(hdev);
3193
3194 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
3195 if (!conn)
3196 goto unlock;
3197
Johan Hedberg03b555e2011-01-04 15:40:05 +02003198 conn->remote_cap = ev->capability;
Johan Hedberg03b555e2011-01-04 15:40:05 +02003199 conn->remote_auth = ev->authentication;
Johan Hedberg58a681e2012-01-16 06:47:28 +02003200 if (ev->oob_data)
3201 set_bit(HCI_CONN_REMOTE_OOB, &conn->flags);
Johan Hedberg03b555e2011-01-04 15:40:05 +02003202
3203unlock:
Marcel Holtmann04936842008-07-14 20:13:48 +02003204 hci_dev_unlock(hdev);
3205}
3206
Gustavo Padovan6039aa732012-05-23 04:04:18 -03003207static void hci_user_confirm_request_evt(struct hci_dev *hdev,
3208 struct sk_buff *skb)
Johan Hedberga5c29682011-02-19 12:05:57 -03003209{
3210 struct hci_ev_user_confirm_req *ev = (void *) skb->data;
Johan Hedberg55bc1a32011-04-28 11:28:56 -07003211 int loc_mitm, rem_mitm, confirm_hint = 0;
Johan Hedberg7a828902011-04-28 11:28:53 -07003212 struct hci_conn *conn;
Johan Hedberga5c29682011-02-19 12:05:57 -03003213
3214 BT_DBG("%s", hdev->name);
3215
3216 hci_dev_lock(hdev);
3217
Johan Hedberga8b2d5c2012-01-08 23:11:15 +02003218 if (!test_bit(HCI_MGMT, &hdev->dev_flags))
Johan Hedberg7a828902011-04-28 11:28:53 -07003219 goto unlock;
Johan Hedberga5c29682011-02-19 12:05:57 -03003220
Johan Hedberg7a828902011-04-28 11:28:53 -07003221 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
3222 if (!conn)
3223 goto unlock;
3224
3225 loc_mitm = (conn->auth_type & 0x01);
3226 rem_mitm = (conn->remote_auth & 0x01);
3227
3228 /* If we require MITM but the remote device can't provide that
3229 * (it has NoInputNoOutput) then reject the confirmation
3230 * request. The only exception is when we're dedicated bonding
3231 * initiators (connect_cfm_cb set) since then we always have the MITM
3232 * bit set. */
3233 if (!conn->connect_cfm_cb && loc_mitm && conn->remote_cap == 0x03) {
3234 BT_DBG("Rejecting request: remote device can't provide MITM");
3235 hci_send_cmd(hdev, HCI_OP_USER_CONFIRM_NEG_REPLY,
Gustavo Padovan807deac2012-05-17 00:36:24 -03003236 sizeof(ev->bdaddr), &ev->bdaddr);
Johan Hedberg7a828902011-04-28 11:28:53 -07003237 goto unlock;
3238 }
3239
3240 /* If no side requires MITM protection; auto-accept */
3241 if ((!loc_mitm || conn->remote_cap == 0x03) &&
Gustavo Padovan807deac2012-05-17 00:36:24 -03003242 (!rem_mitm || conn->io_capability == 0x03)) {
Johan Hedberg55bc1a32011-04-28 11:28:56 -07003243
3244 /* If we're not the initiators request authorization to
3245 * proceed from user space (mgmt_user_confirm with
3246 * confirm_hint set to 1). */
Johan Hedberg51a8efd2012-01-16 06:10:31 +02003247 if (!test_bit(HCI_CONN_AUTH_PEND, &conn->flags)) {
Johan Hedberg55bc1a32011-04-28 11:28:56 -07003248 BT_DBG("Confirming auto-accept as acceptor");
3249 confirm_hint = 1;
3250 goto confirm;
3251 }
3252
Johan Hedberg9f616562011-04-28 11:28:54 -07003253 BT_DBG("Auto-accept of user confirmation with %ums delay",
Gustavo Padovan807deac2012-05-17 00:36:24 -03003254 hdev->auto_accept_delay);
Johan Hedberg9f616562011-04-28 11:28:54 -07003255
3256 if (hdev->auto_accept_delay > 0) {
3257 int delay = msecs_to_jiffies(hdev->auto_accept_delay);
3258 mod_timer(&conn->auto_accept_timer, jiffies + delay);
3259 goto unlock;
3260 }
3261
Johan Hedberg7a828902011-04-28 11:28:53 -07003262 hci_send_cmd(hdev, HCI_OP_USER_CONFIRM_REPLY,
Gustavo Padovan807deac2012-05-17 00:36:24 -03003263 sizeof(ev->bdaddr), &ev->bdaddr);
Johan Hedberg7a828902011-04-28 11:28:53 -07003264 goto unlock;
3265 }
3266
Johan Hedberg55bc1a32011-04-28 11:28:56 -07003267confirm:
Johan Hedberg272d90d2012-02-09 15:26:12 +02003268 mgmt_user_confirm_request(hdev, &ev->bdaddr, ACL_LINK, 0, ev->passkey,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003269 confirm_hint);
Johan Hedberg7a828902011-04-28 11:28:53 -07003270
3271unlock:
Johan Hedberga5c29682011-02-19 12:05:57 -03003272 hci_dev_unlock(hdev);
3273}
3274
Gustavo Padovan6039aa732012-05-23 04:04:18 -03003275static void hci_user_passkey_request_evt(struct hci_dev *hdev,
3276 struct sk_buff *skb)
Brian Gix1143d452011-11-23 08:28:34 -08003277{
3278 struct hci_ev_user_passkey_req *ev = (void *) skb->data;
3279
3280 BT_DBG("%s", hdev->name);
3281
Johan Hedberga8b2d5c2012-01-08 23:11:15 +02003282 if (test_bit(HCI_MGMT, &hdev->dev_flags))
Johan Hedberg272d90d2012-02-09 15:26:12 +02003283 mgmt_user_passkey_request(hdev, &ev->bdaddr, ACL_LINK, 0);
Brian Gix1143d452011-11-23 08:28:34 -08003284}
3285
Johan Hedberg92a25252012-09-06 18:39:26 +03003286static void hci_user_passkey_notify_evt(struct hci_dev *hdev,
3287 struct sk_buff *skb)
3288{
3289 struct hci_ev_user_passkey_notify *ev = (void *) skb->data;
3290 struct hci_conn *conn;
3291
3292 BT_DBG("%s", hdev->name);
3293
3294 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
3295 if (!conn)
3296 return;
3297
3298 conn->passkey_notify = __le32_to_cpu(ev->passkey);
3299 conn->passkey_entered = 0;
3300
3301 if (test_bit(HCI_MGMT, &hdev->dev_flags))
3302 mgmt_user_passkey_notify(hdev, &conn->dst, conn->type,
3303 conn->dst_type, conn->passkey_notify,
3304 conn->passkey_entered);
3305}
3306
3307static void hci_keypress_notify_evt(struct hci_dev *hdev, struct sk_buff *skb)
3308{
3309 struct hci_ev_keypress_notify *ev = (void *) skb->data;
3310 struct hci_conn *conn;
3311
3312 BT_DBG("%s", hdev->name);
3313
3314 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
3315 if (!conn)
3316 return;
3317
3318 switch (ev->type) {
3319 case HCI_KEYPRESS_STARTED:
3320 conn->passkey_entered = 0;
3321 return;
3322
3323 case HCI_KEYPRESS_ENTERED:
3324 conn->passkey_entered++;
3325 break;
3326
3327 case HCI_KEYPRESS_ERASED:
3328 conn->passkey_entered--;
3329 break;
3330
3331 case HCI_KEYPRESS_CLEARED:
3332 conn->passkey_entered = 0;
3333 break;
3334
3335 case HCI_KEYPRESS_COMPLETED:
3336 return;
3337 }
3338
3339 if (test_bit(HCI_MGMT, &hdev->dev_flags))
3340 mgmt_user_passkey_notify(hdev, &conn->dst, conn->type,
3341 conn->dst_type, conn->passkey_notify,
3342 conn->passkey_entered);
3343}
3344
Gustavo Padovan6039aa732012-05-23 04:04:18 -03003345static void hci_simple_pair_complete_evt(struct hci_dev *hdev,
3346 struct sk_buff *skb)
Marcel Holtmann04936842008-07-14 20:13:48 +02003347{
3348 struct hci_ev_simple_pair_complete *ev = (void *) skb->data;
3349 struct hci_conn *conn;
3350
3351 BT_DBG("%s", hdev->name);
3352
3353 hci_dev_lock(hdev);
3354
3355 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
Johan Hedberg2a611692011-02-19 12:06:00 -03003356 if (!conn)
3357 goto unlock;
Marcel Holtmann04936842008-07-14 20:13:48 +02003358
Johan Hedberg2a611692011-02-19 12:06:00 -03003359 /* To avoid duplicate auth_failed events to user space we check
3360 * the HCI_CONN_AUTH_PEND flag which will be set if we
3361 * initiated the authentication. A traditional auth_complete
3362 * event gets always produced as initiator and is also mapped to
3363 * the mgmt_auth_failed event */
Mikel Astizfa1bd912012-08-09 09:52:29 +02003364 if (!test_bit(HCI_CONN_AUTH_PEND, &conn->flags) && ev->status)
Johan Hedbergbab73cb2012-02-09 16:07:29 +02003365 mgmt_auth_failed(hdev, &conn->dst, conn->type, conn->dst_type,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003366 ev->status);
Johan Hedberg2a611692011-02-19 12:06:00 -03003367
3368 hci_conn_put(conn);
3369
3370unlock:
Marcel Holtmann04936842008-07-14 20:13:48 +02003371 hci_dev_unlock(hdev);
3372}
3373
Gustavo Padovan6039aa732012-05-23 04:04:18 -03003374static void hci_remote_host_features_evt(struct hci_dev *hdev,
3375 struct sk_buff *skb)
Marcel Holtmann41a96212008-07-14 20:13:48 +02003376{
3377 struct hci_ev_remote_host_features *ev = (void *) skb->data;
3378 struct inquiry_entry *ie;
3379
3380 BT_DBG("%s", hdev->name);
3381
3382 hci_dev_lock(hdev);
3383
Andrei Emeltchenkocc11b9c2010-11-22 13:21:37 +02003384 ie = hci_inquiry_cache_lookup(hdev, &ev->bdaddr);
3385 if (ie)
Johan Hedberg02b7cc62012-02-28 02:28:43 +02003386 ie->data.ssp_mode = (ev->features[0] & LMP_HOST_SSP);
Marcel Holtmann41a96212008-07-14 20:13:48 +02003387
3388 hci_dev_unlock(hdev);
3389}
3390
Gustavo Padovan6039aa732012-05-23 04:04:18 -03003391static void hci_remote_oob_data_request_evt(struct hci_dev *hdev,
3392 struct sk_buff *skb)
Szymon Janc2763eda2011-03-22 13:12:22 +01003393{
3394 struct hci_ev_remote_oob_data_request *ev = (void *) skb->data;
3395 struct oob_data *data;
3396
3397 BT_DBG("%s", hdev->name);
3398
3399 hci_dev_lock(hdev);
3400
Johan Hedberga8b2d5c2012-01-08 23:11:15 +02003401 if (!test_bit(HCI_MGMT, &hdev->dev_flags))
Szymon Jance1ba1f12011-04-06 13:01:59 +02003402 goto unlock;
3403
Szymon Janc2763eda2011-03-22 13:12:22 +01003404 data = hci_find_remote_oob_data(hdev, &ev->bdaddr);
3405 if (data) {
3406 struct hci_cp_remote_oob_data_reply cp;
3407
3408 bacpy(&cp.bdaddr, &ev->bdaddr);
3409 memcpy(cp.hash, data->hash, sizeof(cp.hash));
3410 memcpy(cp.randomizer, data->randomizer, sizeof(cp.randomizer));
3411
3412 hci_send_cmd(hdev, HCI_OP_REMOTE_OOB_DATA_REPLY, sizeof(cp),
Gustavo Padovan807deac2012-05-17 00:36:24 -03003413 &cp);
Szymon Janc2763eda2011-03-22 13:12:22 +01003414 } else {
3415 struct hci_cp_remote_oob_data_neg_reply cp;
3416
3417 bacpy(&cp.bdaddr, &ev->bdaddr);
3418 hci_send_cmd(hdev, HCI_OP_REMOTE_OOB_DATA_NEG_REPLY, sizeof(cp),
Gustavo Padovan807deac2012-05-17 00:36:24 -03003419 &cp);
Szymon Janc2763eda2011-03-22 13:12:22 +01003420 }
3421
Szymon Jance1ba1f12011-04-06 13:01:59 +02003422unlock:
Szymon Janc2763eda2011-03-22 13:12:22 +01003423 hci_dev_unlock(hdev);
3424}
3425
Gustavo Padovan6039aa732012-05-23 04:04:18 -03003426static void hci_le_conn_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
Ville Tervofcd89c02011-02-10 22:38:47 -03003427{
3428 struct hci_ev_le_conn_complete *ev = (void *) skb->data;
3429 struct hci_conn *conn;
3430
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +03003431 BT_DBG("%s status 0x%2.2x", hdev->name, ev->status);
Ville Tervofcd89c02011-02-10 22:38:47 -03003432
3433 hci_dev_lock(hdev);
3434
Andre Guedesb47a09b2012-07-27 15:10:15 -03003435 conn = hci_conn_hash_lookup_state(hdev, LE_LINK, BT_CONNECT);
Ville Tervob62f3282011-02-10 22:38:50 -03003436 if (!conn) {
3437 conn = hci_conn_add(hdev, LE_LINK, &ev->bdaddr);
3438 if (!conn) {
3439 BT_ERR("No memory for new connection");
Andre Guedes230fd162012-07-27 15:10:10 -03003440 goto unlock;
Ville Tervob62f3282011-02-10 22:38:50 -03003441 }
Andre Guedes29b79882011-05-31 14:20:54 -03003442
3443 conn->dst_type = ev->bdaddr_type;
Andre Guedesb9b343d2012-07-27 15:10:11 -03003444
3445 if (ev->role == LE_CONN_ROLE_MASTER) {
3446 conn->out = true;
3447 conn->link_mode |= HCI_LM_MASTER;
3448 }
Ville Tervob62f3282011-02-10 22:38:50 -03003449 }
Ville Tervofcd89c02011-02-10 22:38:47 -03003450
Andre Guedescd17dec2012-07-27 15:10:16 -03003451 if (ev->status) {
3452 mgmt_connect_failed(hdev, &conn->dst, conn->type,
3453 conn->dst_type, ev->status);
3454 hci_proto_connect_cfm(conn, ev->status);
3455 conn->state = BT_CLOSED;
3456 hci_conn_del(conn);
3457 goto unlock;
3458 }
3459
Johan Hedbergb644ba32012-01-17 21:48:47 +02003460 if (!test_and_set_bit(HCI_CONN_MGMT_CONNECTED, &conn->flags))
3461 mgmt_device_connected(hdev, &ev->bdaddr, conn->type,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003462 conn->dst_type, 0, NULL, 0, NULL);
Vinicius Costa Gomes83bc71b2011-05-06 18:41:43 -03003463
Vinicius Costa Gomes7b5c0d52011-06-09 18:50:50 -03003464 conn->sec_level = BT_SECURITY_LOW;
Ville Tervofcd89c02011-02-10 22:38:47 -03003465 conn->handle = __le16_to_cpu(ev->handle);
3466 conn->state = BT_CONNECTED;
3467
3468 hci_conn_hold_device(conn);
3469 hci_conn_add_sysfs(conn);
3470
3471 hci_proto_connect_cfm(conn, ev->status);
3472
3473unlock:
3474 hci_dev_unlock(hdev);
3475}
3476
Gustavo Padovan6039aa732012-05-23 04:04:18 -03003477static void hci_le_adv_report_evt(struct hci_dev *hdev, struct sk_buff *skb)
Andre Guedes9aa04c92011-05-26 16:23:51 -03003478{
Andre Guedese95beb42011-09-26 20:48:35 -03003479 u8 num_reports = skb->data[0];
3480 void *ptr = &skb->data[1];
Andre Guedes3c9e9192012-01-10 18:20:50 -03003481 s8 rssi;
Andre Guedes9aa04c92011-05-26 16:23:51 -03003482
3483 hci_dev_lock(hdev);
3484
Andre Guedese95beb42011-09-26 20:48:35 -03003485 while (num_reports--) {
3486 struct hci_ev_le_advertising_info *ev = ptr;
Andre Guedes9aa04c92011-05-26 16:23:51 -03003487
Andre Guedes3c9e9192012-01-10 18:20:50 -03003488 rssi = ev->data[ev->length];
3489 mgmt_device_found(hdev, &ev->bdaddr, LE_LINK, ev->bdaddr_type,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003490 NULL, rssi, 0, 1, ev->data, ev->length);
Andre Guedes3c9e9192012-01-10 18:20:50 -03003491
Andre Guedese95beb42011-09-26 20:48:35 -03003492 ptr += sizeof(*ev) + ev->length + 1;
Andre Guedes9aa04c92011-05-26 16:23:51 -03003493 }
3494
3495 hci_dev_unlock(hdev);
3496}
3497
Gustavo Padovan6039aa732012-05-23 04:04:18 -03003498static void hci_le_ltk_request_evt(struct hci_dev *hdev, struct sk_buff *skb)
Vinicius Costa Gomesa7a595f2011-06-09 18:50:47 -03003499{
3500 struct hci_ev_le_ltk_req *ev = (void *) skb->data;
3501 struct hci_cp_le_ltk_reply cp;
Vinicius Costa Gomesbea710f2011-07-07 18:59:37 -03003502 struct hci_cp_le_ltk_neg_reply neg;
Vinicius Costa Gomesa7a595f2011-06-09 18:50:47 -03003503 struct hci_conn *conn;
Vinicius Costa Gomesc9839a12012-02-02 21:08:01 -03003504 struct smp_ltk *ltk;
Vinicius Costa Gomesa7a595f2011-06-09 18:50:47 -03003505
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +03003506 BT_DBG("%s handle 0x%4.4x", hdev->name, __le16_to_cpu(ev->handle));
Vinicius Costa Gomesa7a595f2011-06-09 18:50:47 -03003507
3508 hci_dev_lock(hdev);
3509
3510 conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
Vinicius Costa Gomesbea710f2011-07-07 18:59:37 -03003511 if (conn == NULL)
3512 goto not_found;
Vinicius Costa Gomesa7a595f2011-06-09 18:50:47 -03003513
Vinicius Costa Gomesbea710f2011-07-07 18:59:37 -03003514 ltk = hci_find_ltk(hdev, ev->ediv, ev->random);
3515 if (ltk == NULL)
3516 goto not_found;
3517
3518 memcpy(cp.ltk, ltk->val, sizeof(ltk->val));
Vinicius Costa Gomesa7a595f2011-06-09 18:50:47 -03003519 cp.handle = cpu_to_le16(conn->handle);
Vinicius Costa Gomesc9839a12012-02-02 21:08:01 -03003520
3521 if (ltk->authenticated)
3522 conn->sec_level = BT_SECURITY_HIGH;
Vinicius Costa Gomesa7a595f2011-06-09 18:50:47 -03003523
3524 hci_send_cmd(hdev, HCI_OP_LE_LTK_REPLY, sizeof(cp), &cp);
3525
Vinicius Costa Gomesc9839a12012-02-02 21:08:01 -03003526 if (ltk->type & HCI_SMP_STK) {
3527 list_del(&ltk->list);
3528 kfree(ltk);
3529 }
3530
Vinicius Costa Gomesa7a595f2011-06-09 18:50:47 -03003531 hci_dev_unlock(hdev);
Vinicius Costa Gomesbea710f2011-07-07 18:59:37 -03003532
3533 return;
3534
3535not_found:
3536 neg.handle = ev->handle;
3537 hci_send_cmd(hdev, HCI_OP_LE_LTK_NEG_REPLY, sizeof(neg), &neg);
3538 hci_dev_unlock(hdev);
Vinicius Costa Gomesa7a595f2011-06-09 18:50:47 -03003539}
3540
Gustavo Padovan6039aa732012-05-23 04:04:18 -03003541static void hci_le_meta_evt(struct hci_dev *hdev, struct sk_buff *skb)
Ville Tervofcd89c02011-02-10 22:38:47 -03003542{
3543 struct hci_ev_le_meta *le_ev = (void *) skb->data;
3544
3545 skb_pull(skb, sizeof(*le_ev));
3546
3547 switch (le_ev->subevent) {
3548 case HCI_EV_LE_CONN_COMPLETE:
3549 hci_le_conn_complete_evt(hdev, skb);
3550 break;
3551
Andre Guedes9aa04c92011-05-26 16:23:51 -03003552 case HCI_EV_LE_ADVERTISING_REPORT:
3553 hci_le_adv_report_evt(hdev, skb);
3554 break;
3555
Vinicius Costa Gomesa7a595f2011-06-09 18:50:47 -03003556 case HCI_EV_LE_LTK_REQ:
3557 hci_le_ltk_request_evt(hdev, skb);
3558 break;
3559
Ville Tervofcd89c02011-02-10 22:38:47 -03003560 default:
3561 break;
3562 }
3563}
3564
Linus Torvalds1da177e2005-04-16 15:20:36 -07003565void hci_event_packet(struct hci_dev *hdev, struct sk_buff *skb)
3566{
Marcel Holtmanna9de9242007-10-20 13:33:56 +02003567 struct hci_event_hdr *hdr = (void *) skb->data;
3568 __u8 event = hdr->evt;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003569
3570 skb_pull(skb, HCI_EVENT_HDR_SIZE);
3571
Marcel Holtmanna9de9242007-10-20 13:33:56 +02003572 switch (event) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003573 case HCI_EV_INQUIRY_COMPLETE:
3574 hci_inquiry_complete_evt(hdev, skb);
3575 break;
3576
3577 case HCI_EV_INQUIRY_RESULT:
3578 hci_inquiry_result_evt(hdev, skb);
3579 break;
3580
Marcel Holtmanna9de9242007-10-20 13:33:56 +02003581 case HCI_EV_CONN_COMPLETE:
3582 hci_conn_complete_evt(hdev, skb);
Marcel Holtmann21d9e302005-09-13 01:32:25 +02003583 break;
3584
Linus Torvalds1da177e2005-04-16 15:20:36 -07003585 case HCI_EV_CONN_REQUEST:
3586 hci_conn_request_evt(hdev, skb);
3587 break;
3588
Linus Torvalds1da177e2005-04-16 15:20:36 -07003589 case HCI_EV_DISCONN_COMPLETE:
3590 hci_disconn_complete_evt(hdev, skb);
3591 break;
3592
Linus Torvalds1da177e2005-04-16 15:20:36 -07003593 case HCI_EV_AUTH_COMPLETE:
3594 hci_auth_complete_evt(hdev, skb);
3595 break;
3596
Marcel Holtmanna9de9242007-10-20 13:33:56 +02003597 case HCI_EV_REMOTE_NAME:
3598 hci_remote_name_evt(hdev, skb);
3599 break;
3600
Linus Torvalds1da177e2005-04-16 15:20:36 -07003601 case HCI_EV_ENCRYPT_CHANGE:
3602 hci_encrypt_change_evt(hdev, skb);
3603 break;
3604
Marcel Holtmanna9de9242007-10-20 13:33:56 +02003605 case HCI_EV_CHANGE_LINK_KEY_COMPLETE:
3606 hci_change_link_key_complete_evt(hdev, skb);
3607 break;
3608
3609 case HCI_EV_REMOTE_FEATURES:
3610 hci_remote_features_evt(hdev, skb);
3611 break;
3612
3613 case HCI_EV_REMOTE_VERSION:
3614 hci_remote_version_evt(hdev, skb);
3615 break;
3616
3617 case HCI_EV_QOS_SETUP_COMPLETE:
3618 hci_qos_setup_complete_evt(hdev, skb);
3619 break;
3620
3621 case HCI_EV_CMD_COMPLETE:
3622 hci_cmd_complete_evt(hdev, skb);
3623 break;
3624
3625 case HCI_EV_CMD_STATUS:
3626 hci_cmd_status_evt(hdev, skb);
3627 break;
3628
3629 case HCI_EV_ROLE_CHANGE:
3630 hci_role_change_evt(hdev, skb);
3631 break;
3632
3633 case HCI_EV_NUM_COMP_PKTS:
3634 hci_num_comp_pkts_evt(hdev, skb);
3635 break;
3636
3637 case HCI_EV_MODE_CHANGE:
3638 hci_mode_change_evt(hdev, skb);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003639 break;
3640
3641 case HCI_EV_PIN_CODE_REQ:
3642 hci_pin_code_request_evt(hdev, skb);
3643 break;
3644
3645 case HCI_EV_LINK_KEY_REQ:
3646 hci_link_key_request_evt(hdev, skb);
3647 break;
3648
3649 case HCI_EV_LINK_KEY_NOTIFY:
3650 hci_link_key_notify_evt(hdev, skb);
3651 break;
3652
3653 case HCI_EV_CLOCK_OFFSET:
3654 hci_clock_offset_evt(hdev, skb);
3655 break;
3656
Marcel Holtmanna8746412008-07-14 20:13:46 +02003657 case HCI_EV_PKT_TYPE_CHANGE:
3658 hci_pkt_type_change_evt(hdev, skb);
3659 break;
3660
Marcel Holtmann85a1e932005-08-09 20:28:02 -07003661 case HCI_EV_PSCAN_REP_MODE:
3662 hci_pscan_rep_mode_evt(hdev, skb);
3663 break;
3664
Marcel Holtmanna9de9242007-10-20 13:33:56 +02003665 case HCI_EV_INQUIRY_RESULT_WITH_RSSI:
3666 hci_inquiry_result_with_rssi_evt(hdev, skb);
3667 break;
3668
3669 case HCI_EV_REMOTE_EXT_FEATURES:
3670 hci_remote_ext_features_evt(hdev, skb);
3671 break;
3672
3673 case HCI_EV_SYNC_CONN_COMPLETE:
3674 hci_sync_conn_complete_evt(hdev, skb);
3675 break;
3676
3677 case HCI_EV_SYNC_CONN_CHANGED:
3678 hci_sync_conn_changed_evt(hdev, skb);
3679 break;
3680
Marcel Holtmann04837f62006-07-03 10:02:33 +02003681 case HCI_EV_SNIFF_SUBRATE:
3682 hci_sniff_subrate_evt(hdev, skb);
3683 break;
3684
Marcel Holtmanna9de9242007-10-20 13:33:56 +02003685 case HCI_EV_EXTENDED_INQUIRY_RESULT:
3686 hci_extended_inquiry_result_evt(hdev, skb);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003687 break;
3688
Johan Hedberg1c2e0042012-06-08 23:31:13 +08003689 case HCI_EV_KEY_REFRESH_COMPLETE:
3690 hci_key_refresh_complete_evt(hdev, skb);
3691 break;
3692
Marcel Holtmann04936842008-07-14 20:13:48 +02003693 case HCI_EV_IO_CAPA_REQUEST:
3694 hci_io_capa_request_evt(hdev, skb);
3695 break;
3696
Johan Hedberg03b555e2011-01-04 15:40:05 +02003697 case HCI_EV_IO_CAPA_REPLY:
3698 hci_io_capa_reply_evt(hdev, skb);
3699 break;
3700
Johan Hedberga5c29682011-02-19 12:05:57 -03003701 case HCI_EV_USER_CONFIRM_REQUEST:
3702 hci_user_confirm_request_evt(hdev, skb);
3703 break;
3704
Brian Gix1143d452011-11-23 08:28:34 -08003705 case HCI_EV_USER_PASSKEY_REQUEST:
3706 hci_user_passkey_request_evt(hdev, skb);
3707 break;
3708
Johan Hedberg92a25252012-09-06 18:39:26 +03003709 case HCI_EV_USER_PASSKEY_NOTIFY:
3710 hci_user_passkey_notify_evt(hdev, skb);
3711 break;
3712
3713 case HCI_EV_KEYPRESS_NOTIFY:
3714 hci_keypress_notify_evt(hdev, skb);
3715 break;
3716
Marcel Holtmann04936842008-07-14 20:13:48 +02003717 case HCI_EV_SIMPLE_PAIR_COMPLETE:
3718 hci_simple_pair_complete_evt(hdev, skb);
3719 break;
3720
Marcel Holtmann41a96212008-07-14 20:13:48 +02003721 case HCI_EV_REMOTE_HOST_FEATURES:
3722 hci_remote_host_features_evt(hdev, skb);
3723 break;
3724
Ville Tervofcd89c02011-02-10 22:38:47 -03003725 case HCI_EV_LE_META:
3726 hci_le_meta_evt(hdev, skb);
3727 break;
3728
Szymon Janc2763eda2011-03-22 13:12:22 +01003729 case HCI_EV_REMOTE_OOB_DATA_REQUEST:
3730 hci_remote_oob_data_request_evt(hdev, skb);
3731 break;
3732
Andrei Emeltchenko25e89e92012-01-04 12:41:58 +02003733 case HCI_EV_NUM_COMP_BLOCKS:
3734 hci_num_comp_blocks_evt(hdev, skb);
3735 break;
3736
Marcel Holtmanna9de9242007-10-20 13:33:56 +02003737 default:
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +03003738 BT_DBG("%s event 0x%2.2x", hdev->name, event);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003739 break;
3740 }
3741
3742 kfree_skb(skb);
3743 hdev->stat.evt_rx++;
3744}