blob: 3c6d0a4f78dccc5a9ed684bcbd35194ccdec1ef4 [file] [log] [blame]
YOSHIFUJI Hideaki8e87d142007-02-09 23:24:33 +09001/*
Linus Torvalds1da177e2005-04-16 15:20:36 -07002 BlueZ - Bluetooth protocol stack for Linux
Ron Shaffer2d0a0342010-05-28 11:53:46 -04003 Copyright (c) 2000-2001, 2010, Code Aurora Forum. All rights reserved.
Linus Torvalds1da177e2005-04-16 15:20:36 -07004
5 Written 2000,2001 by Maxim Krasnyansky <maxk@qualcomm.com>
6
7 This program is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License version 2 as
9 published by the Free Software Foundation;
10
11 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
12 OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
13 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF THIRD PARTY RIGHTS.
14 IN NO EVENT SHALL THE COPYRIGHT HOLDER(S) AND AUTHOR(S) BE LIABLE FOR ANY
YOSHIFUJI Hideaki8e87d142007-02-09 23:24:33 +090015 CLAIM, OR ANY SPECIAL INDIRECT OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES
16 WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
17 ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
Linus Torvalds1da177e2005-04-16 15:20:36 -070018 OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
19
YOSHIFUJI Hideaki8e87d142007-02-09 23:24:33 +090020 ALL LIABILITY, INCLUDING LIABILITY FOR INFRINGEMENT OF ANY PATENTS,
21 COPYRIGHTS, TRADEMARKS OR OTHER RIGHTS, RELATING TO USE OF THIS
Linus Torvalds1da177e2005-04-16 15:20:36 -070022 SOFTWARE IS DISCLAIMED.
23*/
24
25/* Bluetooth HCI event handling. */
26
Linus Torvalds1da177e2005-04-16 15:20:36 -070027#include <asm/unaligned.h>
28
29#include <net/bluetooth/bluetooth.h>
30#include <net/bluetooth/hci_core.h>
Mikel Astizf0d6a0e2012-08-09 09:52:30 +020031#include <net/bluetooth/mgmt.h>
Andrei Emeltchenko8e2a0d92012-09-27 17:26:08 +030032#include <net/bluetooth/a2mp.h>
Andrei Emeltchenko903e4542012-09-27 17:26:09 +030033#include <net/bluetooth/amp.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070034
Linus Torvalds1da177e2005-04-16 15:20:36 -070035/* Handle HCI Event packets */
36
Marcel Holtmanna9de9242007-10-20 13:33:56 +020037static void hci_cc_inquiry_cancel(struct hci_dev *hdev, struct sk_buff *skb)
Linus Torvalds1da177e2005-04-16 15:20:36 -070038{
Marcel Holtmanna9de9242007-10-20 13:33:56 +020039 __u8 status = *((__u8 *) skb->data);
Linus Torvalds1da177e2005-04-16 15:20:36 -070040
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +030041 BT_DBG("%s status 0x%2.2x", hdev->name, status);
Linus Torvalds1da177e2005-04-16 15:20:36 -070042
Andre Guedese6d465c2011-11-09 17:14:26 -030043 if (status) {
44 hci_dev_lock(hdev);
45 mgmt_stop_discovery_failed(hdev, status);
46 hci_dev_unlock(hdev);
Marcel Holtmanna9de9242007-10-20 13:33:56 +020047 return;
Andre Guedese6d465c2011-11-09 17:14:26 -030048 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070049
Andre Guedes89352e72011-11-04 14:16:53 -030050 clear_bit(HCI_INQUIRY, &hdev->flags);
51
Johan Hedberg56e5cb82011-11-08 20:40:16 +020052 hci_dev_lock(hdev);
Johan Hedbergff9ef572012-01-04 14:23:45 +020053 hci_discovery_set_state(hdev, DISCOVERY_STOPPED);
Johan Hedberg56e5cb82011-11-08 20:40:16 +020054 hci_dev_unlock(hdev);
Marcel Holtmann6bd57412006-11-18 22:14:22 +010055
Johan Hedberg9238f362013-03-05 20:37:48 +020056 hci_req_cmd_complete(hdev, HCI_OP_INQUIRY, status);
Marcel Holtmann6bd57412006-11-18 22:14:22 +010057
Marcel Holtmanna9de9242007-10-20 13:33:56 +020058 hci_conn_check_pending(hdev);
Linus Torvalds1da177e2005-04-16 15:20:36 -070059}
60
Andre Guedes4d934832012-03-21 00:03:35 -030061static void hci_cc_periodic_inq(struct hci_dev *hdev, struct sk_buff *skb)
62{
63 __u8 status = *((__u8 *) skb->data);
64
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +030065 BT_DBG("%s status 0x%2.2x", hdev->name, status);
Andre Guedesae854a72012-03-21 00:03:36 -030066
67 if (status)
68 return;
69
70 set_bit(HCI_PERIODIC_INQ, &hdev->dev_flags);
Andre Guedes4d934832012-03-21 00:03:35 -030071}
72
Marcel Holtmanna9de9242007-10-20 13:33:56 +020073static void hci_cc_exit_periodic_inq(struct hci_dev *hdev, struct sk_buff *skb)
Linus Torvalds1da177e2005-04-16 15:20:36 -070074{
Marcel Holtmanna9de9242007-10-20 13:33:56 +020075 __u8 status = *((__u8 *) skb->data);
76
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +030077 BT_DBG("%s status 0x%2.2x", hdev->name, status);
Marcel Holtmanna9de9242007-10-20 13:33:56 +020078
79 if (status)
80 return;
81
Andre Guedesae854a72012-03-21 00:03:36 -030082 clear_bit(HCI_PERIODIC_INQ, &hdev->dev_flags);
83
Marcel Holtmanna9de9242007-10-20 13:33:56 +020084 hci_conn_check_pending(hdev);
85}
86
Gustavo Padovan807deac2012-05-17 00:36:24 -030087static void hci_cc_remote_name_req_cancel(struct hci_dev *hdev,
88 struct sk_buff *skb)
Marcel Holtmanna9de9242007-10-20 13:33:56 +020089{
90 BT_DBG("%s", hdev->name);
91}
92
93static void hci_cc_role_discovery(struct hci_dev *hdev, struct sk_buff *skb)
94{
95 struct hci_rp_role_discovery *rp = (void *) skb->data;
Linus Torvalds1da177e2005-04-16 15:20:36 -070096 struct hci_conn *conn;
Linus Torvalds1da177e2005-04-16 15:20:36 -070097
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +030098 BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
Linus Torvalds1da177e2005-04-16 15:20:36 -070099
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200100 if (rp->status)
101 return;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700102
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200103 hci_dev_lock(hdev);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700104
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200105 conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(rp->handle));
106 if (conn) {
107 if (rp->role)
108 conn->link_mode &= ~HCI_LM_MASTER;
109 else
110 conn->link_mode |= HCI_LM_MASTER;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700111 }
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200112
113 hci_dev_unlock(hdev);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700114}
115
Marcel Holtmanne4e8e372008-07-14 20:13:47 +0200116static void hci_cc_read_link_policy(struct hci_dev *hdev, struct sk_buff *skb)
117{
118 struct hci_rp_read_link_policy *rp = (void *) skb->data;
119 struct hci_conn *conn;
120
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +0300121 BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
Marcel Holtmanne4e8e372008-07-14 20:13:47 +0200122
123 if (rp->status)
124 return;
125
126 hci_dev_lock(hdev);
127
128 conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(rp->handle));
129 if (conn)
130 conn->link_policy = __le16_to_cpu(rp->policy);
131
132 hci_dev_unlock(hdev);
133}
134
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200135static void hci_cc_write_link_policy(struct hci_dev *hdev, struct sk_buff *skb)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700136{
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200137 struct hci_rp_write_link_policy *rp = (void *) skb->data;
138 struct hci_conn *conn;
139 void *sent;
140
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +0300141 BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200142
143 if (rp->status)
144 return;
145
146 sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_LINK_POLICY);
147 if (!sent)
148 return;
149
150 hci_dev_lock(hdev);
151
152 conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(rp->handle));
Marcel Holtmanne4e8e372008-07-14 20:13:47 +0200153 if (conn)
Harvey Harrison83985312008-05-02 16:25:46 -0700154 conn->link_policy = get_unaligned_le16(sent + 2);
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200155
156 hci_dev_unlock(hdev);
157}
158
Gustavo Padovan807deac2012-05-17 00:36:24 -0300159static void hci_cc_read_def_link_policy(struct hci_dev *hdev,
160 struct sk_buff *skb)
Marcel Holtmanne4e8e372008-07-14 20:13:47 +0200161{
162 struct hci_rp_read_def_link_policy *rp = (void *) skb->data;
163
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +0300164 BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
Marcel Holtmanne4e8e372008-07-14 20:13:47 +0200165
166 if (rp->status)
167 return;
168
169 hdev->link_policy = __le16_to_cpu(rp->policy);
170}
171
Gustavo Padovan807deac2012-05-17 00:36:24 -0300172static void hci_cc_write_def_link_policy(struct hci_dev *hdev,
173 struct sk_buff *skb)
Marcel Holtmanne4e8e372008-07-14 20:13:47 +0200174{
175 __u8 status = *((__u8 *) skb->data);
176 void *sent;
177
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +0300178 BT_DBG("%s status 0x%2.2x", hdev->name, status);
Marcel Holtmanne4e8e372008-07-14 20:13:47 +0200179
180 sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_DEF_LINK_POLICY);
181 if (!sent)
182 return;
183
184 if (!status)
185 hdev->link_policy = get_unaligned_le16(sent);
Marcel Holtmanne4e8e372008-07-14 20:13:47 +0200186}
187
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200188static void hci_cc_reset(struct hci_dev *hdev, struct sk_buff *skb)
189{
190 __u8 status = *((__u8 *) skb->data);
191
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +0300192 BT_DBG("%s status 0x%2.2x", hdev->name, status);
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200193
Gustavo F. Padovan10572132011-03-16 15:36:29 -0300194 clear_bit(HCI_RESET, &hdev->flags);
195
Johan Hedberga297e972012-02-21 17:55:47 +0200196 /* Reset all non-persistent flags */
Johan Hedberg2cc6fb02013-03-15 17:06:57 -0500197 hdev->dev_flags &= ~HCI_PERSISTENT_MASK;
Andre Guedes69775ff2012-02-23 16:50:05 +0200198
199 hdev->discovery.state = DISCOVERY_STOPPED;
Johan Hedbergbbaf4442012-11-08 01:22:59 +0100200 hdev->inq_tx_power = HCI_TX_POWER_INVALID;
201 hdev->adv_tx_power = HCI_TX_POWER_INVALID;
Johan Hedberg3f0f5242012-11-08 01:23:00 +0100202
203 memset(hdev->adv_data, 0, sizeof(hdev->adv_data));
204 hdev->adv_data_len = 0;
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);
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200226}
227
228static void hci_cc_read_local_name(struct hci_dev *hdev, struct sk_buff *skb)
229{
230 struct hci_rp_read_local_name *rp = (void *) skb->data;
231
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +0300232 BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200233
234 if (rp->status)
235 return;
236
Johan Hedbergdb99b5f2012-02-22 20:14:22 +0200237 if (test_bit(HCI_SETUP, &hdev->dev_flags))
238 memcpy(hdev->dev_name, rp->name, HCI_MAX_NAME_LENGTH);
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200239}
240
241static void hci_cc_write_auth_enable(struct hci_dev *hdev, struct sk_buff *skb)
242{
243 __u8 status = *((__u8 *) skb->data);
244 void *sent;
245
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +0300246 BT_DBG("%s status 0x%2.2x", hdev->name, status);
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200247
248 sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_AUTH_ENABLE);
249 if (!sent)
250 return;
251
252 if (!status) {
253 __u8 param = *((__u8 *) sent);
254
255 if (param == AUTH_ENABLED)
256 set_bit(HCI_AUTH, &hdev->flags);
257 else
258 clear_bit(HCI_AUTH, &hdev->flags);
259 }
260
Johan Hedberg33ef95e2012-02-16 23:56:27 +0200261 if (test_bit(HCI_MGMT, &hdev->dev_flags))
262 mgmt_auth_enable_complete(hdev, status);
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200263}
264
265static void hci_cc_write_encrypt_mode(struct hci_dev *hdev, struct sk_buff *skb)
266{
267 __u8 status = *((__u8 *) skb->data);
268 void *sent;
269
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +0300270 BT_DBG("%s status 0x%2.2x", hdev->name, status);
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200271
272 sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_ENCRYPT_MODE);
273 if (!sent)
274 return;
275
276 if (!status) {
277 __u8 param = *((__u8 *) sent);
278
279 if (param)
280 set_bit(HCI_ENCRYPT, &hdev->flags);
281 else
282 clear_bit(HCI_ENCRYPT, &hdev->flags);
283 }
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200284}
285
286static void hci_cc_write_scan_enable(struct hci_dev *hdev, struct sk_buff *skb)
287{
Johan Hedberg36f7fc72011-11-04 00:17:45 +0200288 __u8 param, status = *((__u8 *) skb->data);
289 int old_pscan, old_iscan;
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200290 void *sent;
291
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +0300292 BT_DBG("%s status 0x%2.2x", hdev->name, status);
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200293
294 sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_SCAN_ENABLE);
295 if (!sent)
296 return;
297
Johan Hedberg36f7fc72011-11-04 00:17:45 +0200298 param = *((__u8 *) sent);
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200299
Johan Hedberg56e5cb82011-11-08 20:40:16 +0200300 hci_dev_lock(hdev);
301
Mikel Astizfa1bd912012-08-09 09:52:29 +0200302 if (status) {
Johan Hedberg744cf192011-11-08 20:40:14 +0200303 mgmt_write_scan_failed(hdev, param, status);
Johan Hedberg2d7cee52011-11-07 22:16:03 +0200304 hdev->discov_timeout = 0;
305 goto done;
306 }
307
Johan Hedberg36f7fc72011-11-04 00:17:45 +0200308 old_pscan = test_and_clear_bit(HCI_PSCAN, &hdev->flags);
309 old_iscan = test_and_clear_bit(HCI_ISCAN, &hdev->flags);
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200310
Johan Hedberg36f7fc72011-11-04 00:17:45 +0200311 if (param & SCAN_INQUIRY) {
312 set_bit(HCI_ISCAN, &hdev->flags);
313 if (!old_iscan)
Johan Hedberg744cf192011-11-08 20:40:14 +0200314 mgmt_discoverable(hdev, 1);
Johan Hedberg16ab91a2011-11-07 22:16:02 +0200315 if (hdev->discov_timeout > 0) {
316 int to = msecs_to_jiffies(hdev->discov_timeout * 1000);
317 queue_delayed_work(hdev->workqueue, &hdev->discov_off,
Gustavo Padovan807deac2012-05-17 00:36:24 -0300318 to);
Johan Hedberg16ab91a2011-11-07 22:16:02 +0200319 }
Johan Hedberg36f7fc72011-11-04 00:17:45 +0200320 } else if (old_iscan)
Johan Hedberg744cf192011-11-08 20:40:14 +0200321 mgmt_discoverable(hdev, 0);
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200322
Johan Hedberg36f7fc72011-11-04 00:17:45 +0200323 if (param & SCAN_PAGE) {
324 set_bit(HCI_PSCAN, &hdev->flags);
325 if (!old_pscan)
Johan Hedberg744cf192011-11-08 20:40:14 +0200326 mgmt_connectable(hdev, 1);
Johan Hedberg36f7fc72011-11-04 00:17:45 +0200327 } else if (old_pscan)
Johan Hedberg744cf192011-11-08 20:40:14 +0200328 mgmt_connectable(hdev, 0);
Johan Hedberg36f7fc72011-11-04 00:17:45 +0200329
330done:
Johan Hedberg56e5cb82011-11-08 20:40:16 +0200331 hci_dev_unlock(hdev);
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200332}
333
334static void hci_cc_read_class_of_dev(struct hci_dev *hdev, struct sk_buff *skb)
335{
336 struct hci_rp_read_class_of_dev *rp = (void *) skb->data;
337
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +0300338 BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200339
340 if (rp->status)
341 return;
342
343 memcpy(hdev->dev_class, rp->dev_class, 3);
344
345 BT_DBG("%s class 0x%.2x%.2x%.2x", hdev->name,
Gustavo Padovan807deac2012-05-17 00:36:24 -0300346 hdev->dev_class[2], hdev->dev_class[1], hdev->dev_class[0]);
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200347}
348
349static void hci_cc_write_class_of_dev(struct hci_dev *hdev, struct sk_buff *skb)
350{
351 __u8 status = *((__u8 *) skb->data);
352 void *sent;
353
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +0300354 BT_DBG("%s status 0x%2.2x", hdev->name, status);
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200355
356 sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_CLASS_OF_DEV);
357 if (!sent)
358 return;
359
Marcel Holtmann7f9a9032012-02-22 18:38:01 +0100360 hci_dev_lock(hdev);
361
362 if (status == 0)
363 memcpy(hdev->dev_class, sent, 3);
364
365 if (test_bit(HCI_MGMT, &hdev->dev_flags))
366 mgmt_set_class_of_dev_complete(hdev, sent, status);
367
368 hci_dev_unlock(hdev);
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200369}
370
371static void hci_cc_read_voice_setting(struct hci_dev *hdev, struct sk_buff *skb)
372{
373 struct hci_rp_read_voice_setting *rp = (void *) skb->data;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700374 __u16 setting;
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200375
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +0300376 BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200377
378 if (rp->status)
379 return;
380
381 setting = __le16_to_cpu(rp->voice_setting);
382
Marcel Holtmannf383f272008-07-14 20:13:47 +0200383 if (hdev->voice_setting == setting)
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200384 return;
385
386 hdev->voice_setting = setting;
387
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +0300388 BT_DBG("%s voice setting 0x%4.4x", hdev->name, setting);
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200389
Gustavo F. Padovan3c547112011-12-14 22:58:44 -0200390 if (hdev->notify)
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200391 hdev->notify(hdev, HCI_NOTIFY_VOICE_SETTING);
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200392}
393
Gustavo Padovan8fc9ced2012-05-23 04:04:21 -0300394static void hci_cc_write_voice_setting(struct hci_dev *hdev,
395 struct sk_buff *skb)
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200396{
397 __u8 status = *((__u8 *) skb->data);
Marcel Holtmannf383f272008-07-14 20:13:47 +0200398 __u16 setting;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700399 void *sent;
400
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +0300401 BT_DBG("%s status 0x%2.2x", hdev->name, status);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700402
Marcel Holtmannf383f272008-07-14 20:13:47 +0200403 if (status)
404 return;
405
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200406 sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_VOICE_SETTING);
407 if (!sent)
408 return;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700409
Marcel Holtmannf383f272008-07-14 20:13:47 +0200410 setting = get_unaligned_le16(sent);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700411
Marcel Holtmannf383f272008-07-14 20:13:47 +0200412 if (hdev->voice_setting == setting)
413 return;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700414
Marcel Holtmannf383f272008-07-14 20:13:47 +0200415 hdev->voice_setting = setting;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700416
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +0300417 BT_DBG("%s voice setting 0x%4.4x", hdev->name, setting);
Marcel Holtmannf383f272008-07-14 20:13:47 +0200418
Gustavo F. Padovan3c547112011-12-14 22:58:44 -0200419 if (hdev->notify)
Marcel Holtmannf383f272008-07-14 20:13:47 +0200420 hdev->notify(hdev, HCI_NOTIFY_VOICE_SETTING);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700421}
422
Marcel Holtmann333140b2008-07-14 20:13:48 +0200423static void hci_cc_write_ssp_mode(struct hci_dev *hdev, struct sk_buff *skb)
424{
425 __u8 status = *((__u8 *) skb->data);
Johan Hedberg5ed8eb22012-10-25 00:09:51 +0300426 struct hci_cp_write_ssp_mode *sent;
Marcel Holtmann333140b2008-07-14 20:13:48 +0200427
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +0300428 BT_DBG("%s status 0x%2.2x", hdev->name, status);
Marcel Holtmann333140b2008-07-14 20:13:48 +0200429
Marcel Holtmann333140b2008-07-14 20:13:48 +0200430 sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_SSP_MODE);
431 if (!sent)
432 return;
433
Johan Hedberg5ed8eb22012-10-25 00:09:51 +0300434 if (!status) {
435 if (sent->mode)
436 hdev->host_features[0] |= LMP_HOST_SSP;
437 else
438 hdev->host_features[0] &= ~LMP_HOST_SSP;
439 }
440
Johan Hedberged2c4ee2012-02-17 00:56:28 +0200441 if (test_bit(HCI_MGMT, &hdev->dev_flags))
Johan Hedberg5ed8eb22012-10-25 00:09:51 +0300442 mgmt_ssp_enable_complete(hdev, sent->mode, status);
Johan Hedbergc0ecddc2012-02-22 12:38:31 +0200443 else if (!status) {
Johan Hedberg5ed8eb22012-10-25 00:09:51 +0300444 if (sent->mode)
Johan Hedbergc0ecddc2012-02-22 12:38:31 +0200445 set_bit(HCI_SSP_ENABLED, &hdev->dev_flags);
446 else
447 clear_bit(HCI_SSP_ENABLED, &hdev->dev_flags);
448 }
Marcel Holtmann333140b2008-07-14 20:13:48 +0200449}
450
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200451static void hci_cc_read_local_version(struct hci_dev *hdev, struct sk_buff *skb)
452{
453 struct hci_rp_read_local_version *rp = (void *) skb->data;
454
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +0300455 BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200456
457 if (rp->status)
Johan Hedberg42c6b122013-03-05 20:37:49 +0200458 return;
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200459
460 hdev->hci_ver = rp->hci_ver;
Marcel Holtmanne4e8e372008-07-14 20:13:47 +0200461 hdev->hci_rev = __le16_to_cpu(rp->hci_rev);
Johan Hedbergd5859e22011-01-25 01:19:58 +0200462 hdev->lmp_ver = rp->lmp_ver;
Marcel Holtmanne4e8e372008-07-14 20:13:47 +0200463 hdev->manufacturer = __le16_to_cpu(rp->manufacturer);
Johan Hedbergd5859e22011-01-25 01:19:58 +0200464 hdev->lmp_subver = __le16_to_cpu(rp->lmp_subver);
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200465
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +0300466 BT_DBG("%s manufacturer 0x%4.4x hci ver %d:%d", hdev->name,
Gustavo Padovan807deac2012-05-17 00:36:24 -0300467 hdev->manufacturer, hdev->hci_ver, hdev->hci_rev);
Johan Hedbergd5859e22011-01-25 01:19:58 +0200468}
469
Gustavo Padovan8fc9ced2012-05-23 04:04:21 -0300470static void hci_cc_read_local_commands(struct hci_dev *hdev,
471 struct sk_buff *skb)
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200472{
473 struct hci_rp_read_local_commands *rp = (void *) skb->data;
474
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +0300475 BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200476
Johan Hedberg2177bab2013-03-05 20:37:43 +0200477 if (!rp->status)
478 memcpy(hdev->commands, rp->commands, sizeof(hdev->commands));
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200479}
480
Gustavo Padovan8fc9ced2012-05-23 04:04:21 -0300481static void hci_cc_read_local_features(struct hci_dev *hdev,
482 struct sk_buff *skb)
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200483{
484 struct hci_rp_read_local_features *rp = (void *) skb->data;
485
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +0300486 BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200487
488 if (rp->status)
489 return;
490
491 memcpy(hdev->features, rp->features, 8);
492
493 /* Adjust default settings according to features
494 * supported by device. */
495
496 if (hdev->features[0] & LMP_3SLOT)
497 hdev->pkt_type |= (HCI_DM3 | HCI_DH3);
498
499 if (hdev->features[0] & LMP_5SLOT)
500 hdev->pkt_type |= (HCI_DM5 | HCI_DH5);
501
502 if (hdev->features[1] & LMP_HV2) {
503 hdev->pkt_type |= (HCI_HV2);
504 hdev->esco_type |= (ESCO_HV2);
505 }
506
507 if (hdev->features[1] & LMP_HV3) {
508 hdev->pkt_type |= (HCI_HV3);
509 hdev->esco_type |= (ESCO_HV3);
510 }
511
Andre Guedes45db810f2012-07-24 15:03:49 -0300512 if (lmp_esco_capable(hdev))
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200513 hdev->esco_type |= (ESCO_EV3);
514
515 if (hdev->features[4] & LMP_EV4)
516 hdev->esco_type |= (ESCO_EV4);
517
518 if (hdev->features[4] & LMP_EV5)
519 hdev->esco_type |= (ESCO_EV5);
520
Marcel Holtmannefc76882009-02-06 09:13:37 +0100521 if (hdev->features[5] & LMP_EDR_ESCO_2M)
522 hdev->esco_type |= (ESCO_2EV3);
523
524 if (hdev->features[5] & LMP_EDR_ESCO_3M)
525 hdev->esco_type |= (ESCO_3EV3);
526
527 if (hdev->features[5] & LMP_EDR_3S_ESCO)
528 hdev->esco_type |= (ESCO_2EV5 | ESCO_3EV5);
529
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200530 BT_DBG("%s features 0x%.2x%.2x%.2x%.2x%.2x%.2x%.2x%.2x", hdev->name,
Gustavo Padovan807deac2012-05-17 00:36:24 -0300531 hdev->features[0], hdev->features[1],
532 hdev->features[2], hdev->features[3],
533 hdev->features[4], hdev->features[5],
534 hdev->features[6], hdev->features[7]);
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200535}
536
Andre Guedes971e3a42011-06-30 19:20:52 -0300537static void hci_cc_read_local_ext_features(struct hci_dev *hdev,
Gustavo Padovan807deac2012-05-17 00:36:24 -0300538 struct sk_buff *skb)
Andre Guedes971e3a42011-06-30 19:20:52 -0300539{
540 struct hci_rp_read_local_ext_features *rp = (void *) skb->data;
541
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +0300542 BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
Andre Guedes971e3a42011-06-30 19:20:52 -0300543
544 if (rp->status)
Johan Hedberg42c6b122013-03-05 20:37:49 +0200545 return;
Andre Guedes971e3a42011-06-30 19:20:52 -0300546
Andre Guedesb5b32b62011-12-30 10:34:04 -0300547 switch (rp->page) {
548 case 0:
549 memcpy(hdev->features, rp->features, 8);
550 break;
551 case 1:
552 memcpy(hdev->host_features, rp->features, 8);
553 break;
554 }
Andre Guedes971e3a42011-06-30 19:20:52 -0300555}
556
Andrei Emeltchenko1e89cff2011-11-24 14:52:02 +0200557static void hci_cc_read_flow_control_mode(struct hci_dev *hdev,
Gustavo Padovan807deac2012-05-17 00:36:24 -0300558 struct sk_buff *skb)
Andrei Emeltchenko1e89cff2011-11-24 14:52:02 +0200559{
560 struct hci_rp_read_flow_control_mode *rp = (void *) skb->data;
561
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +0300562 BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
Andrei Emeltchenko1e89cff2011-11-24 14:52:02 +0200563
Johan Hedberg42c6b122013-03-05 20:37:49 +0200564 if (!rp->status)
565 hdev->flow_ctl_mode = rp->mode;
Andrei Emeltchenko1e89cff2011-11-24 14:52:02 +0200566}
567
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200568static void hci_cc_read_buffer_size(struct hci_dev *hdev, struct sk_buff *skb)
569{
570 struct hci_rp_read_buffer_size *rp = (void *) skb->data;
571
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +0300572 BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200573
574 if (rp->status)
575 return;
576
577 hdev->acl_mtu = __le16_to_cpu(rp->acl_mtu);
578 hdev->sco_mtu = rp->sco_mtu;
579 hdev->acl_pkts = __le16_to_cpu(rp->acl_max_pkt);
580 hdev->sco_pkts = __le16_to_cpu(rp->sco_max_pkt);
581
582 if (test_bit(HCI_QUIRK_FIXUP_BUFFER_SIZE, &hdev->quirks)) {
583 hdev->sco_mtu = 64;
584 hdev->sco_pkts = 8;
585 }
586
587 hdev->acl_cnt = hdev->acl_pkts;
588 hdev->sco_cnt = hdev->sco_pkts;
589
Gustavo Padovan807deac2012-05-17 00:36:24 -0300590 BT_DBG("%s acl mtu %d:%d sco mtu %d:%d", hdev->name, hdev->acl_mtu,
591 hdev->acl_pkts, hdev->sco_mtu, hdev->sco_pkts);
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200592}
593
594static void hci_cc_read_bd_addr(struct hci_dev *hdev, struct sk_buff *skb)
595{
596 struct hci_rp_read_bd_addr *rp = (void *) skb->data;
597
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +0300598 BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200599
600 if (!rp->status)
601 bacpy(&hdev->bdaddr, &rp->bdaddr);
Johan Hedberg23bb5762010-12-21 23:01:27 +0200602}
603
Johan Hedbergf332ec62013-03-15 17:07:11 -0500604static void hci_cc_read_page_scan_activity(struct hci_dev *hdev,
605 struct sk_buff *skb)
606{
607 struct hci_rp_read_page_scan_activity *rp = (void *) skb->data;
608
609 BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
610
611 if (test_bit(HCI_INIT, &hdev->flags) && !rp->status) {
612 hdev->page_scan_interval = __le16_to_cpu(rp->interval);
613 hdev->page_scan_window = __le16_to_cpu(rp->window);
614 }
615}
616
617static void hci_cc_read_page_scan_type(struct hci_dev *hdev,
618 struct sk_buff *skb)
619{
620 struct hci_rp_read_page_scan_type *rp = (void *) skb->data;
621
622 BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
623
624 if (test_bit(HCI_INIT, &hdev->flags) && !rp->status)
625 hdev->page_scan_type = rp->type;
626}
627
Andrei Emeltchenko350ee4c2011-12-07 15:56:51 +0200628static void hci_cc_read_data_block_size(struct hci_dev *hdev,
Gustavo Padovan807deac2012-05-17 00:36:24 -0300629 struct sk_buff *skb)
Andrei Emeltchenko350ee4c2011-12-07 15:56:51 +0200630{
631 struct hci_rp_read_data_block_size *rp = (void *) skb->data;
632
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +0300633 BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
Andrei Emeltchenko350ee4c2011-12-07 15:56:51 +0200634
635 if (rp->status)
636 return;
637
638 hdev->block_mtu = __le16_to_cpu(rp->max_acl_len);
639 hdev->block_len = __le16_to_cpu(rp->block_len);
640 hdev->num_blocks = __le16_to_cpu(rp->num_blocks);
641
642 hdev->block_cnt = hdev->num_blocks;
643
644 BT_DBG("%s blk mtu %d cnt %d len %d", hdev->name, hdev->block_mtu,
Gustavo Padovan807deac2012-05-17 00:36:24 -0300645 hdev->block_cnt, hdev->block_len);
Andrei Emeltchenko350ee4c2011-12-07 15:56:51 +0200646}
647
Andrei Emeltchenko928abaa2011-10-12 10:53:57 +0300648static void hci_cc_read_local_amp_info(struct hci_dev *hdev,
Gustavo Padovan807deac2012-05-17 00:36:24 -0300649 struct sk_buff *skb)
Andrei Emeltchenko928abaa2011-10-12 10:53:57 +0300650{
651 struct hci_rp_read_local_amp_info *rp = (void *) skb->data;
652
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +0300653 BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
Andrei Emeltchenko928abaa2011-10-12 10:53:57 +0300654
655 if (rp->status)
Andrei Emeltchenko8e2a0d92012-09-27 17:26:08 +0300656 goto a2mp_rsp;
Andrei Emeltchenko928abaa2011-10-12 10:53:57 +0300657
658 hdev->amp_status = rp->amp_status;
659 hdev->amp_total_bw = __le32_to_cpu(rp->total_bw);
660 hdev->amp_max_bw = __le32_to_cpu(rp->max_bw);
661 hdev->amp_min_latency = __le32_to_cpu(rp->min_latency);
662 hdev->amp_max_pdu = __le32_to_cpu(rp->max_pdu);
663 hdev->amp_type = rp->amp_type;
664 hdev->amp_pal_cap = __le16_to_cpu(rp->pal_cap);
665 hdev->amp_assoc_size = __le16_to_cpu(rp->max_assoc_size);
666 hdev->amp_be_flush_to = __le32_to_cpu(rp->be_flush_to);
667 hdev->amp_max_flush_to = __le32_to_cpu(rp->max_flush_to);
668
Andrei Emeltchenko8e2a0d92012-09-27 17:26:08 +0300669a2mp_rsp:
670 a2mp_send_getinfo_rsp(hdev);
Andrei Emeltchenko928abaa2011-10-12 10:53:57 +0300671}
672
Andrei Emeltchenko903e4542012-09-27 17:26:09 +0300673static void hci_cc_read_local_amp_assoc(struct hci_dev *hdev,
674 struct sk_buff *skb)
675{
676 struct hci_rp_read_local_amp_assoc *rp = (void *) skb->data;
677 struct amp_assoc *assoc = &hdev->loc_assoc;
678 size_t rem_len, frag_len;
679
680 BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
681
682 if (rp->status)
683 goto a2mp_rsp;
684
685 frag_len = skb->len - sizeof(*rp);
686 rem_len = __le16_to_cpu(rp->rem_len);
687
688 if (rem_len > frag_len) {
Andrei Emeltchenko2e430be32012-09-28 14:44:23 +0300689 BT_DBG("frag_len %zu rem_len %zu", frag_len, rem_len);
Andrei Emeltchenko903e4542012-09-27 17:26:09 +0300690
691 memcpy(assoc->data + assoc->offset, rp->frag, frag_len);
692 assoc->offset += frag_len;
693
694 /* Read other fragments */
695 amp_read_loc_assoc_frag(hdev, rp->phy_handle);
696
697 return;
698 }
699
700 memcpy(assoc->data + assoc->offset, rp->frag, rem_len);
701 assoc->len = assoc->offset + rem_len;
702 assoc->offset = 0;
703
704a2mp_rsp:
705 /* Send A2MP Rsp when all fragments are received */
706 a2mp_send_getampassoc_rsp(hdev, rp->status);
Andrei Emeltchenko9495b2e2012-09-27 17:26:22 +0300707 a2mp_send_create_phy_link_req(hdev, rp->status);
Andrei Emeltchenko903e4542012-09-27 17:26:09 +0300708}
709
Johan Hedbergd5859e22011-01-25 01:19:58 +0200710static void hci_cc_read_inq_rsp_tx_power(struct hci_dev *hdev,
Gustavo Padovan807deac2012-05-17 00:36:24 -0300711 struct sk_buff *skb)
Johan Hedbergd5859e22011-01-25 01:19:58 +0200712{
Marcel Holtmann91c4e9b2012-03-11 19:27:21 -0700713 struct hci_rp_read_inq_rsp_tx_power *rp = (void *) skb->data;
Johan Hedbergd5859e22011-01-25 01:19:58 +0200714
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +0300715 BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
Johan Hedbergd5859e22011-01-25 01:19:58 +0200716
Marcel Holtmann91c4e9b2012-03-11 19:27:21 -0700717 if (!rp->status)
718 hdev->inq_tx_power = rp->tx_power;
Johan Hedbergd5859e22011-01-25 01:19:58 +0200719}
720
Johan Hedberg980e1a52011-01-22 06:10:07 +0200721static void hci_cc_pin_code_reply(struct hci_dev *hdev, struct sk_buff *skb)
722{
723 struct hci_rp_pin_code_reply *rp = (void *) skb->data;
724 struct hci_cp_pin_code_reply *cp;
725 struct hci_conn *conn;
726
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +0300727 BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
Johan Hedberg980e1a52011-01-22 06:10:07 +0200728
Johan Hedberg56e5cb82011-11-08 20:40:16 +0200729 hci_dev_lock(hdev);
730
Johan Hedberga8b2d5c2012-01-08 23:11:15 +0200731 if (test_bit(HCI_MGMT, &hdev->dev_flags))
Johan Hedberg744cf192011-11-08 20:40:14 +0200732 mgmt_pin_code_reply_complete(hdev, &rp->bdaddr, rp->status);
Johan Hedberg980e1a52011-01-22 06:10:07 +0200733
Mikel Astizfa1bd912012-08-09 09:52:29 +0200734 if (rp->status)
Johan Hedberg56e5cb82011-11-08 20:40:16 +0200735 goto unlock;
Johan Hedberg980e1a52011-01-22 06:10:07 +0200736
737 cp = hci_sent_cmd_data(hdev, HCI_OP_PIN_CODE_REPLY);
738 if (!cp)
Johan Hedberg56e5cb82011-11-08 20:40:16 +0200739 goto unlock;
Johan Hedberg980e1a52011-01-22 06:10:07 +0200740
741 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &cp->bdaddr);
742 if (conn)
743 conn->pin_length = cp->pin_len;
Johan Hedberg56e5cb82011-11-08 20:40:16 +0200744
745unlock:
746 hci_dev_unlock(hdev);
Johan Hedberg980e1a52011-01-22 06:10:07 +0200747}
748
749static void hci_cc_pin_code_neg_reply(struct hci_dev *hdev, struct sk_buff *skb)
750{
751 struct hci_rp_pin_code_neg_reply *rp = (void *) skb->data;
752
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +0300753 BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
Johan Hedberg980e1a52011-01-22 06:10:07 +0200754
Johan Hedberg56e5cb82011-11-08 20:40:16 +0200755 hci_dev_lock(hdev);
756
Johan Hedberga8b2d5c2012-01-08 23:11:15 +0200757 if (test_bit(HCI_MGMT, &hdev->dev_flags))
Johan Hedberg744cf192011-11-08 20:40:14 +0200758 mgmt_pin_code_neg_reply_complete(hdev, &rp->bdaddr,
Gustavo Padovan807deac2012-05-17 00:36:24 -0300759 rp->status);
Johan Hedberg56e5cb82011-11-08 20:40:16 +0200760
761 hci_dev_unlock(hdev);
Johan Hedberg980e1a52011-01-22 06:10:07 +0200762}
Johan Hedberg56e5cb82011-11-08 20:40:16 +0200763
Ville Tervo6ed58ec2011-02-10 22:38:48 -0300764static void hci_cc_le_read_buffer_size(struct hci_dev *hdev,
765 struct sk_buff *skb)
766{
767 struct hci_rp_le_read_buffer_size *rp = (void *) skb->data;
768
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +0300769 BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
Ville Tervo6ed58ec2011-02-10 22:38:48 -0300770
771 if (rp->status)
772 return;
773
774 hdev->le_mtu = __le16_to_cpu(rp->le_mtu);
775 hdev->le_pkts = rp->le_max_pkt;
776
777 hdev->le_cnt = hdev->le_pkts;
778
779 BT_DBG("%s le mtu %d:%d", hdev->name, hdev->le_mtu, hdev->le_pkts);
Ville Tervo6ed58ec2011-02-10 22:38:48 -0300780}
Johan Hedberg980e1a52011-01-22 06:10:07 +0200781
Johan Hedberg60e77322013-01-22 14:01:59 +0200782static void hci_cc_le_read_local_features(struct hci_dev *hdev,
783 struct sk_buff *skb)
784{
785 struct hci_rp_le_read_local_features *rp = (void *) skb->data;
786
787 BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
788
789 if (!rp->status)
790 memcpy(hdev->le_features, rp->features, 8);
Johan Hedberg60e77322013-01-22 14:01:59 +0200791}
792
Johan Hedberg8fa19092012-10-19 20:57:49 +0300793static void hci_cc_le_read_adv_tx_power(struct hci_dev *hdev,
794 struct sk_buff *skb)
795{
796 struct hci_rp_le_read_adv_tx_power *rp = (void *) skb->data;
797
798 BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
799
Johan Hedberg04b4edc2013-03-15 17:07:01 -0500800 if (!rp->status)
Johan Hedberg8fa19092012-10-19 20:57:49 +0300801 hdev->adv_tx_power = rp->tx_power;
Johan Hedberg8fa19092012-10-19 20:57:49 +0300802}
803
Johan Hedberga5c29682011-02-19 12:05:57 -0300804static void hci_cc_user_confirm_reply(struct hci_dev *hdev, struct sk_buff *skb)
805{
806 struct hci_rp_user_confirm_reply *rp = (void *) skb->data;
807
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +0300808 BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
Johan Hedberga5c29682011-02-19 12:05:57 -0300809
Johan Hedberg56e5cb82011-11-08 20:40:16 +0200810 hci_dev_lock(hdev);
811
Johan Hedberga8b2d5c2012-01-08 23:11:15 +0200812 if (test_bit(HCI_MGMT, &hdev->dev_flags))
Gustavo F. Padovan04124682012-03-08 01:25:00 -0300813 mgmt_user_confirm_reply_complete(hdev, &rp->bdaddr, ACL_LINK, 0,
814 rp->status);
Johan Hedberg56e5cb82011-11-08 20:40:16 +0200815
816 hci_dev_unlock(hdev);
Johan Hedberga5c29682011-02-19 12:05:57 -0300817}
818
819static void hci_cc_user_confirm_neg_reply(struct hci_dev *hdev,
Gustavo Padovan807deac2012-05-17 00:36:24 -0300820 struct sk_buff *skb)
Johan Hedberga5c29682011-02-19 12:05:57 -0300821{
822 struct hci_rp_user_confirm_reply *rp = (void *) skb->data;
823
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +0300824 BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
Johan Hedberga5c29682011-02-19 12:05:57 -0300825
Johan Hedberg56e5cb82011-11-08 20:40:16 +0200826 hci_dev_lock(hdev);
827
Johan Hedberga8b2d5c2012-01-08 23:11:15 +0200828 if (test_bit(HCI_MGMT, &hdev->dev_flags))
Johan Hedberg744cf192011-11-08 20:40:14 +0200829 mgmt_user_confirm_neg_reply_complete(hdev, &rp->bdaddr,
Gustavo F. Padovan04124682012-03-08 01:25:00 -0300830 ACL_LINK, 0, rp->status);
Johan Hedberg56e5cb82011-11-08 20:40:16 +0200831
832 hci_dev_unlock(hdev);
Johan Hedberga5c29682011-02-19 12:05:57 -0300833}
834
Brian Gix1143d452011-11-23 08:28:34 -0800835static void hci_cc_user_passkey_reply(struct hci_dev *hdev, struct sk_buff *skb)
836{
837 struct hci_rp_user_confirm_reply *rp = (void *) skb->data;
838
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +0300839 BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
Brian Gix1143d452011-11-23 08:28:34 -0800840
841 hci_dev_lock(hdev);
842
Johan Hedberga8b2d5c2012-01-08 23:11:15 +0200843 if (test_bit(HCI_MGMT, &hdev->dev_flags))
Johan Hedberg272d90d2012-02-09 15:26:12 +0200844 mgmt_user_passkey_reply_complete(hdev, &rp->bdaddr, ACL_LINK,
Gustavo F. Padovan04124682012-03-08 01:25:00 -0300845 0, rp->status);
Brian Gix1143d452011-11-23 08:28:34 -0800846
847 hci_dev_unlock(hdev);
848}
849
850static void hci_cc_user_passkey_neg_reply(struct hci_dev *hdev,
Gustavo Padovan807deac2012-05-17 00:36:24 -0300851 struct sk_buff *skb)
Brian Gix1143d452011-11-23 08:28:34 -0800852{
853 struct hci_rp_user_confirm_reply *rp = (void *) skb->data;
854
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +0300855 BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
Brian Gix1143d452011-11-23 08:28:34 -0800856
857 hci_dev_lock(hdev);
858
Johan Hedberga8b2d5c2012-01-08 23:11:15 +0200859 if (test_bit(HCI_MGMT, &hdev->dev_flags))
Brian Gix1143d452011-11-23 08:28:34 -0800860 mgmt_user_passkey_neg_reply_complete(hdev, &rp->bdaddr,
Gustavo F. Padovan04124682012-03-08 01:25:00 -0300861 ACL_LINK, 0, rp->status);
Brian Gix1143d452011-11-23 08:28:34 -0800862
863 hci_dev_unlock(hdev);
864}
865
Szymon Jancc35938b2011-03-22 13:12:21 +0100866static void hci_cc_read_local_oob_data_reply(struct hci_dev *hdev,
Gustavo Padovan807deac2012-05-17 00:36:24 -0300867 struct sk_buff *skb)
Szymon Jancc35938b2011-03-22 13:12:21 +0100868{
869 struct hci_rp_read_local_oob_data *rp = (void *) skb->data;
870
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +0300871 BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
Szymon Jancc35938b2011-03-22 13:12:21 +0100872
Johan Hedberg56e5cb82011-11-08 20:40:16 +0200873 hci_dev_lock(hdev);
Johan Hedberg744cf192011-11-08 20:40:14 +0200874 mgmt_read_local_oob_data_reply_complete(hdev, rp->hash,
Szymon Jancc35938b2011-03-22 13:12:21 +0100875 rp->randomizer, rp->status);
Johan Hedberg56e5cb82011-11-08 20:40:16 +0200876 hci_dev_unlock(hdev);
Szymon Jancc35938b2011-03-22 13:12:21 +0100877}
878
Johan Hedbergc1d5dc42012-11-08 01:23:01 +0100879static void hci_cc_le_set_adv_enable(struct hci_dev *hdev, struct sk_buff *skb)
880{
881 __u8 *sent, status = *((__u8 *) skb->data);
882
883 BT_DBG("%s status 0x%2.2x", hdev->name, status);
884
885 sent = hci_sent_cmd_data(hdev, HCI_OP_LE_SET_ADV_ENABLE);
886 if (!sent)
887 return;
888
889 hci_dev_lock(hdev);
890
891 if (!status) {
892 if (*sent)
893 set_bit(HCI_LE_PERIPHERAL, &hdev->dev_flags);
894 else
895 clear_bit(HCI_LE_PERIPHERAL, &hdev->dev_flags);
896 }
897
Johan Hedberg04b4edc2013-03-15 17:07:01 -0500898 if (!test_bit(HCI_INIT, &hdev->flags)) {
899 struct hci_request req;
Johan Hedbergc1d5dc42012-11-08 01:23:01 +0100900
Johan Hedberg04b4edc2013-03-15 17:07:01 -0500901 hci_req_init(&req, hdev);
902 hci_update_ad(&req);
903 hci_req_run(&req, NULL);
904 }
905
906 hci_dev_unlock(hdev);
Johan Hedbergc1d5dc42012-11-08 01:23:01 +0100907}
908
Andre Guedes07f7fa52011-12-02 21:13:31 +0900909static void hci_cc_le_set_scan_param(struct hci_dev *hdev, struct sk_buff *skb)
910{
911 __u8 status = *((__u8 *) skb->data);
912
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +0300913 BT_DBG("%s status 0x%2.2x", hdev->name, status);
Andre Guedes7ba8b4b2012-02-03 17:47:59 -0300914
Andre Guedes3fd24152012-02-03 17:48:01 -0300915 if (status) {
916 hci_dev_lock(hdev);
917 mgmt_start_discovery_failed(hdev, status);
918 hci_dev_unlock(hdev);
919 return;
920 }
Andre Guedes07f7fa52011-12-02 21:13:31 +0900921}
922
Andre Guedeseb9d91f2011-05-26 16:23:52 -0300923static void hci_cc_le_set_scan_enable(struct hci_dev *hdev,
Gustavo Padovan807deac2012-05-17 00:36:24 -0300924 struct sk_buff *skb)
Andre Guedeseb9d91f2011-05-26 16:23:52 -0300925{
926 struct hci_cp_le_set_scan_enable *cp;
927 __u8 status = *((__u8 *) skb->data);
928
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +0300929 BT_DBG("%s status 0x%2.2x", hdev->name, status);
Andre Guedeseb9d91f2011-05-26 16:23:52 -0300930
Andre Guedeseb9d91f2011-05-26 16:23:52 -0300931 cp = hci_sent_cmd_data(hdev, HCI_OP_LE_SET_SCAN_ENABLE);
932 if (!cp)
933 return;
934
Andrei Emeltchenko68a8aea2011-12-19 16:14:18 +0200935 switch (cp->enable) {
936 case LE_SCANNING_ENABLED:
Andre Guedes3fd24152012-02-03 17:48:01 -0300937 if (status) {
938 hci_dev_lock(hdev);
939 mgmt_start_discovery_failed(hdev, status);
940 hci_dev_unlock(hdev);
Andre Guedes7ba8b4b2012-02-03 17:47:59 -0300941 return;
Andre Guedes3fd24152012-02-03 17:48:01 -0300942 }
Andre Guedes7ba8b4b2012-02-03 17:47:59 -0300943
Andre Guedesd23264a2011-11-25 20:53:38 -0300944 set_bit(HCI_LE_SCAN, &hdev->dev_flags);
945
Andre Guedesa8f13c82011-09-09 18:56:24 -0300946 hci_dev_lock(hdev);
Andre Guedes343f9352012-02-17 20:39:37 -0300947 hci_discovery_set_state(hdev, DISCOVERY_FINDING);
Andre Guedesa8f13c82011-09-09 18:56:24 -0300948 hci_dev_unlock(hdev);
Andrei Emeltchenko68a8aea2011-12-19 16:14:18 +0200949 break;
950
951 case LE_SCANNING_DISABLED:
Andre Guedesc9ecc482012-03-15 16:52:08 -0300952 if (status) {
953 hci_dev_lock(hdev);
954 mgmt_stop_discovery_failed(hdev, status);
955 hci_dev_unlock(hdev);
Andre Guedes7ba8b4b2012-02-03 17:47:59 -0300956 return;
Andre Guedesc9ecc482012-03-15 16:52:08 -0300957 }
Andre Guedes7ba8b4b2012-02-03 17:47:59 -0300958
Andre Guedesd23264a2011-11-25 20:53:38 -0300959 clear_bit(HCI_LE_SCAN, &hdev->dev_flags);
960
Andre Guedesbc3dd332012-03-06 19:37:06 -0300961 if (hdev->discovery.type == DISCOV_TYPE_INTERLEAVED &&
962 hdev->discovery.state == DISCOVERY_FINDING) {
Andre Guedes5e0452c2012-02-17 20:39:38 -0300963 mgmt_interleaved_discovery(hdev);
964 } else {
965 hci_dev_lock(hdev);
966 hci_discovery_set_state(hdev, DISCOVERY_STOPPED);
967 hci_dev_unlock(hdev);
968 }
969
Andrei Emeltchenko68a8aea2011-12-19 16:14:18 +0200970 break;
971
972 default:
973 BT_ERR("Used reserved LE_Scan_Enable param %d", cp->enable);
974 break;
Andre Guedes35815082011-05-26 16:23:53 -0300975 }
Andre Guedeseb9d91f2011-05-26 16:23:52 -0300976}
977
Johan Hedbergcf1d0812013-01-22 14:02:00 +0200978static void hci_cc_le_read_white_list_size(struct hci_dev *hdev,
979 struct sk_buff *skb)
980{
981 struct hci_rp_le_read_white_list_size *rp = (void *) skb->data;
982
983 BT_DBG("%s status 0x%2.2x size %u", hdev->name, rp->status, rp->size);
984
985 if (!rp->status)
986 hdev->le_white_list_size = rp->size;
Johan Hedbergcf1d0812013-01-22 14:02:00 +0200987}
988
Johan Hedberg9b008c02013-01-22 14:02:01 +0200989static void hci_cc_le_read_supported_states(struct hci_dev *hdev,
990 struct sk_buff *skb)
991{
992 struct hci_rp_le_read_supported_states *rp = (void *) skb->data;
993
994 BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
995
996 if (!rp->status)
997 memcpy(hdev->le_states, rp->le_states, 8);
Johan Hedberg9b008c02013-01-22 14:02:01 +0200998}
999
Gustavo Padovan6039aa72012-05-23 04:04:18 -03001000static void hci_cc_write_le_host_supported(struct hci_dev *hdev,
1001 struct sk_buff *skb)
Andre Guedesf9b49302011-06-30 19:20:53 -03001002{
Johan Hedberg06199cf2012-02-22 16:37:11 +02001003 struct hci_cp_write_le_host_supported *sent;
Andre Guedesf9b49302011-06-30 19:20:53 -03001004 __u8 status = *((__u8 *) skb->data);
1005
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +03001006 BT_DBG("%s status 0x%2.2x", hdev->name, status);
Andre Guedesf9b49302011-06-30 19:20:53 -03001007
Johan Hedberg06199cf2012-02-22 16:37:11 +02001008 sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_LE_HOST_SUPPORTED);
Johan Hedberg8f984df2012-02-28 01:07:22 +02001009 if (!sent)
Andre Guedesf9b49302011-06-30 19:20:53 -03001010 return;
1011
Johan Hedberg8f984df2012-02-28 01:07:22 +02001012 if (!status) {
1013 if (sent->le)
1014 hdev->host_features[0] |= LMP_HOST_LE;
1015 else
1016 hdev->host_features[0] &= ~LMP_HOST_LE;
Johan Hedberg53b2caa2012-10-24 21:11:59 +03001017
1018 if (sent->simul)
1019 hdev->host_features[0] |= LMP_HOST_LE_BREDR;
1020 else
1021 hdev->host_features[0] &= ~LMP_HOST_LE_BREDR;
Johan Hedberg8f984df2012-02-28 01:07:22 +02001022 }
1023
1024 if (test_bit(HCI_MGMT, &hdev->dev_flags) &&
Gustavo Padovan807deac2012-05-17 00:36:24 -03001025 !test_bit(HCI_INIT, &hdev->flags))
Johan Hedberg8f984df2012-02-28 01:07:22 +02001026 mgmt_le_enable_complete(hdev, sent->le, status);
Andre Guedesf9b49302011-06-30 19:20:53 -03001027}
1028
Andrei Emeltchenko93c284e2012-09-27 17:26:20 +03001029static void hci_cc_write_remote_amp_assoc(struct hci_dev *hdev,
1030 struct sk_buff *skb)
1031{
1032 struct hci_rp_write_remote_amp_assoc *rp = (void *) skb->data;
1033
1034 BT_DBG("%s status 0x%2.2x phy_handle 0x%2.2x",
1035 hdev->name, rp->status, rp->phy_handle);
1036
1037 if (rp->status)
1038 return;
1039
1040 amp_write_rem_assoc_continue(hdev, rp->phy_handle);
1041}
1042
Gustavo Padovan6039aa72012-05-23 04:04:18 -03001043static void hci_cs_inquiry(struct hci_dev *hdev, __u8 status)
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001044{
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +03001045 BT_DBG("%s status 0x%2.2x", hdev->name, status);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001046
1047 if (status) {
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001048 hci_conn_check_pending(hdev);
Johan Hedberg56e5cb82011-11-08 20:40:16 +02001049 hci_dev_lock(hdev);
Johan Hedberga8b2d5c2012-01-08 23:11:15 +02001050 if (test_bit(HCI_MGMT, &hdev->dev_flags))
Andre Guedes7a135102011-11-09 17:14:25 -03001051 mgmt_start_discovery_failed(hdev, status);
Johan Hedberg56e5cb82011-11-08 20:40:16 +02001052 hci_dev_unlock(hdev);
Johan Hedberg314b2382011-04-27 10:29:57 -04001053 return;
1054 }
1055
Andre Guedes89352e72011-11-04 14:16:53 -03001056 set_bit(HCI_INQUIRY, &hdev->flags);
1057
Johan Hedberg56e5cb82011-11-08 20:40:16 +02001058 hci_dev_lock(hdev);
Andre Guedes343f9352012-02-17 20:39:37 -03001059 hci_discovery_set_state(hdev, DISCOVERY_FINDING);
Johan Hedberg56e5cb82011-11-08 20:40:16 +02001060 hci_dev_unlock(hdev);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001061}
1062
Gustavo Padovan6039aa72012-05-23 04:04:18 -03001063static void hci_cs_create_conn(struct hci_dev *hdev, __u8 status)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001064{
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001065 struct hci_cp_create_conn *cp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001066 struct hci_conn *conn;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001067
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +03001068 BT_DBG("%s status 0x%2.2x", hdev->name, status);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001069
1070 cp = hci_sent_cmd_data(hdev, HCI_OP_CREATE_CONN);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001071 if (!cp)
1072 return;
1073
1074 hci_dev_lock(hdev);
1075
1076 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &cp->bdaddr);
1077
Andrei Emeltchenko6ed93dc2012-09-25 12:49:43 +03001078 BT_DBG("%s bdaddr %pMR hcon %p", hdev->name, &cp->bdaddr, conn);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001079
1080 if (status) {
1081 if (conn && conn->state == BT_CONNECT) {
Marcel Holtmann4c67bc72006-10-15 17:30:56 +02001082 if (status != 0x0c || conn->attempt > 2) {
1083 conn->state = BT_CLOSED;
1084 hci_proto_connect_cfm(conn, status);
1085 hci_conn_del(conn);
1086 } else
1087 conn->state = BT_CONNECT2;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001088 }
1089 } else {
1090 if (!conn) {
1091 conn = hci_conn_add(hdev, ACL_LINK, &cp->bdaddr);
1092 if (conn) {
Johan Hedberga0c808b2012-01-16 09:49:58 +02001093 conn->out = true;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001094 conn->link_mode |= HCI_LM_MASTER;
1095 } else
Gustavo F. Padovan893ef972010-07-18 15:13:37 -03001096 BT_ERR("No memory for new connection");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001097 }
1098 }
1099
1100 hci_dev_unlock(hdev);
1101}
1102
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001103static void hci_cs_add_sco(struct hci_dev *hdev, __u8 status)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001104{
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001105 struct hci_cp_add_sco *cp;
1106 struct hci_conn *acl, *sco;
1107 __u16 handle;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001108
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +03001109 BT_DBG("%s status 0x%2.2x", hdev->name, status);
Marcel Holtmannb6a0dc82007-10-20 14:55:10 +02001110
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001111 if (!status)
1112 return;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001113
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001114 cp = hci_sent_cmd_data(hdev, HCI_OP_ADD_SCO);
1115 if (!cp)
1116 return;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001117
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001118 handle = __le16_to_cpu(cp->handle);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001119
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +03001120 BT_DBG("%s handle 0x%4.4x", hdev->name, handle);
Marcel Holtmann6bd57412006-11-18 22:14:22 +01001121
1122 hci_dev_lock(hdev);
1123
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001124 acl = hci_conn_hash_lookup_handle(hdev, handle);
Andrei Emeltchenko5a08ecc2011-01-11 17:20:20 +02001125 if (acl) {
1126 sco = acl->link;
1127 if (sco) {
1128 sco->state = BT_CLOSED;
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001129
Andrei Emeltchenko5a08ecc2011-01-11 17:20:20 +02001130 hci_proto_connect_cfm(sco, status);
1131 hci_conn_del(sco);
1132 }
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001133 }
Marcel Holtmann6bd57412006-11-18 22:14:22 +01001134
1135 hci_dev_unlock(hdev);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001136}
1137
Marcel Holtmannf8558552008-07-14 20:13:49 +02001138static void hci_cs_auth_requested(struct hci_dev *hdev, __u8 status)
1139{
1140 struct hci_cp_auth_requested *cp;
1141 struct hci_conn *conn;
1142
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +03001143 BT_DBG("%s status 0x%2.2x", hdev->name, status);
Marcel Holtmannf8558552008-07-14 20:13:49 +02001144
1145 if (!status)
1146 return;
1147
1148 cp = hci_sent_cmd_data(hdev, HCI_OP_AUTH_REQUESTED);
1149 if (!cp)
1150 return;
1151
1152 hci_dev_lock(hdev);
1153
1154 conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(cp->handle));
1155 if (conn) {
1156 if (conn->state == BT_CONFIG) {
1157 hci_proto_connect_cfm(conn, status);
1158 hci_conn_put(conn);
1159 }
1160 }
1161
1162 hci_dev_unlock(hdev);
1163}
1164
1165static void hci_cs_set_conn_encrypt(struct hci_dev *hdev, __u8 status)
1166{
1167 struct hci_cp_set_conn_encrypt *cp;
1168 struct hci_conn *conn;
1169
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +03001170 BT_DBG("%s status 0x%2.2x", hdev->name, status);
Marcel Holtmannf8558552008-07-14 20:13:49 +02001171
1172 if (!status)
1173 return;
1174
1175 cp = hci_sent_cmd_data(hdev, HCI_OP_SET_CONN_ENCRYPT);
1176 if (!cp)
1177 return;
1178
1179 hci_dev_lock(hdev);
1180
1181 conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(cp->handle));
1182 if (conn) {
1183 if (conn->state == BT_CONFIG) {
1184 hci_proto_connect_cfm(conn, status);
1185 hci_conn_put(conn);
1186 }
1187 }
1188
1189 hci_dev_unlock(hdev);
1190}
1191
Johan Hedberg127178d2010-11-18 22:22:29 +02001192static int hci_outgoing_auth_needed(struct hci_dev *hdev,
Gustavo Padovan807deac2012-05-17 00:36:24 -03001193 struct hci_conn *conn)
Johan Hedberg392599b2010-11-18 22:22:28 +02001194{
Johan Hedberg392599b2010-11-18 22:22:28 +02001195 if (conn->state != BT_CONFIG || !conn->out)
1196 return 0;
1197
Johan Hedberg765c2a92011-01-19 12:06:52 +05301198 if (conn->pending_sec_level == BT_SECURITY_SDP)
Johan Hedberg392599b2010-11-18 22:22:28 +02001199 return 0;
1200
1201 /* Only request authentication for SSP connections or non-SSP
Vinicius Costa Gomese9bf2bf2011-09-02 14:51:20 -03001202 * devices with sec_level HIGH or if MITM protection is requested */
Gustavo Padovan807deac2012-05-17 00:36:24 -03001203 if (!hci_conn_ssp_enabled(conn) && !(conn->auth_type & 0x01) &&
1204 conn->pending_sec_level != BT_SECURITY_HIGH)
Johan Hedberg392599b2010-11-18 22:22:28 +02001205 return 0;
1206
Johan Hedberg392599b2010-11-18 22:22:28 +02001207 return 1;
1208}
1209
Gustavo Padovan6039aa72012-05-23 04:04:18 -03001210static int hci_resolve_name(struct hci_dev *hdev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001211 struct inquiry_entry *e)
Johan Hedberg30dc78e2012-01-04 15:44:20 +02001212{
1213 struct hci_cp_remote_name_req cp;
1214
1215 memset(&cp, 0, sizeof(cp));
1216
1217 bacpy(&cp.bdaddr, &e->data.bdaddr);
1218 cp.pscan_rep_mode = e->data.pscan_rep_mode;
1219 cp.pscan_mode = e->data.pscan_mode;
1220 cp.clock_offset = e->data.clock_offset;
1221
1222 return hci_send_cmd(hdev, HCI_OP_REMOTE_NAME_REQ, sizeof(cp), &cp);
1223}
1224
Johan Hedbergb644ba32012-01-17 21:48:47 +02001225static bool hci_resolve_next_name(struct hci_dev *hdev)
Johan Hedberg30dc78e2012-01-04 15:44:20 +02001226{
1227 struct discovery_state *discov = &hdev->discovery;
1228 struct inquiry_entry *e;
1229
Johan Hedbergb644ba32012-01-17 21:48:47 +02001230 if (list_empty(&discov->resolve))
1231 return false;
1232
1233 e = hci_inquiry_cache_lookup_resolve(hdev, BDADDR_ANY, NAME_NEEDED);
Ram Malovanyc8100892012-07-19 10:26:09 +03001234 if (!e)
1235 return false;
1236
Johan Hedbergb644ba32012-01-17 21:48:47 +02001237 if (hci_resolve_name(hdev, e) == 0) {
1238 e->name_state = NAME_PENDING;
1239 return true;
1240 }
1241
1242 return false;
1243}
1244
1245static void hci_check_pending_name(struct hci_dev *hdev, struct hci_conn *conn,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001246 bdaddr_t *bdaddr, u8 *name, u8 name_len)
Johan Hedbergb644ba32012-01-17 21:48:47 +02001247{
1248 struct discovery_state *discov = &hdev->discovery;
1249 struct inquiry_entry *e;
1250
1251 if (conn && !test_and_set_bit(HCI_CONN_MGMT_CONNECTED, &conn->flags))
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001252 mgmt_device_connected(hdev, bdaddr, ACL_LINK, 0x00, 0, name,
1253 name_len, conn->dev_class);
Johan Hedbergb644ba32012-01-17 21:48:47 +02001254
1255 if (discov->state == DISCOVERY_STOPPED)
1256 return;
1257
Johan Hedberg30dc78e2012-01-04 15:44:20 +02001258 if (discov->state == DISCOVERY_STOPPING)
1259 goto discov_complete;
1260
1261 if (discov->state != DISCOVERY_RESOLVING)
1262 return;
1263
1264 e = hci_inquiry_cache_lookup_resolve(hdev, bdaddr, NAME_PENDING);
Ram Malovany7cc83802012-07-19 10:26:10 +03001265 /* If the device was not found in a list of found devices names of which
1266 * are pending. there is no need to continue resolving a next name as it
1267 * will be done upon receiving another Remote Name Request Complete
1268 * Event */
1269 if (!e)
1270 return;
1271
1272 list_del(&e->list);
1273 if (name) {
Johan Hedberg30dc78e2012-01-04 15:44:20 +02001274 e->name_state = NAME_KNOWN;
Ram Malovany7cc83802012-07-19 10:26:10 +03001275 mgmt_remote_name(hdev, bdaddr, ACL_LINK, 0x00,
1276 e->data.rssi, name, name_len);
Ram Malovanyc3e7c0d2012-07-19 10:26:11 +03001277 } else {
1278 e->name_state = NAME_NOT_KNOWN;
Johan Hedberg30dc78e2012-01-04 15:44:20 +02001279 }
1280
Johan Hedbergb644ba32012-01-17 21:48:47 +02001281 if (hci_resolve_next_name(hdev))
Johan Hedberg30dc78e2012-01-04 15:44:20 +02001282 return;
Johan Hedberg30dc78e2012-01-04 15:44:20 +02001283
1284discov_complete:
1285 hci_discovery_set_state(hdev, DISCOVERY_STOPPED);
1286}
1287
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001288static void hci_cs_remote_name_req(struct hci_dev *hdev, __u8 status)
1289{
Johan Hedberg127178d2010-11-18 22:22:29 +02001290 struct hci_cp_remote_name_req *cp;
1291 struct hci_conn *conn;
1292
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +03001293 BT_DBG("%s status 0x%2.2x", hdev->name, status);
Johan Hedberg127178d2010-11-18 22:22:29 +02001294
1295 /* If successful wait for the name req complete event before
1296 * checking for the need to do authentication */
1297 if (!status)
1298 return;
1299
1300 cp = hci_sent_cmd_data(hdev, HCI_OP_REMOTE_NAME_REQ);
1301 if (!cp)
1302 return;
1303
1304 hci_dev_lock(hdev);
1305
1306 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &cp->bdaddr);
Johan Hedbergb644ba32012-01-17 21:48:47 +02001307
1308 if (test_bit(HCI_MGMT, &hdev->dev_flags))
1309 hci_check_pending_name(hdev, conn, &cp->bdaddr, NULL, 0);
1310
Johan Hedberg79c6c702011-04-28 11:28:55 -07001311 if (!conn)
1312 goto unlock;
1313
1314 if (!hci_outgoing_auth_needed(hdev, conn))
1315 goto unlock;
1316
Johan Hedberg51a8efd2012-01-16 06:10:31 +02001317 if (!test_and_set_bit(HCI_CONN_AUTH_PEND, &conn->flags)) {
Johan Hedberg127178d2010-11-18 22:22:29 +02001318 struct hci_cp_auth_requested cp;
1319 cp.handle = __cpu_to_le16(conn->handle);
1320 hci_send_cmd(hdev, HCI_OP_AUTH_REQUESTED, sizeof(cp), &cp);
1321 }
1322
Johan Hedberg79c6c702011-04-28 11:28:55 -07001323unlock:
Johan Hedberg127178d2010-11-18 22:22:29 +02001324 hci_dev_unlock(hdev);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001325}
1326
Marcel Holtmann769be972008-07-14 20:13:49 +02001327static void hci_cs_read_remote_features(struct hci_dev *hdev, __u8 status)
1328{
1329 struct hci_cp_read_remote_features *cp;
1330 struct hci_conn *conn;
1331
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +03001332 BT_DBG("%s status 0x%2.2x", hdev->name, status);
Marcel Holtmann769be972008-07-14 20:13:49 +02001333
1334 if (!status)
1335 return;
1336
1337 cp = hci_sent_cmd_data(hdev, HCI_OP_READ_REMOTE_FEATURES);
1338 if (!cp)
1339 return;
1340
1341 hci_dev_lock(hdev);
1342
1343 conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(cp->handle));
1344 if (conn) {
1345 if (conn->state == BT_CONFIG) {
Marcel Holtmann769be972008-07-14 20:13:49 +02001346 hci_proto_connect_cfm(conn, status);
1347 hci_conn_put(conn);
1348 }
1349 }
1350
1351 hci_dev_unlock(hdev);
1352}
1353
1354static void hci_cs_read_remote_ext_features(struct hci_dev *hdev, __u8 status)
1355{
1356 struct hci_cp_read_remote_ext_features *cp;
1357 struct hci_conn *conn;
1358
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +03001359 BT_DBG("%s status 0x%2.2x", hdev->name, status);
Marcel Holtmann769be972008-07-14 20:13:49 +02001360
1361 if (!status)
1362 return;
1363
1364 cp = hci_sent_cmd_data(hdev, HCI_OP_READ_REMOTE_EXT_FEATURES);
1365 if (!cp)
1366 return;
1367
1368 hci_dev_lock(hdev);
1369
1370 conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(cp->handle));
1371 if (conn) {
1372 if (conn->state == BT_CONFIG) {
Marcel Holtmann769be972008-07-14 20:13:49 +02001373 hci_proto_connect_cfm(conn, status);
1374 hci_conn_put(conn);
1375 }
1376 }
1377
1378 hci_dev_unlock(hdev);
1379}
1380
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001381static void hci_cs_setup_sync_conn(struct hci_dev *hdev, __u8 status)
1382{
Marcel Holtmannb6a0dc82007-10-20 14:55:10 +02001383 struct hci_cp_setup_sync_conn *cp;
1384 struct hci_conn *acl, *sco;
1385 __u16 handle;
1386
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +03001387 BT_DBG("%s status 0x%2.2x", hdev->name, status);
Marcel Holtmannb6a0dc82007-10-20 14:55:10 +02001388
1389 if (!status)
1390 return;
1391
1392 cp = hci_sent_cmd_data(hdev, HCI_OP_SETUP_SYNC_CONN);
1393 if (!cp)
1394 return;
1395
1396 handle = __le16_to_cpu(cp->handle);
1397
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +03001398 BT_DBG("%s handle 0x%4.4x", hdev->name, handle);
Marcel Holtmannb6a0dc82007-10-20 14:55:10 +02001399
1400 hci_dev_lock(hdev);
1401
1402 acl = hci_conn_hash_lookup_handle(hdev, handle);
Andrei Emeltchenko5a08ecc2011-01-11 17:20:20 +02001403 if (acl) {
1404 sco = acl->link;
1405 if (sco) {
1406 sco->state = BT_CLOSED;
Marcel Holtmannb6a0dc82007-10-20 14:55:10 +02001407
Andrei Emeltchenko5a08ecc2011-01-11 17:20:20 +02001408 hci_proto_connect_cfm(sco, status);
1409 hci_conn_del(sco);
1410 }
Marcel Holtmannb6a0dc82007-10-20 14:55:10 +02001411 }
1412
1413 hci_dev_unlock(hdev);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001414}
1415
1416static void hci_cs_sniff_mode(struct hci_dev *hdev, __u8 status)
1417{
1418 struct hci_cp_sniff_mode *cp;
1419 struct hci_conn *conn;
1420
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +03001421 BT_DBG("%s status 0x%2.2x", hdev->name, status);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001422
1423 if (!status)
1424 return;
1425
1426 cp = hci_sent_cmd_data(hdev, HCI_OP_SNIFF_MODE);
1427 if (!cp)
1428 return;
1429
1430 hci_dev_lock(hdev);
1431
1432 conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(cp->handle));
Marcel Holtmanne73439d2010-07-26 10:06:00 -04001433 if (conn) {
Johan Hedberg51a8efd2012-01-16 06:10:31 +02001434 clear_bit(HCI_CONN_MODE_CHANGE_PEND, &conn->flags);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001435
Johan Hedberg51a8efd2012-01-16 06:10:31 +02001436 if (test_and_clear_bit(HCI_CONN_SCO_SETUP_PEND, &conn->flags))
Marcel Holtmanne73439d2010-07-26 10:06:00 -04001437 hci_sco_setup(conn, status);
1438 }
1439
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001440 hci_dev_unlock(hdev);
1441}
1442
1443static void hci_cs_exit_sniff_mode(struct hci_dev *hdev, __u8 status)
1444{
1445 struct hci_cp_exit_sniff_mode *cp;
1446 struct hci_conn *conn;
1447
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +03001448 BT_DBG("%s status 0x%2.2x", hdev->name, status);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001449
1450 if (!status)
1451 return;
1452
1453 cp = hci_sent_cmd_data(hdev, HCI_OP_EXIT_SNIFF_MODE);
1454 if (!cp)
1455 return;
1456
1457 hci_dev_lock(hdev);
1458
1459 conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(cp->handle));
Marcel Holtmanne73439d2010-07-26 10:06:00 -04001460 if (conn) {
Johan Hedberg51a8efd2012-01-16 06:10:31 +02001461 clear_bit(HCI_CONN_MODE_CHANGE_PEND, &conn->flags);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001462
Johan Hedberg51a8efd2012-01-16 06:10:31 +02001463 if (test_and_clear_bit(HCI_CONN_SCO_SETUP_PEND, &conn->flags))
Marcel Holtmanne73439d2010-07-26 10:06:00 -04001464 hci_sco_setup(conn, status);
1465 }
1466
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001467 hci_dev_unlock(hdev);
1468}
1469
Johan Hedberg88c3df12012-02-09 14:27:38 +02001470static void hci_cs_disconnect(struct hci_dev *hdev, u8 status)
1471{
1472 struct hci_cp_disconnect *cp;
1473 struct hci_conn *conn;
1474
1475 if (!status)
1476 return;
1477
1478 cp = hci_sent_cmd_data(hdev, HCI_OP_DISCONNECT);
1479 if (!cp)
1480 return;
1481
1482 hci_dev_lock(hdev);
1483
1484 conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(cp->handle));
1485 if (conn)
1486 mgmt_disconnect_failed(hdev, &conn->dst, conn->type,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001487 conn->dst_type, status);
Johan Hedberg88c3df12012-02-09 14:27:38 +02001488
1489 hci_dev_unlock(hdev);
1490}
1491
Ville Tervofcd89c02011-02-10 22:38:47 -03001492static void hci_cs_le_create_conn(struct hci_dev *hdev, __u8 status)
1493{
Ville Tervofcd89c02011-02-10 22:38:47 -03001494 struct hci_conn *conn;
1495
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +03001496 BT_DBG("%s status 0x%2.2x", hdev->name, status);
Ville Tervofcd89c02011-02-10 22:38:47 -03001497
Ville Tervofcd89c02011-02-10 22:38:47 -03001498 if (status) {
Andre Guedesf00a06a2012-07-27 15:10:13 -03001499 hci_dev_lock(hdev);
Ville Tervofcd89c02011-02-10 22:38:47 -03001500
Andre Guedes0c95ab72012-07-27 15:10:14 -03001501 conn = hci_conn_hash_lookup_state(hdev, LE_LINK, BT_CONNECT);
Andre Guedesf00a06a2012-07-27 15:10:13 -03001502 if (!conn) {
1503 hci_dev_unlock(hdev);
1504 return;
1505 }
1506
Andrei Emeltchenko6ed93dc2012-09-25 12:49:43 +03001507 BT_DBG("%s bdaddr %pMR conn %p", hdev->name, &conn->dst, conn);
Andre Guedesf00a06a2012-07-27 15:10:13 -03001508
1509 conn->state = BT_CLOSED;
Andre Guedes0c95ab72012-07-27 15:10:14 -03001510 mgmt_connect_failed(hdev, &conn->dst, conn->type,
Andre Guedesf00a06a2012-07-27 15:10:13 -03001511 conn->dst_type, status);
1512 hci_proto_connect_cfm(conn, status);
1513 hci_conn_del(conn);
1514
1515 hci_dev_unlock(hdev);
1516 }
Ville Tervofcd89c02011-02-10 22:38:47 -03001517}
1518
Andrei Emeltchenkoa02226d2012-09-27 17:26:19 +03001519static void hci_cs_create_phylink(struct hci_dev *hdev, u8 status)
1520{
Andrei Emeltchenko93c284e2012-09-27 17:26:20 +03001521 struct hci_cp_create_phy_link *cp;
1522
Andrei Emeltchenkoa02226d2012-09-27 17:26:19 +03001523 BT_DBG("%s status 0x%2.2x", hdev->name, status);
Andrei Emeltchenko93c284e2012-09-27 17:26:20 +03001524
Andrei Emeltchenko93c284e2012-09-27 17:26:20 +03001525 cp = hci_sent_cmd_data(hdev, HCI_OP_CREATE_PHY_LINK);
1526 if (!cp)
1527 return;
1528
Andrei Emeltchenkoe58917b2012-10-31 15:46:33 +02001529 hci_dev_lock(hdev);
1530
1531 if (status) {
1532 struct hci_conn *hcon;
1533
1534 hcon = hci_conn_hash_lookup_handle(hdev, cp->phy_handle);
1535 if (hcon)
1536 hci_conn_del(hcon);
1537 } else {
1538 amp_write_remote_assoc(hdev, cp->phy_handle);
1539 }
1540
1541 hci_dev_unlock(hdev);
Andrei Emeltchenkoa02226d2012-09-27 17:26:19 +03001542}
1543
Andrei Emeltchenko0b26ab92012-09-27 17:26:24 +03001544static void hci_cs_accept_phylink(struct hci_dev *hdev, u8 status)
1545{
1546 struct hci_cp_accept_phy_link *cp;
1547
1548 BT_DBG("%s status 0x%2.2x", hdev->name, status);
1549
1550 if (status)
1551 return;
1552
1553 cp = hci_sent_cmd_data(hdev, HCI_OP_ACCEPT_PHY_LINK);
1554 if (!cp)
1555 return;
1556
1557 amp_write_remote_assoc(hdev, cp->phy_handle);
1558}
1559
Gustavo Padovan6039aa72012-05-23 04:04:18 -03001560static void hci_inquiry_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001561{
1562 __u8 status = *((__u8 *) skb->data);
Johan Hedberg30dc78e2012-01-04 15:44:20 +02001563 struct discovery_state *discov = &hdev->discovery;
1564 struct inquiry_entry *e;
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001565
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +03001566 BT_DBG("%s status 0x%2.2x", hdev->name, status);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001567
Johan Hedberg9238f362013-03-05 20:37:48 +02001568 hci_req_cmd_complete(hdev, HCI_OP_INQUIRY, status);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001569
1570 hci_conn_check_pending(hdev);
Andre Guedes89352e72011-11-04 14:16:53 -03001571
1572 if (!test_and_clear_bit(HCI_INQUIRY, &hdev->flags))
1573 return;
1574
Johan Hedberga8b2d5c2012-01-08 23:11:15 +02001575 if (!test_bit(HCI_MGMT, &hdev->dev_flags))
Johan Hedberg30dc78e2012-01-04 15:44:20 +02001576 return;
1577
Johan Hedberg56e5cb82011-11-08 20:40:16 +02001578 hci_dev_lock(hdev);
Johan Hedberg30dc78e2012-01-04 15:44:20 +02001579
Andre Guedes343f9352012-02-17 20:39:37 -03001580 if (discov->state != DISCOVERY_FINDING)
Johan Hedberg30dc78e2012-01-04 15:44:20 +02001581 goto unlock;
1582
1583 if (list_empty(&discov->resolve)) {
1584 hci_discovery_set_state(hdev, DISCOVERY_STOPPED);
1585 goto unlock;
1586 }
1587
1588 e = hci_inquiry_cache_lookup_resolve(hdev, BDADDR_ANY, NAME_NEEDED);
1589 if (e && hci_resolve_name(hdev, e) == 0) {
1590 e->name_state = NAME_PENDING;
1591 hci_discovery_set_state(hdev, DISCOVERY_RESOLVING);
1592 } else {
1593 hci_discovery_set_state(hdev, DISCOVERY_STOPPED);
1594 }
1595
1596unlock:
Johan Hedberg56e5cb82011-11-08 20:40:16 +02001597 hci_dev_unlock(hdev);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001598}
1599
Gustavo Padovan6039aa72012-05-23 04:04:18 -03001600static void hci_inquiry_result_evt(struct hci_dev *hdev, struct sk_buff *skb)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001601{
Marcel Holtmann45bb4bf2005-08-09 20:27:49 -07001602 struct inquiry_data data;
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001603 struct inquiry_info *info = (void *) (skb->data + 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001604 int num_rsp = *((__u8 *) skb->data);
1605
1606 BT_DBG("%s num_rsp %d", hdev->name, num_rsp);
1607
Marcel Holtmann45bb4bf2005-08-09 20:27:49 -07001608 if (!num_rsp)
1609 return;
1610
Andre Guedes1519cc12012-03-21 00:03:38 -03001611 if (test_bit(HCI_PERIODIC_INQ, &hdev->dev_flags))
1612 return;
1613
Linus Torvalds1da177e2005-04-16 15:20:36 -07001614 hci_dev_lock(hdev);
Marcel Holtmann45bb4bf2005-08-09 20:27:49 -07001615
Johan Hedberge17acd42011-03-30 23:57:16 +03001616 for (; num_rsp; num_rsp--, info++) {
Johan Hedberg388fc8f2012-02-23 00:38:59 +02001617 bool name_known, ssp;
Johan Hedberg31754052012-01-04 13:39:52 +02001618
Linus Torvalds1da177e2005-04-16 15:20:36 -07001619 bacpy(&data.bdaddr, &info->bdaddr);
1620 data.pscan_rep_mode = info->pscan_rep_mode;
1621 data.pscan_period_mode = info->pscan_period_mode;
1622 data.pscan_mode = info->pscan_mode;
1623 memcpy(data.dev_class, info->dev_class, 3);
1624 data.clock_offset = info->clock_offset;
1625 data.rssi = 0x00;
Marcel Holtmann41a96212008-07-14 20:13:48 +02001626 data.ssp_mode = 0x00;
Johan Hedberg31754052012-01-04 13:39:52 +02001627
Johan Hedberg388fc8f2012-02-23 00:38:59 +02001628 name_known = hci_inquiry_cache_update(hdev, &data, false, &ssp);
Johan Hedberg48264f02011-11-09 13:58:58 +02001629 mgmt_device_found(hdev, &info->bdaddr, ACL_LINK, 0x00,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001630 info->dev_class, 0, !name_known, ssp, NULL,
1631 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001632 }
Marcel Holtmann45bb4bf2005-08-09 20:27:49 -07001633
Linus Torvalds1da177e2005-04-16 15:20:36 -07001634 hci_dev_unlock(hdev);
1635}
1636
Gustavo Padovan6039aa72012-05-23 04:04:18 -03001637static void hci_conn_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001638{
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001639 struct hci_ev_conn_complete *ev = (void *) skb->data;
1640 struct hci_conn *conn;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001641
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001642 BT_DBG("%s", hdev->name);
Marcel Holtmann45bb4bf2005-08-09 20:27:49 -07001643
Linus Torvalds1da177e2005-04-16 15:20:36 -07001644 hci_dev_lock(hdev);
Marcel Holtmann45bb4bf2005-08-09 20:27:49 -07001645
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001646 conn = hci_conn_hash_lookup_ba(hdev, ev->link_type, &ev->bdaddr);
Marcel Holtmann94992372009-04-19 19:30:03 +02001647 if (!conn) {
1648 if (ev->link_type != SCO_LINK)
1649 goto unlock;
1650
1651 conn = hci_conn_hash_lookup_ba(hdev, ESCO_LINK, &ev->bdaddr);
1652 if (!conn)
1653 goto unlock;
1654
1655 conn->type = SCO_LINK;
1656 }
Marcel Holtmann45bb4bf2005-08-09 20:27:49 -07001657
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001658 if (!ev->status) {
1659 conn->handle = __le16_to_cpu(ev->handle);
Marcel Holtmann769be972008-07-14 20:13:49 +02001660
1661 if (conn->type == ACL_LINK) {
1662 conn->state = BT_CONFIG;
1663 hci_conn_hold(conn);
Szymon Janca9ea3ed2012-07-19 14:46:08 +02001664
1665 if (!conn->out && !hci_conn_ssp_enabled(conn) &&
1666 !hci_find_link_key(hdev, &ev->bdaddr))
1667 conn->disc_timeout = HCI_PAIRING_TIMEOUT;
1668 else
1669 conn->disc_timeout = HCI_DISCONN_TIMEOUT;
Marcel Holtmann769be972008-07-14 20:13:49 +02001670 } else
1671 conn->state = BT_CONNECTED;
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001672
Marcel Holtmann9eba32b2009-08-22 14:19:26 -07001673 hci_conn_hold_device(conn);
Marcel Holtmann7d0db0a2008-07-14 20:13:51 +02001674 hci_conn_add_sysfs(conn);
1675
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001676 if (test_bit(HCI_AUTH, &hdev->flags))
1677 conn->link_mode |= HCI_LM_AUTH;
1678
1679 if (test_bit(HCI_ENCRYPT, &hdev->flags))
1680 conn->link_mode |= HCI_LM_ENCRYPT;
1681
1682 /* Get remote features */
1683 if (conn->type == ACL_LINK) {
1684 struct hci_cp_read_remote_features cp;
1685 cp.handle = ev->handle;
Marcel Holtmann769be972008-07-14 20:13:49 +02001686 hci_send_cmd(hdev, HCI_OP_READ_REMOTE_FEATURES,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001687 sizeof(cp), &cp);
Marcel Holtmann45bb4bf2005-08-09 20:27:49 -07001688 }
Marcel Holtmann45bb4bf2005-08-09 20:27:49 -07001689
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001690 /* Set packet type for incoming connection */
Andrei Emeltchenkod095c1e2011-12-01 14:33:27 +02001691 if (!conn->out && hdev->hci_ver < BLUETOOTH_VER_2_0) {
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001692 struct hci_cp_change_conn_ptype cp;
1693 cp.handle = ev->handle;
Marcel Holtmanna8746412008-07-14 20:13:46 +02001694 cp.pkt_type = cpu_to_le16(conn->pkt_type);
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001695 hci_send_cmd(hdev, HCI_OP_CHANGE_CONN_PTYPE, sizeof(cp),
1696 &cp);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001697 }
Johan Hedberg17d5c042011-01-22 06:09:08 +02001698 } else {
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001699 conn->state = BT_CLOSED;
Johan Hedberg17d5c042011-01-22 06:09:08 +02001700 if (conn->type == ACL_LINK)
Johan Hedberg744cf192011-11-08 20:40:14 +02001701 mgmt_connect_failed(hdev, &ev->bdaddr, conn->type,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001702 conn->dst_type, ev->status);
Johan Hedberg17d5c042011-01-22 06:09:08 +02001703 }
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001704
Marcel Holtmanne73439d2010-07-26 10:06:00 -04001705 if (conn->type == ACL_LINK)
1706 hci_sco_setup(conn, ev->status);
Marcel Holtmann45bb4bf2005-08-09 20:27:49 -07001707
Marcel Holtmann769be972008-07-14 20:13:49 +02001708 if (ev->status) {
1709 hci_proto_connect_cfm(conn, ev->status);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001710 hci_conn_del(conn);
Marcel Holtmannc89b6e62009-01-15 21:57:03 +01001711 } else if (ev->link_type != ACL_LINK)
1712 hci_proto_connect_cfm(conn, ev->status);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001713
1714unlock:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001715 hci_dev_unlock(hdev);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001716
1717 hci_conn_check_pending(hdev);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001718}
1719
Frédéric Dalleau20714bf2012-11-21 10:51:12 +01001720void hci_conn_accept(struct hci_conn *conn, int mask)
1721{
1722 struct hci_dev *hdev = conn->hdev;
1723
1724 BT_DBG("conn %p", conn);
1725
1726 conn->state = BT_CONFIG;
1727
1728 if (!lmp_esco_capable(hdev)) {
1729 struct hci_cp_accept_conn_req cp;
1730
1731 bacpy(&cp.bdaddr, &conn->dst);
1732
1733 if (lmp_rswitch_capable(hdev) && (mask & HCI_LM_MASTER))
1734 cp.role = 0x00; /* Become master */
1735 else
1736 cp.role = 0x01; /* Remain slave */
1737
1738 hci_send_cmd(hdev, HCI_OP_ACCEPT_CONN_REQ, sizeof(cp), &cp);
1739 } else /* lmp_esco_capable(hdev)) */ {
1740 struct hci_cp_accept_sync_conn_req cp;
1741
1742 bacpy(&cp.bdaddr, &conn->dst);
1743 cp.pkt_type = cpu_to_le16(conn->pkt_type);
1744
1745 cp.tx_bandwidth = __constant_cpu_to_le32(0x00001f40);
1746 cp.rx_bandwidth = __constant_cpu_to_le32(0x00001f40);
1747 cp.max_latency = __constant_cpu_to_le16(0xffff);
1748 cp.content_format = cpu_to_le16(hdev->voice_setting);
1749 cp.retrans_effort = 0xff;
1750
1751 hci_send_cmd(hdev, HCI_OP_ACCEPT_SYNC_CONN_REQ,
1752 sizeof(cp), &cp);
1753 }
1754}
1755
Gustavo Padovan6039aa72012-05-23 04:04:18 -03001756static void hci_conn_request_evt(struct hci_dev *hdev, struct sk_buff *skb)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001757{
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001758 struct hci_ev_conn_request *ev = (void *) skb->data;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001759 int mask = hdev->link_mode;
Frédéric Dalleau20714bf2012-11-21 10:51:12 +01001760 __u8 flags = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001761
Andrei Emeltchenko6ed93dc2012-09-25 12:49:43 +03001762 BT_DBG("%s bdaddr %pMR type 0x%x", hdev->name, &ev->bdaddr,
Gustavo Padovan807deac2012-05-17 00:36:24 -03001763 ev->link_type);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001764
Frédéric Dalleau20714bf2012-11-21 10:51:12 +01001765 mask |= hci_proto_connect_ind(hdev, &ev->bdaddr, ev->link_type,
1766 &flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001767
Szymon Janc138d22e2011-02-17 16:44:23 +01001768 if ((mask & HCI_LM_ACCEPT) &&
Gustavo Padovan807deac2012-05-17 00:36:24 -03001769 !hci_blacklist_lookup(hdev, &ev->bdaddr)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001770 /* Connection accepted */
Marcel Holtmannc7bdd502008-07-14 20:13:47 +02001771 struct inquiry_entry *ie;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001772 struct hci_conn *conn;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001773
1774 hci_dev_lock(hdev);
Marcel Holtmannb6a0dc82007-10-20 14:55:10 +02001775
Andrei Emeltchenkocc11b9c2010-11-22 13:21:37 +02001776 ie = hci_inquiry_cache_lookup(hdev, &ev->bdaddr);
1777 if (ie)
Marcel Holtmannc7bdd502008-07-14 20:13:47 +02001778 memcpy(ie->data.dev_class, ev->dev_class, 3);
1779
Gustavo Padovan8fc9ced2012-05-23 04:04:21 -03001780 conn = hci_conn_hash_lookup_ba(hdev, ev->link_type,
1781 &ev->bdaddr);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001782 if (!conn) {
Andrei Emeltchenkocc11b9c2010-11-22 13:21:37 +02001783 conn = hci_conn_add(hdev, ev->link_type, &ev->bdaddr);
1784 if (!conn) {
Gustavo F. Padovan893ef972010-07-18 15:13:37 -03001785 BT_ERR("No memory for new connection");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001786 hci_dev_unlock(hdev);
1787 return;
1788 }
1789 }
Marcel Holtmannb6a0dc82007-10-20 14:55:10 +02001790
Linus Torvalds1da177e2005-04-16 15:20:36 -07001791 memcpy(conn->dev_class, ev->dev_class, 3);
Marcel Holtmannb6a0dc82007-10-20 14:55:10 +02001792
Linus Torvalds1da177e2005-04-16 15:20:36 -07001793 hci_dev_unlock(hdev);
1794
Frédéric Dalleau20714bf2012-11-21 10:51:12 +01001795 if (ev->link_type == ACL_LINK ||
1796 (!(flags & HCI_PROTO_DEFER) && !lmp_esco_capable(hdev))) {
Marcel Holtmannb6a0dc82007-10-20 14:55:10 +02001797 struct hci_cp_accept_conn_req cp;
Frédéric Dalleau20714bf2012-11-21 10:51:12 +01001798 conn->state = BT_CONNECT;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001799
Marcel Holtmannb6a0dc82007-10-20 14:55:10 +02001800 bacpy(&cp.bdaddr, &ev->bdaddr);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001801
Marcel Holtmannb6a0dc82007-10-20 14:55:10 +02001802 if (lmp_rswitch_capable(hdev) && (mask & HCI_LM_MASTER))
1803 cp.role = 0x00; /* Become master */
1804 else
1805 cp.role = 0x01; /* Remain slave */
1806
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001807 hci_send_cmd(hdev, HCI_OP_ACCEPT_CONN_REQ, sizeof(cp),
1808 &cp);
Frédéric Dalleau20714bf2012-11-21 10:51:12 +01001809 } else if (!(flags & HCI_PROTO_DEFER)) {
Marcel Holtmannb6a0dc82007-10-20 14:55:10 +02001810 struct hci_cp_accept_sync_conn_req cp;
Frédéric Dalleau20714bf2012-11-21 10:51:12 +01001811 conn->state = BT_CONNECT;
Marcel Holtmannb6a0dc82007-10-20 14:55:10 +02001812
1813 bacpy(&cp.bdaddr, &ev->bdaddr);
Marcel Holtmanna8746412008-07-14 20:13:46 +02001814 cp.pkt_type = cpu_to_le16(conn->pkt_type);
Marcel Holtmannb6a0dc82007-10-20 14:55:10 +02001815
Andrei Emeltchenko82781e62012-05-25 11:38:27 +03001816 cp.tx_bandwidth = __constant_cpu_to_le32(0x00001f40);
1817 cp.rx_bandwidth = __constant_cpu_to_le32(0x00001f40);
1818 cp.max_latency = __constant_cpu_to_le16(0xffff);
Marcel Holtmannb6a0dc82007-10-20 14:55:10 +02001819 cp.content_format = cpu_to_le16(hdev->voice_setting);
1820 cp.retrans_effort = 0xff;
1821
1822 hci_send_cmd(hdev, HCI_OP_ACCEPT_SYNC_CONN_REQ,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001823 sizeof(cp), &cp);
Frédéric Dalleau20714bf2012-11-21 10:51:12 +01001824 } else {
1825 conn->state = BT_CONNECT2;
1826 hci_proto_connect_cfm(conn, 0);
1827 hci_conn_put(conn);
Marcel Holtmannb6a0dc82007-10-20 14:55:10 +02001828 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001829 } else {
1830 /* Connection rejected */
1831 struct hci_cp_reject_conn_req cp;
1832
1833 bacpy(&cp.bdaddr, &ev->bdaddr);
Andrei Emeltchenko9f5a0d72011-11-07 14:20:25 +02001834 cp.reason = HCI_ERROR_REJ_BAD_ADDR;
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001835 hci_send_cmd(hdev, HCI_OP_REJECT_CONN_REQ, sizeof(cp), &cp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001836 }
1837}
1838
Mikel Astizf0d6a0e2012-08-09 09:52:30 +02001839static u8 hci_to_mgmt_reason(u8 err)
1840{
1841 switch (err) {
1842 case HCI_ERROR_CONNECTION_TIMEOUT:
1843 return MGMT_DEV_DISCONN_TIMEOUT;
1844 case HCI_ERROR_REMOTE_USER_TERM:
1845 case HCI_ERROR_REMOTE_LOW_RESOURCES:
1846 case HCI_ERROR_REMOTE_POWER_OFF:
1847 return MGMT_DEV_DISCONN_REMOTE;
1848 case HCI_ERROR_LOCAL_HOST_TERM:
1849 return MGMT_DEV_DISCONN_LOCAL_HOST;
1850 default:
1851 return MGMT_DEV_DISCONN_UNKNOWN;
1852 }
1853}
1854
Gustavo Padovan6039aa72012-05-23 04:04:18 -03001855static void hci_disconn_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001856{
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001857 struct hci_ev_disconn_complete *ev = (void *) skb->data;
Marcel Holtmann04837f62006-07-03 10:02:33 +02001858 struct hci_conn *conn;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001859
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +03001860 BT_DBG("%s status 0x%2.2x", hdev->name, ev->status);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001861
Linus Torvalds1da177e2005-04-16 15:20:36 -07001862 hci_dev_lock(hdev);
1863
Marcel Holtmann04837f62006-07-03 10:02:33 +02001864 conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
Johan Hedbergf7520542011-01-20 12:34:39 +02001865 if (!conn)
1866 goto unlock;
Marcel Holtmann7d0db0a2008-07-14 20:13:51 +02001867
Johan Hedberg37d9ef72011-11-10 15:54:39 +02001868 if (ev->status == 0)
1869 conn->state = BT_CLOSED;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001870
Johan Hedbergb644ba32012-01-17 21:48:47 +02001871 if (test_and_clear_bit(HCI_CONN_MGMT_CONNECTED, &conn->flags) &&
Gustavo Padovan807deac2012-05-17 00:36:24 -03001872 (conn->type == ACL_LINK || conn->type == LE_LINK)) {
Mikel Astizf0d6a0e2012-08-09 09:52:30 +02001873 if (ev->status) {
Johan Hedberg88c3df12012-02-09 14:27:38 +02001874 mgmt_disconnect_failed(hdev, &conn->dst, conn->type,
Gustavo Padovan807deac2012-05-17 00:36:24 -03001875 conn->dst_type, ev->status);
Mikel Astizf0d6a0e2012-08-09 09:52:30 +02001876 } else {
1877 u8 reason = hci_to_mgmt_reason(ev->reason);
1878
Johan Hedbergafc747a2012-01-15 18:11:07 +02001879 mgmt_device_disconnected(hdev, &conn->dst, conn->type,
Mikel Astizf0d6a0e2012-08-09 09:52:30 +02001880 conn->dst_type, reason);
1881 }
Johan Hedberg37d9ef72011-11-10 15:54:39 +02001882 }
Johan Hedbergf7520542011-01-20 12:34:39 +02001883
Johan Hedberg37d9ef72011-11-10 15:54:39 +02001884 if (ev->status == 0) {
Vishal Agarwal6ec5bca2012-04-16 14:44:44 +05301885 if (conn->type == ACL_LINK && conn->flush_key)
1886 hci_remove_link_key(hdev, &conn->dst);
Johan Hedberg37d9ef72011-11-10 15:54:39 +02001887 hci_proto_disconn_cfm(conn, ev->reason);
1888 hci_conn_del(conn);
1889 }
Johan Hedbergf7520542011-01-20 12:34:39 +02001890
1891unlock:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001892 hci_dev_unlock(hdev);
1893}
1894
Gustavo Padovan6039aa72012-05-23 04:04:18 -03001895static void hci_auth_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001896{
1897 struct hci_ev_auth_complete *ev = (void *) skb->data;
1898 struct hci_conn *conn;
1899
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +03001900 BT_DBG("%s status 0x%2.2x", hdev->name, ev->status);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001901
1902 hci_dev_lock(hdev);
1903
1904 conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
Waldemar Rymarkiewiczd7556e22011-05-31 15:49:26 +02001905 if (!conn)
1906 goto unlock;
1907
1908 if (!ev->status) {
Johan Hedbergaa64a8b2012-01-18 21:33:12 +02001909 if (!hci_conn_ssp_enabled(conn) &&
Gustavo Padovan807deac2012-05-17 00:36:24 -03001910 test_bit(HCI_CONN_REAUTH_PEND, &conn->flags)) {
Waldemar Rymarkiewiczd7556e22011-05-31 15:49:26 +02001911 BT_INFO("re-auth of legacy device is not possible.");
Johan Hedberg2a611692011-02-19 12:06:00 -03001912 } else {
Waldemar Rymarkiewiczd7556e22011-05-31 15:49:26 +02001913 conn->link_mode |= HCI_LM_AUTH;
1914 conn->sec_level = conn->pending_sec_level;
Johan Hedberg2a611692011-02-19 12:06:00 -03001915 }
Waldemar Rymarkiewiczd7556e22011-05-31 15:49:26 +02001916 } else {
Johan Hedbergbab73cb2012-02-09 16:07:29 +02001917 mgmt_auth_failed(hdev, &conn->dst, conn->type, conn->dst_type,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001918 ev->status);
Waldemar Rymarkiewiczd7556e22011-05-31 15:49:26 +02001919 }
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001920
Johan Hedberg51a8efd2012-01-16 06:10:31 +02001921 clear_bit(HCI_CONN_AUTH_PEND, &conn->flags);
1922 clear_bit(HCI_CONN_REAUTH_PEND, &conn->flags);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001923
Waldemar Rymarkiewiczd7556e22011-05-31 15:49:26 +02001924 if (conn->state == BT_CONFIG) {
Johan Hedbergaa64a8b2012-01-18 21:33:12 +02001925 if (!ev->status && hci_conn_ssp_enabled(conn)) {
Waldemar Rymarkiewiczd7556e22011-05-31 15:49:26 +02001926 struct hci_cp_set_conn_encrypt cp;
1927 cp.handle = ev->handle;
1928 cp.encrypt = 0x01;
1929 hci_send_cmd(hdev, HCI_OP_SET_CONN_ENCRYPT, sizeof(cp),
Gustavo Padovan807deac2012-05-17 00:36:24 -03001930 &cp);
Marcel Holtmann052b30b2009-04-26 20:01:22 +02001931 } else {
Waldemar Rymarkiewiczd7556e22011-05-31 15:49:26 +02001932 conn->state = BT_CONNECTED;
1933 hci_proto_connect_cfm(conn, ev->status);
Marcel Holtmann052b30b2009-04-26 20:01:22 +02001934 hci_conn_put(conn);
1935 }
Waldemar Rymarkiewiczd7556e22011-05-31 15:49:26 +02001936 } else {
1937 hci_auth_cfm(conn, ev->status);
Marcel Holtmann052b30b2009-04-26 20:01:22 +02001938
Waldemar Rymarkiewiczd7556e22011-05-31 15:49:26 +02001939 hci_conn_hold(conn);
1940 conn->disc_timeout = HCI_DISCONN_TIMEOUT;
1941 hci_conn_put(conn);
1942 }
1943
Johan Hedberg51a8efd2012-01-16 06:10:31 +02001944 if (test_bit(HCI_CONN_ENCRYPT_PEND, &conn->flags)) {
Waldemar Rymarkiewiczd7556e22011-05-31 15:49:26 +02001945 if (!ev->status) {
1946 struct hci_cp_set_conn_encrypt cp;
1947 cp.handle = ev->handle;
1948 cp.encrypt = 0x01;
1949 hci_send_cmd(hdev, HCI_OP_SET_CONN_ENCRYPT, sizeof(cp),
Gustavo Padovan807deac2012-05-17 00:36:24 -03001950 &cp);
Waldemar Rymarkiewiczd7556e22011-05-31 15:49:26 +02001951 } else {
Johan Hedberg51a8efd2012-01-16 06:10:31 +02001952 clear_bit(HCI_CONN_ENCRYPT_PEND, &conn->flags);
Waldemar Rymarkiewiczd7556e22011-05-31 15:49:26 +02001953 hci_encrypt_cfm(conn, ev->status, 0x00);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001954 }
1955 }
1956
Waldemar Rymarkiewiczd7556e22011-05-31 15:49:26 +02001957unlock:
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001958 hci_dev_unlock(hdev);
1959}
1960
Gustavo Padovan6039aa72012-05-23 04:04:18 -03001961static void hci_remote_name_evt(struct hci_dev *hdev, struct sk_buff *skb)
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001962{
Johan Hedberg127178d2010-11-18 22:22:29 +02001963 struct hci_ev_remote_name *ev = (void *) skb->data;
1964 struct hci_conn *conn;
1965
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001966 BT_DBG("%s", hdev->name);
1967
1968 hci_conn_check_pending(hdev);
Johan Hedberg127178d2010-11-18 22:22:29 +02001969
1970 hci_dev_lock(hdev);
1971
1972 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
Johan Hedbergb644ba32012-01-17 21:48:47 +02001973
1974 if (!test_bit(HCI_MGMT, &hdev->dev_flags))
1975 goto check_auth;
1976
1977 if (ev->status == 0)
1978 hci_check_pending_name(hdev, conn, &ev->bdaddr, ev->name,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001979 strnlen(ev->name, HCI_MAX_NAME_LENGTH));
Johan Hedbergb644ba32012-01-17 21:48:47 +02001980 else
1981 hci_check_pending_name(hdev, conn, &ev->bdaddr, NULL, 0);
1982
1983check_auth:
Johan Hedberg79c6c702011-04-28 11:28:55 -07001984 if (!conn)
1985 goto unlock;
1986
1987 if (!hci_outgoing_auth_needed(hdev, conn))
1988 goto unlock;
1989
Johan Hedberg51a8efd2012-01-16 06:10:31 +02001990 if (!test_and_set_bit(HCI_CONN_AUTH_PEND, &conn->flags)) {
Johan Hedberg127178d2010-11-18 22:22:29 +02001991 struct hci_cp_auth_requested cp;
1992 cp.handle = __cpu_to_le16(conn->handle);
1993 hci_send_cmd(hdev, HCI_OP_AUTH_REQUESTED, sizeof(cp), &cp);
1994 }
1995
Johan Hedberg79c6c702011-04-28 11:28:55 -07001996unlock:
Johan Hedberg127178d2010-11-18 22:22:29 +02001997 hci_dev_unlock(hdev);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001998}
1999
Gustavo Padovan6039aa72012-05-23 04:04:18 -03002000static void hci_encrypt_change_evt(struct hci_dev *hdev, struct sk_buff *skb)
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002001{
2002 struct hci_ev_encrypt_change *ev = (void *) skb->data;
2003 struct hci_conn *conn;
2004
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +03002005 BT_DBG("%s status 0x%2.2x", hdev->name, ev->status);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002006
2007 hci_dev_lock(hdev);
2008
2009 conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
2010 if (conn) {
2011 if (!ev->status) {
Marcel Holtmannae293192008-07-14 20:13:45 +02002012 if (ev->encrypt) {
2013 /* Encryption implies authentication */
2014 conn->link_mode |= HCI_LM_AUTH;
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002015 conn->link_mode |= HCI_LM_ENCRYPT;
Vinicius Costa Gomesda85e5e2011-06-09 18:50:53 -03002016 conn->sec_level = conn->pending_sec_level;
Marcel Holtmannae293192008-07-14 20:13:45 +02002017 } else
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002018 conn->link_mode &= ~HCI_LM_ENCRYPT;
2019 }
2020
Johan Hedberg51a8efd2012-01-16 06:10:31 +02002021 clear_bit(HCI_CONN_ENCRYPT_PEND, &conn->flags);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002022
Gustavo Padovana7d77232012-05-13 03:20:07 -03002023 if (ev->status && conn->state == BT_CONNECTED) {
Andre Guedesbed71742013-01-30 11:50:56 -03002024 hci_disconnect(conn, HCI_ERROR_AUTH_FAILURE);
Gustavo Padovana7d77232012-05-13 03:20:07 -03002025 hci_conn_put(conn);
2026 goto unlock;
2027 }
2028
Marcel Holtmannf8558552008-07-14 20:13:49 +02002029 if (conn->state == BT_CONFIG) {
2030 if (!ev->status)
2031 conn->state = BT_CONNECTED;
2032
2033 hci_proto_connect_cfm(conn, ev->status);
2034 hci_conn_put(conn);
2035 } else
2036 hci_encrypt_cfm(conn, ev->status, ev->encrypt);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002037 }
2038
Gustavo Padovana7d77232012-05-13 03:20:07 -03002039unlock:
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002040 hci_dev_unlock(hdev);
2041}
2042
Gustavo Padovan6039aa72012-05-23 04:04:18 -03002043static void hci_change_link_key_complete_evt(struct hci_dev *hdev,
2044 struct sk_buff *skb)
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002045{
2046 struct hci_ev_change_link_key_complete *ev = (void *) skb->data;
2047 struct hci_conn *conn;
2048
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +03002049 BT_DBG("%s status 0x%2.2x", hdev->name, ev->status);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002050
2051 hci_dev_lock(hdev);
2052
2053 conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
2054 if (conn) {
2055 if (!ev->status)
2056 conn->link_mode |= HCI_LM_SECURE;
2057
Johan Hedberg51a8efd2012-01-16 06:10:31 +02002058 clear_bit(HCI_CONN_AUTH_PEND, &conn->flags);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002059
2060 hci_key_change_cfm(conn, ev->status);
2061 }
2062
2063 hci_dev_unlock(hdev);
2064}
2065
Gustavo Padovan6039aa72012-05-23 04:04:18 -03002066static void hci_remote_features_evt(struct hci_dev *hdev,
2067 struct sk_buff *skb)
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002068{
2069 struct hci_ev_remote_features *ev = (void *) skb->data;
2070 struct hci_conn *conn;
2071
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +03002072 BT_DBG("%s status 0x%2.2x", hdev->name, ev->status);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002073
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002074 hci_dev_lock(hdev);
2075
2076 conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
Johan Hedbergccd556f2010-11-10 17:11:51 +02002077 if (!conn)
2078 goto unlock;
Marcel Holtmann769be972008-07-14 20:13:49 +02002079
Johan Hedbergccd556f2010-11-10 17:11:51 +02002080 if (!ev->status)
2081 memcpy(conn->features, ev->features, 8);
2082
2083 if (conn->state != BT_CONFIG)
2084 goto unlock;
2085
2086 if (!ev->status && lmp_ssp_capable(hdev) && lmp_ssp_capable(conn)) {
2087 struct hci_cp_read_remote_ext_features cp;
2088 cp.handle = ev->handle;
2089 cp.page = 0x01;
2090 hci_send_cmd(hdev, HCI_OP_READ_REMOTE_EXT_FEATURES,
Gustavo Padovan807deac2012-05-17 00:36:24 -03002091 sizeof(cp), &cp);
Johan Hedberg392599b2010-11-18 22:22:28 +02002092 goto unlock;
2093 }
2094
Johan Hedberg671267b2012-05-12 16:11:50 -03002095 if (!ev->status && !test_bit(HCI_CONN_MGMT_CONNECTED, &conn->flags)) {
Johan Hedberg127178d2010-11-18 22:22:29 +02002096 struct hci_cp_remote_name_req cp;
2097 memset(&cp, 0, sizeof(cp));
2098 bacpy(&cp.bdaddr, &conn->dst);
2099 cp.pscan_rep_mode = 0x02;
2100 hci_send_cmd(hdev, HCI_OP_REMOTE_NAME_REQ, sizeof(cp), &cp);
Johan Hedbergb644ba32012-01-17 21:48:47 +02002101 } else if (!test_and_set_bit(HCI_CONN_MGMT_CONNECTED, &conn->flags))
2102 mgmt_device_connected(hdev, &conn->dst, conn->type,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002103 conn->dst_type, 0, NULL, 0,
2104 conn->dev_class);
Johan Hedberg392599b2010-11-18 22:22:28 +02002105
Johan Hedberg127178d2010-11-18 22:22:29 +02002106 if (!hci_outgoing_auth_needed(hdev, conn)) {
Johan Hedbergccd556f2010-11-10 17:11:51 +02002107 conn->state = BT_CONNECTED;
2108 hci_proto_connect_cfm(conn, ev->status);
2109 hci_conn_put(conn);
Marcel Holtmann769be972008-07-14 20:13:49 +02002110 }
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002111
Johan Hedbergccd556f2010-11-10 17:11:51 +02002112unlock:
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002113 hci_dev_unlock(hdev);
2114}
2115
Gustavo Padovan6039aa72012-05-23 04:04:18 -03002116static void hci_cmd_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002117{
2118 struct hci_ev_cmd_complete *ev = (void *) skb->data;
Johan Hedberg9238f362013-03-05 20:37:48 +02002119 u8 status = skb->data[sizeof(*ev)];
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002120 __u16 opcode;
2121
2122 skb_pull(skb, sizeof(*ev));
2123
2124 opcode = __le16_to_cpu(ev->opcode);
2125
2126 switch (opcode) {
2127 case HCI_OP_INQUIRY_CANCEL:
2128 hci_cc_inquiry_cancel(hdev, skb);
2129 break;
2130
Andre Guedes4d934832012-03-21 00:03:35 -03002131 case HCI_OP_PERIODIC_INQ:
2132 hci_cc_periodic_inq(hdev, skb);
2133 break;
2134
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002135 case HCI_OP_EXIT_PERIODIC_INQ:
2136 hci_cc_exit_periodic_inq(hdev, skb);
2137 break;
2138
2139 case HCI_OP_REMOTE_NAME_REQ_CANCEL:
2140 hci_cc_remote_name_req_cancel(hdev, skb);
2141 break;
2142
2143 case HCI_OP_ROLE_DISCOVERY:
2144 hci_cc_role_discovery(hdev, skb);
2145 break;
2146
Marcel Holtmanne4e8e372008-07-14 20:13:47 +02002147 case HCI_OP_READ_LINK_POLICY:
2148 hci_cc_read_link_policy(hdev, skb);
2149 break;
2150
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002151 case HCI_OP_WRITE_LINK_POLICY:
2152 hci_cc_write_link_policy(hdev, skb);
2153 break;
2154
Marcel Holtmanne4e8e372008-07-14 20:13:47 +02002155 case HCI_OP_READ_DEF_LINK_POLICY:
2156 hci_cc_read_def_link_policy(hdev, skb);
2157 break;
2158
2159 case HCI_OP_WRITE_DEF_LINK_POLICY:
2160 hci_cc_write_def_link_policy(hdev, skb);
2161 break;
2162
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002163 case HCI_OP_RESET:
2164 hci_cc_reset(hdev, skb);
2165 break;
2166
2167 case HCI_OP_WRITE_LOCAL_NAME:
2168 hci_cc_write_local_name(hdev, skb);
2169 break;
2170
2171 case HCI_OP_READ_LOCAL_NAME:
2172 hci_cc_read_local_name(hdev, skb);
2173 break;
2174
2175 case HCI_OP_WRITE_AUTH_ENABLE:
2176 hci_cc_write_auth_enable(hdev, skb);
2177 break;
2178
2179 case HCI_OP_WRITE_ENCRYPT_MODE:
2180 hci_cc_write_encrypt_mode(hdev, skb);
2181 break;
2182
2183 case HCI_OP_WRITE_SCAN_ENABLE:
2184 hci_cc_write_scan_enable(hdev, skb);
2185 break;
2186
2187 case HCI_OP_READ_CLASS_OF_DEV:
2188 hci_cc_read_class_of_dev(hdev, skb);
2189 break;
2190
2191 case HCI_OP_WRITE_CLASS_OF_DEV:
2192 hci_cc_write_class_of_dev(hdev, skb);
2193 break;
2194
2195 case HCI_OP_READ_VOICE_SETTING:
2196 hci_cc_read_voice_setting(hdev, skb);
2197 break;
2198
2199 case HCI_OP_WRITE_VOICE_SETTING:
2200 hci_cc_write_voice_setting(hdev, skb);
2201 break;
2202
Marcel Holtmann333140b2008-07-14 20:13:48 +02002203 case HCI_OP_WRITE_SSP_MODE:
2204 hci_cc_write_ssp_mode(hdev, skb);
2205 break;
2206
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002207 case HCI_OP_READ_LOCAL_VERSION:
2208 hci_cc_read_local_version(hdev, skb);
2209 break;
2210
2211 case HCI_OP_READ_LOCAL_COMMANDS:
2212 hci_cc_read_local_commands(hdev, skb);
2213 break;
2214
2215 case HCI_OP_READ_LOCAL_FEATURES:
2216 hci_cc_read_local_features(hdev, skb);
2217 break;
2218
Andre Guedes971e3a42011-06-30 19:20:52 -03002219 case HCI_OP_READ_LOCAL_EXT_FEATURES:
2220 hci_cc_read_local_ext_features(hdev, skb);
2221 break;
2222
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002223 case HCI_OP_READ_BUFFER_SIZE:
2224 hci_cc_read_buffer_size(hdev, skb);
2225 break;
2226
2227 case HCI_OP_READ_BD_ADDR:
2228 hci_cc_read_bd_addr(hdev, skb);
2229 break;
2230
Johan Hedbergf332ec62013-03-15 17:07:11 -05002231 case HCI_OP_READ_PAGE_SCAN_ACTIVITY:
2232 hci_cc_read_page_scan_activity(hdev, skb);
2233 break;
2234
2235 case HCI_OP_READ_PAGE_SCAN_TYPE:
2236 hci_cc_read_page_scan_type(hdev, skb);
2237 break;
2238
Andrei Emeltchenko350ee4c2011-12-07 15:56:51 +02002239 case HCI_OP_READ_DATA_BLOCK_SIZE:
2240 hci_cc_read_data_block_size(hdev, skb);
2241 break;
2242
Andrei Emeltchenko1e89cff2011-11-24 14:52:02 +02002243 case HCI_OP_READ_FLOW_CONTROL_MODE:
2244 hci_cc_read_flow_control_mode(hdev, skb);
2245 break;
2246
Andrei Emeltchenko928abaa2011-10-12 10:53:57 +03002247 case HCI_OP_READ_LOCAL_AMP_INFO:
2248 hci_cc_read_local_amp_info(hdev, skb);
2249 break;
2250
Andrei Emeltchenko903e4542012-09-27 17:26:09 +03002251 case HCI_OP_READ_LOCAL_AMP_ASSOC:
2252 hci_cc_read_local_amp_assoc(hdev, skb);
2253 break;
2254
Johan Hedbergd5859e22011-01-25 01:19:58 +02002255 case HCI_OP_READ_INQ_RSP_TX_POWER:
2256 hci_cc_read_inq_rsp_tx_power(hdev, skb);
2257 break;
2258
Johan Hedberg980e1a52011-01-22 06:10:07 +02002259 case HCI_OP_PIN_CODE_REPLY:
2260 hci_cc_pin_code_reply(hdev, skb);
2261 break;
2262
2263 case HCI_OP_PIN_CODE_NEG_REPLY:
2264 hci_cc_pin_code_neg_reply(hdev, skb);
2265 break;
2266
Szymon Jancc35938b2011-03-22 13:12:21 +01002267 case HCI_OP_READ_LOCAL_OOB_DATA:
2268 hci_cc_read_local_oob_data_reply(hdev, skb);
2269 break;
2270
Ville Tervo6ed58ec2011-02-10 22:38:48 -03002271 case HCI_OP_LE_READ_BUFFER_SIZE:
2272 hci_cc_le_read_buffer_size(hdev, skb);
2273 break;
2274
Johan Hedberg60e77322013-01-22 14:01:59 +02002275 case HCI_OP_LE_READ_LOCAL_FEATURES:
2276 hci_cc_le_read_local_features(hdev, skb);
2277 break;
2278
Johan Hedberg8fa19092012-10-19 20:57:49 +03002279 case HCI_OP_LE_READ_ADV_TX_POWER:
2280 hci_cc_le_read_adv_tx_power(hdev, skb);
2281 break;
2282
Johan Hedberga5c29682011-02-19 12:05:57 -03002283 case HCI_OP_USER_CONFIRM_REPLY:
2284 hci_cc_user_confirm_reply(hdev, skb);
2285 break;
2286
2287 case HCI_OP_USER_CONFIRM_NEG_REPLY:
2288 hci_cc_user_confirm_neg_reply(hdev, skb);
2289 break;
2290
Brian Gix1143d452011-11-23 08:28:34 -08002291 case HCI_OP_USER_PASSKEY_REPLY:
2292 hci_cc_user_passkey_reply(hdev, skb);
2293 break;
2294
2295 case HCI_OP_USER_PASSKEY_NEG_REPLY:
2296 hci_cc_user_passkey_neg_reply(hdev, skb);
Szymon Janc16cde992012-04-13 12:32:42 +02002297 break;
Andre Guedes07f7fa52011-12-02 21:13:31 +09002298
2299 case HCI_OP_LE_SET_SCAN_PARAM:
2300 hci_cc_le_set_scan_param(hdev, skb);
Brian Gix1143d452011-11-23 08:28:34 -08002301 break;
2302
Johan Hedbergc1d5dc42012-11-08 01:23:01 +01002303 case HCI_OP_LE_SET_ADV_ENABLE:
2304 hci_cc_le_set_adv_enable(hdev, skb);
2305 break;
2306
Andre Guedeseb9d91f2011-05-26 16:23:52 -03002307 case HCI_OP_LE_SET_SCAN_ENABLE:
2308 hci_cc_le_set_scan_enable(hdev, skb);
2309 break;
2310
Johan Hedbergcf1d0812013-01-22 14:02:00 +02002311 case HCI_OP_LE_READ_WHITE_LIST_SIZE:
2312 hci_cc_le_read_white_list_size(hdev, skb);
2313 break;
2314
Johan Hedberg9b008c02013-01-22 14:02:01 +02002315 case HCI_OP_LE_READ_SUPPORTED_STATES:
2316 hci_cc_le_read_supported_states(hdev, skb);
2317 break;
2318
Andre Guedesf9b49302011-06-30 19:20:53 -03002319 case HCI_OP_WRITE_LE_HOST_SUPPORTED:
2320 hci_cc_write_le_host_supported(hdev, skb);
2321 break;
2322
Andrei Emeltchenko93c284e2012-09-27 17:26:20 +03002323 case HCI_OP_WRITE_REMOTE_AMP_ASSOC:
2324 hci_cc_write_remote_amp_assoc(hdev, skb);
2325 break;
2326
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002327 default:
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +03002328 BT_DBG("%s opcode 0x%4.4x", hdev->name, opcode);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002329 break;
2330 }
2331
Johan Hedbergad82cdd2013-03-09 09:53:50 +02002332 if (opcode != HCI_OP_NOP)
Ville Tervo6bd32322011-02-16 16:32:41 +02002333 del_timer(&hdev->cmd_timer);
2334
Johan Hedbergad82cdd2013-03-09 09:53:50 +02002335 hci_req_cmd_complete(hdev, opcode, status);
Johan Hedberg9238f362013-03-05 20:37:48 +02002336
Szymon Jancdbccd792012-12-11 08:51:19 +01002337 if (ev->ncmd && !test_bit(HCI_RESET, &hdev->flags)) {
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002338 atomic_set(&hdev->cmd_cnt, 1);
2339 if (!skb_queue_empty(&hdev->cmd_q))
Gustavo F. Padovanc347b762011-12-14 23:53:47 -02002340 queue_work(hdev->workqueue, &hdev->cmd_work);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002341 }
2342}
2343
Gustavo Padovan6039aa72012-05-23 04:04:18 -03002344static void hci_cmd_status_evt(struct hci_dev *hdev, struct sk_buff *skb)
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002345{
2346 struct hci_ev_cmd_status *ev = (void *) skb->data;
2347 __u16 opcode;
2348
2349 skb_pull(skb, sizeof(*ev));
2350
2351 opcode = __le16_to_cpu(ev->opcode);
2352
2353 switch (opcode) {
2354 case HCI_OP_INQUIRY:
2355 hci_cs_inquiry(hdev, ev->status);
2356 break;
2357
2358 case HCI_OP_CREATE_CONN:
2359 hci_cs_create_conn(hdev, ev->status);
2360 break;
2361
2362 case HCI_OP_ADD_SCO:
2363 hci_cs_add_sco(hdev, ev->status);
2364 break;
2365
Marcel Holtmannf8558552008-07-14 20:13:49 +02002366 case HCI_OP_AUTH_REQUESTED:
2367 hci_cs_auth_requested(hdev, ev->status);
2368 break;
2369
2370 case HCI_OP_SET_CONN_ENCRYPT:
2371 hci_cs_set_conn_encrypt(hdev, ev->status);
2372 break;
2373
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002374 case HCI_OP_REMOTE_NAME_REQ:
2375 hci_cs_remote_name_req(hdev, ev->status);
2376 break;
2377
Marcel Holtmann769be972008-07-14 20:13:49 +02002378 case HCI_OP_READ_REMOTE_FEATURES:
2379 hci_cs_read_remote_features(hdev, ev->status);
2380 break;
2381
2382 case HCI_OP_READ_REMOTE_EXT_FEATURES:
2383 hci_cs_read_remote_ext_features(hdev, ev->status);
2384 break;
2385
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002386 case HCI_OP_SETUP_SYNC_CONN:
2387 hci_cs_setup_sync_conn(hdev, ev->status);
2388 break;
2389
2390 case HCI_OP_SNIFF_MODE:
2391 hci_cs_sniff_mode(hdev, ev->status);
2392 break;
2393
2394 case HCI_OP_EXIT_SNIFF_MODE:
2395 hci_cs_exit_sniff_mode(hdev, ev->status);
2396 break;
2397
Johan Hedberg8962ee72011-01-20 12:40:27 +02002398 case HCI_OP_DISCONNECT:
Johan Hedberg88c3df12012-02-09 14:27:38 +02002399 hci_cs_disconnect(hdev, ev->status);
Johan Hedberg8962ee72011-01-20 12:40:27 +02002400 break;
2401
Ville Tervofcd89c02011-02-10 22:38:47 -03002402 case HCI_OP_LE_CREATE_CONN:
2403 hci_cs_le_create_conn(hdev, ev->status);
2404 break;
2405
Andrei Emeltchenkoa02226d2012-09-27 17:26:19 +03002406 case HCI_OP_CREATE_PHY_LINK:
2407 hci_cs_create_phylink(hdev, ev->status);
2408 break;
2409
Andrei Emeltchenko0b26ab92012-09-27 17:26:24 +03002410 case HCI_OP_ACCEPT_PHY_LINK:
2411 hci_cs_accept_phylink(hdev, ev->status);
2412 break;
2413
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002414 default:
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +03002415 BT_DBG("%s opcode 0x%4.4x", hdev->name, opcode);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002416 break;
2417 }
2418
Johan Hedbergad82cdd2013-03-09 09:53:50 +02002419 if (opcode != HCI_OP_NOP)
Ville Tervo6bd32322011-02-16 16:32:41 +02002420 del_timer(&hdev->cmd_timer);
2421
Johan Hedbergad82cdd2013-03-09 09:53:50 +02002422 hci_req_cmd_status(hdev, opcode, ev->status);
Johan Hedberg9238f362013-03-05 20:37:48 +02002423
Gustavo F. Padovan10572132011-03-16 15:36:29 -03002424 if (ev->ncmd && !test_bit(HCI_RESET, &hdev->flags)) {
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002425 atomic_set(&hdev->cmd_cnt, 1);
2426 if (!skb_queue_empty(&hdev->cmd_q))
Gustavo F. Padovanc347b762011-12-14 23:53:47 -02002427 queue_work(hdev->workqueue, &hdev->cmd_work);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002428 }
2429}
2430
Gustavo Padovan6039aa72012-05-23 04:04:18 -03002431static void hci_role_change_evt(struct hci_dev *hdev, struct sk_buff *skb)
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002432{
2433 struct hci_ev_role_change *ev = (void *) skb->data;
2434 struct hci_conn *conn;
2435
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +03002436 BT_DBG("%s status 0x%2.2x", hdev->name, ev->status);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002437
2438 hci_dev_lock(hdev);
2439
2440 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
2441 if (conn) {
2442 if (!ev->status) {
2443 if (ev->role)
2444 conn->link_mode &= ~HCI_LM_MASTER;
2445 else
2446 conn->link_mode |= HCI_LM_MASTER;
2447 }
2448
Johan Hedberg51a8efd2012-01-16 06:10:31 +02002449 clear_bit(HCI_CONN_RSWITCH_PEND, &conn->flags);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002450
2451 hci_role_switch_cfm(conn, ev->status, ev->role);
2452 }
2453
2454 hci_dev_unlock(hdev);
2455}
2456
Gustavo Padovan6039aa72012-05-23 04:04:18 -03002457static void hci_num_comp_pkts_evt(struct hci_dev *hdev, struct sk_buff *skb)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002458{
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002459 struct hci_ev_num_comp_pkts *ev = (void *) skb->data;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002460 int i;
2461
Andrei Emeltchenko32ac5b92011-12-19 16:31:29 +02002462 if (hdev->flow_ctl_mode != HCI_FLOW_CTL_MODE_PACKET_BASED) {
2463 BT_ERR("Wrong event for mode %d", hdev->flow_ctl_mode);
2464 return;
2465 }
2466
Andrei Emeltchenkoc5993de2011-12-30 12:07:47 +02002467 if (skb->len < sizeof(*ev) || skb->len < sizeof(*ev) +
Gustavo Padovan807deac2012-05-17 00:36:24 -03002468 ev->num_hndl * sizeof(struct hci_comp_pkts_info)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002469 BT_DBG("%s bad parameters", hdev->name);
2470 return;
2471 }
2472
Andrei Emeltchenkoc5993de2011-12-30 12:07:47 +02002473 BT_DBG("%s num_hndl %d", hdev->name, ev->num_hndl);
2474
Andrei Emeltchenko613a1c02011-12-19 16:31:30 +02002475 for (i = 0; i < ev->num_hndl; i++) {
2476 struct hci_comp_pkts_info *info = &ev->handles[i];
Linus Torvalds1da177e2005-04-16 15:20:36 -07002477 struct hci_conn *conn;
2478 __u16 handle, count;
2479
Andrei Emeltchenko613a1c02011-12-19 16:31:30 +02002480 handle = __le16_to_cpu(info->handle);
2481 count = __le16_to_cpu(info->count);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002482
2483 conn = hci_conn_hash_lookup_handle(hdev, handle);
Andrei Emeltchenkof4280912011-12-07 15:56:52 +02002484 if (!conn)
2485 continue;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002486
Andrei Emeltchenkof4280912011-12-07 15:56:52 +02002487 conn->sent -= count;
2488
2489 switch (conn->type) {
2490 case ACL_LINK:
2491 hdev->acl_cnt += count;
2492 if (hdev->acl_cnt > hdev->acl_pkts)
2493 hdev->acl_cnt = hdev->acl_pkts;
2494 break;
2495
2496 case LE_LINK:
2497 if (hdev->le_pkts) {
2498 hdev->le_cnt += count;
2499 if (hdev->le_cnt > hdev->le_pkts)
2500 hdev->le_cnt = hdev->le_pkts;
2501 } else {
Andrei Emeltchenko70f230202010-12-01 16:58:25 +02002502 hdev->acl_cnt += count;
2503 if (hdev->acl_cnt > hdev->acl_pkts)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002504 hdev->acl_cnt = hdev->acl_pkts;
2505 }
Andrei Emeltchenkof4280912011-12-07 15:56:52 +02002506 break;
2507
2508 case SCO_LINK:
2509 hdev->sco_cnt += count;
2510 if (hdev->sco_cnt > hdev->sco_pkts)
2511 hdev->sco_cnt = hdev->sco_pkts;
2512 break;
2513
2514 default:
2515 BT_ERR("Unknown type %d conn %p", conn->type, conn);
2516 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002517 }
2518 }
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002519
Gustavo F. Padovan3eff45e2011-12-15 00:50:02 -02002520 queue_work(hdev->workqueue, &hdev->tx_work);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002521}
2522
Andrei Emeltchenko76ef7cf2012-10-10 17:38:29 +03002523static struct hci_conn *__hci_conn_lookup_handle(struct hci_dev *hdev,
2524 __u16 handle)
2525{
2526 struct hci_chan *chan;
2527
2528 switch (hdev->dev_type) {
2529 case HCI_BREDR:
2530 return hci_conn_hash_lookup_handle(hdev, handle);
2531 case HCI_AMP:
2532 chan = hci_chan_lookup_handle(hdev, handle);
2533 if (chan)
2534 return chan->conn;
2535 break;
2536 default:
2537 BT_ERR("%s unknown dev_type %d", hdev->name, hdev->dev_type);
2538 break;
2539 }
2540
2541 return NULL;
2542}
2543
Gustavo Padovan6039aa72012-05-23 04:04:18 -03002544static void hci_num_comp_blocks_evt(struct hci_dev *hdev, struct sk_buff *skb)
Andrei Emeltchenko25e89e92012-01-04 12:41:58 +02002545{
2546 struct hci_ev_num_comp_blocks *ev = (void *) skb->data;
2547 int i;
2548
2549 if (hdev->flow_ctl_mode != HCI_FLOW_CTL_MODE_BLOCK_BASED) {
2550 BT_ERR("Wrong event for mode %d", hdev->flow_ctl_mode);
2551 return;
2552 }
2553
2554 if (skb->len < sizeof(*ev) || skb->len < sizeof(*ev) +
Gustavo Padovan807deac2012-05-17 00:36:24 -03002555 ev->num_hndl * sizeof(struct hci_comp_blocks_info)) {
Andrei Emeltchenko25e89e92012-01-04 12:41:58 +02002556 BT_DBG("%s bad parameters", hdev->name);
2557 return;
2558 }
2559
2560 BT_DBG("%s num_blocks %d num_hndl %d", hdev->name, ev->num_blocks,
Gustavo Padovan807deac2012-05-17 00:36:24 -03002561 ev->num_hndl);
Andrei Emeltchenko25e89e92012-01-04 12:41:58 +02002562
2563 for (i = 0; i < ev->num_hndl; i++) {
2564 struct hci_comp_blocks_info *info = &ev->handles[i];
Andrei Emeltchenko76ef7cf2012-10-10 17:38:29 +03002565 struct hci_conn *conn = NULL;
Andrei Emeltchenko25e89e92012-01-04 12:41:58 +02002566 __u16 handle, block_count;
2567
2568 handle = __le16_to_cpu(info->handle);
2569 block_count = __le16_to_cpu(info->blocks);
2570
Andrei Emeltchenko76ef7cf2012-10-10 17:38:29 +03002571 conn = __hci_conn_lookup_handle(hdev, handle);
Andrei Emeltchenko25e89e92012-01-04 12:41:58 +02002572 if (!conn)
2573 continue;
2574
2575 conn->sent -= block_count;
2576
2577 switch (conn->type) {
2578 case ACL_LINK:
Andrei Emeltchenkobd1eb662012-10-10 17:38:30 +03002579 case AMP_LINK:
Andrei Emeltchenko25e89e92012-01-04 12:41:58 +02002580 hdev->block_cnt += block_count;
2581 if (hdev->block_cnt > hdev->num_blocks)
2582 hdev->block_cnt = hdev->num_blocks;
2583 break;
2584
2585 default:
2586 BT_ERR("Unknown type %d conn %p", conn->type, conn);
2587 break;
2588 }
2589 }
2590
2591 queue_work(hdev->workqueue, &hdev->tx_work);
2592}
2593
Gustavo Padovan6039aa72012-05-23 04:04:18 -03002594static void hci_mode_change_evt(struct hci_dev *hdev, struct sk_buff *skb)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002595{
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002596 struct hci_ev_mode_change *ev = (void *) skb->data;
Marcel Holtmann04837f62006-07-03 10:02:33 +02002597 struct hci_conn *conn;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002598
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +03002599 BT_DBG("%s status 0x%2.2x", hdev->name, ev->status);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002600
2601 hci_dev_lock(hdev);
2602
Marcel Holtmann04837f62006-07-03 10:02:33 +02002603 conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
2604 if (conn) {
2605 conn->mode = ev->mode;
2606 conn->interval = __le16_to_cpu(ev->interval);
2607
Gustavo Padovan8fc9ced2012-05-23 04:04:21 -03002608 if (!test_and_clear_bit(HCI_CONN_MODE_CHANGE_PEND,
2609 &conn->flags)) {
Marcel Holtmann04837f62006-07-03 10:02:33 +02002610 if (conn->mode == HCI_CM_ACTIVE)
Johan Hedberg58a681e2012-01-16 06:47:28 +02002611 set_bit(HCI_CONN_POWER_SAVE, &conn->flags);
Marcel Holtmann04837f62006-07-03 10:02:33 +02002612 else
Johan Hedberg58a681e2012-01-16 06:47:28 +02002613 clear_bit(HCI_CONN_POWER_SAVE, &conn->flags);
Marcel Holtmann04837f62006-07-03 10:02:33 +02002614 }
Marcel Holtmanne73439d2010-07-26 10:06:00 -04002615
Johan Hedberg51a8efd2012-01-16 06:10:31 +02002616 if (test_and_clear_bit(HCI_CONN_SCO_SETUP_PEND, &conn->flags))
Marcel Holtmanne73439d2010-07-26 10:06:00 -04002617 hci_sco_setup(conn, ev->status);
Marcel Holtmann04837f62006-07-03 10:02:33 +02002618 }
2619
2620 hci_dev_unlock(hdev);
2621}
2622
Gustavo Padovan6039aa72012-05-23 04:04:18 -03002623static void hci_pin_code_request_evt(struct hci_dev *hdev, struct sk_buff *skb)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002624{
Marcel Holtmann052b30b2009-04-26 20:01:22 +02002625 struct hci_ev_pin_code_req *ev = (void *) skb->data;
2626 struct hci_conn *conn;
2627
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002628 BT_DBG("%s", hdev->name);
Marcel Holtmann052b30b2009-04-26 20:01:22 +02002629
2630 hci_dev_lock(hdev);
2631
2632 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
Waldemar Rymarkiewiczb6f98042011-09-23 10:01:30 +02002633 if (!conn)
2634 goto unlock;
2635
2636 if (conn->state == BT_CONNECTED) {
Marcel Holtmann052b30b2009-04-26 20:01:22 +02002637 hci_conn_hold(conn);
2638 conn->disc_timeout = HCI_PAIRING_TIMEOUT;
2639 hci_conn_put(conn);
2640 }
2641
Johan Hedberga8b2d5c2012-01-08 23:11:15 +02002642 if (!test_bit(HCI_PAIRABLE, &hdev->dev_flags))
Johan Hedberg03b555e2011-01-04 15:40:05 +02002643 hci_send_cmd(hdev, HCI_OP_PIN_CODE_NEG_REPLY,
Gustavo Padovan807deac2012-05-17 00:36:24 -03002644 sizeof(ev->bdaddr), &ev->bdaddr);
Johan Hedberga8b2d5c2012-01-08 23:11:15 +02002645 else if (test_bit(HCI_MGMT, &hdev->dev_flags)) {
Waldemar Rymarkiewicza770bb52011-04-28 12:07:59 +02002646 u8 secure;
2647
2648 if (conn->pending_sec_level == BT_SECURITY_HIGH)
2649 secure = 1;
2650 else
2651 secure = 0;
2652
Johan Hedberg744cf192011-11-08 20:40:14 +02002653 mgmt_pin_code_request(hdev, &ev->bdaddr, secure);
Waldemar Rymarkiewicza770bb52011-04-28 12:07:59 +02002654 }
Johan Hedberg980e1a52011-01-22 06:10:07 +02002655
Waldemar Rymarkiewiczb6f98042011-09-23 10:01:30 +02002656unlock:
Marcel Holtmann052b30b2009-04-26 20:01:22 +02002657 hci_dev_unlock(hdev);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002658}
2659
Gustavo Padovan6039aa72012-05-23 04:04:18 -03002660static void hci_link_key_request_evt(struct hci_dev *hdev, struct sk_buff *skb)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002661{
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002662 struct hci_ev_link_key_req *ev = (void *) skb->data;
2663 struct hci_cp_link_key_reply cp;
2664 struct hci_conn *conn;
2665 struct link_key *key;
2666
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002667 BT_DBG("%s", hdev->name);
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002668
Johan Hedberga8b2d5c2012-01-08 23:11:15 +02002669 if (!test_bit(HCI_LINK_KEYS, &hdev->dev_flags))
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002670 return;
2671
2672 hci_dev_lock(hdev);
2673
2674 key = hci_find_link_key(hdev, &ev->bdaddr);
2675 if (!key) {
Andrei Emeltchenko6ed93dc2012-09-25 12:49:43 +03002676 BT_DBG("%s link key not found for %pMR", hdev->name,
2677 &ev->bdaddr);
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002678 goto not_found;
2679 }
2680
Andrei Emeltchenko6ed93dc2012-09-25 12:49:43 +03002681 BT_DBG("%s found key type %u for %pMR", hdev->name, key->type,
2682 &ev->bdaddr);
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002683
Johan Hedberga8b2d5c2012-01-08 23:11:15 +02002684 if (!test_bit(HCI_DEBUG_KEYS, &hdev->dev_flags) &&
Gustavo Padovan807deac2012-05-17 00:36:24 -03002685 key->type == HCI_LK_DEBUG_COMBINATION) {
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002686 BT_DBG("%s ignoring debug key", hdev->name);
2687 goto not_found;
2688 }
2689
2690 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
Waldemar Rymarkiewicz60b83f52011-04-28 12:07:56 +02002691 if (conn) {
2692 if (key->type == HCI_LK_UNAUTH_COMBINATION &&
Gustavo Padovan807deac2012-05-17 00:36:24 -03002693 conn->auth_type != 0xff && (conn->auth_type & 0x01)) {
Waldemar Rymarkiewicz60b83f52011-04-28 12:07:56 +02002694 BT_DBG("%s ignoring unauthenticated key", hdev->name);
2695 goto not_found;
2696 }
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002697
Waldemar Rymarkiewicz60b83f52011-04-28 12:07:56 +02002698 if (key->type == HCI_LK_COMBINATION && key->pin_len < 16 &&
Gustavo Padovan807deac2012-05-17 00:36:24 -03002699 conn->pending_sec_level == BT_SECURITY_HIGH) {
Gustavo Padovan8fc9ced2012-05-23 04:04:21 -03002700 BT_DBG("%s ignoring key unauthenticated for high security",
2701 hdev->name);
Waldemar Rymarkiewicz60b83f52011-04-28 12:07:56 +02002702 goto not_found;
2703 }
2704
2705 conn->key_type = key->type;
2706 conn->pin_length = key->pin_len;
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002707 }
2708
2709 bacpy(&cp.bdaddr, &ev->bdaddr);
Andrei Emeltchenko9b3b4462012-05-23 11:31:20 +03002710 memcpy(cp.link_key, key->val, HCI_LINK_KEY_SIZE);
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002711
2712 hci_send_cmd(hdev, HCI_OP_LINK_KEY_REPLY, sizeof(cp), &cp);
2713
2714 hci_dev_unlock(hdev);
2715
2716 return;
2717
2718not_found:
2719 hci_send_cmd(hdev, HCI_OP_LINK_KEY_NEG_REPLY, 6, &ev->bdaddr);
2720 hci_dev_unlock(hdev);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002721}
2722
Gustavo Padovan6039aa72012-05-23 04:04:18 -03002723static void hci_link_key_notify_evt(struct hci_dev *hdev, struct sk_buff *skb)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002724{
Marcel Holtmann052b30b2009-04-26 20:01:22 +02002725 struct hci_ev_link_key_notify *ev = (void *) skb->data;
2726 struct hci_conn *conn;
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002727 u8 pin_len = 0;
Marcel Holtmann052b30b2009-04-26 20:01:22 +02002728
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002729 BT_DBG("%s", hdev->name);
Marcel Holtmann052b30b2009-04-26 20:01:22 +02002730
2731 hci_dev_lock(hdev);
2732
2733 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
2734 if (conn) {
2735 hci_conn_hold(conn);
2736 conn->disc_timeout = HCI_DISCONN_TIMEOUT;
Johan Hedberg980e1a52011-01-22 06:10:07 +02002737 pin_len = conn->pin_length;
Waldemar Rymarkiewicz13d39312011-04-28 12:07:55 +02002738
2739 if (ev->key_type != HCI_LK_CHANGED_COMBINATION)
2740 conn->key_type = ev->key_type;
2741
Marcel Holtmann052b30b2009-04-26 20:01:22 +02002742 hci_conn_put(conn);
2743 }
2744
Johan Hedberga8b2d5c2012-01-08 23:11:15 +02002745 if (test_bit(HCI_LINK_KEYS, &hdev->dev_flags))
Johan Hedbergd25e28a2011-04-28 11:28:59 -07002746 hci_add_link_key(hdev, conn, 1, &ev->bdaddr, ev->link_key,
Gustavo Padovan807deac2012-05-17 00:36:24 -03002747 ev->key_type, pin_len);
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002748
Marcel Holtmann052b30b2009-04-26 20:01:22 +02002749 hci_dev_unlock(hdev);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002750}
2751
Gustavo Padovan6039aa72012-05-23 04:04:18 -03002752static void hci_clock_offset_evt(struct hci_dev *hdev, struct sk_buff *skb)
Marcel Holtmann04837f62006-07-03 10:02:33 +02002753{
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002754 struct hci_ev_clock_offset *ev = (void *) skb->data;
Marcel Holtmann04837f62006-07-03 10:02:33 +02002755 struct hci_conn *conn;
2756
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +03002757 BT_DBG("%s status 0x%2.2x", hdev->name, ev->status);
Marcel Holtmann04837f62006-07-03 10:02:33 +02002758
2759 hci_dev_lock(hdev);
2760
2761 conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
Linus Torvalds1da177e2005-04-16 15:20:36 -07002762 if (conn && !ev->status) {
2763 struct inquiry_entry *ie;
2764
Andrei Emeltchenkocc11b9c2010-11-22 13:21:37 +02002765 ie = hci_inquiry_cache_lookup(hdev, &conn->dst);
2766 if (ie) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002767 ie->data.clock_offset = ev->clock_offset;
2768 ie->timestamp = jiffies;
2769 }
2770 }
2771
2772 hci_dev_unlock(hdev);
2773}
2774
Gustavo Padovan6039aa72012-05-23 04:04:18 -03002775static void hci_pkt_type_change_evt(struct hci_dev *hdev, struct sk_buff *skb)
Marcel Holtmanna8746412008-07-14 20:13:46 +02002776{
2777 struct hci_ev_pkt_type_change *ev = (void *) skb->data;
2778 struct hci_conn *conn;
2779
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +03002780 BT_DBG("%s status 0x%2.2x", hdev->name, ev->status);
Marcel Holtmanna8746412008-07-14 20:13:46 +02002781
2782 hci_dev_lock(hdev);
2783
2784 conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
2785 if (conn && !ev->status)
2786 conn->pkt_type = __le16_to_cpu(ev->pkt_type);
2787
2788 hci_dev_unlock(hdev);
2789}
2790
Gustavo Padovan6039aa72012-05-23 04:04:18 -03002791static void hci_pscan_rep_mode_evt(struct hci_dev *hdev, struct sk_buff *skb)
Marcel Holtmann85a1e932005-08-09 20:28:02 -07002792{
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002793 struct hci_ev_pscan_rep_mode *ev = (void *) skb->data;
Marcel Holtmann85a1e932005-08-09 20:28:02 -07002794 struct inquiry_entry *ie;
2795
2796 BT_DBG("%s", hdev->name);
2797
2798 hci_dev_lock(hdev);
2799
Andrei Emeltchenkocc11b9c2010-11-22 13:21:37 +02002800 ie = hci_inquiry_cache_lookup(hdev, &ev->bdaddr);
2801 if (ie) {
Marcel Holtmann85a1e932005-08-09 20:28:02 -07002802 ie->data.pscan_rep_mode = ev->pscan_rep_mode;
2803 ie->timestamp = jiffies;
2804 }
2805
2806 hci_dev_unlock(hdev);
2807}
2808
Gustavo Padovan6039aa72012-05-23 04:04:18 -03002809static void hci_inquiry_result_with_rssi_evt(struct hci_dev *hdev,
2810 struct sk_buff *skb)
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002811{
2812 struct inquiry_data data;
2813 int num_rsp = *((__u8 *) skb->data);
Johan Hedberg388fc8f2012-02-23 00:38:59 +02002814 bool name_known, ssp;
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002815
2816 BT_DBG("%s num_rsp %d", hdev->name, num_rsp);
2817
2818 if (!num_rsp)
2819 return;
2820
Andre Guedes1519cc12012-03-21 00:03:38 -03002821 if (test_bit(HCI_PERIODIC_INQ, &hdev->dev_flags))
2822 return;
2823
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002824 hci_dev_lock(hdev);
2825
2826 if ((skb->len - 1) / num_rsp != sizeof(struct inquiry_info_with_rssi)) {
Szymon Janc138d22e2011-02-17 16:44:23 +01002827 struct inquiry_info_with_rssi_and_pscan_mode *info;
2828 info = (void *) (skb->data + 1);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002829
Johan Hedberge17acd42011-03-30 23:57:16 +03002830 for (; num_rsp; num_rsp--, info++) {
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002831 bacpy(&data.bdaddr, &info->bdaddr);
2832 data.pscan_rep_mode = info->pscan_rep_mode;
2833 data.pscan_period_mode = info->pscan_period_mode;
2834 data.pscan_mode = info->pscan_mode;
2835 memcpy(data.dev_class, info->dev_class, 3);
2836 data.clock_offset = info->clock_offset;
2837 data.rssi = info->rssi;
Marcel Holtmann41a96212008-07-14 20:13:48 +02002838 data.ssp_mode = 0x00;
Johan Hedberg31754052012-01-04 13:39:52 +02002839
2840 name_known = hci_inquiry_cache_update(hdev, &data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002841 false, &ssp);
Johan Hedberg48264f02011-11-09 13:58:58 +02002842 mgmt_device_found(hdev, &info->bdaddr, ACL_LINK, 0x00,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002843 info->dev_class, info->rssi,
2844 !name_known, ssp, NULL, 0);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002845 }
2846 } else {
2847 struct inquiry_info_with_rssi *info = (void *) (skb->data + 1);
2848
Johan Hedberge17acd42011-03-30 23:57:16 +03002849 for (; num_rsp; num_rsp--, info++) {
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002850 bacpy(&data.bdaddr, &info->bdaddr);
2851 data.pscan_rep_mode = info->pscan_rep_mode;
2852 data.pscan_period_mode = info->pscan_period_mode;
2853 data.pscan_mode = 0x00;
2854 memcpy(data.dev_class, info->dev_class, 3);
2855 data.clock_offset = info->clock_offset;
2856 data.rssi = info->rssi;
Marcel Holtmann41a96212008-07-14 20:13:48 +02002857 data.ssp_mode = 0x00;
Johan Hedberg31754052012-01-04 13:39:52 +02002858 name_known = hci_inquiry_cache_update(hdev, &data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002859 false, &ssp);
Johan Hedberg48264f02011-11-09 13:58:58 +02002860 mgmt_device_found(hdev, &info->bdaddr, ACL_LINK, 0x00,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002861 info->dev_class, info->rssi,
2862 !name_known, ssp, NULL, 0);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002863 }
2864 }
2865
2866 hci_dev_unlock(hdev);
2867}
2868
Gustavo Padovan6039aa72012-05-23 04:04:18 -03002869static void hci_remote_ext_features_evt(struct hci_dev *hdev,
2870 struct sk_buff *skb)
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002871{
Marcel Holtmann41a96212008-07-14 20:13:48 +02002872 struct hci_ev_remote_ext_features *ev = (void *) skb->data;
2873 struct hci_conn *conn;
2874
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002875 BT_DBG("%s", hdev->name);
Marcel Holtmann41a96212008-07-14 20:13:48 +02002876
Marcel Holtmann41a96212008-07-14 20:13:48 +02002877 hci_dev_lock(hdev);
2878
2879 conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
Johan Hedbergccd556f2010-11-10 17:11:51 +02002880 if (!conn)
2881 goto unlock;
Marcel Holtmann41a96212008-07-14 20:13:48 +02002882
Johan Hedbergccd556f2010-11-10 17:11:51 +02002883 if (!ev->status && ev->page == 0x01) {
2884 struct inquiry_entry *ie;
Marcel Holtmann41a96212008-07-14 20:13:48 +02002885
Andrei Emeltchenkocc11b9c2010-11-22 13:21:37 +02002886 ie = hci_inquiry_cache_lookup(hdev, &conn->dst);
2887 if (ie)
Johan Hedberg02b7cc62012-02-28 02:28:43 +02002888 ie->data.ssp_mode = (ev->features[0] & LMP_HOST_SSP);
Marcel Holtmann769be972008-07-14 20:13:49 +02002889
Johan Hedberg02b7cc62012-02-28 02:28:43 +02002890 if (ev->features[0] & LMP_HOST_SSP)
Johan Hedberg58a681e2012-01-16 06:47:28 +02002891 set_bit(HCI_CONN_SSP_ENABLED, &conn->flags);
Marcel Holtmann41a96212008-07-14 20:13:48 +02002892 }
2893
Johan Hedbergccd556f2010-11-10 17:11:51 +02002894 if (conn->state != BT_CONFIG)
2895 goto unlock;
2896
Johan Hedberg671267b2012-05-12 16:11:50 -03002897 if (!ev->status && !test_bit(HCI_CONN_MGMT_CONNECTED, &conn->flags)) {
Johan Hedberg127178d2010-11-18 22:22:29 +02002898 struct hci_cp_remote_name_req cp;
2899 memset(&cp, 0, sizeof(cp));
2900 bacpy(&cp.bdaddr, &conn->dst);
2901 cp.pscan_rep_mode = 0x02;
2902 hci_send_cmd(hdev, HCI_OP_REMOTE_NAME_REQ, sizeof(cp), &cp);
Johan Hedbergb644ba32012-01-17 21:48:47 +02002903 } else if (!test_and_set_bit(HCI_CONN_MGMT_CONNECTED, &conn->flags))
2904 mgmt_device_connected(hdev, &conn->dst, conn->type,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002905 conn->dst_type, 0, NULL, 0,
2906 conn->dev_class);
Johan Hedberg392599b2010-11-18 22:22:28 +02002907
Johan Hedberg127178d2010-11-18 22:22:29 +02002908 if (!hci_outgoing_auth_needed(hdev, conn)) {
Johan Hedbergccd556f2010-11-10 17:11:51 +02002909 conn->state = BT_CONNECTED;
2910 hci_proto_connect_cfm(conn, ev->status);
2911 hci_conn_put(conn);
2912 }
2913
2914unlock:
Marcel Holtmann41a96212008-07-14 20:13:48 +02002915 hci_dev_unlock(hdev);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002916}
2917
Gustavo Padovan6039aa72012-05-23 04:04:18 -03002918static void hci_sync_conn_complete_evt(struct hci_dev *hdev,
2919 struct sk_buff *skb)
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002920{
Marcel Holtmannb6a0dc82007-10-20 14:55:10 +02002921 struct hci_ev_sync_conn_complete *ev = (void *) skb->data;
2922 struct hci_conn *conn;
2923
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +03002924 BT_DBG("%s status 0x%2.2x", hdev->name, ev->status);
Marcel Holtmannb6a0dc82007-10-20 14:55:10 +02002925
2926 hci_dev_lock(hdev);
2927
2928 conn = hci_conn_hash_lookup_ba(hdev, ev->link_type, &ev->bdaddr);
Marcel Holtmann9dc0a3a2008-07-14 20:13:46 +02002929 if (!conn) {
2930 if (ev->link_type == ESCO_LINK)
2931 goto unlock;
2932
2933 conn = hci_conn_hash_lookup_ba(hdev, ESCO_LINK, &ev->bdaddr);
2934 if (!conn)
2935 goto unlock;
2936
2937 conn->type = SCO_LINK;
2938 }
Marcel Holtmannb6a0dc82007-10-20 14:55:10 +02002939
Marcel Holtmann732547f2009-04-19 19:14:14 +02002940 switch (ev->status) {
2941 case 0x00:
Marcel Holtmannb6a0dc82007-10-20 14:55:10 +02002942 conn->handle = __le16_to_cpu(ev->handle);
2943 conn->state = BT_CONNECTED;
Marcel Holtmann7d0db0a2008-07-14 20:13:51 +02002944
Marcel Holtmann9eba32b2009-08-22 14:19:26 -07002945 hci_conn_hold_device(conn);
Marcel Holtmann7d0db0a2008-07-14 20:13:51 +02002946 hci_conn_add_sysfs(conn);
Marcel Holtmann732547f2009-04-19 19:14:14 +02002947 break;
2948
Stephen Coe705e5712010-02-16 11:29:44 -05002949 case 0x11: /* Unsupported Feature or Parameter Value */
Marcel Holtmann732547f2009-04-19 19:14:14 +02002950 case 0x1c: /* SCO interval rejected */
Nick Pelly1038a002010-02-03 11:42:26 -08002951 case 0x1a: /* Unsupported Remote Feature */
Marcel Holtmann732547f2009-04-19 19:14:14 +02002952 case 0x1f: /* Unspecified error */
2953 if (conn->out && conn->attempt < 2) {
2954 conn->pkt_type = (hdev->esco_type & SCO_ESCO_MASK) |
2955 (hdev->esco_type & EDR_ESCO_MASK);
2956 hci_setup_sync(conn, conn->link->handle);
2957 goto unlock;
2958 }
2959 /* fall through */
2960
2961 default:
Marcel Holtmannb6a0dc82007-10-20 14:55:10 +02002962 conn->state = BT_CLOSED;
Marcel Holtmann732547f2009-04-19 19:14:14 +02002963 break;
2964 }
Marcel Holtmannb6a0dc82007-10-20 14:55:10 +02002965
2966 hci_proto_connect_cfm(conn, ev->status);
2967 if (ev->status)
2968 hci_conn_del(conn);
2969
2970unlock:
2971 hci_dev_unlock(hdev);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002972}
2973
Gustavo Padovan6039aa72012-05-23 04:04:18 -03002974static void hci_extended_inquiry_result_evt(struct hci_dev *hdev,
2975 struct sk_buff *skb)
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002976{
2977 struct inquiry_data data;
2978 struct extended_inquiry_info *info = (void *) (skb->data + 1);
2979 int num_rsp = *((__u8 *) skb->data);
Vishal Agarwal9d939d92012-04-26 19:19:56 +05302980 size_t eir_len;
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002981
2982 BT_DBG("%s num_rsp %d", hdev->name, num_rsp);
2983
2984 if (!num_rsp)
2985 return;
2986
Andre Guedes1519cc12012-03-21 00:03:38 -03002987 if (test_bit(HCI_PERIODIC_INQ, &hdev->dev_flags))
2988 return;
2989
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002990 hci_dev_lock(hdev);
2991
Johan Hedberge17acd42011-03-30 23:57:16 +03002992 for (; num_rsp; num_rsp--, info++) {
Johan Hedberg388fc8f2012-02-23 00:38:59 +02002993 bool name_known, ssp;
Johan Hedberg561aafb2012-01-04 13:31:59 +02002994
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002995 bacpy(&data.bdaddr, &info->bdaddr);
Szymon Janc138d22e2011-02-17 16:44:23 +01002996 data.pscan_rep_mode = info->pscan_rep_mode;
2997 data.pscan_period_mode = info->pscan_period_mode;
2998 data.pscan_mode = 0x00;
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002999 memcpy(data.dev_class, info->dev_class, 3);
Szymon Janc138d22e2011-02-17 16:44:23 +01003000 data.clock_offset = info->clock_offset;
3001 data.rssi = info->rssi;
Marcel Holtmann41a96212008-07-14 20:13:48 +02003002 data.ssp_mode = 0x01;
Johan Hedberg561aafb2012-01-04 13:31:59 +02003003
Johan Hedberga8b2d5c2012-01-08 23:11:15 +02003004 if (test_bit(HCI_MGMT, &hdev->dev_flags))
Johan Hedberg4ddb1932012-01-15 20:04:43 +02003005 name_known = eir_has_data_type(info->data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003006 sizeof(info->data),
3007 EIR_NAME_COMPLETE);
Johan Hedberg561aafb2012-01-04 13:31:59 +02003008 else
3009 name_known = true;
3010
Johan Hedberg388fc8f2012-02-23 00:38:59 +02003011 name_known = hci_inquiry_cache_update(hdev, &data, name_known,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003012 &ssp);
Vishal Agarwal9d939d92012-04-26 19:19:56 +05303013 eir_len = eir_get_length(info->data, sizeof(info->data));
Johan Hedberg48264f02011-11-09 13:58:58 +02003014 mgmt_device_found(hdev, &info->bdaddr, ACL_LINK, 0x00,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003015 info->dev_class, info->rssi, !name_known,
Vishal Agarwal9d939d92012-04-26 19:19:56 +05303016 ssp, info->data, eir_len);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02003017 }
3018
3019 hci_dev_unlock(hdev);
3020}
3021
Johan Hedberg1c2e0042012-06-08 23:31:13 +08003022static void hci_key_refresh_complete_evt(struct hci_dev *hdev,
3023 struct sk_buff *skb)
3024{
3025 struct hci_ev_key_refresh_complete *ev = (void *) skb->data;
3026 struct hci_conn *conn;
3027
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +03003028 BT_DBG("%s status 0x%2.2x handle 0x%4.4x", hdev->name, ev->status,
Johan Hedberg1c2e0042012-06-08 23:31:13 +08003029 __le16_to_cpu(ev->handle));
3030
3031 hci_dev_lock(hdev);
3032
3033 conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
3034 if (!conn)
3035 goto unlock;
3036
3037 if (!ev->status)
3038 conn->sec_level = conn->pending_sec_level;
3039
3040 clear_bit(HCI_CONN_ENCRYPT_PEND, &conn->flags);
3041
3042 if (ev->status && conn->state == BT_CONNECTED) {
Andre Guedesbed71742013-01-30 11:50:56 -03003043 hci_disconnect(conn, HCI_ERROR_AUTH_FAILURE);
Johan Hedberg1c2e0042012-06-08 23:31:13 +08003044 hci_conn_put(conn);
3045 goto unlock;
3046 }
3047
3048 if (conn->state == BT_CONFIG) {
3049 if (!ev->status)
3050 conn->state = BT_CONNECTED;
3051
3052 hci_proto_connect_cfm(conn, ev->status);
3053 hci_conn_put(conn);
3054 } else {
3055 hci_auth_cfm(conn, ev->status);
3056
3057 hci_conn_hold(conn);
3058 conn->disc_timeout = HCI_DISCONN_TIMEOUT;
3059 hci_conn_put(conn);
3060 }
3061
3062unlock:
3063 hci_dev_unlock(hdev);
3064}
3065
Gustavo Padovan6039aa72012-05-23 04:04:18 -03003066static u8 hci_get_auth_req(struct hci_conn *conn)
Johan Hedberg17fa4b92011-01-25 13:28:33 +02003067{
3068 /* If remote requests dedicated bonding follow that lead */
3069 if (conn->remote_auth == 0x02 || conn->remote_auth == 0x03) {
3070 /* If both remote and local IO capabilities allow MITM
3071 * protection then require it, otherwise don't */
3072 if (conn->remote_cap == 0x03 || conn->io_capability == 0x03)
3073 return 0x02;
3074 else
3075 return 0x03;
3076 }
3077
3078 /* If remote requests no-bonding follow that lead */
3079 if (conn->remote_auth == 0x00 || conn->remote_auth == 0x01)
Waldemar Rymarkiewicz58797bf2011-04-28 12:07:58 +02003080 return conn->remote_auth | (conn->auth_type & 0x01);
Johan Hedberg17fa4b92011-01-25 13:28:33 +02003081
3082 return conn->auth_type;
3083}
3084
Gustavo Padovan6039aa72012-05-23 04:04:18 -03003085static void hci_io_capa_request_evt(struct hci_dev *hdev, struct sk_buff *skb)
Marcel Holtmann04936842008-07-14 20:13:48 +02003086{
3087 struct hci_ev_io_capa_request *ev = (void *) skb->data;
3088 struct hci_conn *conn;
3089
3090 BT_DBG("%s", hdev->name);
3091
3092 hci_dev_lock(hdev);
3093
3094 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
Johan Hedberg03b555e2011-01-04 15:40:05 +02003095 if (!conn)
3096 goto unlock;
Marcel Holtmann04936842008-07-14 20:13:48 +02003097
Johan Hedberg03b555e2011-01-04 15:40:05 +02003098 hci_conn_hold(conn);
3099
Johan Hedberga8b2d5c2012-01-08 23:11:15 +02003100 if (!test_bit(HCI_MGMT, &hdev->dev_flags))
Johan Hedberg03b555e2011-01-04 15:40:05 +02003101 goto unlock;
3102
Johan Hedberga8b2d5c2012-01-08 23:11:15 +02003103 if (test_bit(HCI_PAIRABLE, &hdev->dev_flags) ||
Gustavo Padovan807deac2012-05-17 00:36:24 -03003104 (conn->remote_auth & ~0x01) == HCI_AT_NO_BONDING) {
Johan Hedberg17fa4b92011-01-25 13:28:33 +02003105 struct hci_cp_io_capability_reply cp;
3106
3107 bacpy(&cp.bdaddr, &ev->bdaddr);
Hemant Gupta7a7f1e72012-01-16 13:34:29 +05303108 /* Change the IO capability from KeyboardDisplay
3109 * to DisplayYesNo as it is not supported by BT spec. */
3110 cp.capability = (conn->io_capability == 0x04) ?
3111 0x01 : conn->io_capability;
Johan Hedberg7cbc9bd2011-04-28 11:29:04 -07003112 conn->auth_type = hci_get_auth_req(conn);
3113 cp.authentication = conn->auth_type;
Johan Hedberg17fa4b92011-01-25 13:28:33 +02003114
Gustavo Padovan8fc9ced2012-05-23 04:04:21 -03003115 if (hci_find_remote_oob_data(hdev, &conn->dst) &&
3116 (conn->out || test_bit(HCI_CONN_REMOTE_OOB, &conn->flags)))
Szymon Jancce85ee12011-03-22 13:12:23 +01003117 cp.oob_data = 0x01;
3118 else
3119 cp.oob_data = 0x00;
3120
Johan Hedberg17fa4b92011-01-25 13:28:33 +02003121 hci_send_cmd(hdev, HCI_OP_IO_CAPABILITY_REPLY,
Gustavo Padovan807deac2012-05-17 00:36:24 -03003122 sizeof(cp), &cp);
Johan Hedberg03b555e2011-01-04 15:40:05 +02003123 } else {
3124 struct hci_cp_io_capability_neg_reply cp;
3125
3126 bacpy(&cp.bdaddr, &ev->bdaddr);
Andrei Emeltchenko9f5a0d72011-11-07 14:20:25 +02003127 cp.reason = HCI_ERROR_PAIRING_NOT_ALLOWED;
Johan Hedberg03b555e2011-01-04 15:40:05 +02003128
3129 hci_send_cmd(hdev, HCI_OP_IO_CAPABILITY_NEG_REPLY,
Gustavo Padovan807deac2012-05-17 00:36:24 -03003130 sizeof(cp), &cp);
Johan Hedberg03b555e2011-01-04 15:40:05 +02003131 }
3132
3133unlock:
3134 hci_dev_unlock(hdev);
3135}
3136
Gustavo Padovan6039aa72012-05-23 04:04:18 -03003137static void hci_io_capa_reply_evt(struct hci_dev *hdev, struct sk_buff *skb)
Johan Hedberg03b555e2011-01-04 15:40:05 +02003138{
3139 struct hci_ev_io_capa_reply *ev = (void *) skb->data;
3140 struct hci_conn *conn;
3141
3142 BT_DBG("%s", hdev->name);
3143
3144 hci_dev_lock(hdev);
3145
3146 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
3147 if (!conn)
3148 goto unlock;
3149
Johan Hedberg03b555e2011-01-04 15:40:05 +02003150 conn->remote_cap = ev->capability;
Johan Hedberg03b555e2011-01-04 15:40:05 +02003151 conn->remote_auth = ev->authentication;
Johan Hedberg58a681e2012-01-16 06:47:28 +02003152 if (ev->oob_data)
3153 set_bit(HCI_CONN_REMOTE_OOB, &conn->flags);
Johan Hedberg03b555e2011-01-04 15:40:05 +02003154
3155unlock:
Marcel Holtmann04936842008-07-14 20:13:48 +02003156 hci_dev_unlock(hdev);
3157}
3158
Gustavo Padovan6039aa72012-05-23 04:04:18 -03003159static void hci_user_confirm_request_evt(struct hci_dev *hdev,
3160 struct sk_buff *skb)
Johan Hedberga5c29682011-02-19 12:05:57 -03003161{
3162 struct hci_ev_user_confirm_req *ev = (void *) skb->data;
Johan Hedberg55bc1a32011-04-28 11:28:56 -07003163 int loc_mitm, rem_mitm, confirm_hint = 0;
Johan Hedberg7a828902011-04-28 11:28:53 -07003164 struct hci_conn *conn;
Johan Hedberga5c29682011-02-19 12:05:57 -03003165
3166 BT_DBG("%s", hdev->name);
3167
3168 hci_dev_lock(hdev);
3169
Johan Hedberga8b2d5c2012-01-08 23:11:15 +02003170 if (!test_bit(HCI_MGMT, &hdev->dev_flags))
Johan Hedberg7a828902011-04-28 11:28:53 -07003171 goto unlock;
Johan Hedberga5c29682011-02-19 12:05:57 -03003172
Johan Hedberg7a828902011-04-28 11:28:53 -07003173 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
3174 if (!conn)
3175 goto unlock;
3176
3177 loc_mitm = (conn->auth_type & 0x01);
3178 rem_mitm = (conn->remote_auth & 0x01);
3179
3180 /* If we require MITM but the remote device can't provide that
3181 * (it has NoInputNoOutput) then reject the confirmation
3182 * request. The only exception is when we're dedicated bonding
3183 * initiators (connect_cfm_cb set) since then we always have the MITM
3184 * bit set. */
3185 if (!conn->connect_cfm_cb && loc_mitm && conn->remote_cap == 0x03) {
3186 BT_DBG("Rejecting request: remote device can't provide MITM");
3187 hci_send_cmd(hdev, HCI_OP_USER_CONFIRM_NEG_REPLY,
Gustavo Padovan807deac2012-05-17 00:36:24 -03003188 sizeof(ev->bdaddr), &ev->bdaddr);
Johan Hedberg7a828902011-04-28 11:28:53 -07003189 goto unlock;
3190 }
3191
3192 /* If no side requires MITM protection; auto-accept */
3193 if ((!loc_mitm || conn->remote_cap == 0x03) &&
Gustavo Padovan807deac2012-05-17 00:36:24 -03003194 (!rem_mitm || conn->io_capability == 0x03)) {
Johan Hedberg55bc1a32011-04-28 11:28:56 -07003195
3196 /* If we're not the initiators request authorization to
3197 * proceed from user space (mgmt_user_confirm with
3198 * confirm_hint set to 1). */
Johan Hedberg51a8efd2012-01-16 06:10:31 +02003199 if (!test_bit(HCI_CONN_AUTH_PEND, &conn->flags)) {
Johan Hedberg55bc1a32011-04-28 11:28:56 -07003200 BT_DBG("Confirming auto-accept as acceptor");
3201 confirm_hint = 1;
3202 goto confirm;
3203 }
3204
Johan Hedberg9f616562011-04-28 11:28:54 -07003205 BT_DBG("Auto-accept of user confirmation with %ums delay",
Gustavo Padovan807deac2012-05-17 00:36:24 -03003206 hdev->auto_accept_delay);
Johan Hedberg9f616562011-04-28 11:28:54 -07003207
3208 if (hdev->auto_accept_delay > 0) {
3209 int delay = msecs_to_jiffies(hdev->auto_accept_delay);
3210 mod_timer(&conn->auto_accept_timer, jiffies + delay);
3211 goto unlock;
3212 }
3213
Johan Hedberg7a828902011-04-28 11:28:53 -07003214 hci_send_cmd(hdev, HCI_OP_USER_CONFIRM_REPLY,
Gustavo Padovan807deac2012-05-17 00:36:24 -03003215 sizeof(ev->bdaddr), &ev->bdaddr);
Johan Hedberg7a828902011-04-28 11:28:53 -07003216 goto unlock;
3217 }
3218
Johan Hedberg55bc1a32011-04-28 11:28:56 -07003219confirm:
Johan Hedberg272d90d2012-02-09 15:26:12 +02003220 mgmt_user_confirm_request(hdev, &ev->bdaddr, ACL_LINK, 0, ev->passkey,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003221 confirm_hint);
Johan Hedberg7a828902011-04-28 11:28:53 -07003222
3223unlock:
Johan Hedberga5c29682011-02-19 12:05:57 -03003224 hci_dev_unlock(hdev);
3225}
3226
Gustavo Padovan6039aa72012-05-23 04:04:18 -03003227static void hci_user_passkey_request_evt(struct hci_dev *hdev,
3228 struct sk_buff *skb)
Brian Gix1143d452011-11-23 08:28:34 -08003229{
3230 struct hci_ev_user_passkey_req *ev = (void *) skb->data;
3231
3232 BT_DBG("%s", hdev->name);
3233
Johan Hedberga8b2d5c2012-01-08 23:11:15 +02003234 if (test_bit(HCI_MGMT, &hdev->dev_flags))
Johan Hedberg272d90d2012-02-09 15:26:12 +02003235 mgmt_user_passkey_request(hdev, &ev->bdaddr, ACL_LINK, 0);
Brian Gix1143d452011-11-23 08:28:34 -08003236}
3237
Johan Hedberg92a25252012-09-06 18:39:26 +03003238static void hci_user_passkey_notify_evt(struct hci_dev *hdev,
3239 struct sk_buff *skb)
3240{
3241 struct hci_ev_user_passkey_notify *ev = (void *) skb->data;
3242 struct hci_conn *conn;
3243
3244 BT_DBG("%s", hdev->name);
3245
3246 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
3247 if (!conn)
3248 return;
3249
3250 conn->passkey_notify = __le32_to_cpu(ev->passkey);
3251 conn->passkey_entered = 0;
3252
3253 if (test_bit(HCI_MGMT, &hdev->dev_flags))
3254 mgmt_user_passkey_notify(hdev, &conn->dst, conn->type,
3255 conn->dst_type, conn->passkey_notify,
3256 conn->passkey_entered);
3257}
3258
3259static void hci_keypress_notify_evt(struct hci_dev *hdev, struct sk_buff *skb)
3260{
3261 struct hci_ev_keypress_notify *ev = (void *) skb->data;
3262 struct hci_conn *conn;
3263
3264 BT_DBG("%s", hdev->name);
3265
3266 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
3267 if (!conn)
3268 return;
3269
3270 switch (ev->type) {
3271 case HCI_KEYPRESS_STARTED:
3272 conn->passkey_entered = 0;
3273 return;
3274
3275 case HCI_KEYPRESS_ENTERED:
3276 conn->passkey_entered++;
3277 break;
3278
3279 case HCI_KEYPRESS_ERASED:
3280 conn->passkey_entered--;
3281 break;
3282
3283 case HCI_KEYPRESS_CLEARED:
3284 conn->passkey_entered = 0;
3285 break;
3286
3287 case HCI_KEYPRESS_COMPLETED:
3288 return;
3289 }
3290
3291 if (test_bit(HCI_MGMT, &hdev->dev_flags))
3292 mgmt_user_passkey_notify(hdev, &conn->dst, conn->type,
3293 conn->dst_type, conn->passkey_notify,
3294 conn->passkey_entered);
3295}
3296
Gustavo Padovan6039aa72012-05-23 04:04:18 -03003297static void hci_simple_pair_complete_evt(struct hci_dev *hdev,
3298 struct sk_buff *skb)
Marcel Holtmann04936842008-07-14 20:13:48 +02003299{
3300 struct hci_ev_simple_pair_complete *ev = (void *) skb->data;
3301 struct hci_conn *conn;
3302
3303 BT_DBG("%s", hdev->name);
3304
3305 hci_dev_lock(hdev);
3306
3307 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
Johan Hedberg2a611692011-02-19 12:06:00 -03003308 if (!conn)
3309 goto unlock;
Marcel Holtmann04936842008-07-14 20:13:48 +02003310
Johan Hedberg2a611692011-02-19 12:06:00 -03003311 /* To avoid duplicate auth_failed events to user space we check
3312 * the HCI_CONN_AUTH_PEND flag which will be set if we
3313 * initiated the authentication. A traditional auth_complete
3314 * event gets always produced as initiator and is also mapped to
3315 * the mgmt_auth_failed event */
Mikel Astizfa1bd912012-08-09 09:52:29 +02003316 if (!test_bit(HCI_CONN_AUTH_PEND, &conn->flags) && ev->status)
Johan Hedbergbab73cb2012-02-09 16:07:29 +02003317 mgmt_auth_failed(hdev, &conn->dst, conn->type, conn->dst_type,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003318 ev->status);
Johan Hedberg2a611692011-02-19 12:06:00 -03003319
3320 hci_conn_put(conn);
3321
3322unlock:
Marcel Holtmann04936842008-07-14 20:13:48 +02003323 hci_dev_unlock(hdev);
3324}
3325
Gustavo Padovan6039aa72012-05-23 04:04:18 -03003326static void hci_remote_host_features_evt(struct hci_dev *hdev,
3327 struct sk_buff *skb)
Marcel Holtmann41a96212008-07-14 20:13:48 +02003328{
3329 struct hci_ev_remote_host_features *ev = (void *) skb->data;
3330 struct inquiry_entry *ie;
3331
3332 BT_DBG("%s", hdev->name);
3333
3334 hci_dev_lock(hdev);
3335
Andrei Emeltchenkocc11b9c2010-11-22 13:21:37 +02003336 ie = hci_inquiry_cache_lookup(hdev, &ev->bdaddr);
3337 if (ie)
Johan Hedberg02b7cc62012-02-28 02:28:43 +02003338 ie->data.ssp_mode = (ev->features[0] & LMP_HOST_SSP);
Marcel Holtmann41a96212008-07-14 20:13:48 +02003339
3340 hci_dev_unlock(hdev);
3341}
3342
Gustavo Padovan6039aa72012-05-23 04:04:18 -03003343static void hci_remote_oob_data_request_evt(struct hci_dev *hdev,
3344 struct sk_buff *skb)
Szymon Janc2763eda2011-03-22 13:12:22 +01003345{
3346 struct hci_ev_remote_oob_data_request *ev = (void *) skb->data;
3347 struct oob_data *data;
3348
3349 BT_DBG("%s", hdev->name);
3350
3351 hci_dev_lock(hdev);
3352
Johan Hedberga8b2d5c2012-01-08 23:11:15 +02003353 if (!test_bit(HCI_MGMT, &hdev->dev_flags))
Szymon Jance1ba1f12011-04-06 13:01:59 +02003354 goto unlock;
3355
Szymon Janc2763eda2011-03-22 13:12:22 +01003356 data = hci_find_remote_oob_data(hdev, &ev->bdaddr);
3357 if (data) {
3358 struct hci_cp_remote_oob_data_reply cp;
3359
3360 bacpy(&cp.bdaddr, &ev->bdaddr);
3361 memcpy(cp.hash, data->hash, sizeof(cp.hash));
3362 memcpy(cp.randomizer, data->randomizer, sizeof(cp.randomizer));
3363
3364 hci_send_cmd(hdev, HCI_OP_REMOTE_OOB_DATA_REPLY, sizeof(cp),
Gustavo Padovan807deac2012-05-17 00:36:24 -03003365 &cp);
Szymon Janc2763eda2011-03-22 13:12:22 +01003366 } else {
3367 struct hci_cp_remote_oob_data_neg_reply cp;
3368
3369 bacpy(&cp.bdaddr, &ev->bdaddr);
3370 hci_send_cmd(hdev, HCI_OP_REMOTE_OOB_DATA_NEG_REPLY, sizeof(cp),
Gustavo Padovan807deac2012-05-17 00:36:24 -03003371 &cp);
Szymon Janc2763eda2011-03-22 13:12:22 +01003372 }
3373
Szymon Jance1ba1f12011-04-06 13:01:59 +02003374unlock:
Szymon Janc2763eda2011-03-22 13:12:22 +01003375 hci_dev_unlock(hdev);
3376}
3377
Andrei Emeltchenkod5e91192012-10-25 15:20:44 +03003378static void hci_phy_link_complete_evt(struct hci_dev *hdev,
3379 struct sk_buff *skb)
3380{
3381 struct hci_ev_phy_link_complete *ev = (void *) skb->data;
3382 struct hci_conn *hcon, *bredr_hcon;
3383
3384 BT_DBG("%s handle 0x%2.2x status 0x%2.2x", hdev->name, ev->phy_handle,
3385 ev->status);
3386
3387 hci_dev_lock(hdev);
3388
3389 hcon = hci_conn_hash_lookup_handle(hdev, ev->phy_handle);
3390 if (!hcon) {
3391 hci_dev_unlock(hdev);
3392 return;
3393 }
3394
3395 if (ev->status) {
3396 hci_conn_del(hcon);
3397 hci_dev_unlock(hdev);
3398 return;
3399 }
3400
3401 bredr_hcon = hcon->amp_mgr->l2cap_conn->hcon;
3402
3403 hcon->state = BT_CONNECTED;
3404 bacpy(&hcon->dst, &bredr_hcon->dst);
3405
3406 hci_conn_hold(hcon);
3407 hcon->disc_timeout = HCI_DISCONN_TIMEOUT;
3408 hci_conn_put(hcon);
3409
3410 hci_conn_hold_device(hcon);
3411 hci_conn_add_sysfs(hcon);
3412
Andrei Emeltchenkocf70ff22012-10-31 15:46:36 +02003413 amp_physical_cfm(bredr_hcon, hcon);
3414
Andrei Emeltchenkod5e91192012-10-25 15:20:44 +03003415 hci_dev_unlock(hdev);
Andrei Emeltchenkod5e91192012-10-25 15:20:44 +03003416}
3417
Andrei Emeltchenko27695fb2012-10-25 15:20:45 +03003418static void hci_loglink_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
3419{
3420 struct hci_ev_logical_link_complete *ev = (void *) skb->data;
3421 struct hci_conn *hcon;
3422 struct hci_chan *hchan;
3423 struct amp_mgr *mgr;
3424
3425 BT_DBG("%s log_handle 0x%4.4x phy_handle 0x%2.2x status 0x%2.2x",
3426 hdev->name, le16_to_cpu(ev->handle), ev->phy_handle,
3427 ev->status);
3428
3429 hcon = hci_conn_hash_lookup_handle(hdev, ev->phy_handle);
3430 if (!hcon)
3431 return;
3432
3433 /* Create AMP hchan */
3434 hchan = hci_chan_create(hcon);
3435 if (!hchan)
3436 return;
3437
3438 hchan->handle = le16_to_cpu(ev->handle);
3439
3440 BT_DBG("hcon %p mgr %p hchan %p", hcon, hcon->amp_mgr, hchan);
3441
3442 mgr = hcon->amp_mgr;
3443 if (mgr && mgr->bredr_chan) {
3444 struct l2cap_chan *bredr_chan = mgr->bredr_chan;
3445
3446 l2cap_chan_lock(bredr_chan);
3447
3448 bredr_chan->conn->mtu = hdev->block_mtu;
3449 l2cap_logical_cfm(bredr_chan, hchan, 0);
3450 hci_conn_hold(hcon);
3451
3452 l2cap_chan_unlock(bredr_chan);
3453 }
3454}
3455
Andrei Emeltchenko606e2a12012-10-31 15:46:31 +02003456static void hci_disconn_loglink_complete_evt(struct hci_dev *hdev,
3457 struct sk_buff *skb)
3458{
3459 struct hci_ev_disconn_logical_link_complete *ev = (void *) skb->data;
3460 struct hci_chan *hchan;
3461
3462 BT_DBG("%s log handle 0x%4.4x status 0x%2.2x", hdev->name,
3463 le16_to_cpu(ev->handle), ev->status);
3464
3465 if (ev->status)
3466 return;
3467
3468 hci_dev_lock(hdev);
3469
3470 hchan = hci_chan_lookup_handle(hdev, le16_to_cpu(ev->handle));
3471 if (!hchan)
3472 goto unlock;
3473
3474 amp_destroy_logical_link(hchan, ev->reason);
3475
3476unlock:
3477 hci_dev_unlock(hdev);
3478}
3479
Andrei Emeltchenko9eef6b32012-10-31 15:46:32 +02003480static void hci_disconn_phylink_complete_evt(struct hci_dev *hdev,
3481 struct sk_buff *skb)
3482{
3483 struct hci_ev_disconn_phy_link_complete *ev = (void *) skb->data;
3484 struct hci_conn *hcon;
3485
3486 BT_DBG("%s status 0x%2.2x", hdev->name, ev->status);
3487
3488 if (ev->status)
3489 return;
3490
3491 hci_dev_lock(hdev);
3492
3493 hcon = hci_conn_hash_lookup_handle(hdev, ev->phy_handle);
3494 if (hcon) {
3495 hcon->state = BT_CLOSED;
3496 hci_conn_del(hcon);
3497 }
3498
3499 hci_dev_unlock(hdev);
3500}
3501
Gustavo Padovan6039aa72012-05-23 04:04:18 -03003502static void hci_le_conn_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
Ville Tervofcd89c02011-02-10 22:38:47 -03003503{
3504 struct hci_ev_le_conn_complete *ev = (void *) skb->data;
3505 struct hci_conn *conn;
3506
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +03003507 BT_DBG("%s status 0x%2.2x", hdev->name, ev->status);
Ville Tervofcd89c02011-02-10 22:38:47 -03003508
3509 hci_dev_lock(hdev);
3510
Andre Guedesb47a09b2012-07-27 15:10:15 -03003511 conn = hci_conn_hash_lookup_state(hdev, LE_LINK, BT_CONNECT);
Ville Tervob62f3282011-02-10 22:38:50 -03003512 if (!conn) {
3513 conn = hci_conn_add(hdev, LE_LINK, &ev->bdaddr);
3514 if (!conn) {
3515 BT_ERR("No memory for new connection");
Andre Guedes230fd162012-07-27 15:10:10 -03003516 goto unlock;
Ville Tervob62f3282011-02-10 22:38:50 -03003517 }
Andre Guedes29b79882011-05-31 14:20:54 -03003518
3519 conn->dst_type = ev->bdaddr_type;
Andre Guedesb9b343d2012-07-27 15:10:11 -03003520
3521 if (ev->role == LE_CONN_ROLE_MASTER) {
3522 conn->out = true;
3523 conn->link_mode |= HCI_LM_MASTER;
3524 }
Ville Tervob62f3282011-02-10 22:38:50 -03003525 }
Ville Tervofcd89c02011-02-10 22:38:47 -03003526
Andre Guedescd17dec2012-07-27 15:10:16 -03003527 if (ev->status) {
3528 mgmt_connect_failed(hdev, &conn->dst, conn->type,
3529 conn->dst_type, ev->status);
3530 hci_proto_connect_cfm(conn, ev->status);
3531 conn->state = BT_CLOSED;
3532 hci_conn_del(conn);
3533 goto unlock;
3534 }
3535
Johan Hedbergb644ba32012-01-17 21:48:47 +02003536 if (!test_and_set_bit(HCI_CONN_MGMT_CONNECTED, &conn->flags))
3537 mgmt_device_connected(hdev, &ev->bdaddr, conn->type,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003538 conn->dst_type, 0, NULL, 0, NULL);
Vinicius Costa Gomes83bc71b2011-05-06 18:41:43 -03003539
Vinicius Costa Gomes7b5c0d52011-06-09 18:50:50 -03003540 conn->sec_level = BT_SECURITY_LOW;
Ville Tervofcd89c02011-02-10 22:38:47 -03003541 conn->handle = __le16_to_cpu(ev->handle);
3542 conn->state = BT_CONNECTED;
3543
3544 hci_conn_hold_device(conn);
3545 hci_conn_add_sysfs(conn);
3546
3547 hci_proto_connect_cfm(conn, ev->status);
3548
3549unlock:
3550 hci_dev_unlock(hdev);
3551}
3552
Gustavo Padovan6039aa72012-05-23 04:04:18 -03003553static void hci_le_adv_report_evt(struct hci_dev *hdev, struct sk_buff *skb)
Andre Guedes9aa04c92011-05-26 16:23:51 -03003554{
Andre Guedese95beb42011-09-26 20:48:35 -03003555 u8 num_reports = skb->data[0];
3556 void *ptr = &skb->data[1];
Andre Guedes3c9e9192012-01-10 18:20:50 -03003557 s8 rssi;
Andre Guedes9aa04c92011-05-26 16:23:51 -03003558
Andre Guedese95beb42011-09-26 20:48:35 -03003559 while (num_reports--) {
3560 struct hci_ev_le_advertising_info *ev = ptr;
Andre Guedes9aa04c92011-05-26 16:23:51 -03003561
Andre Guedes3c9e9192012-01-10 18:20:50 -03003562 rssi = ev->data[ev->length];
3563 mgmt_device_found(hdev, &ev->bdaddr, LE_LINK, ev->bdaddr_type,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003564 NULL, rssi, 0, 1, ev->data, ev->length);
Andre Guedes3c9e9192012-01-10 18:20:50 -03003565
Andre Guedese95beb42011-09-26 20:48:35 -03003566 ptr += sizeof(*ev) + ev->length + 1;
Andre Guedes9aa04c92011-05-26 16:23:51 -03003567 }
Andre Guedes9aa04c92011-05-26 16:23:51 -03003568}
3569
Gustavo Padovan6039aa72012-05-23 04:04:18 -03003570static void hci_le_ltk_request_evt(struct hci_dev *hdev, struct sk_buff *skb)
Vinicius Costa Gomesa7a595f2011-06-09 18:50:47 -03003571{
3572 struct hci_ev_le_ltk_req *ev = (void *) skb->data;
3573 struct hci_cp_le_ltk_reply cp;
Vinicius Costa Gomesbea710f2011-07-07 18:59:37 -03003574 struct hci_cp_le_ltk_neg_reply neg;
Vinicius Costa Gomesa7a595f2011-06-09 18:50:47 -03003575 struct hci_conn *conn;
Vinicius Costa Gomesc9839a12012-02-02 21:08:01 -03003576 struct smp_ltk *ltk;
Vinicius Costa Gomesa7a595f2011-06-09 18:50:47 -03003577
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +03003578 BT_DBG("%s handle 0x%4.4x", hdev->name, __le16_to_cpu(ev->handle));
Vinicius Costa Gomesa7a595f2011-06-09 18:50:47 -03003579
3580 hci_dev_lock(hdev);
3581
3582 conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
Vinicius Costa Gomesbea710f2011-07-07 18:59:37 -03003583 if (conn == NULL)
3584 goto not_found;
Vinicius Costa Gomesa7a595f2011-06-09 18:50:47 -03003585
Vinicius Costa Gomesbea710f2011-07-07 18:59:37 -03003586 ltk = hci_find_ltk(hdev, ev->ediv, ev->random);
3587 if (ltk == NULL)
3588 goto not_found;
3589
3590 memcpy(cp.ltk, ltk->val, sizeof(ltk->val));
Vinicius Costa Gomesa7a595f2011-06-09 18:50:47 -03003591 cp.handle = cpu_to_le16(conn->handle);
Vinicius Costa Gomesc9839a12012-02-02 21:08:01 -03003592
3593 if (ltk->authenticated)
3594 conn->sec_level = BT_SECURITY_HIGH;
Vinicius Costa Gomesa7a595f2011-06-09 18:50:47 -03003595
3596 hci_send_cmd(hdev, HCI_OP_LE_LTK_REPLY, sizeof(cp), &cp);
3597
Vinicius Costa Gomesc9839a12012-02-02 21:08:01 -03003598 if (ltk->type & HCI_SMP_STK) {
3599 list_del(&ltk->list);
3600 kfree(ltk);
3601 }
3602
Vinicius Costa Gomesa7a595f2011-06-09 18:50:47 -03003603 hci_dev_unlock(hdev);
Vinicius Costa Gomesbea710f2011-07-07 18:59:37 -03003604
3605 return;
3606
3607not_found:
3608 neg.handle = ev->handle;
3609 hci_send_cmd(hdev, HCI_OP_LE_LTK_NEG_REPLY, sizeof(neg), &neg);
3610 hci_dev_unlock(hdev);
Vinicius Costa Gomesa7a595f2011-06-09 18:50:47 -03003611}
3612
Gustavo Padovan6039aa72012-05-23 04:04:18 -03003613static void hci_le_meta_evt(struct hci_dev *hdev, struct sk_buff *skb)
Ville Tervofcd89c02011-02-10 22:38:47 -03003614{
3615 struct hci_ev_le_meta *le_ev = (void *) skb->data;
3616
3617 skb_pull(skb, sizeof(*le_ev));
3618
3619 switch (le_ev->subevent) {
3620 case HCI_EV_LE_CONN_COMPLETE:
3621 hci_le_conn_complete_evt(hdev, skb);
3622 break;
3623
Andre Guedes9aa04c92011-05-26 16:23:51 -03003624 case HCI_EV_LE_ADVERTISING_REPORT:
3625 hci_le_adv_report_evt(hdev, skb);
3626 break;
3627
Vinicius Costa Gomesa7a595f2011-06-09 18:50:47 -03003628 case HCI_EV_LE_LTK_REQ:
3629 hci_le_ltk_request_evt(hdev, skb);
3630 break;
3631
Ville Tervofcd89c02011-02-10 22:38:47 -03003632 default:
3633 break;
3634 }
3635}
3636
Andrei Emeltchenko9495b2e2012-09-27 17:26:22 +03003637static void hci_chan_selected_evt(struct hci_dev *hdev, struct sk_buff *skb)
3638{
3639 struct hci_ev_channel_selected *ev = (void *) skb->data;
3640 struct hci_conn *hcon;
3641
3642 BT_DBG("%s handle 0x%2.2x", hdev->name, ev->phy_handle);
3643
3644 skb_pull(skb, sizeof(*ev));
3645
3646 hcon = hci_conn_hash_lookup_handle(hdev, ev->phy_handle);
3647 if (!hcon)
3648 return;
3649
3650 amp_read_loc_assoc_final_data(hdev, hcon);
3651}
3652
Linus Torvalds1da177e2005-04-16 15:20:36 -07003653void hci_event_packet(struct hci_dev *hdev, struct sk_buff *skb)
3654{
Marcel Holtmanna9de9242007-10-20 13:33:56 +02003655 struct hci_event_hdr *hdr = (void *) skb->data;
3656 __u8 event = hdr->evt;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003657
3658 skb_pull(skb, HCI_EVENT_HDR_SIZE);
3659
Marcel Holtmanna9de9242007-10-20 13:33:56 +02003660 switch (event) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003661 case HCI_EV_INQUIRY_COMPLETE:
3662 hci_inquiry_complete_evt(hdev, skb);
3663 break;
3664
3665 case HCI_EV_INQUIRY_RESULT:
3666 hci_inquiry_result_evt(hdev, skb);
3667 break;
3668
Marcel Holtmanna9de9242007-10-20 13:33:56 +02003669 case HCI_EV_CONN_COMPLETE:
3670 hci_conn_complete_evt(hdev, skb);
Marcel Holtmann21d9e302005-09-13 01:32:25 +02003671 break;
3672
Linus Torvalds1da177e2005-04-16 15:20:36 -07003673 case HCI_EV_CONN_REQUEST:
3674 hci_conn_request_evt(hdev, skb);
3675 break;
3676
Linus Torvalds1da177e2005-04-16 15:20:36 -07003677 case HCI_EV_DISCONN_COMPLETE:
3678 hci_disconn_complete_evt(hdev, skb);
3679 break;
3680
Linus Torvalds1da177e2005-04-16 15:20:36 -07003681 case HCI_EV_AUTH_COMPLETE:
3682 hci_auth_complete_evt(hdev, skb);
3683 break;
3684
Marcel Holtmanna9de9242007-10-20 13:33:56 +02003685 case HCI_EV_REMOTE_NAME:
3686 hci_remote_name_evt(hdev, skb);
3687 break;
3688
Linus Torvalds1da177e2005-04-16 15:20:36 -07003689 case HCI_EV_ENCRYPT_CHANGE:
3690 hci_encrypt_change_evt(hdev, skb);
3691 break;
3692
Marcel Holtmanna9de9242007-10-20 13:33:56 +02003693 case HCI_EV_CHANGE_LINK_KEY_COMPLETE:
3694 hci_change_link_key_complete_evt(hdev, skb);
3695 break;
3696
3697 case HCI_EV_REMOTE_FEATURES:
3698 hci_remote_features_evt(hdev, skb);
3699 break;
3700
Marcel Holtmanna9de9242007-10-20 13:33:56 +02003701 case HCI_EV_CMD_COMPLETE:
3702 hci_cmd_complete_evt(hdev, skb);
3703 break;
3704
3705 case HCI_EV_CMD_STATUS:
3706 hci_cmd_status_evt(hdev, skb);
3707 break;
3708
3709 case HCI_EV_ROLE_CHANGE:
3710 hci_role_change_evt(hdev, skb);
3711 break;
3712
3713 case HCI_EV_NUM_COMP_PKTS:
3714 hci_num_comp_pkts_evt(hdev, skb);
3715 break;
3716
3717 case HCI_EV_MODE_CHANGE:
3718 hci_mode_change_evt(hdev, skb);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003719 break;
3720
3721 case HCI_EV_PIN_CODE_REQ:
3722 hci_pin_code_request_evt(hdev, skb);
3723 break;
3724
3725 case HCI_EV_LINK_KEY_REQ:
3726 hci_link_key_request_evt(hdev, skb);
3727 break;
3728
3729 case HCI_EV_LINK_KEY_NOTIFY:
3730 hci_link_key_notify_evt(hdev, skb);
3731 break;
3732
3733 case HCI_EV_CLOCK_OFFSET:
3734 hci_clock_offset_evt(hdev, skb);
3735 break;
3736
Marcel Holtmanna8746412008-07-14 20:13:46 +02003737 case HCI_EV_PKT_TYPE_CHANGE:
3738 hci_pkt_type_change_evt(hdev, skb);
3739 break;
3740
Marcel Holtmann85a1e932005-08-09 20:28:02 -07003741 case HCI_EV_PSCAN_REP_MODE:
3742 hci_pscan_rep_mode_evt(hdev, skb);
3743 break;
3744
Marcel Holtmanna9de9242007-10-20 13:33:56 +02003745 case HCI_EV_INQUIRY_RESULT_WITH_RSSI:
3746 hci_inquiry_result_with_rssi_evt(hdev, skb);
3747 break;
3748
3749 case HCI_EV_REMOTE_EXT_FEATURES:
3750 hci_remote_ext_features_evt(hdev, skb);
3751 break;
3752
3753 case HCI_EV_SYNC_CONN_COMPLETE:
3754 hci_sync_conn_complete_evt(hdev, skb);
3755 break;
3756
Marcel Holtmanna9de9242007-10-20 13:33:56 +02003757 case HCI_EV_EXTENDED_INQUIRY_RESULT:
3758 hci_extended_inquiry_result_evt(hdev, skb);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003759 break;
3760
Johan Hedberg1c2e0042012-06-08 23:31:13 +08003761 case HCI_EV_KEY_REFRESH_COMPLETE:
3762 hci_key_refresh_complete_evt(hdev, skb);
3763 break;
3764
Marcel Holtmann04936842008-07-14 20:13:48 +02003765 case HCI_EV_IO_CAPA_REQUEST:
3766 hci_io_capa_request_evt(hdev, skb);
3767 break;
3768
Johan Hedberg03b555e2011-01-04 15:40:05 +02003769 case HCI_EV_IO_CAPA_REPLY:
3770 hci_io_capa_reply_evt(hdev, skb);
3771 break;
3772
Johan Hedberga5c29682011-02-19 12:05:57 -03003773 case HCI_EV_USER_CONFIRM_REQUEST:
3774 hci_user_confirm_request_evt(hdev, skb);
3775 break;
3776
Brian Gix1143d452011-11-23 08:28:34 -08003777 case HCI_EV_USER_PASSKEY_REQUEST:
3778 hci_user_passkey_request_evt(hdev, skb);
3779 break;
3780
Johan Hedberg92a25252012-09-06 18:39:26 +03003781 case HCI_EV_USER_PASSKEY_NOTIFY:
3782 hci_user_passkey_notify_evt(hdev, skb);
3783 break;
3784
3785 case HCI_EV_KEYPRESS_NOTIFY:
3786 hci_keypress_notify_evt(hdev, skb);
3787 break;
3788
Marcel Holtmann04936842008-07-14 20:13:48 +02003789 case HCI_EV_SIMPLE_PAIR_COMPLETE:
3790 hci_simple_pair_complete_evt(hdev, skb);
3791 break;
3792
Marcel Holtmann41a96212008-07-14 20:13:48 +02003793 case HCI_EV_REMOTE_HOST_FEATURES:
3794 hci_remote_host_features_evt(hdev, skb);
3795 break;
3796
Ville Tervofcd89c02011-02-10 22:38:47 -03003797 case HCI_EV_LE_META:
3798 hci_le_meta_evt(hdev, skb);
3799 break;
3800
Andrei Emeltchenko9495b2e2012-09-27 17:26:22 +03003801 case HCI_EV_CHANNEL_SELECTED:
3802 hci_chan_selected_evt(hdev, skb);
3803 break;
3804
Szymon Janc2763eda2011-03-22 13:12:22 +01003805 case HCI_EV_REMOTE_OOB_DATA_REQUEST:
3806 hci_remote_oob_data_request_evt(hdev, skb);
3807 break;
3808
Andrei Emeltchenkod5e91192012-10-25 15:20:44 +03003809 case HCI_EV_PHY_LINK_COMPLETE:
3810 hci_phy_link_complete_evt(hdev, skb);
3811 break;
3812
Andrei Emeltchenko27695fb2012-10-25 15:20:45 +03003813 case HCI_EV_LOGICAL_LINK_COMPLETE:
3814 hci_loglink_complete_evt(hdev, skb);
3815 break;
3816
Andrei Emeltchenko606e2a12012-10-31 15:46:31 +02003817 case HCI_EV_DISCONN_LOGICAL_LINK_COMPLETE:
3818 hci_disconn_loglink_complete_evt(hdev, skb);
3819 break;
3820
Andrei Emeltchenko9eef6b32012-10-31 15:46:32 +02003821 case HCI_EV_DISCONN_PHY_LINK_COMPLETE:
3822 hci_disconn_phylink_complete_evt(hdev, skb);
3823 break;
3824
Andrei Emeltchenko25e89e92012-01-04 12:41:58 +02003825 case HCI_EV_NUM_COMP_BLOCKS:
3826 hci_num_comp_blocks_evt(hdev, skb);
3827 break;
3828
Marcel Holtmanna9de9242007-10-20 13:33:56 +02003829 default:
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +03003830 BT_DBG("%s event 0x%2.2x", hdev->name, event);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003831 break;
3832 }
3833
3834 kfree_skb(skb);
3835 hdev->stat.evt_rx++;
3836}