blob: 84edacbc14a10b2d929d1bc978a211572a2aa3b5 [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
Andrei Emeltchenko350ee4c2011-12-07 15:56:51 +0200604static void hci_cc_read_data_block_size(struct hci_dev *hdev,
Gustavo Padovan807deac2012-05-17 00:36:24 -0300605 struct sk_buff *skb)
Andrei Emeltchenko350ee4c2011-12-07 15:56:51 +0200606{
607 struct hci_rp_read_data_block_size *rp = (void *) skb->data;
608
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +0300609 BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
Andrei Emeltchenko350ee4c2011-12-07 15:56:51 +0200610
611 if (rp->status)
612 return;
613
614 hdev->block_mtu = __le16_to_cpu(rp->max_acl_len);
615 hdev->block_len = __le16_to_cpu(rp->block_len);
616 hdev->num_blocks = __le16_to_cpu(rp->num_blocks);
617
618 hdev->block_cnt = hdev->num_blocks;
619
620 BT_DBG("%s blk mtu %d cnt %d len %d", hdev->name, hdev->block_mtu,
Gustavo Padovan807deac2012-05-17 00:36:24 -0300621 hdev->block_cnt, hdev->block_len);
Andrei Emeltchenko350ee4c2011-12-07 15:56:51 +0200622}
623
Andrei Emeltchenko928abaa2011-10-12 10:53:57 +0300624static void hci_cc_read_local_amp_info(struct hci_dev *hdev,
Gustavo Padovan807deac2012-05-17 00:36:24 -0300625 struct sk_buff *skb)
Andrei Emeltchenko928abaa2011-10-12 10:53:57 +0300626{
627 struct hci_rp_read_local_amp_info *rp = (void *) skb->data;
628
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +0300629 BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
Andrei Emeltchenko928abaa2011-10-12 10:53:57 +0300630
631 if (rp->status)
Andrei Emeltchenko8e2a0d92012-09-27 17:26:08 +0300632 goto a2mp_rsp;
Andrei Emeltchenko928abaa2011-10-12 10:53:57 +0300633
634 hdev->amp_status = rp->amp_status;
635 hdev->amp_total_bw = __le32_to_cpu(rp->total_bw);
636 hdev->amp_max_bw = __le32_to_cpu(rp->max_bw);
637 hdev->amp_min_latency = __le32_to_cpu(rp->min_latency);
638 hdev->amp_max_pdu = __le32_to_cpu(rp->max_pdu);
639 hdev->amp_type = rp->amp_type;
640 hdev->amp_pal_cap = __le16_to_cpu(rp->pal_cap);
641 hdev->amp_assoc_size = __le16_to_cpu(rp->max_assoc_size);
642 hdev->amp_be_flush_to = __le32_to_cpu(rp->be_flush_to);
643 hdev->amp_max_flush_to = __le32_to_cpu(rp->max_flush_to);
644
Andrei Emeltchenko8e2a0d92012-09-27 17:26:08 +0300645a2mp_rsp:
646 a2mp_send_getinfo_rsp(hdev);
Andrei Emeltchenko928abaa2011-10-12 10:53:57 +0300647}
648
Andrei Emeltchenko903e4542012-09-27 17:26:09 +0300649static void hci_cc_read_local_amp_assoc(struct hci_dev *hdev,
650 struct sk_buff *skb)
651{
652 struct hci_rp_read_local_amp_assoc *rp = (void *) skb->data;
653 struct amp_assoc *assoc = &hdev->loc_assoc;
654 size_t rem_len, frag_len;
655
656 BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
657
658 if (rp->status)
659 goto a2mp_rsp;
660
661 frag_len = skb->len - sizeof(*rp);
662 rem_len = __le16_to_cpu(rp->rem_len);
663
664 if (rem_len > frag_len) {
Andrei Emeltchenko2e430be32012-09-28 14:44:23 +0300665 BT_DBG("frag_len %zu rem_len %zu", frag_len, rem_len);
Andrei Emeltchenko903e4542012-09-27 17:26:09 +0300666
667 memcpy(assoc->data + assoc->offset, rp->frag, frag_len);
668 assoc->offset += frag_len;
669
670 /* Read other fragments */
671 amp_read_loc_assoc_frag(hdev, rp->phy_handle);
672
673 return;
674 }
675
676 memcpy(assoc->data + assoc->offset, rp->frag, rem_len);
677 assoc->len = assoc->offset + rem_len;
678 assoc->offset = 0;
679
680a2mp_rsp:
681 /* Send A2MP Rsp when all fragments are received */
682 a2mp_send_getampassoc_rsp(hdev, rp->status);
Andrei Emeltchenko9495b2e2012-09-27 17:26:22 +0300683 a2mp_send_create_phy_link_req(hdev, rp->status);
Andrei Emeltchenko903e4542012-09-27 17:26:09 +0300684}
685
Johan Hedbergd5859e22011-01-25 01:19:58 +0200686static void hci_cc_read_inq_rsp_tx_power(struct hci_dev *hdev,
Gustavo Padovan807deac2012-05-17 00:36:24 -0300687 struct sk_buff *skb)
Johan Hedbergd5859e22011-01-25 01:19:58 +0200688{
Marcel Holtmann91c4e9b2012-03-11 19:27:21 -0700689 struct hci_rp_read_inq_rsp_tx_power *rp = (void *) skb->data;
Johan Hedbergd5859e22011-01-25 01:19:58 +0200690
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +0300691 BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
Johan Hedbergd5859e22011-01-25 01:19:58 +0200692
Marcel Holtmann91c4e9b2012-03-11 19:27:21 -0700693 if (!rp->status)
694 hdev->inq_tx_power = rp->tx_power;
Johan Hedbergd5859e22011-01-25 01:19:58 +0200695}
696
Johan Hedberg980e1a52011-01-22 06:10:07 +0200697static void hci_cc_pin_code_reply(struct hci_dev *hdev, struct sk_buff *skb)
698{
699 struct hci_rp_pin_code_reply *rp = (void *) skb->data;
700 struct hci_cp_pin_code_reply *cp;
701 struct hci_conn *conn;
702
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +0300703 BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
Johan Hedberg980e1a52011-01-22 06:10:07 +0200704
Johan Hedberg56e5cb82011-11-08 20:40:16 +0200705 hci_dev_lock(hdev);
706
Johan Hedberga8b2d5c2012-01-08 23:11:15 +0200707 if (test_bit(HCI_MGMT, &hdev->dev_flags))
Johan Hedberg744cf192011-11-08 20:40:14 +0200708 mgmt_pin_code_reply_complete(hdev, &rp->bdaddr, rp->status);
Johan Hedberg980e1a52011-01-22 06:10:07 +0200709
Mikel Astizfa1bd912012-08-09 09:52:29 +0200710 if (rp->status)
Johan Hedberg56e5cb82011-11-08 20:40:16 +0200711 goto unlock;
Johan Hedberg980e1a52011-01-22 06:10:07 +0200712
713 cp = hci_sent_cmd_data(hdev, HCI_OP_PIN_CODE_REPLY);
714 if (!cp)
Johan Hedberg56e5cb82011-11-08 20:40:16 +0200715 goto unlock;
Johan Hedberg980e1a52011-01-22 06:10:07 +0200716
717 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &cp->bdaddr);
718 if (conn)
719 conn->pin_length = cp->pin_len;
Johan Hedberg56e5cb82011-11-08 20:40:16 +0200720
721unlock:
722 hci_dev_unlock(hdev);
Johan Hedberg980e1a52011-01-22 06:10:07 +0200723}
724
725static void hci_cc_pin_code_neg_reply(struct hci_dev *hdev, struct sk_buff *skb)
726{
727 struct hci_rp_pin_code_neg_reply *rp = (void *) skb->data;
728
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +0300729 BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
Johan Hedberg980e1a52011-01-22 06:10:07 +0200730
Johan Hedberg56e5cb82011-11-08 20:40:16 +0200731 hci_dev_lock(hdev);
732
Johan Hedberga8b2d5c2012-01-08 23:11:15 +0200733 if (test_bit(HCI_MGMT, &hdev->dev_flags))
Johan Hedberg744cf192011-11-08 20:40:14 +0200734 mgmt_pin_code_neg_reply_complete(hdev, &rp->bdaddr,
Gustavo Padovan807deac2012-05-17 00:36:24 -0300735 rp->status);
Johan Hedberg56e5cb82011-11-08 20:40:16 +0200736
737 hci_dev_unlock(hdev);
Johan Hedberg980e1a52011-01-22 06:10:07 +0200738}
Johan Hedberg56e5cb82011-11-08 20:40:16 +0200739
Ville Tervo6ed58ec2011-02-10 22:38:48 -0300740static void hci_cc_le_read_buffer_size(struct hci_dev *hdev,
741 struct sk_buff *skb)
742{
743 struct hci_rp_le_read_buffer_size *rp = (void *) skb->data;
744
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +0300745 BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
Ville Tervo6ed58ec2011-02-10 22:38:48 -0300746
747 if (rp->status)
748 return;
749
750 hdev->le_mtu = __le16_to_cpu(rp->le_mtu);
751 hdev->le_pkts = rp->le_max_pkt;
752
753 hdev->le_cnt = hdev->le_pkts;
754
755 BT_DBG("%s le mtu %d:%d", hdev->name, hdev->le_mtu, hdev->le_pkts);
Ville Tervo6ed58ec2011-02-10 22:38:48 -0300756}
Johan Hedberg980e1a52011-01-22 06:10:07 +0200757
Johan Hedberg60e77322013-01-22 14:01:59 +0200758static void hci_cc_le_read_local_features(struct hci_dev *hdev,
759 struct sk_buff *skb)
760{
761 struct hci_rp_le_read_local_features *rp = (void *) skb->data;
762
763 BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
764
765 if (!rp->status)
766 memcpy(hdev->le_features, rp->features, 8);
Johan Hedberg60e77322013-01-22 14:01:59 +0200767}
768
Johan Hedberg8fa19092012-10-19 20:57:49 +0300769static void hci_cc_le_read_adv_tx_power(struct hci_dev *hdev,
770 struct sk_buff *skb)
771{
772 struct hci_rp_le_read_adv_tx_power *rp = (void *) skb->data;
773
774 BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
775
Johan Hedberg04b4edc2013-03-15 17:07:01 -0500776 if (!rp->status)
Johan Hedberg8fa19092012-10-19 20:57:49 +0300777 hdev->adv_tx_power = rp->tx_power;
Johan Hedberg8fa19092012-10-19 20:57:49 +0300778}
779
Johan Hedberga5c29682011-02-19 12:05:57 -0300780static void hci_cc_user_confirm_reply(struct hci_dev *hdev, struct sk_buff *skb)
781{
782 struct hci_rp_user_confirm_reply *rp = (void *) skb->data;
783
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +0300784 BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
Johan Hedberga5c29682011-02-19 12:05:57 -0300785
Johan Hedberg56e5cb82011-11-08 20:40:16 +0200786 hci_dev_lock(hdev);
787
Johan Hedberga8b2d5c2012-01-08 23:11:15 +0200788 if (test_bit(HCI_MGMT, &hdev->dev_flags))
Gustavo F. Padovan04124682012-03-08 01:25:00 -0300789 mgmt_user_confirm_reply_complete(hdev, &rp->bdaddr, ACL_LINK, 0,
790 rp->status);
Johan Hedberg56e5cb82011-11-08 20:40:16 +0200791
792 hci_dev_unlock(hdev);
Johan Hedberga5c29682011-02-19 12:05:57 -0300793}
794
795static void hci_cc_user_confirm_neg_reply(struct hci_dev *hdev,
Gustavo Padovan807deac2012-05-17 00:36:24 -0300796 struct sk_buff *skb)
Johan Hedberga5c29682011-02-19 12:05:57 -0300797{
798 struct hci_rp_user_confirm_reply *rp = (void *) skb->data;
799
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +0300800 BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
Johan Hedberga5c29682011-02-19 12:05:57 -0300801
Johan Hedberg56e5cb82011-11-08 20:40:16 +0200802 hci_dev_lock(hdev);
803
Johan Hedberga8b2d5c2012-01-08 23:11:15 +0200804 if (test_bit(HCI_MGMT, &hdev->dev_flags))
Johan Hedberg744cf192011-11-08 20:40:14 +0200805 mgmt_user_confirm_neg_reply_complete(hdev, &rp->bdaddr,
Gustavo F. Padovan04124682012-03-08 01:25:00 -0300806 ACL_LINK, 0, rp->status);
Johan Hedberg56e5cb82011-11-08 20:40:16 +0200807
808 hci_dev_unlock(hdev);
Johan Hedberga5c29682011-02-19 12:05:57 -0300809}
810
Brian Gix1143d452011-11-23 08:28:34 -0800811static void hci_cc_user_passkey_reply(struct hci_dev *hdev, struct sk_buff *skb)
812{
813 struct hci_rp_user_confirm_reply *rp = (void *) skb->data;
814
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +0300815 BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
Brian Gix1143d452011-11-23 08:28:34 -0800816
817 hci_dev_lock(hdev);
818
Johan Hedberga8b2d5c2012-01-08 23:11:15 +0200819 if (test_bit(HCI_MGMT, &hdev->dev_flags))
Johan Hedberg272d90d2012-02-09 15:26:12 +0200820 mgmt_user_passkey_reply_complete(hdev, &rp->bdaddr, ACL_LINK,
Gustavo F. Padovan04124682012-03-08 01:25:00 -0300821 0, rp->status);
Brian Gix1143d452011-11-23 08:28:34 -0800822
823 hci_dev_unlock(hdev);
824}
825
826static void hci_cc_user_passkey_neg_reply(struct hci_dev *hdev,
Gustavo Padovan807deac2012-05-17 00:36:24 -0300827 struct sk_buff *skb)
Brian Gix1143d452011-11-23 08:28:34 -0800828{
829 struct hci_rp_user_confirm_reply *rp = (void *) skb->data;
830
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +0300831 BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
Brian Gix1143d452011-11-23 08:28:34 -0800832
833 hci_dev_lock(hdev);
834
Johan Hedberga8b2d5c2012-01-08 23:11:15 +0200835 if (test_bit(HCI_MGMT, &hdev->dev_flags))
Brian Gix1143d452011-11-23 08:28:34 -0800836 mgmt_user_passkey_neg_reply_complete(hdev, &rp->bdaddr,
Gustavo F. Padovan04124682012-03-08 01:25:00 -0300837 ACL_LINK, 0, rp->status);
Brian Gix1143d452011-11-23 08:28:34 -0800838
839 hci_dev_unlock(hdev);
840}
841
Szymon Jancc35938b2011-03-22 13:12:21 +0100842static void hci_cc_read_local_oob_data_reply(struct hci_dev *hdev,
Gustavo Padovan807deac2012-05-17 00:36:24 -0300843 struct sk_buff *skb)
Szymon Jancc35938b2011-03-22 13:12:21 +0100844{
845 struct hci_rp_read_local_oob_data *rp = (void *) skb->data;
846
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +0300847 BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
Szymon Jancc35938b2011-03-22 13:12:21 +0100848
Johan Hedberg56e5cb82011-11-08 20:40:16 +0200849 hci_dev_lock(hdev);
Johan Hedberg744cf192011-11-08 20:40:14 +0200850 mgmt_read_local_oob_data_reply_complete(hdev, rp->hash,
Szymon Jancc35938b2011-03-22 13:12:21 +0100851 rp->randomizer, rp->status);
Johan Hedberg56e5cb82011-11-08 20:40:16 +0200852 hci_dev_unlock(hdev);
Szymon Jancc35938b2011-03-22 13:12:21 +0100853}
854
Johan Hedbergc1d5dc42012-11-08 01:23:01 +0100855static void hci_cc_le_set_adv_enable(struct hci_dev *hdev, struct sk_buff *skb)
856{
857 __u8 *sent, status = *((__u8 *) skb->data);
858
859 BT_DBG("%s status 0x%2.2x", hdev->name, status);
860
861 sent = hci_sent_cmd_data(hdev, HCI_OP_LE_SET_ADV_ENABLE);
862 if (!sent)
863 return;
864
865 hci_dev_lock(hdev);
866
867 if (!status) {
868 if (*sent)
869 set_bit(HCI_LE_PERIPHERAL, &hdev->dev_flags);
870 else
871 clear_bit(HCI_LE_PERIPHERAL, &hdev->dev_flags);
872 }
873
Johan Hedberg04b4edc2013-03-15 17:07:01 -0500874 if (!test_bit(HCI_INIT, &hdev->flags)) {
875 struct hci_request req;
Johan Hedbergc1d5dc42012-11-08 01:23:01 +0100876
Johan Hedberg04b4edc2013-03-15 17:07:01 -0500877 hci_req_init(&req, hdev);
878 hci_update_ad(&req);
879 hci_req_run(&req, NULL);
880 }
881
882 hci_dev_unlock(hdev);
Johan Hedbergc1d5dc42012-11-08 01:23:01 +0100883}
884
Andre Guedes07f7fa52011-12-02 21:13:31 +0900885static void hci_cc_le_set_scan_param(struct hci_dev *hdev, struct sk_buff *skb)
886{
887 __u8 status = *((__u8 *) skb->data);
888
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +0300889 BT_DBG("%s status 0x%2.2x", hdev->name, status);
Andre Guedes7ba8b4b2012-02-03 17:47:59 -0300890
Andre Guedes3fd24152012-02-03 17:48:01 -0300891 if (status) {
892 hci_dev_lock(hdev);
893 mgmt_start_discovery_failed(hdev, status);
894 hci_dev_unlock(hdev);
895 return;
896 }
Andre Guedes07f7fa52011-12-02 21:13:31 +0900897}
898
Andre Guedeseb9d91f2011-05-26 16:23:52 -0300899static void hci_cc_le_set_scan_enable(struct hci_dev *hdev,
Gustavo Padovan807deac2012-05-17 00:36:24 -0300900 struct sk_buff *skb)
Andre Guedeseb9d91f2011-05-26 16:23:52 -0300901{
902 struct hci_cp_le_set_scan_enable *cp;
903 __u8 status = *((__u8 *) skb->data);
904
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +0300905 BT_DBG("%s status 0x%2.2x", hdev->name, status);
Andre Guedeseb9d91f2011-05-26 16:23:52 -0300906
Andre Guedeseb9d91f2011-05-26 16:23:52 -0300907 cp = hci_sent_cmd_data(hdev, HCI_OP_LE_SET_SCAN_ENABLE);
908 if (!cp)
909 return;
910
Andrei Emeltchenko68a8aea2011-12-19 16:14:18 +0200911 switch (cp->enable) {
912 case LE_SCANNING_ENABLED:
Andre Guedes3fd24152012-02-03 17:48:01 -0300913 if (status) {
914 hci_dev_lock(hdev);
915 mgmt_start_discovery_failed(hdev, status);
916 hci_dev_unlock(hdev);
Andre Guedes7ba8b4b2012-02-03 17:47:59 -0300917 return;
Andre Guedes3fd24152012-02-03 17:48:01 -0300918 }
Andre Guedes7ba8b4b2012-02-03 17:47:59 -0300919
Andre Guedesd23264a2011-11-25 20:53:38 -0300920 set_bit(HCI_LE_SCAN, &hdev->dev_flags);
921
Andre Guedesa8f13c82011-09-09 18:56:24 -0300922 hci_dev_lock(hdev);
Andre Guedes343f9352012-02-17 20:39:37 -0300923 hci_discovery_set_state(hdev, DISCOVERY_FINDING);
Andre Guedesa8f13c82011-09-09 18:56:24 -0300924 hci_dev_unlock(hdev);
Andrei Emeltchenko68a8aea2011-12-19 16:14:18 +0200925 break;
926
927 case LE_SCANNING_DISABLED:
Andre Guedesc9ecc482012-03-15 16:52:08 -0300928 if (status) {
929 hci_dev_lock(hdev);
930 mgmt_stop_discovery_failed(hdev, status);
931 hci_dev_unlock(hdev);
Andre Guedes7ba8b4b2012-02-03 17:47:59 -0300932 return;
Andre Guedesc9ecc482012-03-15 16:52:08 -0300933 }
Andre Guedes7ba8b4b2012-02-03 17:47:59 -0300934
Andre Guedesd23264a2011-11-25 20:53:38 -0300935 clear_bit(HCI_LE_SCAN, &hdev->dev_flags);
936
Andre Guedesbc3dd332012-03-06 19:37:06 -0300937 if (hdev->discovery.type == DISCOV_TYPE_INTERLEAVED &&
938 hdev->discovery.state == DISCOVERY_FINDING) {
Andre Guedes5e0452c2012-02-17 20:39:38 -0300939 mgmt_interleaved_discovery(hdev);
940 } else {
941 hci_dev_lock(hdev);
942 hci_discovery_set_state(hdev, DISCOVERY_STOPPED);
943 hci_dev_unlock(hdev);
944 }
945
Andrei Emeltchenko68a8aea2011-12-19 16:14:18 +0200946 break;
947
948 default:
949 BT_ERR("Used reserved LE_Scan_Enable param %d", cp->enable);
950 break;
Andre Guedes35815082011-05-26 16:23:53 -0300951 }
Andre Guedeseb9d91f2011-05-26 16:23:52 -0300952}
953
Johan Hedbergcf1d0812013-01-22 14:02:00 +0200954static void hci_cc_le_read_white_list_size(struct hci_dev *hdev,
955 struct sk_buff *skb)
956{
957 struct hci_rp_le_read_white_list_size *rp = (void *) skb->data;
958
959 BT_DBG("%s status 0x%2.2x size %u", hdev->name, rp->status, rp->size);
960
961 if (!rp->status)
962 hdev->le_white_list_size = rp->size;
Johan Hedbergcf1d0812013-01-22 14:02:00 +0200963}
964
Johan Hedberg9b008c02013-01-22 14:02:01 +0200965static void hci_cc_le_read_supported_states(struct hci_dev *hdev,
966 struct sk_buff *skb)
967{
968 struct hci_rp_le_read_supported_states *rp = (void *) skb->data;
969
970 BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
971
972 if (!rp->status)
973 memcpy(hdev->le_states, rp->le_states, 8);
Johan Hedberg9b008c02013-01-22 14:02:01 +0200974}
975
Gustavo Padovan6039aa732012-05-23 04:04:18 -0300976static void hci_cc_write_le_host_supported(struct hci_dev *hdev,
977 struct sk_buff *skb)
Andre Guedesf9b49302011-06-30 19:20:53 -0300978{
Johan Hedberg06199cf2012-02-22 16:37:11 +0200979 struct hci_cp_write_le_host_supported *sent;
Andre Guedesf9b49302011-06-30 19:20:53 -0300980 __u8 status = *((__u8 *) skb->data);
981
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +0300982 BT_DBG("%s status 0x%2.2x", hdev->name, status);
Andre Guedesf9b49302011-06-30 19:20:53 -0300983
Johan Hedberg06199cf2012-02-22 16:37:11 +0200984 sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_LE_HOST_SUPPORTED);
Johan Hedberg8f984df2012-02-28 01:07:22 +0200985 if (!sent)
Andre Guedesf9b49302011-06-30 19:20:53 -0300986 return;
987
Johan Hedberg8f984df2012-02-28 01:07:22 +0200988 if (!status) {
989 if (sent->le)
990 hdev->host_features[0] |= LMP_HOST_LE;
991 else
992 hdev->host_features[0] &= ~LMP_HOST_LE;
Johan Hedberg53b2caa2012-10-24 21:11:59 +0300993
994 if (sent->simul)
995 hdev->host_features[0] |= LMP_HOST_LE_BREDR;
996 else
997 hdev->host_features[0] &= ~LMP_HOST_LE_BREDR;
Johan Hedberg8f984df2012-02-28 01:07:22 +0200998 }
999
1000 if (test_bit(HCI_MGMT, &hdev->dev_flags) &&
Gustavo Padovan807deac2012-05-17 00:36:24 -03001001 !test_bit(HCI_INIT, &hdev->flags))
Johan Hedberg8f984df2012-02-28 01:07:22 +02001002 mgmt_le_enable_complete(hdev, sent->le, status);
Andre Guedesf9b49302011-06-30 19:20:53 -03001003}
1004
Andrei Emeltchenko93c284e2012-09-27 17:26:20 +03001005static void hci_cc_write_remote_amp_assoc(struct hci_dev *hdev,
1006 struct sk_buff *skb)
1007{
1008 struct hci_rp_write_remote_amp_assoc *rp = (void *) skb->data;
1009
1010 BT_DBG("%s status 0x%2.2x phy_handle 0x%2.2x",
1011 hdev->name, rp->status, rp->phy_handle);
1012
1013 if (rp->status)
1014 return;
1015
1016 amp_write_rem_assoc_continue(hdev, rp->phy_handle);
1017}
1018
Gustavo Padovan6039aa732012-05-23 04:04:18 -03001019static void hci_cs_inquiry(struct hci_dev *hdev, __u8 status)
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001020{
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +03001021 BT_DBG("%s status 0x%2.2x", hdev->name, status);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001022
1023 if (status) {
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001024 hci_conn_check_pending(hdev);
Johan Hedberg56e5cb82011-11-08 20:40:16 +02001025 hci_dev_lock(hdev);
Johan Hedberga8b2d5c2012-01-08 23:11:15 +02001026 if (test_bit(HCI_MGMT, &hdev->dev_flags))
Andre Guedes7a135102011-11-09 17:14:25 -03001027 mgmt_start_discovery_failed(hdev, status);
Johan Hedberg56e5cb82011-11-08 20:40:16 +02001028 hci_dev_unlock(hdev);
Johan Hedberg314b2382011-04-27 10:29:57 -04001029 return;
1030 }
1031
Andre Guedes89352e72011-11-04 14:16:53 -03001032 set_bit(HCI_INQUIRY, &hdev->flags);
1033
Johan Hedberg56e5cb82011-11-08 20:40:16 +02001034 hci_dev_lock(hdev);
Andre Guedes343f9352012-02-17 20:39:37 -03001035 hci_discovery_set_state(hdev, DISCOVERY_FINDING);
Johan Hedberg56e5cb82011-11-08 20:40:16 +02001036 hci_dev_unlock(hdev);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001037}
1038
Gustavo Padovan6039aa732012-05-23 04:04:18 -03001039static void hci_cs_create_conn(struct hci_dev *hdev, __u8 status)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001040{
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001041 struct hci_cp_create_conn *cp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001042 struct hci_conn *conn;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001043
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +03001044 BT_DBG("%s status 0x%2.2x", hdev->name, status);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001045
1046 cp = hci_sent_cmd_data(hdev, HCI_OP_CREATE_CONN);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001047 if (!cp)
1048 return;
1049
1050 hci_dev_lock(hdev);
1051
1052 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &cp->bdaddr);
1053
Andrei Emeltchenko6ed93dc2012-09-25 12:49:43 +03001054 BT_DBG("%s bdaddr %pMR hcon %p", hdev->name, &cp->bdaddr, conn);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001055
1056 if (status) {
1057 if (conn && conn->state == BT_CONNECT) {
Marcel Holtmann4c67bc72006-10-15 17:30:56 +02001058 if (status != 0x0c || conn->attempt > 2) {
1059 conn->state = BT_CLOSED;
1060 hci_proto_connect_cfm(conn, status);
1061 hci_conn_del(conn);
1062 } else
1063 conn->state = BT_CONNECT2;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001064 }
1065 } else {
1066 if (!conn) {
1067 conn = hci_conn_add(hdev, ACL_LINK, &cp->bdaddr);
1068 if (conn) {
Johan Hedberga0c808b2012-01-16 09:49:58 +02001069 conn->out = true;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001070 conn->link_mode |= HCI_LM_MASTER;
1071 } else
Gustavo F. Padovan893ef972010-07-18 15:13:37 -03001072 BT_ERR("No memory for new connection");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001073 }
1074 }
1075
1076 hci_dev_unlock(hdev);
1077}
1078
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001079static void hci_cs_add_sco(struct hci_dev *hdev, __u8 status)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001080{
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001081 struct hci_cp_add_sco *cp;
1082 struct hci_conn *acl, *sco;
1083 __u16 handle;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001084
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +03001085 BT_DBG("%s status 0x%2.2x", hdev->name, status);
Marcel Holtmannb6a0dc82007-10-20 14:55:10 +02001086
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001087 if (!status)
1088 return;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001089
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001090 cp = hci_sent_cmd_data(hdev, HCI_OP_ADD_SCO);
1091 if (!cp)
1092 return;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001093
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001094 handle = __le16_to_cpu(cp->handle);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001095
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +03001096 BT_DBG("%s handle 0x%4.4x", hdev->name, handle);
Marcel Holtmann6bd57412006-11-18 22:14:22 +01001097
1098 hci_dev_lock(hdev);
1099
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001100 acl = hci_conn_hash_lookup_handle(hdev, handle);
Andrei Emeltchenko5a08ecc2011-01-11 17:20:20 +02001101 if (acl) {
1102 sco = acl->link;
1103 if (sco) {
1104 sco->state = BT_CLOSED;
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001105
Andrei Emeltchenko5a08ecc2011-01-11 17:20:20 +02001106 hci_proto_connect_cfm(sco, status);
1107 hci_conn_del(sco);
1108 }
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001109 }
Marcel Holtmann6bd57412006-11-18 22:14:22 +01001110
1111 hci_dev_unlock(hdev);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001112}
1113
Marcel Holtmannf8558552008-07-14 20:13:49 +02001114static void hci_cs_auth_requested(struct hci_dev *hdev, __u8 status)
1115{
1116 struct hci_cp_auth_requested *cp;
1117 struct hci_conn *conn;
1118
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +03001119 BT_DBG("%s status 0x%2.2x", hdev->name, status);
Marcel Holtmannf8558552008-07-14 20:13:49 +02001120
1121 if (!status)
1122 return;
1123
1124 cp = hci_sent_cmd_data(hdev, HCI_OP_AUTH_REQUESTED);
1125 if (!cp)
1126 return;
1127
1128 hci_dev_lock(hdev);
1129
1130 conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(cp->handle));
1131 if (conn) {
1132 if (conn->state == BT_CONFIG) {
1133 hci_proto_connect_cfm(conn, status);
1134 hci_conn_put(conn);
1135 }
1136 }
1137
1138 hci_dev_unlock(hdev);
1139}
1140
1141static void hci_cs_set_conn_encrypt(struct hci_dev *hdev, __u8 status)
1142{
1143 struct hci_cp_set_conn_encrypt *cp;
1144 struct hci_conn *conn;
1145
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +03001146 BT_DBG("%s status 0x%2.2x", hdev->name, status);
Marcel Holtmannf8558552008-07-14 20:13:49 +02001147
1148 if (!status)
1149 return;
1150
1151 cp = hci_sent_cmd_data(hdev, HCI_OP_SET_CONN_ENCRYPT);
1152 if (!cp)
1153 return;
1154
1155 hci_dev_lock(hdev);
1156
1157 conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(cp->handle));
1158 if (conn) {
1159 if (conn->state == BT_CONFIG) {
1160 hci_proto_connect_cfm(conn, status);
1161 hci_conn_put(conn);
1162 }
1163 }
1164
1165 hci_dev_unlock(hdev);
1166}
1167
Johan Hedberg127178d2010-11-18 22:22:29 +02001168static int hci_outgoing_auth_needed(struct hci_dev *hdev,
Gustavo Padovan807deac2012-05-17 00:36:24 -03001169 struct hci_conn *conn)
Johan Hedberg392599b2010-11-18 22:22:28 +02001170{
Johan Hedberg392599b2010-11-18 22:22:28 +02001171 if (conn->state != BT_CONFIG || !conn->out)
1172 return 0;
1173
Johan Hedberg765c2a92011-01-19 12:06:52 +05301174 if (conn->pending_sec_level == BT_SECURITY_SDP)
Johan Hedberg392599b2010-11-18 22:22:28 +02001175 return 0;
1176
1177 /* Only request authentication for SSP connections or non-SSP
Vinicius Costa Gomese9bf2bf2011-09-02 14:51:20 -03001178 * devices with sec_level HIGH or if MITM protection is requested */
Gustavo Padovan807deac2012-05-17 00:36:24 -03001179 if (!hci_conn_ssp_enabled(conn) && !(conn->auth_type & 0x01) &&
1180 conn->pending_sec_level != BT_SECURITY_HIGH)
Johan Hedberg392599b2010-11-18 22:22:28 +02001181 return 0;
1182
Johan Hedberg392599b2010-11-18 22:22:28 +02001183 return 1;
1184}
1185
Gustavo Padovan6039aa732012-05-23 04:04:18 -03001186static int hci_resolve_name(struct hci_dev *hdev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001187 struct inquiry_entry *e)
Johan Hedberg30dc78e2012-01-04 15:44:20 +02001188{
1189 struct hci_cp_remote_name_req cp;
1190
1191 memset(&cp, 0, sizeof(cp));
1192
1193 bacpy(&cp.bdaddr, &e->data.bdaddr);
1194 cp.pscan_rep_mode = e->data.pscan_rep_mode;
1195 cp.pscan_mode = e->data.pscan_mode;
1196 cp.clock_offset = e->data.clock_offset;
1197
1198 return hci_send_cmd(hdev, HCI_OP_REMOTE_NAME_REQ, sizeof(cp), &cp);
1199}
1200
Johan Hedbergb644ba32012-01-17 21:48:47 +02001201static bool hci_resolve_next_name(struct hci_dev *hdev)
Johan Hedberg30dc78e2012-01-04 15:44:20 +02001202{
1203 struct discovery_state *discov = &hdev->discovery;
1204 struct inquiry_entry *e;
1205
Johan Hedbergb644ba32012-01-17 21:48:47 +02001206 if (list_empty(&discov->resolve))
1207 return false;
1208
1209 e = hci_inquiry_cache_lookup_resolve(hdev, BDADDR_ANY, NAME_NEEDED);
Ram Malovanyc8100892012-07-19 10:26:09 +03001210 if (!e)
1211 return false;
1212
Johan Hedbergb644ba32012-01-17 21:48:47 +02001213 if (hci_resolve_name(hdev, e) == 0) {
1214 e->name_state = NAME_PENDING;
1215 return true;
1216 }
1217
1218 return false;
1219}
1220
1221static void hci_check_pending_name(struct hci_dev *hdev, struct hci_conn *conn,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001222 bdaddr_t *bdaddr, u8 *name, u8 name_len)
Johan Hedbergb644ba32012-01-17 21:48:47 +02001223{
1224 struct discovery_state *discov = &hdev->discovery;
1225 struct inquiry_entry *e;
1226
1227 if (conn && !test_and_set_bit(HCI_CONN_MGMT_CONNECTED, &conn->flags))
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001228 mgmt_device_connected(hdev, bdaddr, ACL_LINK, 0x00, 0, name,
1229 name_len, conn->dev_class);
Johan Hedbergb644ba32012-01-17 21:48:47 +02001230
1231 if (discov->state == DISCOVERY_STOPPED)
1232 return;
1233
Johan Hedberg30dc78e2012-01-04 15:44:20 +02001234 if (discov->state == DISCOVERY_STOPPING)
1235 goto discov_complete;
1236
1237 if (discov->state != DISCOVERY_RESOLVING)
1238 return;
1239
1240 e = hci_inquiry_cache_lookup_resolve(hdev, bdaddr, NAME_PENDING);
Ram Malovany7cc83802012-07-19 10:26:10 +03001241 /* If the device was not found in a list of found devices names of which
1242 * are pending. there is no need to continue resolving a next name as it
1243 * will be done upon receiving another Remote Name Request Complete
1244 * Event */
1245 if (!e)
1246 return;
1247
1248 list_del(&e->list);
1249 if (name) {
Johan Hedberg30dc78e2012-01-04 15:44:20 +02001250 e->name_state = NAME_KNOWN;
Ram Malovany7cc83802012-07-19 10:26:10 +03001251 mgmt_remote_name(hdev, bdaddr, ACL_LINK, 0x00,
1252 e->data.rssi, name, name_len);
Ram Malovanyc3e7c0d2012-07-19 10:26:11 +03001253 } else {
1254 e->name_state = NAME_NOT_KNOWN;
Johan Hedberg30dc78e2012-01-04 15:44:20 +02001255 }
1256
Johan Hedbergb644ba32012-01-17 21:48:47 +02001257 if (hci_resolve_next_name(hdev))
Johan Hedberg30dc78e2012-01-04 15:44:20 +02001258 return;
Johan Hedberg30dc78e2012-01-04 15:44:20 +02001259
1260discov_complete:
1261 hci_discovery_set_state(hdev, DISCOVERY_STOPPED);
1262}
1263
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001264static void hci_cs_remote_name_req(struct hci_dev *hdev, __u8 status)
1265{
Johan Hedberg127178d2010-11-18 22:22:29 +02001266 struct hci_cp_remote_name_req *cp;
1267 struct hci_conn *conn;
1268
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +03001269 BT_DBG("%s status 0x%2.2x", hdev->name, status);
Johan Hedberg127178d2010-11-18 22:22:29 +02001270
1271 /* If successful wait for the name req complete event before
1272 * checking for the need to do authentication */
1273 if (!status)
1274 return;
1275
1276 cp = hci_sent_cmd_data(hdev, HCI_OP_REMOTE_NAME_REQ);
1277 if (!cp)
1278 return;
1279
1280 hci_dev_lock(hdev);
1281
1282 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &cp->bdaddr);
Johan Hedbergb644ba32012-01-17 21:48:47 +02001283
1284 if (test_bit(HCI_MGMT, &hdev->dev_flags))
1285 hci_check_pending_name(hdev, conn, &cp->bdaddr, NULL, 0);
1286
Johan Hedberg79c6c702011-04-28 11:28:55 -07001287 if (!conn)
1288 goto unlock;
1289
1290 if (!hci_outgoing_auth_needed(hdev, conn))
1291 goto unlock;
1292
Johan Hedberg51a8efd2012-01-16 06:10:31 +02001293 if (!test_and_set_bit(HCI_CONN_AUTH_PEND, &conn->flags)) {
Johan Hedberg127178d2010-11-18 22:22:29 +02001294 struct hci_cp_auth_requested cp;
1295 cp.handle = __cpu_to_le16(conn->handle);
1296 hci_send_cmd(hdev, HCI_OP_AUTH_REQUESTED, sizeof(cp), &cp);
1297 }
1298
Johan Hedberg79c6c702011-04-28 11:28:55 -07001299unlock:
Johan Hedberg127178d2010-11-18 22:22:29 +02001300 hci_dev_unlock(hdev);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001301}
1302
Marcel Holtmann769be972008-07-14 20:13:49 +02001303static void hci_cs_read_remote_features(struct hci_dev *hdev, __u8 status)
1304{
1305 struct hci_cp_read_remote_features *cp;
1306 struct hci_conn *conn;
1307
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +03001308 BT_DBG("%s status 0x%2.2x", hdev->name, status);
Marcel Holtmann769be972008-07-14 20:13:49 +02001309
1310 if (!status)
1311 return;
1312
1313 cp = hci_sent_cmd_data(hdev, HCI_OP_READ_REMOTE_FEATURES);
1314 if (!cp)
1315 return;
1316
1317 hci_dev_lock(hdev);
1318
1319 conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(cp->handle));
1320 if (conn) {
1321 if (conn->state == BT_CONFIG) {
Marcel Holtmann769be972008-07-14 20:13:49 +02001322 hci_proto_connect_cfm(conn, status);
1323 hci_conn_put(conn);
1324 }
1325 }
1326
1327 hci_dev_unlock(hdev);
1328}
1329
1330static void hci_cs_read_remote_ext_features(struct hci_dev *hdev, __u8 status)
1331{
1332 struct hci_cp_read_remote_ext_features *cp;
1333 struct hci_conn *conn;
1334
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +03001335 BT_DBG("%s status 0x%2.2x", hdev->name, status);
Marcel Holtmann769be972008-07-14 20:13:49 +02001336
1337 if (!status)
1338 return;
1339
1340 cp = hci_sent_cmd_data(hdev, HCI_OP_READ_REMOTE_EXT_FEATURES);
1341 if (!cp)
1342 return;
1343
1344 hci_dev_lock(hdev);
1345
1346 conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(cp->handle));
1347 if (conn) {
1348 if (conn->state == BT_CONFIG) {
Marcel Holtmann769be972008-07-14 20:13:49 +02001349 hci_proto_connect_cfm(conn, status);
1350 hci_conn_put(conn);
1351 }
1352 }
1353
1354 hci_dev_unlock(hdev);
1355}
1356
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001357static void hci_cs_setup_sync_conn(struct hci_dev *hdev, __u8 status)
1358{
Marcel Holtmannb6a0dc82007-10-20 14:55:10 +02001359 struct hci_cp_setup_sync_conn *cp;
1360 struct hci_conn *acl, *sco;
1361 __u16 handle;
1362
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +03001363 BT_DBG("%s status 0x%2.2x", hdev->name, status);
Marcel Holtmannb6a0dc82007-10-20 14:55:10 +02001364
1365 if (!status)
1366 return;
1367
1368 cp = hci_sent_cmd_data(hdev, HCI_OP_SETUP_SYNC_CONN);
1369 if (!cp)
1370 return;
1371
1372 handle = __le16_to_cpu(cp->handle);
1373
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +03001374 BT_DBG("%s handle 0x%4.4x", hdev->name, handle);
Marcel Holtmannb6a0dc82007-10-20 14:55:10 +02001375
1376 hci_dev_lock(hdev);
1377
1378 acl = hci_conn_hash_lookup_handle(hdev, handle);
Andrei Emeltchenko5a08ecc2011-01-11 17:20:20 +02001379 if (acl) {
1380 sco = acl->link;
1381 if (sco) {
1382 sco->state = BT_CLOSED;
Marcel Holtmannb6a0dc82007-10-20 14:55:10 +02001383
Andrei Emeltchenko5a08ecc2011-01-11 17:20:20 +02001384 hci_proto_connect_cfm(sco, status);
1385 hci_conn_del(sco);
1386 }
Marcel Holtmannb6a0dc82007-10-20 14:55:10 +02001387 }
1388
1389 hci_dev_unlock(hdev);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001390}
1391
1392static void hci_cs_sniff_mode(struct hci_dev *hdev, __u8 status)
1393{
1394 struct hci_cp_sniff_mode *cp;
1395 struct hci_conn *conn;
1396
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +03001397 BT_DBG("%s status 0x%2.2x", hdev->name, status);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001398
1399 if (!status)
1400 return;
1401
1402 cp = hci_sent_cmd_data(hdev, HCI_OP_SNIFF_MODE);
1403 if (!cp)
1404 return;
1405
1406 hci_dev_lock(hdev);
1407
1408 conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(cp->handle));
Marcel Holtmanne73439d2010-07-26 10:06:00 -04001409 if (conn) {
Johan Hedberg51a8efd2012-01-16 06:10:31 +02001410 clear_bit(HCI_CONN_MODE_CHANGE_PEND, &conn->flags);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001411
Johan Hedberg51a8efd2012-01-16 06:10:31 +02001412 if (test_and_clear_bit(HCI_CONN_SCO_SETUP_PEND, &conn->flags))
Marcel Holtmanne73439d2010-07-26 10:06:00 -04001413 hci_sco_setup(conn, status);
1414 }
1415
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001416 hci_dev_unlock(hdev);
1417}
1418
1419static void hci_cs_exit_sniff_mode(struct hci_dev *hdev, __u8 status)
1420{
1421 struct hci_cp_exit_sniff_mode *cp;
1422 struct hci_conn *conn;
1423
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +03001424 BT_DBG("%s status 0x%2.2x", hdev->name, status);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001425
1426 if (!status)
1427 return;
1428
1429 cp = hci_sent_cmd_data(hdev, HCI_OP_EXIT_SNIFF_MODE);
1430 if (!cp)
1431 return;
1432
1433 hci_dev_lock(hdev);
1434
1435 conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(cp->handle));
Marcel Holtmanne73439d2010-07-26 10:06:00 -04001436 if (conn) {
Johan Hedberg51a8efd2012-01-16 06:10:31 +02001437 clear_bit(HCI_CONN_MODE_CHANGE_PEND, &conn->flags);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001438
Johan Hedberg51a8efd2012-01-16 06:10:31 +02001439 if (test_and_clear_bit(HCI_CONN_SCO_SETUP_PEND, &conn->flags))
Marcel Holtmanne73439d2010-07-26 10:06:00 -04001440 hci_sco_setup(conn, status);
1441 }
1442
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001443 hci_dev_unlock(hdev);
1444}
1445
Johan Hedberg88c3df12012-02-09 14:27:38 +02001446static void hci_cs_disconnect(struct hci_dev *hdev, u8 status)
1447{
1448 struct hci_cp_disconnect *cp;
1449 struct hci_conn *conn;
1450
1451 if (!status)
1452 return;
1453
1454 cp = hci_sent_cmd_data(hdev, HCI_OP_DISCONNECT);
1455 if (!cp)
1456 return;
1457
1458 hci_dev_lock(hdev);
1459
1460 conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(cp->handle));
1461 if (conn)
1462 mgmt_disconnect_failed(hdev, &conn->dst, conn->type,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001463 conn->dst_type, status);
Johan Hedberg88c3df12012-02-09 14:27:38 +02001464
1465 hci_dev_unlock(hdev);
1466}
1467
Ville Tervofcd89c02011-02-10 22:38:47 -03001468static void hci_cs_le_create_conn(struct hci_dev *hdev, __u8 status)
1469{
Ville Tervofcd89c02011-02-10 22:38:47 -03001470 struct hci_conn *conn;
1471
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +03001472 BT_DBG("%s status 0x%2.2x", hdev->name, status);
Ville Tervofcd89c02011-02-10 22:38:47 -03001473
Ville Tervofcd89c02011-02-10 22:38:47 -03001474 if (status) {
Andre Guedesf00a06a2012-07-27 15:10:13 -03001475 hci_dev_lock(hdev);
Ville Tervofcd89c02011-02-10 22:38:47 -03001476
Andre Guedes0c95ab72012-07-27 15:10:14 -03001477 conn = hci_conn_hash_lookup_state(hdev, LE_LINK, BT_CONNECT);
Andre Guedesf00a06a2012-07-27 15:10:13 -03001478 if (!conn) {
1479 hci_dev_unlock(hdev);
1480 return;
1481 }
1482
Andrei Emeltchenko6ed93dc2012-09-25 12:49:43 +03001483 BT_DBG("%s bdaddr %pMR conn %p", hdev->name, &conn->dst, conn);
Andre Guedesf00a06a2012-07-27 15:10:13 -03001484
1485 conn->state = BT_CLOSED;
Andre Guedes0c95ab72012-07-27 15:10:14 -03001486 mgmt_connect_failed(hdev, &conn->dst, conn->type,
Andre Guedesf00a06a2012-07-27 15:10:13 -03001487 conn->dst_type, status);
1488 hci_proto_connect_cfm(conn, status);
1489 hci_conn_del(conn);
1490
1491 hci_dev_unlock(hdev);
1492 }
Ville Tervofcd89c02011-02-10 22:38:47 -03001493}
1494
Andrei Emeltchenkoa02226d2012-09-27 17:26:19 +03001495static void hci_cs_create_phylink(struct hci_dev *hdev, u8 status)
1496{
Andrei Emeltchenko93c284e2012-09-27 17:26:20 +03001497 struct hci_cp_create_phy_link *cp;
1498
Andrei Emeltchenkoa02226d2012-09-27 17:26:19 +03001499 BT_DBG("%s status 0x%2.2x", hdev->name, status);
Andrei Emeltchenko93c284e2012-09-27 17:26:20 +03001500
Andrei Emeltchenko93c284e2012-09-27 17:26:20 +03001501 cp = hci_sent_cmd_data(hdev, HCI_OP_CREATE_PHY_LINK);
1502 if (!cp)
1503 return;
1504
Andrei Emeltchenkoe58917b2012-10-31 15:46:33 +02001505 hci_dev_lock(hdev);
1506
1507 if (status) {
1508 struct hci_conn *hcon;
1509
1510 hcon = hci_conn_hash_lookup_handle(hdev, cp->phy_handle);
1511 if (hcon)
1512 hci_conn_del(hcon);
1513 } else {
1514 amp_write_remote_assoc(hdev, cp->phy_handle);
1515 }
1516
1517 hci_dev_unlock(hdev);
Andrei Emeltchenkoa02226d2012-09-27 17:26:19 +03001518}
1519
Andrei Emeltchenko0b26ab92012-09-27 17:26:24 +03001520static void hci_cs_accept_phylink(struct hci_dev *hdev, u8 status)
1521{
1522 struct hci_cp_accept_phy_link *cp;
1523
1524 BT_DBG("%s status 0x%2.2x", hdev->name, status);
1525
1526 if (status)
1527 return;
1528
1529 cp = hci_sent_cmd_data(hdev, HCI_OP_ACCEPT_PHY_LINK);
1530 if (!cp)
1531 return;
1532
1533 amp_write_remote_assoc(hdev, cp->phy_handle);
1534}
1535
Gustavo Padovan6039aa732012-05-23 04:04:18 -03001536static void hci_inquiry_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001537{
1538 __u8 status = *((__u8 *) skb->data);
Johan Hedberg30dc78e2012-01-04 15:44:20 +02001539 struct discovery_state *discov = &hdev->discovery;
1540 struct inquiry_entry *e;
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001541
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +03001542 BT_DBG("%s status 0x%2.2x", hdev->name, status);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001543
Johan Hedberg9238f362013-03-05 20:37:48 +02001544 hci_req_cmd_complete(hdev, HCI_OP_INQUIRY, status);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001545
1546 hci_conn_check_pending(hdev);
Andre Guedes89352e72011-11-04 14:16:53 -03001547
1548 if (!test_and_clear_bit(HCI_INQUIRY, &hdev->flags))
1549 return;
1550
Johan Hedberga8b2d5c2012-01-08 23:11:15 +02001551 if (!test_bit(HCI_MGMT, &hdev->dev_flags))
Johan Hedberg30dc78e2012-01-04 15:44:20 +02001552 return;
1553
Johan Hedberg56e5cb82011-11-08 20:40:16 +02001554 hci_dev_lock(hdev);
Johan Hedberg30dc78e2012-01-04 15:44:20 +02001555
Andre Guedes343f9352012-02-17 20:39:37 -03001556 if (discov->state != DISCOVERY_FINDING)
Johan Hedberg30dc78e2012-01-04 15:44:20 +02001557 goto unlock;
1558
1559 if (list_empty(&discov->resolve)) {
1560 hci_discovery_set_state(hdev, DISCOVERY_STOPPED);
1561 goto unlock;
1562 }
1563
1564 e = hci_inquiry_cache_lookup_resolve(hdev, BDADDR_ANY, NAME_NEEDED);
1565 if (e && hci_resolve_name(hdev, e) == 0) {
1566 e->name_state = NAME_PENDING;
1567 hci_discovery_set_state(hdev, DISCOVERY_RESOLVING);
1568 } else {
1569 hci_discovery_set_state(hdev, DISCOVERY_STOPPED);
1570 }
1571
1572unlock:
Johan Hedberg56e5cb82011-11-08 20:40:16 +02001573 hci_dev_unlock(hdev);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001574}
1575
Gustavo Padovan6039aa732012-05-23 04:04:18 -03001576static void hci_inquiry_result_evt(struct hci_dev *hdev, struct sk_buff *skb)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001577{
Marcel Holtmann45bb4bf2005-08-09 20:27:49 -07001578 struct inquiry_data data;
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001579 struct inquiry_info *info = (void *) (skb->data + 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001580 int num_rsp = *((__u8 *) skb->data);
1581
1582 BT_DBG("%s num_rsp %d", hdev->name, num_rsp);
1583
Marcel Holtmann45bb4bf2005-08-09 20:27:49 -07001584 if (!num_rsp)
1585 return;
1586
Andre Guedes1519cc12012-03-21 00:03:38 -03001587 if (test_bit(HCI_PERIODIC_INQ, &hdev->dev_flags))
1588 return;
1589
Linus Torvalds1da177e2005-04-16 15:20:36 -07001590 hci_dev_lock(hdev);
Marcel Holtmann45bb4bf2005-08-09 20:27:49 -07001591
Johan Hedberge17acd42011-03-30 23:57:16 +03001592 for (; num_rsp; num_rsp--, info++) {
Johan Hedberg388fc8f2012-02-23 00:38:59 +02001593 bool name_known, ssp;
Johan Hedberg31754052012-01-04 13:39:52 +02001594
Linus Torvalds1da177e2005-04-16 15:20:36 -07001595 bacpy(&data.bdaddr, &info->bdaddr);
1596 data.pscan_rep_mode = info->pscan_rep_mode;
1597 data.pscan_period_mode = info->pscan_period_mode;
1598 data.pscan_mode = info->pscan_mode;
1599 memcpy(data.dev_class, info->dev_class, 3);
1600 data.clock_offset = info->clock_offset;
1601 data.rssi = 0x00;
Marcel Holtmann41a96212008-07-14 20:13:48 +02001602 data.ssp_mode = 0x00;
Johan Hedberg31754052012-01-04 13:39:52 +02001603
Johan Hedberg388fc8f2012-02-23 00:38:59 +02001604 name_known = hci_inquiry_cache_update(hdev, &data, false, &ssp);
Johan Hedberg48264f02011-11-09 13:58:58 +02001605 mgmt_device_found(hdev, &info->bdaddr, ACL_LINK, 0x00,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001606 info->dev_class, 0, !name_known, ssp, NULL,
1607 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001608 }
Marcel Holtmann45bb4bf2005-08-09 20:27:49 -07001609
Linus Torvalds1da177e2005-04-16 15:20:36 -07001610 hci_dev_unlock(hdev);
1611}
1612
Gustavo Padovan6039aa732012-05-23 04:04:18 -03001613static void hci_conn_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001614{
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001615 struct hci_ev_conn_complete *ev = (void *) skb->data;
1616 struct hci_conn *conn;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001617
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001618 BT_DBG("%s", hdev->name);
Marcel Holtmann45bb4bf2005-08-09 20:27:49 -07001619
Linus Torvalds1da177e2005-04-16 15:20:36 -07001620 hci_dev_lock(hdev);
Marcel Holtmann45bb4bf2005-08-09 20:27:49 -07001621
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001622 conn = hci_conn_hash_lookup_ba(hdev, ev->link_type, &ev->bdaddr);
Marcel Holtmann94992372009-04-19 19:30:03 +02001623 if (!conn) {
1624 if (ev->link_type != SCO_LINK)
1625 goto unlock;
1626
1627 conn = hci_conn_hash_lookup_ba(hdev, ESCO_LINK, &ev->bdaddr);
1628 if (!conn)
1629 goto unlock;
1630
1631 conn->type = SCO_LINK;
1632 }
Marcel Holtmann45bb4bf2005-08-09 20:27:49 -07001633
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001634 if (!ev->status) {
1635 conn->handle = __le16_to_cpu(ev->handle);
Marcel Holtmann769be972008-07-14 20:13:49 +02001636
1637 if (conn->type == ACL_LINK) {
1638 conn->state = BT_CONFIG;
1639 hci_conn_hold(conn);
Szymon Janca9ea3ed2012-07-19 14:46:08 +02001640
1641 if (!conn->out && !hci_conn_ssp_enabled(conn) &&
1642 !hci_find_link_key(hdev, &ev->bdaddr))
1643 conn->disc_timeout = HCI_PAIRING_TIMEOUT;
1644 else
1645 conn->disc_timeout = HCI_DISCONN_TIMEOUT;
Marcel Holtmann769be972008-07-14 20:13:49 +02001646 } else
1647 conn->state = BT_CONNECTED;
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001648
Marcel Holtmann9eba32b2009-08-22 14:19:26 -07001649 hci_conn_hold_device(conn);
Marcel Holtmann7d0db0a2008-07-14 20:13:51 +02001650 hci_conn_add_sysfs(conn);
1651
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001652 if (test_bit(HCI_AUTH, &hdev->flags))
1653 conn->link_mode |= HCI_LM_AUTH;
1654
1655 if (test_bit(HCI_ENCRYPT, &hdev->flags))
1656 conn->link_mode |= HCI_LM_ENCRYPT;
1657
1658 /* Get remote features */
1659 if (conn->type == ACL_LINK) {
1660 struct hci_cp_read_remote_features cp;
1661 cp.handle = ev->handle;
Marcel Holtmann769be972008-07-14 20:13:49 +02001662 hci_send_cmd(hdev, HCI_OP_READ_REMOTE_FEATURES,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001663 sizeof(cp), &cp);
Marcel Holtmann45bb4bf2005-08-09 20:27:49 -07001664 }
Marcel Holtmann45bb4bf2005-08-09 20:27:49 -07001665
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001666 /* Set packet type for incoming connection */
Andrei Emeltchenkod095c1e2011-12-01 14:33:27 +02001667 if (!conn->out && hdev->hci_ver < BLUETOOTH_VER_2_0) {
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001668 struct hci_cp_change_conn_ptype cp;
1669 cp.handle = ev->handle;
Marcel Holtmanna8746412008-07-14 20:13:46 +02001670 cp.pkt_type = cpu_to_le16(conn->pkt_type);
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001671 hci_send_cmd(hdev, HCI_OP_CHANGE_CONN_PTYPE, sizeof(cp),
1672 &cp);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001673 }
Johan Hedberg17d5c042011-01-22 06:09:08 +02001674 } else {
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001675 conn->state = BT_CLOSED;
Johan Hedberg17d5c042011-01-22 06:09:08 +02001676 if (conn->type == ACL_LINK)
Johan Hedberg744cf192011-11-08 20:40:14 +02001677 mgmt_connect_failed(hdev, &ev->bdaddr, conn->type,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001678 conn->dst_type, ev->status);
Johan Hedberg17d5c042011-01-22 06:09:08 +02001679 }
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001680
Marcel Holtmanne73439d2010-07-26 10:06:00 -04001681 if (conn->type == ACL_LINK)
1682 hci_sco_setup(conn, ev->status);
Marcel Holtmann45bb4bf2005-08-09 20:27:49 -07001683
Marcel Holtmann769be972008-07-14 20:13:49 +02001684 if (ev->status) {
1685 hci_proto_connect_cfm(conn, ev->status);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001686 hci_conn_del(conn);
Marcel Holtmannc89b6e62009-01-15 21:57:03 +01001687 } else if (ev->link_type != ACL_LINK)
1688 hci_proto_connect_cfm(conn, ev->status);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001689
1690unlock:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001691 hci_dev_unlock(hdev);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001692
1693 hci_conn_check_pending(hdev);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001694}
1695
Frédéric Dalleau20714bf2012-11-21 10:51:12 +01001696void hci_conn_accept(struct hci_conn *conn, int mask)
1697{
1698 struct hci_dev *hdev = conn->hdev;
1699
1700 BT_DBG("conn %p", conn);
1701
1702 conn->state = BT_CONFIG;
1703
1704 if (!lmp_esco_capable(hdev)) {
1705 struct hci_cp_accept_conn_req cp;
1706
1707 bacpy(&cp.bdaddr, &conn->dst);
1708
1709 if (lmp_rswitch_capable(hdev) && (mask & HCI_LM_MASTER))
1710 cp.role = 0x00; /* Become master */
1711 else
1712 cp.role = 0x01; /* Remain slave */
1713
1714 hci_send_cmd(hdev, HCI_OP_ACCEPT_CONN_REQ, sizeof(cp), &cp);
1715 } else /* lmp_esco_capable(hdev)) */ {
1716 struct hci_cp_accept_sync_conn_req cp;
1717
1718 bacpy(&cp.bdaddr, &conn->dst);
1719 cp.pkt_type = cpu_to_le16(conn->pkt_type);
1720
1721 cp.tx_bandwidth = __constant_cpu_to_le32(0x00001f40);
1722 cp.rx_bandwidth = __constant_cpu_to_le32(0x00001f40);
1723 cp.max_latency = __constant_cpu_to_le16(0xffff);
1724 cp.content_format = cpu_to_le16(hdev->voice_setting);
1725 cp.retrans_effort = 0xff;
1726
1727 hci_send_cmd(hdev, HCI_OP_ACCEPT_SYNC_CONN_REQ,
1728 sizeof(cp), &cp);
1729 }
1730}
1731
Gustavo Padovan6039aa732012-05-23 04:04:18 -03001732static void hci_conn_request_evt(struct hci_dev *hdev, struct sk_buff *skb)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001733{
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001734 struct hci_ev_conn_request *ev = (void *) skb->data;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001735 int mask = hdev->link_mode;
Frédéric Dalleau20714bf2012-11-21 10:51:12 +01001736 __u8 flags = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001737
Andrei Emeltchenko6ed93dc2012-09-25 12:49:43 +03001738 BT_DBG("%s bdaddr %pMR type 0x%x", hdev->name, &ev->bdaddr,
Gustavo Padovan807deac2012-05-17 00:36:24 -03001739 ev->link_type);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001740
Frédéric Dalleau20714bf2012-11-21 10:51:12 +01001741 mask |= hci_proto_connect_ind(hdev, &ev->bdaddr, ev->link_type,
1742 &flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001743
Szymon Janc138d22e2011-02-17 16:44:23 +01001744 if ((mask & HCI_LM_ACCEPT) &&
Gustavo Padovan807deac2012-05-17 00:36:24 -03001745 !hci_blacklist_lookup(hdev, &ev->bdaddr)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001746 /* Connection accepted */
Marcel Holtmannc7bdd502008-07-14 20:13:47 +02001747 struct inquiry_entry *ie;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001748 struct hci_conn *conn;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001749
1750 hci_dev_lock(hdev);
Marcel Holtmannb6a0dc82007-10-20 14:55:10 +02001751
Andrei Emeltchenkocc11b9c2010-11-22 13:21:37 +02001752 ie = hci_inquiry_cache_lookup(hdev, &ev->bdaddr);
1753 if (ie)
Marcel Holtmannc7bdd502008-07-14 20:13:47 +02001754 memcpy(ie->data.dev_class, ev->dev_class, 3);
1755
Gustavo Padovan8fc9ced2012-05-23 04:04:21 -03001756 conn = hci_conn_hash_lookup_ba(hdev, ev->link_type,
1757 &ev->bdaddr);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001758 if (!conn) {
Andrei Emeltchenkocc11b9c2010-11-22 13:21:37 +02001759 conn = hci_conn_add(hdev, ev->link_type, &ev->bdaddr);
1760 if (!conn) {
Gustavo F. Padovan893ef972010-07-18 15:13:37 -03001761 BT_ERR("No memory for new connection");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001762 hci_dev_unlock(hdev);
1763 return;
1764 }
1765 }
Marcel Holtmannb6a0dc82007-10-20 14:55:10 +02001766
Linus Torvalds1da177e2005-04-16 15:20:36 -07001767 memcpy(conn->dev_class, ev->dev_class, 3);
Marcel Holtmannb6a0dc82007-10-20 14:55:10 +02001768
Linus Torvalds1da177e2005-04-16 15:20:36 -07001769 hci_dev_unlock(hdev);
1770
Frédéric Dalleau20714bf2012-11-21 10:51:12 +01001771 if (ev->link_type == ACL_LINK ||
1772 (!(flags & HCI_PROTO_DEFER) && !lmp_esco_capable(hdev))) {
Marcel Holtmannb6a0dc82007-10-20 14:55:10 +02001773 struct hci_cp_accept_conn_req cp;
Frédéric Dalleau20714bf2012-11-21 10:51:12 +01001774 conn->state = BT_CONNECT;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001775
Marcel Holtmannb6a0dc82007-10-20 14:55:10 +02001776 bacpy(&cp.bdaddr, &ev->bdaddr);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001777
Marcel Holtmannb6a0dc82007-10-20 14:55:10 +02001778 if (lmp_rswitch_capable(hdev) && (mask & HCI_LM_MASTER))
1779 cp.role = 0x00; /* Become master */
1780 else
1781 cp.role = 0x01; /* Remain slave */
1782
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001783 hci_send_cmd(hdev, HCI_OP_ACCEPT_CONN_REQ, sizeof(cp),
1784 &cp);
Frédéric Dalleau20714bf2012-11-21 10:51:12 +01001785 } else if (!(flags & HCI_PROTO_DEFER)) {
Marcel Holtmannb6a0dc82007-10-20 14:55:10 +02001786 struct hci_cp_accept_sync_conn_req cp;
Frédéric Dalleau20714bf2012-11-21 10:51:12 +01001787 conn->state = BT_CONNECT;
Marcel Holtmannb6a0dc82007-10-20 14:55:10 +02001788
1789 bacpy(&cp.bdaddr, &ev->bdaddr);
Marcel Holtmanna8746412008-07-14 20:13:46 +02001790 cp.pkt_type = cpu_to_le16(conn->pkt_type);
Marcel Holtmannb6a0dc82007-10-20 14:55:10 +02001791
Andrei Emeltchenko82781e62012-05-25 11:38:27 +03001792 cp.tx_bandwidth = __constant_cpu_to_le32(0x00001f40);
1793 cp.rx_bandwidth = __constant_cpu_to_le32(0x00001f40);
1794 cp.max_latency = __constant_cpu_to_le16(0xffff);
Marcel Holtmannb6a0dc82007-10-20 14:55:10 +02001795 cp.content_format = cpu_to_le16(hdev->voice_setting);
1796 cp.retrans_effort = 0xff;
1797
1798 hci_send_cmd(hdev, HCI_OP_ACCEPT_SYNC_CONN_REQ,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001799 sizeof(cp), &cp);
Frédéric Dalleau20714bf2012-11-21 10:51:12 +01001800 } else {
1801 conn->state = BT_CONNECT2;
1802 hci_proto_connect_cfm(conn, 0);
1803 hci_conn_put(conn);
Marcel Holtmannb6a0dc82007-10-20 14:55:10 +02001804 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001805 } else {
1806 /* Connection rejected */
1807 struct hci_cp_reject_conn_req cp;
1808
1809 bacpy(&cp.bdaddr, &ev->bdaddr);
Andrei Emeltchenko9f5a0d72011-11-07 14:20:25 +02001810 cp.reason = HCI_ERROR_REJ_BAD_ADDR;
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001811 hci_send_cmd(hdev, HCI_OP_REJECT_CONN_REQ, sizeof(cp), &cp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001812 }
1813}
1814
Mikel Astizf0d6a0e2012-08-09 09:52:30 +02001815static u8 hci_to_mgmt_reason(u8 err)
1816{
1817 switch (err) {
1818 case HCI_ERROR_CONNECTION_TIMEOUT:
1819 return MGMT_DEV_DISCONN_TIMEOUT;
1820 case HCI_ERROR_REMOTE_USER_TERM:
1821 case HCI_ERROR_REMOTE_LOW_RESOURCES:
1822 case HCI_ERROR_REMOTE_POWER_OFF:
1823 return MGMT_DEV_DISCONN_REMOTE;
1824 case HCI_ERROR_LOCAL_HOST_TERM:
1825 return MGMT_DEV_DISCONN_LOCAL_HOST;
1826 default:
1827 return MGMT_DEV_DISCONN_UNKNOWN;
1828 }
1829}
1830
Gustavo Padovan6039aa732012-05-23 04:04:18 -03001831static void hci_disconn_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001832{
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001833 struct hci_ev_disconn_complete *ev = (void *) skb->data;
Marcel Holtmann04837f62006-07-03 10:02:33 +02001834 struct hci_conn *conn;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001835
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +03001836 BT_DBG("%s status 0x%2.2x", hdev->name, ev->status);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001837
Linus Torvalds1da177e2005-04-16 15:20:36 -07001838 hci_dev_lock(hdev);
1839
Marcel Holtmann04837f62006-07-03 10:02:33 +02001840 conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
Johan Hedbergf7520542011-01-20 12:34:39 +02001841 if (!conn)
1842 goto unlock;
Marcel Holtmann7d0db0a2008-07-14 20:13:51 +02001843
Johan Hedberg37d9ef72011-11-10 15:54:39 +02001844 if (ev->status == 0)
1845 conn->state = BT_CLOSED;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001846
Johan Hedbergb644ba32012-01-17 21:48:47 +02001847 if (test_and_clear_bit(HCI_CONN_MGMT_CONNECTED, &conn->flags) &&
Gustavo Padovan807deac2012-05-17 00:36:24 -03001848 (conn->type == ACL_LINK || conn->type == LE_LINK)) {
Mikel Astizf0d6a0e2012-08-09 09:52:30 +02001849 if (ev->status) {
Johan Hedberg88c3df12012-02-09 14:27:38 +02001850 mgmt_disconnect_failed(hdev, &conn->dst, conn->type,
Gustavo Padovan807deac2012-05-17 00:36:24 -03001851 conn->dst_type, ev->status);
Mikel Astizf0d6a0e2012-08-09 09:52:30 +02001852 } else {
1853 u8 reason = hci_to_mgmt_reason(ev->reason);
1854
Johan Hedbergafc747a2012-01-15 18:11:07 +02001855 mgmt_device_disconnected(hdev, &conn->dst, conn->type,
Mikel Astizf0d6a0e2012-08-09 09:52:30 +02001856 conn->dst_type, reason);
1857 }
Johan Hedberg37d9ef72011-11-10 15:54:39 +02001858 }
Johan Hedbergf7520542011-01-20 12:34:39 +02001859
Johan Hedberg37d9ef72011-11-10 15:54:39 +02001860 if (ev->status == 0) {
Vishal Agarwal6ec5bca2012-04-16 14:44:44 +05301861 if (conn->type == ACL_LINK && conn->flush_key)
1862 hci_remove_link_key(hdev, &conn->dst);
Johan Hedberg37d9ef72011-11-10 15:54:39 +02001863 hci_proto_disconn_cfm(conn, ev->reason);
1864 hci_conn_del(conn);
1865 }
Johan Hedbergf7520542011-01-20 12:34:39 +02001866
1867unlock:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001868 hci_dev_unlock(hdev);
1869}
1870
Gustavo Padovan6039aa732012-05-23 04:04:18 -03001871static void hci_auth_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001872{
1873 struct hci_ev_auth_complete *ev = (void *) skb->data;
1874 struct hci_conn *conn;
1875
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +03001876 BT_DBG("%s status 0x%2.2x", hdev->name, ev->status);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001877
1878 hci_dev_lock(hdev);
1879
1880 conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
Waldemar Rymarkiewiczd7556e22011-05-31 15:49:26 +02001881 if (!conn)
1882 goto unlock;
1883
1884 if (!ev->status) {
Johan Hedbergaa64a8b2012-01-18 21:33:12 +02001885 if (!hci_conn_ssp_enabled(conn) &&
Gustavo Padovan807deac2012-05-17 00:36:24 -03001886 test_bit(HCI_CONN_REAUTH_PEND, &conn->flags)) {
Waldemar Rymarkiewiczd7556e22011-05-31 15:49:26 +02001887 BT_INFO("re-auth of legacy device is not possible.");
Johan Hedberg2a611692011-02-19 12:06:00 -03001888 } else {
Waldemar Rymarkiewiczd7556e22011-05-31 15:49:26 +02001889 conn->link_mode |= HCI_LM_AUTH;
1890 conn->sec_level = conn->pending_sec_level;
Johan Hedberg2a611692011-02-19 12:06:00 -03001891 }
Waldemar Rymarkiewiczd7556e22011-05-31 15:49:26 +02001892 } else {
Johan Hedbergbab73cb2012-02-09 16:07:29 +02001893 mgmt_auth_failed(hdev, &conn->dst, conn->type, conn->dst_type,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001894 ev->status);
Waldemar Rymarkiewiczd7556e22011-05-31 15:49:26 +02001895 }
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001896
Johan Hedberg51a8efd2012-01-16 06:10:31 +02001897 clear_bit(HCI_CONN_AUTH_PEND, &conn->flags);
1898 clear_bit(HCI_CONN_REAUTH_PEND, &conn->flags);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001899
Waldemar Rymarkiewiczd7556e22011-05-31 15:49:26 +02001900 if (conn->state == BT_CONFIG) {
Johan Hedbergaa64a8b2012-01-18 21:33:12 +02001901 if (!ev->status && hci_conn_ssp_enabled(conn)) {
Waldemar Rymarkiewiczd7556e22011-05-31 15:49:26 +02001902 struct hci_cp_set_conn_encrypt cp;
1903 cp.handle = ev->handle;
1904 cp.encrypt = 0x01;
1905 hci_send_cmd(hdev, HCI_OP_SET_CONN_ENCRYPT, sizeof(cp),
Gustavo Padovan807deac2012-05-17 00:36:24 -03001906 &cp);
Marcel Holtmann052b30b2009-04-26 20:01:22 +02001907 } else {
Waldemar Rymarkiewiczd7556e22011-05-31 15:49:26 +02001908 conn->state = BT_CONNECTED;
1909 hci_proto_connect_cfm(conn, ev->status);
Marcel Holtmann052b30b2009-04-26 20:01:22 +02001910 hci_conn_put(conn);
1911 }
Waldemar Rymarkiewiczd7556e22011-05-31 15:49:26 +02001912 } else {
1913 hci_auth_cfm(conn, ev->status);
Marcel Holtmann052b30b2009-04-26 20:01:22 +02001914
Waldemar Rymarkiewiczd7556e22011-05-31 15:49:26 +02001915 hci_conn_hold(conn);
1916 conn->disc_timeout = HCI_DISCONN_TIMEOUT;
1917 hci_conn_put(conn);
1918 }
1919
Johan Hedberg51a8efd2012-01-16 06:10:31 +02001920 if (test_bit(HCI_CONN_ENCRYPT_PEND, &conn->flags)) {
Waldemar Rymarkiewiczd7556e22011-05-31 15:49:26 +02001921 if (!ev->status) {
1922 struct hci_cp_set_conn_encrypt cp;
1923 cp.handle = ev->handle;
1924 cp.encrypt = 0x01;
1925 hci_send_cmd(hdev, HCI_OP_SET_CONN_ENCRYPT, sizeof(cp),
Gustavo Padovan807deac2012-05-17 00:36:24 -03001926 &cp);
Waldemar Rymarkiewiczd7556e22011-05-31 15:49:26 +02001927 } else {
Johan Hedberg51a8efd2012-01-16 06:10:31 +02001928 clear_bit(HCI_CONN_ENCRYPT_PEND, &conn->flags);
Waldemar Rymarkiewiczd7556e22011-05-31 15:49:26 +02001929 hci_encrypt_cfm(conn, ev->status, 0x00);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001930 }
1931 }
1932
Waldemar Rymarkiewiczd7556e22011-05-31 15:49:26 +02001933unlock:
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001934 hci_dev_unlock(hdev);
1935}
1936
Gustavo Padovan6039aa732012-05-23 04:04:18 -03001937static void hci_remote_name_evt(struct hci_dev *hdev, struct sk_buff *skb)
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001938{
Johan Hedberg127178d2010-11-18 22:22:29 +02001939 struct hci_ev_remote_name *ev = (void *) skb->data;
1940 struct hci_conn *conn;
1941
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001942 BT_DBG("%s", hdev->name);
1943
1944 hci_conn_check_pending(hdev);
Johan Hedberg127178d2010-11-18 22:22:29 +02001945
1946 hci_dev_lock(hdev);
1947
1948 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
Johan Hedbergb644ba32012-01-17 21:48:47 +02001949
1950 if (!test_bit(HCI_MGMT, &hdev->dev_flags))
1951 goto check_auth;
1952
1953 if (ev->status == 0)
1954 hci_check_pending_name(hdev, conn, &ev->bdaddr, ev->name,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001955 strnlen(ev->name, HCI_MAX_NAME_LENGTH));
Johan Hedbergb644ba32012-01-17 21:48:47 +02001956 else
1957 hci_check_pending_name(hdev, conn, &ev->bdaddr, NULL, 0);
1958
1959check_auth:
Johan Hedberg79c6c702011-04-28 11:28:55 -07001960 if (!conn)
1961 goto unlock;
1962
1963 if (!hci_outgoing_auth_needed(hdev, conn))
1964 goto unlock;
1965
Johan Hedberg51a8efd2012-01-16 06:10:31 +02001966 if (!test_and_set_bit(HCI_CONN_AUTH_PEND, &conn->flags)) {
Johan Hedberg127178d2010-11-18 22:22:29 +02001967 struct hci_cp_auth_requested cp;
1968 cp.handle = __cpu_to_le16(conn->handle);
1969 hci_send_cmd(hdev, HCI_OP_AUTH_REQUESTED, sizeof(cp), &cp);
1970 }
1971
Johan Hedberg79c6c702011-04-28 11:28:55 -07001972unlock:
Johan Hedberg127178d2010-11-18 22:22:29 +02001973 hci_dev_unlock(hdev);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001974}
1975
Gustavo Padovan6039aa732012-05-23 04:04:18 -03001976static void hci_encrypt_change_evt(struct hci_dev *hdev, struct sk_buff *skb)
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001977{
1978 struct hci_ev_encrypt_change *ev = (void *) skb->data;
1979 struct hci_conn *conn;
1980
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +03001981 BT_DBG("%s status 0x%2.2x", hdev->name, ev->status);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001982
1983 hci_dev_lock(hdev);
1984
1985 conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
1986 if (conn) {
1987 if (!ev->status) {
Marcel Holtmannae293192008-07-14 20:13:45 +02001988 if (ev->encrypt) {
1989 /* Encryption implies authentication */
1990 conn->link_mode |= HCI_LM_AUTH;
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001991 conn->link_mode |= HCI_LM_ENCRYPT;
Vinicius Costa Gomesda85e5e2011-06-09 18:50:53 -03001992 conn->sec_level = conn->pending_sec_level;
Marcel Holtmannae293192008-07-14 20:13:45 +02001993 } else
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001994 conn->link_mode &= ~HCI_LM_ENCRYPT;
1995 }
1996
Johan Hedberg51a8efd2012-01-16 06:10:31 +02001997 clear_bit(HCI_CONN_ENCRYPT_PEND, &conn->flags);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001998
Gustavo Padovana7d77232012-05-13 03:20:07 -03001999 if (ev->status && conn->state == BT_CONNECTED) {
Andre Guedesbed71742013-01-30 11:50:56 -03002000 hci_disconnect(conn, HCI_ERROR_AUTH_FAILURE);
Gustavo Padovana7d77232012-05-13 03:20:07 -03002001 hci_conn_put(conn);
2002 goto unlock;
2003 }
2004
Marcel Holtmannf8558552008-07-14 20:13:49 +02002005 if (conn->state == BT_CONFIG) {
2006 if (!ev->status)
2007 conn->state = BT_CONNECTED;
2008
2009 hci_proto_connect_cfm(conn, ev->status);
2010 hci_conn_put(conn);
2011 } else
2012 hci_encrypt_cfm(conn, ev->status, ev->encrypt);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002013 }
2014
Gustavo Padovana7d77232012-05-13 03:20:07 -03002015unlock:
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002016 hci_dev_unlock(hdev);
2017}
2018
Gustavo Padovan6039aa732012-05-23 04:04:18 -03002019static void hci_change_link_key_complete_evt(struct hci_dev *hdev,
2020 struct sk_buff *skb)
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002021{
2022 struct hci_ev_change_link_key_complete *ev = (void *) skb->data;
2023 struct hci_conn *conn;
2024
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +03002025 BT_DBG("%s status 0x%2.2x", hdev->name, ev->status);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002026
2027 hci_dev_lock(hdev);
2028
2029 conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
2030 if (conn) {
2031 if (!ev->status)
2032 conn->link_mode |= HCI_LM_SECURE;
2033
Johan Hedberg51a8efd2012-01-16 06:10:31 +02002034 clear_bit(HCI_CONN_AUTH_PEND, &conn->flags);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002035
2036 hci_key_change_cfm(conn, ev->status);
2037 }
2038
2039 hci_dev_unlock(hdev);
2040}
2041
Gustavo Padovan6039aa732012-05-23 04:04:18 -03002042static void hci_remote_features_evt(struct hci_dev *hdev,
2043 struct sk_buff *skb)
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002044{
2045 struct hci_ev_remote_features *ev = (void *) skb->data;
2046 struct hci_conn *conn;
2047
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +03002048 BT_DBG("%s status 0x%2.2x", hdev->name, ev->status);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002049
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002050 hci_dev_lock(hdev);
2051
2052 conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
Johan Hedbergccd556f2010-11-10 17:11:51 +02002053 if (!conn)
2054 goto unlock;
Marcel Holtmann769be972008-07-14 20:13:49 +02002055
Johan Hedbergccd556f2010-11-10 17:11:51 +02002056 if (!ev->status)
2057 memcpy(conn->features, ev->features, 8);
2058
2059 if (conn->state != BT_CONFIG)
2060 goto unlock;
2061
2062 if (!ev->status && lmp_ssp_capable(hdev) && lmp_ssp_capable(conn)) {
2063 struct hci_cp_read_remote_ext_features cp;
2064 cp.handle = ev->handle;
2065 cp.page = 0x01;
2066 hci_send_cmd(hdev, HCI_OP_READ_REMOTE_EXT_FEATURES,
Gustavo Padovan807deac2012-05-17 00:36:24 -03002067 sizeof(cp), &cp);
Johan Hedberg392599b2010-11-18 22:22:28 +02002068 goto unlock;
2069 }
2070
Johan Hedberg671267b2012-05-12 16:11:50 -03002071 if (!ev->status && !test_bit(HCI_CONN_MGMT_CONNECTED, &conn->flags)) {
Johan Hedberg127178d2010-11-18 22:22:29 +02002072 struct hci_cp_remote_name_req cp;
2073 memset(&cp, 0, sizeof(cp));
2074 bacpy(&cp.bdaddr, &conn->dst);
2075 cp.pscan_rep_mode = 0x02;
2076 hci_send_cmd(hdev, HCI_OP_REMOTE_NAME_REQ, sizeof(cp), &cp);
Johan Hedbergb644ba32012-01-17 21:48:47 +02002077 } else if (!test_and_set_bit(HCI_CONN_MGMT_CONNECTED, &conn->flags))
2078 mgmt_device_connected(hdev, &conn->dst, conn->type,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002079 conn->dst_type, 0, NULL, 0,
2080 conn->dev_class);
Johan Hedberg392599b2010-11-18 22:22:28 +02002081
Johan Hedberg127178d2010-11-18 22:22:29 +02002082 if (!hci_outgoing_auth_needed(hdev, conn)) {
Johan Hedbergccd556f2010-11-10 17:11:51 +02002083 conn->state = BT_CONNECTED;
2084 hci_proto_connect_cfm(conn, ev->status);
2085 hci_conn_put(conn);
Marcel Holtmann769be972008-07-14 20:13:49 +02002086 }
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002087
Johan Hedbergccd556f2010-11-10 17:11:51 +02002088unlock:
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002089 hci_dev_unlock(hdev);
2090}
2091
Gustavo Padovan6039aa732012-05-23 04:04:18 -03002092static void hci_cmd_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002093{
2094 struct hci_ev_cmd_complete *ev = (void *) skb->data;
Johan Hedberg9238f362013-03-05 20:37:48 +02002095 u8 status = skb->data[sizeof(*ev)];
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002096 __u16 opcode;
2097
2098 skb_pull(skb, sizeof(*ev));
2099
2100 opcode = __le16_to_cpu(ev->opcode);
2101
2102 switch (opcode) {
2103 case HCI_OP_INQUIRY_CANCEL:
2104 hci_cc_inquiry_cancel(hdev, skb);
2105 break;
2106
Andre Guedes4d934832012-03-21 00:03:35 -03002107 case HCI_OP_PERIODIC_INQ:
2108 hci_cc_periodic_inq(hdev, skb);
2109 break;
2110
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002111 case HCI_OP_EXIT_PERIODIC_INQ:
2112 hci_cc_exit_periodic_inq(hdev, skb);
2113 break;
2114
2115 case HCI_OP_REMOTE_NAME_REQ_CANCEL:
2116 hci_cc_remote_name_req_cancel(hdev, skb);
2117 break;
2118
2119 case HCI_OP_ROLE_DISCOVERY:
2120 hci_cc_role_discovery(hdev, skb);
2121 break;
2122
Marcel Holtmanne4e8e372008-07-14 20:13:47 +02002123 case HCI_OP_READ_LINK_POLICY:
2124 hci_cc_read_link_policy(hdev, skb);
2125 break;
2126
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002127 case HCI_OP_WRITE_LINK_POLICY:
2128 hci_cc_write_link_policy(hdev, skb);
2129 break;
2130
Marcel Holtmanne4e8e372008-07-14 20:13:47 +02002131 case HCI_OP_READ_DEF_LINK_POLICY:
2132 hci_cc_read_def_link_policy(hdev, skb);
2133 break;
2134
2135 case HCI_OP_WRITE_DEF_LINK_POLICY:
2136 hci_cc_write_def_link_policy(hdev, skb);
2137 break;
2138
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002139 case HCI_OP_RESET:
2140 hci_cc_reset(hdev, skb);
2141 break;
2142
2143 case HCI_OP_WRITE_LOCAL_NAME:
2144 hci_cc_write_local_name(hdev, skb);
2145 break;
2146
2147 case HCI_OP_READ_LOCAL_NAME:
2148 hci_cc_read_local_name(hdev, skb);
2149 break;
2150
2151 case HCI_OP_WRITE_AUTH_ENABLE:
2152 hci_cc_write_auth_enable(hdev, skb);
2153 break;
2154
2155 case HCI_OP_WRITE_ENCRYPT_MODE:
2156 hci_cc_write_encrypt_mode(hdev, skb);
2157 break;
2158
2159 case HCI_OP_WRITE_SCAN_ENABLE:
2160 hci_cc_write_scan_enable(hdev, skb);
2161 break;
2162
2163 case HCI_OP_READ_CLASS_OF_DEV:
2164 hci_cc_read_class_of_dev(hdev, skb);
2165 break;
2166
2167 case HCI_OP_WRITE_CLASS_OF_DEV:
2168 hci_cc_write_class_of_dev(hdev, skb);
2169 break;
2170
2171 case HCI_OP_READ_VOICE_SETTING:
2172 hci_cc_read_voice_setting(hdev, skb);
2173 break;
2174
2175 case HCI_OP_WRITE_VOICE_SETTING:
2176 hci_cc_write_voice_setting(hdev, skb);
2177 break;
2178
Marcel Holtmann333140b2008-07-14 20:13:48 +02002179 case HCI_OP_WRITE_SSP_MODE:
2180 hci_cc_write_ssp_mode(hdev, skb);
2181 break;
2182
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002183 case HCI_OP_READ_LOCAL_VERSION:
2184 hci_cc_read_local_version(hdev, skb);
2185 break;
2186
2187 case HCI_OP_READ_LOCAL_COMMANDS:
2188 hci_cc_read_local_commands(hdev, skb);
2189 break;
2190
2191 case HCI_OP_READ_LOCAL_FEATURES:
2192 hci_cc_read_local_features(hdev, skb);
2193 break;
2194
Andre Guedes971e3a42011-06-30 19:20:52 -03002195 case HCI_OP_READ_LOCAL_EXT_FEATURES:
2196 hci_cc_read_local_ext_features(hdev, skb);
2197 break;
2198
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002199 case HCI_OP_READ_BUFFER_SIZE:
2200 hci_cc_read_buffer_size(hdev, skb);
2201 break;
2202
2203 case HCI_OP_READ_BD_ADDR:
2204 hci_cc_read_bd_addr(hdev, skb);
2205 break;
2206
Andrei Emeltchenko350ee4c2011-12-07 15:56:51 +02002207 case HCI_OP_READ_DATA_BLOCK_SIZE:
2208 hci_cc_read_data_block_size(hdev, skb);
2209 break;
2210
Andrei Emeltchenko1e89cff2011-11-24 14:52:02 +02002211 case HCI_OP_READ_FLOW_CONTROL_MODE:
2212 hci_cc_read_flow_control_mode(hdev, skb);
2213 break;
2214
Andrei Emeltchenko928abaa2011-10-12 10:53:57 +03002215 case HCI_OP_READ_LOCAL_AMP_INFO:
2216 hci_cc_read_local_amp_info(hdev, skb);
2217 break;
2218
Andrei Emeltchenko903e4542012-09-27 17:26:09 +03002219 case HCI_OP_READ_LOCAL_AMP_ASSOC:
2220 hci_cc_read_local_amp_assoc(hdev, skb);
2221 break;
2222
Johan Hedbergd5859e22011-01-25 01:19:58 +02002223 case HCI_OP_READ_INQ_RSP_TX_POWER:
2224 hci_cc_read_inq_rsp_tx_power(hdev, skb);
2225 break;
2226
Johan Hedberg980e1a52011-01-22 06:10:07 +02002227 case HCI_OP_PIN_CODE_REPLY:
2228 hci_cc_pin_code_reply(hdev, skb);
2229 break;
2230
2231 case HCI_OP_PIN_CODE_NEG_REPLY:
2232 hci_cc_pin_code_neg_reply(hdev, skb);
2233 break;
2234
Szymon Jancc35938b2011-03-22 13:12:21 +01002235 case HCI_OP_READ_LOCAL_OOB_DATA:
2236 hci_cc_read_local_oob_data_reply(hdev, skb);
2237 break;
2238
Ville Tervo6ed58ec2011-02-10 22:38:48 -03002239 case HCI_OP_LE_READ_BUFFER_SIZE:
2240 hci_cc_le_read_buffer_size(hdev, skb);
2241 break;
2242
Johan Hedberg60e77322013-01-22 14:01:59 +02002243 case HCI_OP_LE_READ_LOCAL_FEATURES:
2244 hci_cc_le_read_local_features(hdev, skb);
2245 break;
2246
Johan Hedberg8fa19092012-10-19 20:57:49 +03002247 case HCI_OP_LE_READ_ADV_TX_POWER:
2248 hci_cc_le_read_adv_tx_power(hdev, skb);
2249 break;
2250
Johan Hedberga5c29682011-02-19 12:05:57 -03002251 case HCI_OP_USER_CONFIRM_REPLY:
2252 hci_cc_user_confirm_reply(hdev, skb);
2253 break;
2254
2255 case HCI_OP_USER_CONFIRM_NEG_REPLY:
2256 hci_cc_user_confirm_neg_reply(hdev, skb);
2257 break;
2258
Brian Gix1143d452011-11-23 08:28:34 -08002259 case HCI_OP_USER_PASSKEY_REPLY:
2260 hci_cc_user_passkey_reply(hdev, skb);
2261 break;
2262
2263 case HCI_OP_USER_PASSKEY_NEG_REPLY:
2264 hci_cc_user_passkey_neg_reply(hdev, skb);
Szymon Janc16cde992012-04-13 12:32:42 +02002265 break;
Andre Guedes07f7fa52011-12-02 21:13:31 +09002266
2267 case HCI_OP_LE_SET_SCAN_PARAM:
2268 hci_cc_le_set_scan_param(hdev, skb);
Brian Gix1143d452011-11-23 08:28:34 -08002269 break;
2270
Johan Hedbergc1d5dc42012-11-08 01:23:01 +01002271 case HCI_OP_LE_SET_ADV_ENABLE:
2272 hci_cc_le_set_adv_enable(hdev, skb);
2273 break;
2274
Andre Guedeseb9d91f2011-05-26 16:23:52 -03002275 case HCI_OP_LE_SET_SCAN_ENABLE:
2276 hci_cc_le_set_scan_enable(hdev, skb);
2277 break;
2278
Johan Hedbergcf1d0812013-01-22 14:02:00 +02002279 case HCI_OP_LE_READ_WHITE_LIST_SIZE:
2280 hci_cc_le_read_white_list_size(hdev, skb);
2281 break;
2282
Johan Hedberg9b008c02013-01-22 14:02:01 +02002283 case HCI_OP_LE_READ_SUPPORTED_STATES:
2284 hci_cc_le_read_supported_states(hdev, skb);
2285 break;
2286
Andre Guedesf9b49302011-06-30 19:20:53 -03002287 case HCI_OP_WRITE_LE_HOST_SUPPORTED:
2288 hci_cc_write_le_host_supported(hdev, skb);
2289 break;
2290
Andrei Emeltchenko93c284e2012-09-27 17:26:20 +03002291 case HCI_OP_WRITE_REMOTE_AMP_ASSOC:
2292 hci_cc_write_remote_amp_assoc(hdev, skb);
2293 break;
2294
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002295 default:
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +03002296 BT_DBG("%s opcode 0x%4.4x", hdev->name, opcode);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002297 break;
2298 }
2299
Johan Hedbergad82cdd2013-03-09 09:53:50 +02002300 if (opcode != HCI_OP_NOP)
Ville Tervo6bd32322011-02-16 16:32:41 +02002301 del_timer(&hdev->cmd_timer);
2302
Johan Hedbergad82cdd2013-03-09 09:53:50 +02002303 hci_req_cmd_complete(hdev, opcode, status);
Johan Hedberg9238f362013-03-05 20:37:48 +02002304
Szymon Jancdbccd792012-12-11 08:51:19 +01002305 if (ev->ncmd && !test_bit(HCI_RESET, &hdev->flags)) {
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002306 atomic_set(&hdev->cmd_cnt, 1);
2307 if (!skb_queue_empty(&hdev->cmd_q))
Gustavo F. Padovanc347b762011-12-14 23:53:47 -02002308 queue_work(hdev->workqueue, &hdev->cmd_work);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002309 }
2310}
2311
Gustavo Padovan6039aa732012-05-23 04:04:18 -03002312static void hci_cmd_status_evt(struct hci_dev *hdev, struct sk_buff *skb)
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002313{
2314 struct hci_ev_cmd_status *ev = (void *) skb->data;
2315 __u16 opcode;
2316
2317 skb_pull(skb, sizeof(*ev));
2318
2319 opcode = __le16_to_cpu(ev->opcode);
2320
2321 switch (opcode) {
2322 case HCI_OP_INQUIRY:
2323 hci_cs_inquiry(hdev, ev->status);
2324 break;
2325
2326 case HCI_OP_CREATE_CONN:
2327 hci_cs_create_conn(hdev, ev->status);
2328 break;
2329
2330 case HCI_OP_ADD_SCO:
2331 hci_cs_add_sco(hdev, ev->status);
2332 break;
2333
Marcel Holtmannf8558552008-07-14 20:13:49 +02002334 case HCI_OP_AUTH_REQUESTED:
2335 hci_cs_auth_requested(hdev, ev->status);
2336 break;
2337
2338 case HCI_OP_SET_CONN_ENCRYPT:
2339 hci_cs_set_conn_encrypt(hdev, ev->status);
2340 break;
2341
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002342 case HCI_OP_REMOTE_NAME_REQ:
2343 hci_cs_remote_name_req(hdev, ev->status);
2344 break;
2345
Marcel Holtmann769be972008-07-14 20:13:49 +02002346 case HCI_OP_READ_REMOTE_FEATURES:
2347 hci_cs_read_remote_features(hdev, ev->status);
2348 break;
2349
2350 case HCI_OP_READ_REMOTE_EXT_FEATURES:
2351 hci_cs_read_remote_ext_features(hdev, ev->status);
2352 break;
2353
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002354 case HCI_OP_SETUP_SYNC_CONN:
2355 hci_cs_setup_sync_conn(hdev, ev->status);
2356 break;
2357
2358 case HCI_OP_SNIFF_MODE:
2359 hci_cs_sniff_mode(hdev, ev->status);
2360 break;
2361
2362 case HCI_OP_EXIT_SNIFF_MODE:
2363 hci_cs_exit_sniff_mode(hdev, ev->status);
2364 break;
2365
Johan Hedberg8962ee72011-01-20 12:40:27 +02002366 case HCI_OP_DISCONNECT:
Johan Hedberg88c3df12012-02-09 14:27:38 +02002367 hci_cs_disconnect(hdev, ev->status);
Johan Hedberg8962ee72011-01-20 12:40:27 +02002368 break;
2369
Ville Tervofcd89c02011-02-10 22:38:47 -03002370 case HCI_OP_LE_CREATE_CONN:
2371 hci_cs_le_create_conn(hdev, ev->status);
2372 break;
2373
Andrei Emeltchenkoa02226d2012-09-27 17:26:19 +03002374 case HCI_OP_CREATE_PHY_LINK:
2375 hci_cs_create_phylink(hdev, ev->status);
2376 break;
2377
Andrei Emeltchenko0b26ab92012-09-27 17:26:24 +03002378 case HCI_OP_ACCEPT_PHY_LINK:
2379 hci_cs_accept_phylink(hdev, ev->status);
2380 break;
2381
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002382 default:
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +03002383 BT_DBG("%s opcode 0x%4.4x", hdev->name, opcode);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002384 break;
2385 }
2386
Johan Hedbergad82cdd2013-03-09 09:53:50 +02002387 if (opcode != HCI_OP_NOP)
Ville Tervo6bd32322011-02-16 16:32:41 +02002388 del_timer(&hdev->cmd_timer);
2389
Johan Hedbergad82cdd2013-03-09 09:53:50 +02002390 hci_req_cmd_status(hdev, opcode, ev->status);
Johan Hedberg9238f362013-03-05 20:37:48 +02002391
Gustavo F. Padovan10572132011-03-16 15:36:29 -03002392 if (ev->ncmd && !test_bit(HCI_RESET, &hdev->flags)) {
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002393 atomic_set(&hdev->cmd_cnt, 1);
2394 if (!skb_queue_empty(&hdev->cmd_q))
Gustavo F. Padovanc347b762011-12-14 23:53:47 -02002395 queue_work(hdev->workqueue, &hdev->cmd_work);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002396 }
2397}
2398
Gustavo Padovan6039aa732012-05-23 04:04:18 -03002399static void hci_role_change_evt(struct hci_dev *hdev, struct sk_buff *skb)
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002400{
2401 struct hci_ev_role_change *ev = (void *) skb->data;
2402 struct hci_conn *conn;
2403
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +03002404 BT_DBG("%s status 0x%2.2x", hdev->name, ev->status);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002405
2406 hci_dev_lock(hdev);
2407
2408 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
2409 if (conn) {
2410 if (!ev->status) {
2411 if (ev->role)
2412 conn->link_mode &= ~HCI_LM_MASTER;
2413 else
2414 conn->link_mode |= HCI_LM_MASTER;
2415 }
2416
Johan Hedberg51a8efd2012-01-16 06:10:31 +02002417 clear_bit(HCI_CONN_RSWITCH_PEND, &conn->flags);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002418
2419 hci_role_switch_cfm(conn, ev->status, ev->role);
2420 }
2421
2422 hci_dev_unlock(hdev);
2423}
2424
Gustavo Padovan6039aa732012-05-23 04:04:18 -03002425static void hci_num_comp_pkts_evt(struct hci_dev *hdev, struct sk_buff *skb)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002426{
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002427 struct hci_ev_num_comp_pkts *ev = (void *) skb->data;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002428 int i;
2429
Andrei Emeltchenko32ac5b92011-12-19 16:31:29 +02002430 if (hdev->flow_ctl_mode != HCI_FLOW_CTL_MODE_PACKET_BASED) {
2431 BT_ERR("Wrong event for mode %d", hdev->flow_ctl_mode);
2432 return;
2433 }
2434
Andrei Emeltchenkoc5993de2011-12-30 12:07:47 +02002435 if (skb->len < sizeof(*ev) || skb->len < sizeof(*ev) +
Gustavo Padovan807deac2012-05-17 00:36:24 -03002436 ev->num_hndl * sizeof(struct hci_comp_pkts_info)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002437 BT_DBG("%s bad parameters", hdev->name);
2438 return;
2439 }
2440
Andrei Emeltchenkoc5993de2011-12-30 12:07:47 +02002441 BT_DBG("%s num_hndl %d", hdev->name, ev->num_hndl);
2442
Andrei Emeltchenko613a1c02011-12-19 16:31:30 +02002443 for (i = 0; i < ev->num_hndl; i++) {
2444 struct hci_comp_pkts_info *info = &ev->handles[i];
Linus Torvalds1da177e2005-04-16 15:20:36 -07002445 struct hci_conn *conn;
2446 __u16 handle, count;
2447
Andrei Emeltchenko613a1c02011-12-19 16:31:30 +02002448 handle = __le16_to_cpu(info->handle);
2449 count = __le16_to_cpu(info->count);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002450
2451 conn = hci_conn_hash_lookup_handle(hdev, handle);
Andrei Emeltchenkof4280912011-12-07 15:56:52 +02002452 if (!conn)
2453 continue;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002454
Andrei Emeltchenkof4280912011-12-07 15:56:52 +02002455 conn->sent -= count;
2456
2457 switch (conn->type) {
2458 case ACL_LINK:
2459 hdev->acl_cnt += count;
2460 if (hdev->acl_cnt > hdev->acl_pkts)
2461 hdev->acl_cnt = hdev->acl_pkts;
2462 break;
2463
2464 case LE_LINK:
2465 if (hdev->le_pkts) {
2466 hdev->le_cnt += count;
2467 if (hdev->le_cnt > hdev->le_pkts)
2468 hdev->le_cnt = hdev->le_pkts;
2469 } else {
Andrei Emeltchenko70f230202010-12-01 16:58:25 +02002470 hdev->acl_cnt += count;
2471 if (hdev->acl_cnt > hdev->acl_pkts)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002472 hdev->acl_cnt = hdev->acl_pkts;
2473 }
Andrei Emeltchenkof4280912011-12-07 15:56:52 +02002474 break;
2475
2476 case SCO_LINK:
2477 hdev->sco_cnt += count;
2478 if (hdev->sco_cnt > hdev->sco_pkts)
2479 hdev->sco_cnt = hdev->sco_pkts;
2480 break;
2481
2482 default:
2483 BT_ERR("Unknown type %d conn %p", conn->type, conn);
2484 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002485 }
2486 }
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002487
Gustavo F. Padovan3eff45e2011-12-15 00:50:02 -02002488 queue_work(hdev->workqueue, &hdev->tx_work);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002489}
2490
Andrei Emeltchenko76ef7cf2012-10-10 17:38:29 +03002491static struct hci_conn *__hci_conn_lookup_handle(struct hci_dev *hdev,
2492 __u16 handle)
2493{
2494 struct hci_chan *chan;
2495
2496 switch (hdev->dev_type) {
2497 case HCI_BREDR:
2498 return hci_conn_hash_lookup_handle(hdev, handle);
2499 case HCI_AMP:
2500 chan = hci_chan_lookup_handle(hdev, handle);
2501 if (chan)
2502 return chan->conn;
2503 break;
2504 default:
2505 BT_ERR("%s unknown dev_type %d", hdev->name, hdev->dev_type);
2506 break;
2507 }
2508
2509 return NULL;
2510}
2511
Gustavo Padovan6039aa732012-05-23 04:04:18 -03002512static void hci_num_comp_blocks_evt(struct hci_dev *hdev, struct sk_buff *skb)
Andrei Emeltchenko25e89e92012-01-04 12:41:58 +02002513{
2514 struct hci_ev_num_comp_blocks *ev = (void *) skb->data;
2515 int i;
2516
2517 if (hdev->flow_ctl_mode != HCI_FLOW_CTL_MODE_BLOCK_BASED) {
2518 BT_ERR("Wrong event for mode %d", hdev->flow_ctl_mode);
2519 return;
2520 }
2521
2522 if (skb->len < sizeof(*ev) || skb->len < sizeof(*ev) +
Gustavo Padovan807deac2012-05-17 00:36:24 -03002523 ev->num_hndl * sizeof(struct hci_comp_blocks_info)) {
Andrei Emeltchenko25e89e92012-01-04 12:41:58 +02002524 BT_DBG("%s bad parameters", hdev->name);
2525 return;
2526 }
2527
2528 BT_DBG("%s num_blocks %d num_hndl %d", hdev->name, ev->num_blocks,
Gustavo Padovan807deac2012-05-17 00:36:24 -03002529 ev->num_hndl);
Andrei Emeltchenko25e89e92012-01-04 12:41:58 +02002530
2531 for (i = 0; i < ev->num_hndl; i++) {
2532 struct hci_comp_blocks_info *info = &ev->handles[i];
Andrei Emeltchenko76ef7cf2012-10-10 17:38:29 +03002533 struct hci_conn *conn = NULL;
Andrei Emeltchenko25e89e92012-01-04 12:41:58 +02002534 __u16 handle, block_count;
2535
2536 handle = __le16_to_cpu(info->handle);
2537 block_count = __le16_to_cpu(info->blocks);
2538
Andrei Emeltchenko76ef7cf2012-10-10 17:38:29 +03002539 conn = __hci_conn_lookup_handle(hdev, handle);
Andrei Emeltchenko25e89e92012-01-04 12:41:58 +02002540 if (!conn)
2541 continue;
2542
2543 conn->sent -= block_count;
2544
2545 switch (conn->type) {
2546 case ACL_LINK:
Andrei Emeltchenkobd1eb662012-10-10 17:38:30 +03002547 case AMP_LINK:
Andrei Emeltchenko25e89e92012-01-04 12:41:58 +02002548 hdev->block_cnt += block_count;
2549 if (hdev->block_cnt > hdev->num_blocks)
2550 hdev->block_cnt = hdev->num_blocks;
2551 break;
2552
2553 default:
2554 BT_ERR("Unknown type %d conn %p", conn->type, conn);
2555 break;
2556 }
2557 }
2558
2559 queue_work(hdev->workqueue, &hdev->tx_work);
2560}
2561
Gustavo Padovan6039aa732012-05-23 04:04:18 -03002562static void hci_mode_change_evt(struct hci_dev *hdev, struct sk_buff *skb)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002563{
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002564 struct hci_ev_mode_change *ev = (void *) skb->data;
Marcel Holtmann04837f62006-07-03 10:02:33 +02002565 struct hci_conn *conn;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002566
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +03002567 BT_DBG("%s status 0x%2.2x", hdev->name, ev->status);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002568
2569 hci_dev_lock(hdev);
2570
Marcel Holtmann04837f62006-07-03 10:02:33 +02002571 conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
2572 if (conn) {
2573 conn->mode = ev->mode;
2574 conn->interval = __le16_to_cpu(ev->interval);
2575
Gustavo Padovan8fc9ced2012-05-23 04:04:21 -03002576 if (!test_and_clear_bit(HCI_CONN_MODE_CHANGE_PEND,
2577 &conn->flags)) {
Marcel Holtmann04837f62006-07-03 10:02:33 +02002578 if (conn->mode == HCI_CM_ACTIVE)
Johan Hedberg58a681e2012-01-16 06:47:28 +02002579 set_bit(HCI_CONN_POWER_SAVE, &conn->flags);
Marcel Holtmann04837f62006-07-03 10:02:33 +02002580 else
Johan Hedberg58a681e2012-01-16 06:47:28 +02002581 clear_bit(HCI_CONN_POWER_SAVE, &conn->flags);
Marcel Holtmann04837f62006-07-03 10:02:33 +02002582 }
Marcel Holtmanne73439d2010-07-26 10:06:00 -04002583
Johan Hedberg51a8efd2012-01-16 06:10:31 +02002584 if (test_and_clear_bit(HCI_CONN_SCO_SETUP_PEND, &conn->flags))
Marcel Holtmanne73439d2010-07-26 10:06:00 -04002585 hci_sco_setup(conn, ev->status);
Marcel Holtmann04837f62006-07-03 10:02:33 +02002586 }
2587
2588 hci_dev_unlock(hdev);
2589}
2590
Gustavo Padovan6039aa732012-05-23 04:04:18 -03002591static void hci_pin_code_request_evt(struct hci_dev *hdev, struct sk_buff *skb)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002592{
Marcel Holtmann052b30b2009-04-26 20:01:22 +02002593 struct hci_ev_pin_code_req *ev = (void *) skb->data;
2594 struct hci_conn *conn;
2595
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002596 BT_DBG("%s", hdev->name);
Marcel Holtmann052b30b2009-04-26 20:01:22 +02002597
2598 hci_dev_lock(hdev);
2599
2600 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
Waldemar Rymarkiewiczb6f98042011-09-23 10:01:30 +02002601 if (!conn)
2602 goto unlock;
2603
2604 if (conn->state == BT_CONNECTED) {
Marcel Holtmann052b30b2009-04-26 20:01:22 +02002605 hci_conn_hold(conn);
2606 conn->disc_timeout = HCI_PAIRING_TIMEOUT;
2607 hci_conn_put(conn);
2608 }
2609
Johan Hedberga8b2d5c2012-01-08 23:11:15 +02002610 if (!test_bit(HCI_PAIRABLE, &hdev->dev_flags))
Johan Hedberg03b555e2011-01-04 15:40:05 +02002611 hci_send_cmd(hdev, HCI_OP_PIN_CODE_NEG_REPLY,
Gustavo Padovan807deac2012-05-17 00:36:24 -03002612 sizeof(ev->bdaddr), &ev->bdaddr);
Johan Hedberga8b2d5c2012-01-08 23:11:15 +02002613 else if (test_bit(HCI_MGMT, &hdev->dev_flags)) {
Waldemar Rymarkiewicza770bb52011-04-28 12:07:59 +02002614 u8 secure;
2615
2616 if (conn->pending_sec_level == BT_SECURITY_HIGH)
2617 secure = 1;
2618 else
2619 secure = 0;
2620
Johan Hedberg744cf192011-11-08 20:40:14 +02002621 mgmt_pin_code_request(hdev, &ev->bdaddr, secure);
Waldemar Rymarkiewicza770bb52011-04-28 12:07:59 +02002622 }
Johan Hedberg980e1a52011-01-22 06:10:07 +02002623
Waldemar Rymarkiewiczb6f98042011-09-23 10:01:30 +02002624unlock:
Marcel Holtmann052b30b2009-04-26 20:01:22 +02002625 hci_dev_unlock(hdev);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002626}
2627
Gustavo Padovan6039aa732012-05-23 04:04:18 -03002628static void hci_link_key_request_evt(struct hci_dev *hdev, struct sk_buff *skb)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002629{
Johan Hedberg55ed8ca2011-01-17 14:41:05 +02002630 struct hci_ev_link_key_req *ev = (void *) skb->data;
2631 struct hci_cp_link_key_reply cp;
2632 struct hci_conn *conn;
2633 struct link_key *key;
2634
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002635 BT_DBG("%s", hdev->name);
Johan Hedberg55ed8ca2011-01-17 14:41:05 +02002636
Johan Hedberga8b2d5c2012-01-08 23:11:15 +02002637 if (!test_bit(HCI_LINK_KEYS, &hdev->dev_flags))
Johan Hedberg55ed8ca2011-01-17 14:41:05 +02002638 return;
2639
2640 hci_dev_lock(hdev);
2641
2642 key = hci_find_link_key(hdev, &ev->bdaddr);
2643 if (!key) {
Andrei Emeltchenko6ed93dc2012-09-25 12:49:43 +03002644 BT_DBG("%s link key not found for %pMR", hdev->name,
2645 &ev->bdaddr);
Johan Hedberg55ed8ca2011-01-17 14:41:05 +02002646 goto not_found;
2647 }
2648
Andrei Emeltchenko6ed93dc2012-09-25 12:49:43 +03002649 BT_DBG("%s found key type %u for %pMR", hdev->name, key->type,
2650 &ev->bdaddr);
Johan Hedberg55ed8ca2011-01-17 14:41:05 +02002651
Johan Hedberga8b2d5c2012-01-08 23:11:15 +02002652 if (!test_bit(HCI_DEBUG_KEYS, &hdev->dev_flags) &&
Gustavo Padovan807deac2012-05-17 00:36:24 -03002653 key->type == HCI_LK_DEBUG_COMBINATION) {
Johan Hedberg55ed8ca2011-01-17 14:41:05 +02002654 BT_DBG("%s ignoring debug key", hdev->name);
2655 goto not_found;
2656 }
2657
2658 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
Waldemar Rymarkiewicz60b83f52011-04-28 12:07:56 +02002659 if (conn) {
2660 if (key->type == HCI_LK_UNAUTH_COMBINATION &&
Gustavo Padovan807deac2012-05-17 00:36:24 -03002661 conn->auth_type != 0xff && (conn->auth_type & 0x01)) {
Waldemar Rymarkiewicz60b83f52011-04-28 12:07:56 +02002662 BT_DBG("%s ignoring unauthenticated key", hdev->name);
2663 goto not_found;
2664 }
Johan Hedberg55ed8ca2011-01-17 14:41:05 +02002665
Waldemar Rymarkiewicz60b83f52011-04-28 12:07:56 +02002666 if (key->type == HCI_LK_COMBINATION && key->pin_len < 16 &&
Gustavo Padovan807deac2012-05-17 00:36:24 -03002667 conn->pending_sec_level == BT_SECURITY_HIGH) {
Gustavo Padovan8fc9ced2012-05-23 04:04:21 -03002668 BT_DBG("%s ignoring key unauthenticated for high security",
2669 hdev->name);
Waldemar Rymarkiewicz60b83f52011-04-28 12:07:56 +02002670 goto not_found;
2671 }
2672
2673 conn->key_type = key->type;
2674 conn->pin_length = key->pin_len;
Johan Hedberg55ed8ca2011-01-17 14:41:05 +02002675 }
2676
2677 bacpy(&cp.bdaddr, &ev->bdaddr);
Andrei Emeltchenko9b3b4462012-05-23 11:31:20 +03002678 memcpy(cp.link_key, key->val, HCI_LINK_KEY_SIZE);
Johan Hedberg55ed8ca2011-01-17 14:41:05 +02002679
2680 hci_send_cmd(hdev, HCI_OP_LINK_KEY_REPLY, sizeof(cp), &cp);
2681
2682 hci_dev_unlock(hdev);
2683
2684 return;
2685
2686not_found:
2687 hci_send_cmd(hdev, HCI_OP_LINK_KEY_NEG_REPLY, 6, &ev->bdaddr);
2688 hci_dev_unlock(hdev);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002689}
2690
Gustavo Padovan6039aa732012-05-23 04:04:18 -03002691static void hci_link_key_notify_evt(struct hci_dev *hdev, struct sk_buff *skb)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002692{
Marcel Holtmann052b30b2009-04-26 20:01:22 +02002693 struct hci_ev_link_key_notify *ev = (void *) skb->data;
2694 struct hci_conn *conn;
Johan Hedberg55ed8ca2011-01-17 14:41:05 +02002695 u8 pin_len = 0;
Marcel Holtmann052b30b2009-04-26 20:01:22 +02002696
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002697 BT_DBG("%s", hdev->name);
Marcel Holtmann052b30b2009-04-26 20:01:22 +02002698
2699 hci_dev_lock(hdev);
2700
2701 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
2702 if (conn) {
2703 hci_conn_hold(conn);
2704 conn->disc_timeout = HCI_DISCONN_TIMEOUT;
Johan Hedberg980e1a52011-01-22 06:10:07 +02002705 pin_len = conn->pin_length;
Waldemar Rymarkiewicz13d39312011-04-28 12:07:55 +02002706
2707 if (ev->key_type != HCI_LK_CHANGED_COMBINATION)
2708 conn->key_type = ev->key_type;
2709
Marcel Holtmann052b30b2009-04-26 20:01:22 +02002710 hci_conn_put(conn);
2711 }
2712
Johan Hedberga8b2d5c2012-01-08 23:11:15 +02002713 if (test_bit(HCI_LINK_KEYS, &hdev->dev_flags))
Johan Hedbergd25e28a2011-04-28 11:28:59 -07002714 hci_add_link_key(hdev, conn, 1, &ev->bdaddr, ev->link_key,
Gustavo Padovan807deac2012-05-17 00:36:24 -03002715 ev->key_type, pin_len);
Johan Hedberg55ed8ca2011-01-17 14:41:05 +02002716
Marcel Holtmann052b30b2009-04-26 20:01:22 +02002717 hci_dev_unlock(hdev);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002718}
2719
Gustavo Padovan6039aa732012-05-23 04:04:18 -03002720static void hci_clock_offset_evt(struct hci_dev *hdev, struct sk_buff *skb)
Marcel Holtmann04837f62006-07-03 10:02:33 +02002721{
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002722 struct hci_ev_clock_offset *ev = (void *) skb->data;
Marcel Holtmann04837f62006-07-03 10:02:33 +02002723 struct hci_conn *conn;
2724
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +03002725 BT_DBG("%s status 0x%2.2x", hdev->name, ev->status);
Marcel Holtmann04837f62006-07-03 10:02:33 +02002726
2727 hci_dev_lock(hdev);
2728
2729 conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
Linus Torvalds1da177e2005-04-16 15:20:36 -07002730 if (conn && !ev->status) {
2731 struct inquiry_entry *ie;
2732
Andrei Emeltchenkocc11b9c2010-11-22 13:21:37 +02002733 ie = hci_inquiry_cache_lookup(hdev, &conn->dst);
2734 if (ie) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002735 ie->data.clock_offset = ev->clock_offset;
2736 ie->timestamp = jiffies;
2737 }
2738 }
2739
2740 hci_dev_unlock(hdev);
2741}
2742
Gustavo Padovan6039aa732012-05-23 04:04:18 -03002743static void hci_pkt_type_change_evt(struct hci_dev *hdev, struct sk_buff *skb)
Marcel Holtmanna8746412008-07-14 20:13:46 +02002744{
2745 struct hci_ev_pkt_type_change *ev = (void *) skb->data;
2746 struct hci_conn *conn;
2747
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +03002748 BT_DBG("%s status 0x%2.2x", hdev->name, ev->status);
Marcel Holtmanna8746412008-07-14 20:13:46 +02002749
2750 hci_dev_lock(hdev);
2751
2752 conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
2753 if (conn && !ev->status)
2754 conn->pkt_type = __le16_to_cpu(ev->pkt_type);
2755
2756 hci_dev_unlock(hdev);
2757}
2758
Gustavo Padovan6039aa732012-05-23 04:04:18 -03002759static void hci_pscan_rep_mode_evt(struct hci_dev *hdev, struct sk_buff *skb)
Marcel Holtmann85a1e932005-08-09 20:28:02 -07002760{
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002761 struct hci_ev_pscan_rep_mode *ev = (void *) skb->data;
Marcel Holtmann85a1e932005-08-09 20:28:02 -07002762 struct inquiry_entry *ie;
2763
2764 BT_DBG("%s", hdev->name);
2765
2766 hci_dev_lock(hdev);
2767
Andrei Emeltchenkocc11b9c2010-11-22 13:21:37 +02002768 ie = hci_inquiry_cache_lookup(hdev, &ev->bdaddr);
2769 if (ie) {
Marcel Holtmann85a1e932005-08-09 20:28:02 -07002770 ie->data.pscan_rep_mode = ev->pscan_rep_mode;
2771 ie->timestamp = jiffies;
2772 }
2773
2774 hci_dev_unlock(hdev);
2775}
2776
Gustavo Padovan6039aa732012-05-23 04:04:18 -03002777static void hci_inquiry_result_with_rssi_evt(struct hci_dev *hdev,
2778 struct sk_buff *skb)
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002779{
2780 struct inquiry_data data;
2781 int num_rsp = *((__u8 *) skb->data);
Johan Hedberg388fc8f2012-02-23 00:38:59 +02002782 bool name_known, ssp;
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002783
2784 BT_DBG("%s num_rsp %d", hdev->name, num_rsp);
2785
2786 if (!num_rsp)
2787 return;
2788
Andre Guedes1519cc12012-03-21 00:03:38 -03002789 if (test_bit(HCI_PERIODIC_INQ, &hdev->dev_flags))
2790 return;
2791
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002792 hci_dev_lock(hdev);
2793
2794 if ((skb->len - 1) / num_rsp != sizeof(struct inquiry_info_with_rssi)) {
Szymon Janc138d22e2011-02-17 16:44:23 +01002795 struct inquiry_info_with_rssi_and_pscan_mode *info;
2796 info = (void *) (skb->data + 1);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002797
Johan Hedberge17acd42011-03-30 23:57:16 +03002798 for (; num_rsp; num_rsp--, info++) {
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002799 bacpy(&data.bdaddr, &info->bdaddr);
2800 data.pscan_rep_mode = info->pscan_rep_mode;
2801 data.pscan_period_mode = info->pscan_period_mode;
2802 data.pscan_mode = info->pscan_mode;
2803 memcpy(data.dev_class, info->dev_class, 3);
2804 data.clock_offset = info->clock_offset;
2805 data.rssi = info->rssi;
Marcel Holtmann41a96212008-07-14 20:13:48 +02002806 data.ssp_mode = 0x00;
Johan Hedberg31754052012-01-04 13:39:52 +02002807
2808 name_known = hci_inquiry_cache_update(hdev, &data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002809 false, &ssp);
Johan Hedberg48264f02011-11-09 13:58:58 +02002810 mgmt_device_found(hdev, &info->bdaddr, ACL_LINK, 0x00,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002811 info->dev_class, info->rssi,
2812 !name_known, ssp, NULL, 0);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002813 }
2814 } else {
2815 struct inquiry_info_with_rssi *info = (void *) (skb->data + 1);
2816
Johan Hedberge17acd42011-03-30 23:57:16 +03002817 for (; num_rsp; num_rsp--, info++) {
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002818 bacpy(&data.bdaddr, &info->bdaddr);
2819 data.pscan_rep_mode = info->pscan_rep_mode;
2820 data.pscan_period_mode = info->pscan_period_mode;
2821 data.pscan_mode = 0x00;
2822 memcpy(data.dev_class, info->dev_class, 3);
2823 data.clock_offset = info->clock_offset;
2824 data.rssi = info->rssi;
Marcel Holtmann41a96212008-07-14 20:13:48 +02002825 data.ssp_mode = 0x00;
Johan Hedberg31754052012-01-04 13:39:52 +02002826 name_known = hci_inquiry_cache_update(hdev, &data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002827 false, &ssp);
Johan Hedberg48264f02011-11-09 13:58:58 +02002828 mgmt_device_found(hdev, &info->bdaddr, ACL_LINK, 0x00,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002829 info->dev_class, info->rssi,
2830 !name_known, ssp, NULL, 0);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002831 }
2832 }
2833
2834 hci_dev_unlock(hdev);
2835}
2836
Gustavo Padovan6039aa732012-05-23 04:04:18 -03002837static void hci_remote_ext_features_evt(struct hci_dev *hdev,
2838 struct sk_buff *skb)
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002839{
Marcel Holtmann41a96212008-07-14 20:13:48 +02002840 struct hci_ev_remote_ext_features *ev = (void *) skb->data;
2841 struct hci_conn *conn;
2842
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002843 BT_DBG("%s", hdev->name);
Marcel Holtmann41a96212008-07-14 20:13:48 +02002844
Marcel Holtmann41a96212008-07-14 20:13:48 +02002845 hci_dev_lock(hdev);
2846
2847 conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
Johan Hedbergccd556f2010-11-10 17:11:51 +02002848 if (!conn)
2849 goto unlock;
Marcel Holtmann41a96212008-07-14 20:13:48 +02002850
Johan Hedbergccd556f2010-11-10 17:11:51 +02002851 if (!ev->status && ev->page == 0x01) {
2852 struct inquiry_entry *ie;
Marcel Holtmann41a96212008-07-14 20:13:48 +02002853
Andrei Emeltchenkocc11b9c2010-11-22 13:21:37 +02002854 ie = hci_inquiry_cache_lookup(hdev, &conn->dst);
2855 if (ie)
Johan Hedberg02b7cc62012-02-28 02:28:43 +02002856 ie->data.ssp_mode = (ev->features[0] & LMP_HOST_SSP);
Marcel Holtmann769be972008-07-14 20:13:49 +02002857
Johan Hedberg02b7cc62012-02-28 02:28:43 +02002858 if (ev->features[0] & LMP_HOST_SSP)
Johan Hedberg58a681e2012-01-16 06:47:28 +02002859 set_bit(HCI_CONN_SSP_ENABLED, &conn->flags);
Marcel Holtmann41a96212008-07-14 20:13:48 +02002860 }
2861
Johan Hedbergccd556f2010-11-10 17:11:51 +02002862 if (conn->state != BT_CONFIG)
2863 goto unlock;
2864
Johan Hedberg671267b2012-05-12 16:11:50 -03002865 if (!ev->status && !test_bit(HCI_CONN_MGMT_CONNECTED, &conn->flags)) {
Johan Hedberg127178d2010-11-18 22:22:29 +02002866 struct hci_cp_remote_name_req cp;
2867 memset(&cp, 0, sizeof(cp));
2868 bacpy(&cp.bdaddr, &conn->dst);
2869 cp.pscan_rep_mode = 0x02;
2870 hci_send_cmd(hdev, HCI_OP_REMOTE_NAME_REQ, sizeof(cp), &cp);
Johan Hedbergb644ba32012-01-17 21:48:47 +02002871 } else if (!test_and_set_bit(HCI_CONN_MGMT_CONNECTED, &conn->flags))
2872 mgmt_device_connected(hdev, &conn->dst, conn->type,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002873 conn->dst_type, 0, NULL, 0,
2874 conn->dev_class);
Johan Hedberg392599b2010-11-18 22:22:28 +02002875
Johan Hedberg127178d2010-11-18 22:22:29 +02002876 if (!hci_outgoing_auth_needed(hdev, conn)) {
Johan Hedbergccd556f2010-11-10 17:11:51 +02002877 conn->state = BT_CONNECTED;
2878 hci_proto_connect_cfm(conn, ev->status);
2879 hci_conn_put(conn);
2880 }
2881
2882unlock:
Marcel Holtmann41a96212008-07-14 20:13:48 +02002883 hci_dev_unlock(hdev);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002884}
2885
Gustavo Padovan6039aa732012-05-23 04:04:18 -03002886static void hci_sync_conn_complete_evt(struct hci_dev *hdev,
2887 struct sk_buff *skb)
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002888{
Marcel Holtmannb6a0dc82007-10-20 14:55:10 +02002889 struct hci_ev_sync_conn_complete *ev = (void *) skb->data;
2890 struct hci_conn *conn;
2891
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +03002892 BT_DBG("%s status 0x%2.2x", hdev->name, ev->status);
Marcel Holtmannb6a0dc82007-10-20 14:55:10 +02002893
2894 hci_dev_lock(hdev);
2895
2896 conn = hci_conn_hash_lookup_ba(hdev, ev->link_type, &ev->bdaddr);
Marcel Holtmann9dc0a3a2008-07-14 20:13:46 +02002897 if (!conn) {
2898 if (ev->link_type == ESCO_LINK)
2899 goto unlock;
2900
2901 conn = hci_conn_hash_lookup_ba(hdev, ESCO_LINK, &ev->bdaddr);
2902 if (!conn)
2903 goto unlock;
2904
2905 conn->type = SCO_LINK;
2906 }
Marcel Holtmannb6a0dc82007-10-20 14:55:10 +02002907
Marcel Holtmann732547f2009-04-19 19:14:14 +02002908 switch (ev->status) {
2909 case 0x00:
Marcel Holtmannb6a0dc82007-10-20 14:55:10 +02002910 conn->handle = __le16_to_cpu(ev->handle);
2911 conn->state = BT_CONNECTED;
Marcel Holtmann7d0db0a2008-07-14 20:13:51 +02002912
Marcel Holtmann9eba32b2009-08-22 14:19:26 -07002913 hci_conn_hold_device(conn);
Marcel Holtmann7d0db0a2008-07-14 20:13:51 +02002914 hci_conn_add_sysfs(conn);
Marcel Holtmann732547f2009-04-19 19:14:14 +02002915 break;
2916
Stephen Coe705e5712010-02-16 11:29:44 -05002917 case 0x11: /* Unsupported Feature or Parameter Value */
Marcel Holtmann732547f2009-04-19 19:14:14 +02002918 case 0x1c: /* SCO interval rejected */
Nick Pelly1038a002010-02-03 11:42:26 -08002919 case 0x1a: /* Unsupported Remote Feature */
Marcel Holtmann732547f2009-04-19 19:14:14 +02002920 case 0x1f: /* Unspecified error */
2921 if (conn->out && conn->attempt < 2) {
2922 conn->pkt_type = (hdev->esco_type & SCO_ESCO_MASK) |
2923 (hdev->esco_type & EDR_ESCO_MASK);
2924 hci_setup_sync(conn, conn->link->handle);
2925 goto unlock;
2926 }
2927 /* fall through */
2928
2929 default:
Marcel Holtmannb6a0dc82007-10-20 14:55:10 +02002930 conn->state = BT_CLOSED;
Marcel Holtmann732547f2009-04-19 19:14:14 +02002931 break;
2932 }
Marcel Holtmannb6a0dc82007-10-20 14:55:10 +02002933
2934 hci_proto_connect_cfm(conn, ev->status);
2935 if (ev->status)
2936 hci_conn_del(conn);
2937
2938unlock:
2939 hci_dev_unlock(hdev);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002940}
2941
Gustavo Padovan6039aa732012-05-23 04:04:18 -03002942static void hci_extended_inquiry_result_evt(struct hci_dev *hdev,
2943 struct sk_buff *skb)
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002944{
2945 struct inquiry_data data;
2946 struct extended_inquiry_info *info = (void *) (skb->data + 1);
2947 int num_rsp = *((__u8 *) skb->data);
Vishal Agarwal9d939d92012-04-26 19:19:56 +05302948 size_t eir_len;
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002949
2950 BT_DBG("%s num_rsp %d", hdev->name, num_rsp);
2951
2952 if (!num_rsp)
2953 return;
2954
Andre Guedes1519cc12012-03-21 00:03:38 -03002955 if (test_bit(HCI_PERIODIC_INQ, &hdev->dev_flags))
2956 return;
2957
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002958 hci_dev_lock(hdev);
2959
Johan Hedberge17acd42011-03-30 23:57:16 +03002960 for (; num_rsp; num_rsp--, info++) {
Johan Hedberg388fc8f2012-02-23 00:38:59 +02002961 bool name_known, ssp;
Johan Hedberg561aafb2012-01-04 13:31:59 +02002962
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002963 bacpy(&data.bdaddr, &info->bdaddr);
Szymon Janc138d22e2011-02-17 16:44:23 +01002964 data.pscan_rep_mode = info->pscan_rep_mode;
2965 data.pscan_period_mode = info->pscan_period_mode;
2966 data.pscan_mode = 0x00;
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002967 memcpy(data.dev_class, info->dev_class, 3);
Szymon Janc138d22e2011-02-17 16:44:23 +01002968 data.clock_offset = info->clock_offset;
2969 data.rssi = info->rssi;
Marcel Holtmann41a96212008-07-14 20:13:48 +02002970 data.ssp_mode = 0x01;
Johan Hedberg561aafb2012-01-04 13:31:59 +02002971
Johan Hedberga8b2d5c2012-01-08 23:11:15 +02002972 if (test_bit(HCI_MGMT, &hdev->dev_flags))
Johan Hedberg4ddb1932012-01-15 20:04:43 +02002973 name_known = eir_has_data_type(info->data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002974 sizeof(info->data),
2975 EIR_NAME_COMPLETE);
Johan Hedberg561aafb2012-01-04 13:31:59 +02002976 else
2977 name_known = true;
2978
Johan Hedberg388fc8f2012-02-23 00:38:59 +02002979 name_known = hci_inquiry_cache_update(hdev, &data, name_known,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002980 &ssp);
Vishal Agarwal9d939d92012-04-26 19:19:56 +05302981 eir_len = eir_get_length(info->data, sizeof(info->data));
Johan Hedberg48264f02011-11-09 13:58:58 +02002982 mgmt_device_found(hdev, &info->bdaddr, ACL_LINK, 0x00,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002983 info->dev_class, info->rssi, !name_known,
Vishal Agarwal9d939d92012-04-26 19:19:56 +05302984 ssp, info->data, eir_len);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002985 }
2986
2987 hci_dev_unlock(hdev);
2988}
2989
Johan Hedberg1c2e0042012-06-08 23:31:13 +08002990static void hci_key_refresh_complete_evt(struct hci_dev *hdev,
2991 struct sk_buff *skb)
2992{
2993 struct hci_ev_key_refresh_complete *ev = (void *) skb->data;
2994 struct hci_conn *conn;
2995
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +03002996 BT_DBG("%s status 0x%2.2x handle 0x%4.4x", hdev->name, ev->status,
Johan Hedberg1c2e0042012-06-08 23:31:13 +08002997 __le16_to_cpu(ev->handle));
2998
2999 hci_dev_lock(hdev);
3000
3001 conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
3002 if (!conn)
3003 goto unlock;
3004
3005 if (!ev->status)
3006 conn->sec_level = conn->pending_sec_level;
3007
3008 clear_bit(HCI_CONN_ENCRYPT_PEND, &conn->flags);
3009
3010 if (ev->status && conn->state == BT_CONNECTED) {
Andre Guedesbed71742013-01-30 11:50:56 -03003011 hci_disconnect(conn, HCI_ERROR_AUTH_FAILURE);
Johan Hedberg1c2e0042012-06-08 23:31:13 +08003012 hci_conn_put(conn);
3013 goto unlock;
3014 }
3015
3016 if (conn->state == BT_CONFIG) {
3017 if (!ev->status)
3018 conn->state = BT_CONNECTED;
3019
3020 hci_proto_connect_cfm(conn, ev->status);
3021 hci_conn_put(conn);
3022 } else {
3023 hci_auth_cfm(conn, ev->status);
3024
3025 hci_conn_hold(conn);
3026 conn->disc_timeout = HCI_DISCONN_TIMEOUT;
3027 hci_conn_put(conn);
3028 }
3029
3030unlock:
3031 hci_dev_unlock(hdev);
3032}
3033
Gustavo Padovan6039aa732012-05-23 04:04:18 -03003034static u8 hci_get_auth_req(struct hci_conn *conn)
Johan Hedberg17fa4b92011-01-25 13:28:33 +02003035{
3036 /* If remote requests dedicated bonding follow that lead */
3037 if (conn->remote_auth == 0x02 || conn->remote_auth == 0x03) {
3038 /* If both remote and local IO capabilities allow MITM
3039 * protection then require it, otherwise don't */
3040 if (conn->remote_cap == 0x03 || conn->io_capability == 0x03)
3041 return 0x02;
3042 else
3043 return 0x03;
3044 }
3045
3046 /* If remote requests no-bonding follow that lead */
3047 if (conn->remote_auth == 0x00 || conn->remote_auth == 0x01)
Waldemar Rymarkiewicz58797bf2011-04-28 12:07:58 +02003048 return conn->remote_auth | (conn->auth_type & 0x01);
Johan Hedberg17fa4b92011-01-25 13:28:33 +02003049
3050 return conn->auth_type;
3051}
3052
Gustavo Padovan6039aa732012-05-23 04:04:18 -03003053static void hci_io_capa_request_evt(struct hci_dev *hdev, struct sk_buff *skb)
Marcel Holtmann04936842008-07-14 20:13:48 +02003054{
3055 struct hci_ev_io_capa_request *ev = (void *) skb->data;
3056 struct hci_conn *conn;
3057
3058 BT_DBG("%s", hdev->name);
3059
3060 hci_dev_lock(hdev);
3061
3062 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
Johan Hedberg03b555e2011-01-04 15:40:05 +02003063 if (!conn)
3064 goto unlock;
Marcel Holtmann04936842008-07-14 20:13:48 +02003065
Johan Hedberg03b555e2011-01-04 15:40:05 +02003066 hci_conn_hold(conn);
3067
Johan Hedberga8b2d5c2012-01-08 23:11:15 +02003068 if (!test_bit(HCI_MGMT, &hdev->dev_flags))
Johan Hedberg03b555e2011-01-04 15:40:05 +02003069 goto unlock;
3070
Johan Hedberga8b2d5c2012-01-08 23:11:15 +02003071 if (test_bit(HCI_PAIRABLE, &hdev->dev_flags) ||
Gustavo Padovan807deac2012-05-17 00:36:24 -03003072 (conn->remote_auth & ~0x01) == HCI_AT_NO_BONDING) {
Johan Hedberg17fa4b92011-01-25 13:28:33 +02003073 struct hci_cp_io_capability_reply cp;
3074
3075 bacpy(&cp.bdaddr, &ev->bdaddr);
Hemant Gupta7a7f1e72012-01-16 13:34:29 +05303076 /* Change the IO capability from KeyboardDisplay
3077 * to DisplayYesNo as it is not supported by BT spec. */
3078 cp.capability = (conn->io_capability == 0x04) ?
3079 0x01 : conn->io_capability;
Johan Hedberg7cbc9bd2011-04-28 11:29:04 -07003080 conn->auth_type = hci_get_auth_req(conn);
3081 cp.authentication = conn->auth_type;
Johan Hedberg17fa4b92011-01-25 13:28:33 +02003082
Gustavo Padovan8fc9ced2012-05-23 04:04:21 -03003083 if (hci_find_remote_oob_data(hdev, &conn->dst) &&
3084 (conn->out || test_bit(HCI_CONN_REMOTE_OOB, &conn->flags)))
Szymon Jancce85ee12011-03-22 13:12:23 +01003085 cp.oob_data = 0x01;
3086 else
3087 cp.oob_data = 0x00;
3088
Johan Hedberg17fa4b92011-01-25 13:28:33 +02003089 hci_send_cmd(hdev, HCI_OP_IO_CAPABILITY_REPLY,
Gustavo Padovan807deac2012-05-17 00:36:24 -03003090 sizeof(cp), &cp);
Johan Hedberg03b555e2011-01-04 15:40:05 +02003091 } else {
3092 struct hci_cp_io_capability_neg_reply cp;
3093
3094 bacpy(&cp.bdaddr, &ev->bdaddr);
Andrei Emeltchenko9f5a0d72011-11-07 14:20:25 +02003095 cp.reason = HCI_ERROR_PAIRING_NOT_ALLOWED;
Johan Hedberg03b555e2011-01-04 15:40:05 +02003096
3097 hci_send_cmd(hdev, HCI_OP_IO_CAPABILITY_NEG_REPLY,
Gustavo Padovan807deac2012-05-17 00:36:24 -03003098 sizeof(cp), &cp);
Johan Hedberg03b555e2011-01-04 15:40:05 +02003099 }
3100
3101unlock:
3102 hci_dev_unlock(hdev);
3103}
3104
Gustavo Padovan6039aa732012-05-23 04:04:18 -03003105static void hci_io_capa_reply_evt(struct hci_dev *hdev, struct sk_buff *skb)
Johan Hedberg03b555e2011-01-04 15:40:05 +02003106{
3107 struct hci_ev_io_capa_reply *ev = (void *) skb->data;
3108 struct hci_conn *conn;
3109
3110 BT_DBG("%s", hdev->name);
3111
3112 hci_dev_lock(hdev);
3113
3114 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
3115 if (!conn)
3116 goto unlock;
3117
Johan Hedberg03b555e2011-01-04 15:40:05 +02003118 conn->remote_cap = ev->capability;
Johan Hedberg03b555e2011-01-04 15:40:05 +02003119 conn->remote_auth = ev->authentication;
Johan Hedberg58a681e2012-01-16 06:47:28 +02003120 if (ev->oob_data)
3121 set_bit(HCI_CONN_REMOTE_OOB, &conn->flags);
Johan Hedberg03b555e2011-01-04 15:40:05 +02003122
3123unlock:
Marcel Holtmann04936842008-07-14 20:13:48 +02003124 hci_dev_unlock(hdev);
3125}
3126
Gustavo Padovan6039aa732012-05-23 04:04:18 -03003127static void hci_user_confirm_request_evt(struct hci_dev *hdev,
3128 struct sk_buff *skb)
Johan Hedberga5c29682011-02-19 12:05:57 -03003129{
3130 struct hci_ev_user_confirm_req *ev = (void *) skb->data;
Johan Hedberg55bc1a32011-04-28 11:28:56 -07003131 int loc_mitm, rem_mitm, confirm_hint = 0;
Johan Hedberg7a828902011-04-28 11:28:53 -07003132 struct hci_conn *conn;
Johan Hedberga5c29682011-02-19 12:05:57 -03003133
3134 BT_DBG("%s", hdev->name);
3135
3136 hci_dev_lock(hdev);
3137
Johan Hedberga8b2d5c2012-01-08 23:11:15 +02003138 if (!test_bit(HCI_MGMT, &hdev->dev_flags))
Johan Hedberg7a828902011-04-28 11:28:53 -07003139 goto unlock;
Johan Hedberga5c29682011-02-19 12:05:57 -03003140
Johan Hedberg7a828902011-04-28 11:28:53 -07003141 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
3142 if (!conn)
3143 goto unlock;
3144
3145 loc_mitm = (conn->auth_type & 0x01);
3146 rem_mitm = (conn->remote_auth & 0x01);
3147
3148 /* If we require MITM but the remote device can't provide that
3149 * (it has NoInputNoOutput) then reject the confirmation
3150 * request. The only exception is when we're dedicated bonding
3151 * initiators (connect_cfm_cb set) since then we always have the MITM
3152 * bit set. */
3153 if (!conn->connect_cfm_cb && loc_mitm && conn->remote_cap == 0x03) {
3154 BT_DBG("Rejecting request: remote device can't provide MITM");
3155 hci_send_cmd(hdev, HCI_OP_USER_CONFIRM_NEG_REPLY,
Gustavo Padovan807deac2012-05-17 00:36:24 -03003156 sizeof(ev->bdaddr), &ev->bdaddr);
Johan Hedberg7a828902011-04-28 11:28:53 -07003157 goto unlock;
3158 }
3159
3160 /* If no side requires MITM protection; auto-accept */
3161 if ((!loc_mitm || conn->remote_cap == 0x03) &&
Gustavo Padovan807deac2012-05-17 00:36:24 -03003162 (!rem_mitm || conn->io_capability == 0x03)) {
Johan Hedberg55bc1a32011-04-28 11:28:56 -07003163
3164 /* If we're not the initiators request authorization to
3165 * proceed from user space (mgmt_user_confirm with
3166 * confirm_hint set to 1). */
Johan Hedberg51a8efd2012-01-16 06:10:31 +02003167 if (!test_bit(HCI_CONN_AUTH_PEND, &conn->flags)) {
Johan Hedberg55bc1a32011-04-28 11:28:56 -07003168 BT_DBG("Confirming auto-accept as acceptor");
3169 confirm_hint = 1;
3170 goto confirm;
3171 }
3172
Johan Hedberg9f616562011-04-28 11:28:54 -07003173 BT_DBG("Auto-accept of user confirmation with %ums delay",
Gustavo Padovan807deac2012-05-17 00:36:24 -03003174 hdev->auto_accept_delay);
Johan Hedberg9f616562011-04-28 11:28:54 -07003175
3176 if (hdev->auto_accept_delay > 0) {
3177 int delay = msecs_to_jiffies(hdev->auto_accept_delay);
3178 mod_timer(&conn->auto_accept_timer, jiffies + delay);
3179 goto unlock;
3180 }
3181
Johan Hedberg7a828902011-04-28 11:28:53 -07003182 hci_send_cmd(hdev, HCI_OP_USER_CONFIRM_REPLY,
Gustavo Padovan807deac2012-05-17 00:36:24 -03003183 sizeof(ev->bdaddr), &ev->bdaddr);
Johan Hedberg7a828902011-04-28 11:28:53 -07003184 goto unlock;
3185 }
3186
Johan Hedberg55bc1a32011-04-28 11:28:56 -07003187confirm:
Johan Hedberg272d90d2012-02-09 15:26:12 +02003188 mgmt_user_confirm_request(hdev, &ev->bdaddr, ACL_LINK, 0, ev->passkey,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003189 confirm_hint);
Johan Hedberg7a828902011-04-28 11:28:53 -07003190
3191unlock:
Johan Hedberga5c29682011-02-19 12:05:57 -03003192 hci_dev_unlock(hdev);
3193}
3194
Gustavo Padovan6039aa732012-05-23 04:04:18 -03003195static void hci_user_passkey_request_evt(struct hci_dev *hdev,
3196 struct sk_buff *skb)
Brian Gix1143d452011-11-23 08:28:34 -08003197{
3198 struct hci_ev_user_passkey_req *ev = (void *) skb->data;
3199
3200 BT_DBG("%s", hdev->name);
3201
Johan Hedberga8b2d5c2012-01-08 23:11:15 +02003202 if (test_bit(HCI_MGMT, &hdev->dev_flags))
Johan Hedberg272d90d2012-02-09 15:26:12 +02003203 mgmt_user_passkey_request(hdev, &ev->bdaddr, ACL_LINK, 0);
Brian Gix1143d452011-11-23 08:28:34 -08003204}
3205
Johan Hedberg92a25252012-09-06 18:39:26 +03003206static void hci_user_passkey_notify_evt(struct hci_dev *hdev,
3207 struct sk_buff *skb)
3208{
3209 struct hci_ev_user_passkey_notify *ev = (void *) skb->data;
3210 struct hci_conn *conn;
3211
3212 BT_DBG("%s", hdev->name);
3213
3214 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
3215 if (!conn)
3216 return;
3217
3218 conn->passkey_notify = __le32_to_cpu(ev->passkey);
3219 conn->passkey_entered = 0;
3220
3221 if (test_bit(HCI_MGMT, &hdev->dev_flags))
3222 mgmt_user_passkey_notify(hdev, &conn->dst, conn->type,
3223 conn->dst_type, conn->passkey_notify,
3224 conn->passkey_entered);
3225}
3226
3227static void hci_keypress_notify_evt(struct hci_dev *hdev, struct sk_buff *skb)
3228{
3229 struct hci_ev_keypress_notify *ev = (void *) skb->data;
3230 struct hci_conn *conn;
3231
3232 BT_DBG("%s", hdev->name);
3233
3234 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
3235 if (!conn)
3236 return;
3237
3238 switch (ev->type) {
3239 case HCI_KEYPRESS_STARTED:
3240 conn->passkey_entered = 0;
3241 return;
3242
3243 case HCI_KEYPRESS_ENTERED:
3244 conn->passkey_entered++;
3245 break;
3246
3247 case HCI_KEYPRESS_ERASED:
3248 conn->passkey_entered--;
3249 break;
3250
3251 case HCI_KEYPRESS_CLEARED:
3252 conn->passkey_entered = 0;
3253 break;
3254
3255 case HCI_KEYPRESS_COMPLETED:
3256 return;
3257 }
3258
3259 if (test_bit(HCI_MGMT, &hdev->dev_flags))
3260 mgmt_user_passkey_notify(hdev, &conn->dst, conn->type,
3261 conn->dst_type, conn->passkey_notify,
3262 conn->passkey_entered);
3263}
3264
Gustavo Padovan6039aa732012-05-23 04:04:18 -03003265static void hci_simple_pair_complete_evt(struct hci_dev *hdev,
3266 struct sk_buff *skb)
Marcel Holtmann04936842008-07-14 20:13:48 +02003267{
3268 struct hci_ev_simple_pair_complete *ev = (void *) skb->data;
3269 struct hci_conn *conn;
3270
3271 BT_DBG("%s", hdev->name);
3272
3273 hci_dev_lock(hdev);
3274
3275 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
Johan Hedberg2a611692011-02-19 12:06:00 -03003276 if (!conn)
3277 goto unlock;
Marcel Holtmann04936842008-07-14 20:13:48 +02003278
Johan Hedberg2a611692011-02-19 12:06:00 -03003279 /* To avoid duplicate auth_failed events to user space we check
3280 * the HCI_CONN_AUTH_PEND flag which will be set if we
3281 * initiated the authentication. A traditional auth_complete
3282 * event gets always produced as initiator and is also mapped to
3283 * the mgmt_auth_failed event */
Mikel Astizfa1bd912012-08-09 09:52:29 +02003284 if (!test_bit(HCI_CONN_AUTH_PEND, &conn->flags) && ev->status)
Johan Hedbergbab73cb2012-02-09 16:07:29 +02003285 mgmt_auth_failed(hdev, &conn->dst, conn->type, conn->dst_type,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003286 ev->status);
Johan Hedberg2a611692011-02-19 12:06:00 -03003287
3288 hci_conn_put(conn);
3289
3290unlock:
Marcel Holtmann04936842008-07-14 20:13:48 +02003291 hci_dev_unlock(hdev);
3292}
3293
Gustavo Padovan6039aa732012-05-23 04:04:18 -03003294static void hci_remote_host_features_evt(struct hci_dev *hdev,
3295 struct sk_buff *skb)
Marcel Holtmann41a96212008-07-14 20:13:48 +02003296{
3297 struct hci_ev_remote_host_features *ev = (void *) skb->data;
3298 struct inquiry_entry *ie;
3299
3300 BT_DBG("%s", hdev->name);
3301
3302 hci_dev_lock(hdev);
3303
Andrei Emeltchenkocc11b9c2010-11-22 13:21:37 +02003304 ie = hci_inquiry_cache_lookup(hdev, &ev->bdaddr);
3305 if (ie)
Johan Hedberg02b7cc62012-02-28 02:28:43 +02003306 ie->data.ssp_mode = (ev->features[0] & LMP_HOST_SSP);
Marcel Holtmann41a96212008-07-14 20:13:48 +02003307
3308 hci_dev_unlock(hdev);
3309}
3310
Gustavo Padovan6039aa732012-05-23 04:04:18 -03003311static void hci_remote_oob_data_request_evt(struct hci_dev *hdev,
3312 struct sk_buff *skb)
Szymon Janc2763eda2011-03-22 13:12:22 +01003313{
3314 struct hci_ev_remote_oob_data_request *ev = (void *) skb->data;
3315 struct oob_data *data;
3316
3317 BT_DBG("%s", hdev->name);
3318
3319 hci_dev_lock(hdev);
3320
Johan Hedberga8b2d5c2012-01-08 23:11:15 +02003321 if (!test_bit(HCI_MGMT, &hdev->dev_flags))
Szymon Jance1ba1f12011-04-06 13:01:59 +02003322 goto unlock;
3323
Szymon Janc2763eda2011-03-22 13:12:22 +01003324 data = hci_find_remote_oob_data(hdev, &ev->bdaddr);
3325 if (data) {
3326 struct hci_cp_remote_oob_data_reply cp;
3327
3328 bacpy(&cp.bdaddr, &ev->bdaddr);
3329 memcpy(cp.hash, data->hash, sizeof(cp.hash));
3330 memcpy(cp.randomizer, data->randomizer, sizeof(cp.randomizer));
3331
3332 hci_send_cmd(hdev, HCI_OP_REMOTE_OOB_DATA_REPLY, sizeof(cp),
Gustavo Padovan807deac2012-05-17 00:36:24 -03003333 &cp);
Szymon Janc2763eda2011-03-22 13:12:22 +01003334 } else {
3335 struct hci_cp_remote_oob_data_neg_reply cp;
3336
3337 bacpy(&cp.bdaddr, &ev->bdaddr);
3338 hci_send_cmd(hdev, HCI_OP_REMOTE_OOB_DATA_NEG_REPLY, sizeof(cp),
Gustavo Padovan807deac2012-05-17 00:36:24 -03003339 &cp);
Szymon Janc2763eda2011-03-22 13:12:22 +01003340 }
3341
Szymon Jance1ba1f12011-04-06 13:01:59 +02003342unlock:
Szymon Janc2763eda2011-03-22 13:12:22 +01003343 hci_dev_unlock(hdev);
3344}
3345
Andrei Emeltchenkod5e91192012-10-25 15:20:44 +03003346static void hci_phy_link_complete_evt(struct hci_dev *hdev,
3347 struct sk_buff *skb)
3348{
3349 struct hci_ev_phy_link_complete *ev = (void *) skb->data;
3350 struct hci_conn *hcon, *bredr_hcon;
3351
3352 BT_DBG("%s handle 0x%2.2x status 0x%2.2x", hdev->name, ev->phy_handle,
3353 ev->status);
3354
3355 hci_dev_lock(hdev);
3356
3357 hcon = hci_conn_hash_lookup_handle(hdev, ev->phy_handle);
3358 if (!hcon) {
3359 hci_dev_unlock(hdev);
3360 return;
3361 }
3362
3363 if (ev->status) {
3364 hci_conn_del(hcon);
3365 hci_dev_unlock(hdev);
3366 return;
3367 }
3368
3369 bredr_hcon = hcon->amp_mgr->l2cap_conn->hcon;
3370
3371 hcon->state = BT_CONNECTED;
3372 bacpy(&hcon->dst, &bredr_hcon->dst);
3373
3374 hci_conn_hold(hcon);
3375 hcon->disc_timeout = HCI_DISCONN_TIMEOUT;
3376 hci_conn_put(hcon);
3377
3378 hci_conn_hold_device(hcon);
3379 hci_conn_add_sysfs(hcon);
3380
Andrei Emeltchenkocf70ff22012-10-31 15:46:36 +02003381 amp_physical_cfm(bredr_hcon, hcon);
3382
Andrei Emeltchenkod5e91192012-10-25 15:20:44 +03003383 hci_dev_unlock(hdev);
Andrei Emeltchenkod5e91192012-10-25 15:20:44 +03003384}
3385
Andrei Emeltchenko27695fb2012-10-25 15:20:45 +03003386static void hci_loglink_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
3387{
3388 struct hci_ev_logical_link_complete *ev = (void *) skb->data;
3389 struct hci_conn *hcon;
3390 struct hci_chan *hchan;
3391 struct amp_mgr *mgr;
3392
3393 BT_DBG("%s log_handle 0x%4.4x phy_handle 0x%2.2x status 0x%2.2x",
3394 hdev->name, le16_to_cpu(ev->handle), ev->phy_handle,
3395 ev->status);
3396
3397 hcon = hci_conn_hash_lookup_handle(hdev, ev->phy_handle);
3398 if (!hcon)
3399 return;
3400
3401 /* Create AMP hchan */
3402 hchan = hci_chan_create(hcon);
3403 if (!hchan)
3404 return;
3405
3406 hchan->handle = le16_to_cpu(ev->handle);
3407
3408 BT_DBG("hcon %p mgr %p hchan %p", hcon, hcon->amp_mgr, hchan);
3409
3410 mgr = hcon->amp_mgr;
3411 if (mgr && mgr->bredr_chan) {
3412 struct l2cap_chan *bredr_chan = mgr->bredr_chan;
3413
3414 l2cap_chan_lock(bredr_chan);
3415
3416 bredr_chan->conn->mtu = hdev->block_mtu;
3417 l2cap_logical_cfm(bredr_chan, hchan, 0);
3418 hci_conn_hold(hcon);
3419
3420 l2cap_chan_unlock(bredr_chan);
3421 }
3422}
3423
Andrei Emeltchenko606e2a12012-10-31 15:46:31 +02003424static void hci_disconn_loglink_complete_evt(struct hci_dev *hdev,
3425 struct sk_buff *skb)
3426{
3427 struct hci_ev_disconn_logical_link_complete *ev = (void *) skb->data;
3428 struct hci_chan *hchan;
3429
3430 BT_DBG("%s log handle 0x%4.4x status 0x%2.2x", hdev->name,
3431 le16_to_cpu(ev->handle), ev->status);
3432
3433 if (ev->status)
3434 return;
3435
3436 hci_dev_lock(hdev);
3437
3438 hchan = hci_chan_lookup_handle(hdev, le16_to_cpu(ev->handle));
3439 if (!hchan)
3440 goto unlock;
3441
3442 amp_destroy_logical_link(hchan, ev->reason);
3443
3444unlock:
3445 hci_dev_unlock(hdev);
3446}
3447
Andrei Emeltchenko9eef6b32012-10-31 15:46:32 +02003448static void hci_disconn_phylink_complete_evt(struct hci_dev *hdev,
3449 struct sk_buff *skb)
3450{
3451 struct hci_ev_disconn_phy_link_complete *ev = (void *) skb->data;
3452 struct hci_conn *hcon;
3453
3454 BT_DBG("%s status 0x%2.2x", hdev->name, ev->status);
3455
3456 if (ev->status)
3457 return;
3458
3459 hci_dev_lock(hdev);
3460
3461 hcon = hci_conn_hash_lookup_handle(hdev, ev->phy_handle);
3462 if (hcon) {
3463 hcon->state = BT_CLOSED;
3464 hci_conn_del(hcon);
3465 }
3466
3467 hci_dev_unlock(hdev);
3468}
3469
Gustavo Padovan6039aa732012-05-23 04:04:18 -03003470static void hci_le_conn_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
Ville Tervofcd89c02011-02-10 22:38:47 -03003471{
3472 struct hci_ev_le_conn_complete *ev = (void *) skb->data;
3473 struct hci_conn *conn;
3474
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +03003475 BT_DBG("%s status 0x%2.2x", hdev->name, ev->status);
Ville Tervofcd89c02011-02-10 22:38:47 -03003476
3477 hci_dev_lock(hdev);
3478
Andre Guedesb47a09b2012-07-27 15:10:15 -03003479 conn = hci_conn_hash_lookup_state(hdev, LE_LINK, BT_CONNECT);
Ville Tervob62f3282011-02-10 22:38:50 -03003480 if (!conn) {
3481 conn = hci_conn_add(hdev, LE_LINK, &ev->bdaddr);
3482 if (!conn) {
3483 BT_ERR("No memory for new connection");
Andre Guedes230fd162012-07-27 15:10:10 -03003484 goto unlock;
Ville Tervob62f3282011-02-10 22:38:50 -03003485 }
Andre Guedes29b79882011-05-31 14:20:54 -03003486
3487 conn->dst_type = ev->bdaddr_type;
Andre Guedesb9b343d2012-07-27 15:10:11 -03003488
3489 if (ev->role == LE_CONN_ROLE_MASTER) {
3490 conn->out = true;
3491 conn->link_mode |= HCI_LM_MASTER;
3492 }
Ville Tervob62f3282011-02-10 22:38:50 -03003493 }
Ville Tervofcd89c02011-02-10 22:38:47 -03003494
Andre Guedescd17dec2012-07-27 15:10:16 -03003495 if (ev->status) {
3496 mgmt_connect_failed(hdev, &conn->dst, conn->type,
3497 conn->dst_type, ev->status);
3498 hci_proto_connect_cfm(conn, ev->status);
3499 conn->state = BT_CLOSED;
3500 hci_conn_del(conn);
3501 goto unlock;
3502 }
3503
Johan Hedbergb644ba32012-01-17 21:48:47 +02003504 if (!test_and_set_bit(HCI_CONN_MGMT_CONNECTED, &conn->flags))
3505 mgmt_device_connected(hdev, &ev->bdaddr, conn->type,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003506 conn->dst_type, 0, NULL, 0, NULL);
Vinicius Costa Gomes83bc71b2011-05-06 18:41:43 -03003507
Vinicius Costa Gomes7b5c0d52011-06-09 18:50:50 -03003508 conn->sec_level = BT_SECURITY_LOW;
Ville Tervofcd89c02011-02-10 22:38:47 -03003509 conn->handle = __le16_to_cpu(ev->handle);
3510 conn->state = BT_CONNECTED;
3511
3512 hci_conn_hold_device(conn);
3513 hci_conn_add_sysfs(conn);
3514
3515 hci_proto_connect_cfm(conn, ev->status);
3516
3517unlock:
3518 hci_dev_unlock(hdev);
3519}
3520
Gustavo Padovan6039aa732012-05-23 04:04:18 -03003521static void hci_le_adv_report_evt(struct hci_dev *hdev, struct sk_buff *skb)
Andre Guedes9aa04c92011-05-26 16:23:51 -03003522{
Andre Guedese95beb42011-09-26 20:48:35 -03003523 u8 num_reports = skb->data[0];
3524 void *ptr = &skb->data[1];
Andre Guedes3c9e9192012-01-10 18:20:50 -03003525 s8 rssi;
Andre Guedes9aa04c92011-05-26 16:23:51 -03003526
Andre Guedese95beb42011-09-26 20:48:35 -03003527 while (num_reports--) {
3528 struct hci_ev_le_advertising_info *ev = ptr;
Andre Guedes9aa04c92011-05-26 16:23:51 -03003529
Andre Guedes3c9e9192012-01-10 18:20:50 -03003530 rssi = ev->data[ev->length];
3531 mgmt_device_found(hdev, &ev->bdaddr, LE_LINK, ev->bdaddr_type,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003532 NULL, rssi, 0, 1, ev->data, ev->length);
Andre Guedes3c9e9192012-01-10 18:20:50 -03003533
Andre Guedese95beb42011-09-26 20:48:35 -03003534 ptr += sizeof(*ev) + ev->length + 1;
Andre Guedes9aa04c92011-05-26 16:23:51 -03003535 }
Andre Guedes9aa04c92011-05-26 16:23:51 -03003536}
3537
Gustavo Padovan6039aa732012-05-23 04:04:18 -03003538static void hci_le_ltk_request_evt(struct hci_dev *hdev, struct sk_buff *skb)
Vinicius Costa Gomesa7a595f2011-06-09 18:50:47 -03003539{
3540 struct hci_ev_le_ltk_req *ev = (void *) skb->data;
3541 struct hci_cp_le_ltk_reply cp;
Vinicius Costa Gomesbea710f2011-07-07 18:59:37 -03003542 struct hci_cp_le_ltk_neg_reply neg;
Vinicius Costa Gomesa7a595f2011-06-09 18:50:47 -03003543 struct hci_conn *conn;
Vinicius Costa Gomesc9839a12012-02-02 21:08:01 -03003544 struct smp_ltk *ltk;
Vinicius Costa Gomesa7a595f2011-06-09 18:50:47 -03003545
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +03003546 BT_DBG("%s handle 0x%4.4x", hdev->name, __le16_to_cpu(ev->handle));
Vinicius Costa Gomesa7a595f2011-06-09 18:50:47 -03003547
3548 hci_dev_lock(hdev);
3549
3550 conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
Vinicius Costa Gomesbea710f2011-07-07 18:59:37 -03003551 if (conn == NULL)
3552 goto not_found;
Vinicius Costa Gomesa7a595f2011-06-09 18:50:47 -03003553
Vinicius Costa Gomesbea710f2011-07-07 18:59:37 -03003554 ltk = hci_find_ltk(hdev, ev->ediv, ev->random);
3555 if (ltk == NULL)
3556 goto not_found;
3557
3558 memcpy(cp.ltk, ltk->val, sizeof(ltk->val));
Vinicius Costa Gomesa7a595f2011-06-09 18:50:47 -03003559 cp.handle = cpu_to_le16(conn->handle);
Vinicius Costa Gomesc9839a12012-02-02 21:08:01 -03003560
3561 if (ltk->authenticated)
3562 conn->sec_level = BT_SECURITY_HIGH;
Vinicius Costa Gomesa7a595f2011-06-09 18:50:47 -03003563
3564 hci_send_cmd(hdev, HCI_OP_LE_LTK_REPLY, sizeof(cp), &cp);
3565
Vinicius Costa Gomesc9839a12012-02-02 21:08:01 -03003566 if (ltk->type & HCI_SMP_STK) {
3567 list_del(&ltk->list);
3568 kfree(ltk);
3569 }
3570
Vinicius Costa Gomesa7a595f2011-06-09 18:50:47 -03003571 hci_dev_unlock(hdev);
Vinicius Costa Gomesbea710f2011-07-07 18:59:37 -03003572
3573 return;
3574
3575not_found:
3576 neg.handle = ev->handle;
3577 hci_send_cmd(hdev, HCI_OP_LE_LTK_NEG_REPLY, sizeof(neg), &neg);
3578 hci_dev_unlock(hdev);
Vinicius Costa Gomesa7a595f2011-06-09 18:50:47 -03003579}
3580
Gustavo Padovan6039aa732012-05-23 04:04:18 -03003581static void hci_le_meta_evt(struct hci_dev *hdev, struct sk_buff *skb)
Ville Tervofcd89c02011-02-10 22:38:47 -03003582{
3583 struct hci_ev_le_meta *le_ev = (void *) skb->data;
3584
3585 skb_pull(skb, sizeof(*le_ev));
3586
3587 switch (le_ev->subevent) {
3588 case HCI_EV_LE_CONN_COMPLETE:
3589 hci_le_conn_complete_evt(hdev, skb);
3590 break;
3591
Andre Guedes9aa04c92011-05-26 16:23:51 -03003592 case HCI_EV_LE_ADVERTISING_REPORT:
3593 hci_le_adv_report_evt(hdev, skb);
3594 break;
3595
Vinicius Costa Gomesa7a595f2011-06-09 18:50:47 -03003596 case HCI_EV_LE_LTK_REQ:
3597 hci_le_ltk_request_evt(hdev, skb);
3598 break;
3599
Ville Tervofcd89c02011-02-10 22:38:47 -03003600 default:
3601 break;
3602 }
3603}
3604
Andrei Emeltchenko9495b2e2012-09-27 17:26:22 +03003605static void hci_chan_selected_evt(struct hci_dev *hdev, struct sk_buff *skb)
3606{
3607 struct hci_ev_channel_selected *ev = (void *) skb->data;
3608 struct hci_conn *hcon;
3609
3610 BT_DBG("%s handle 0x%2.2x", hdev->name, ev->phy_handle);
3611
3612 skb_pull(skb, sizeof(*ev));
3613
3614 hcon = hci_conn_hash_lookup_handle(hdev, ev->phy_handle);
3615 if (!hcon)
3616 return;
3617
3618 amp_read_loc_assoc_final_data(hdev, hcon);
3619}
3620
Linus Torvalds1da177e2005-04-16 15:20:36 -07003621void hci_event_packet(struct hci_dev *hdev, struct sk_buff *skb)
3622{
Marcel Holtmanna9de9242007-10-20 13:33:56 +02003623 struct hci_event_hdr *hdr = (void *) skb->data;
3624 __u8 event = hdr->evt;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003625
3626 skb_pull(skb, HCI_EVENT_HDR_SIZE);
3627
Marcel Holtmanna9de9242007-10-20 13:33:56 +02003628 switch (event) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003629 case HCI_EV_INQUIRY_COMPLETE:
3630 hci_inquiry_complete_evt(hdev, skb);
3631 break;
3632
3633 case HCI_EV_INQUIRY_RESULT:
3634 hci_inquiry_result_evt(hdev, skb);
3635 break;
3636
Marcel Holtmanna9de9242007-10-20 13:33:56 +02003637 case HCI_EV_CONN_COMPLETE:
3638 hci_conn_complete_evt(hdev, skb);
Marcel Holtmann21d9e302005-09-13 01:32:25 +02003639 break;
3640
Linus Torvalds1da177e2005-04-16 15:20:36 -07003641 case HCI_EV_CONN_REQUEST:
3642 hci_conn_request_evt(hdev, skb);
3643 break;
3644
Linus Torvalds1da177e2005-04-16 15:20:36 -07003645 case HCI_EV_DISCONN_COMPLETE:
3646 hci_disconn_complete_evt(hdev, skb);
3647 break;
3648
Linus Torvalds1da177e2005-04-16 15:20:36 -07003649 case HCI_EV_AUTH_COMPLETE:
3650 hci_auth_complete_evt(hdev, skb);
3651 break;
3652
Marcel Holtmanna9de9242007-10-20 13:33:56 +02003653 case HCI_EV_REMOTE_NAME:
3654 hci_remote_name_evt(hdev, skb);
3655 break;
3656
Linus Torvalds1da177e2005-04-16 15:20:36 -07003657 case HCI_EV_ENCRYPT_CHANGE:
3658 hci_encrypt_change_evt(hdev, skb);
3659 break;
3660
Marcel Holtmanna9de9242007-10-20 13:33:56 +02003661 case HCI_EV_CHANGE_LINK_KEY_COMPLETE:
3662 hci_change_link_key_complete_evt(hdev, skb);
3663 break;
3664
3665 case HCI_EV_REMOTE_FEATURES:
3666 hci_remote_features_evt(hdev, skb);
3667 break;
3668
Marcel Holtmanna9de9242007-10-20 13:33:56 +02003669 case HCI_EV_CMD_COMPLETE:
3670 hci_cmd_complete_evt(hdev, skb);
3671 break;
3672
3673 case HCI_EV_CMD_STATUS:
3674 hci_cmd_status_evt(hdev, skb);
3675 break;
3676
3677 case HCI_EV_ROLE_CHANGE:
3678 hci_role_change_evt(hdev, skb);
3679 break;
3680
3681 case HCI_EV_NUM_COMP_PKTS:
3682 hci_num_comp_pkts_evt(hdev, skb);
3683 break;
3684
3685 case HCI_EV_MODE_CHANGE:
3686 hci_mode_change_evt(hdev, skb);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003687 break;
3688
3689 case HCI_EV_PIN_CODE_REQ:
3690 hci_pin_code_request_evt(hdev, skb);
3691 break;
3692
3693 case HCI_EV_LINK_KEY_REQ:
3694 hci_link_key_request_evt(hdev, skb);
3695 break;
3696
3697 case HCI_EV_LINK_KEY_NOTIFY:
3698 hci_link_key_notify_evt(hdev, skb);
3699 break;
3700
3701 case HCI_EV_CLOCK_OFFSET:
3702 hci_clock_offset_evt(hdev, skb);
3703 break;
3704
Marcel Holtmanna8746412008-07-14 20:13:46 +02003705 case HCI_EV_PKT_TYPE_CHANGE:
3706 hci_pkt_type_change_evt(hdev, skb);
3707 break;
3708
Marcel Holtmann85a1e932005-08-09 20:28:02 -07003709 case HCI_EV_PSCAN_REP_MODE:
3710 hci_pscan_rep_mode_evt(hdev, skb);
3711 break;
3712
Marcel Holtmanna9de9242007-10-20 13:33:56 +02003713 case HCI_EV_INQUIRY_RESULT_WITH_RSSI:
3714 hci_inquiry_result_with_rssi_evt(hdev, skb);
3715 break;
3716
3717 case HCI_EV_REMOTE_EXT_FEATURES:
3718 hci_remote_ext_features_evt(hdev, skb);
3719 break;
3720
3721 case HCI_EV_SYNC_CONN_COMPLETE:
3722 hci_sync_conn_complete_evt(hdev, skb);
3723 break;
3724
Marcel Holtmanna9de9242007-10-20 13:33:56 +02003725 case HCI_EV_EXTENDED_INQUIRY_RESULT:
3726 hci_extended_inquiry_result_evt(hdev, skb);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003727 break;
3728
Johan Hedberg1c2e0042012-06-08 23:31:13 +08003729 case HCI_EV_KEY_REFRESH_COMPLETE:
3730 hci_key_refresh_complete_evt(hdev, skb);
3731 break;
3732
Marcel Holtmann04936842008-07-14 20:13:48 +02003733 case HCI_EV_IO_CAPA_REQUEST:
3734 hci_io_capa_request_evt(hdev, skb);
3735 break;
3736
Johan Hedberg03b555e2011-01-04 15:40:05 +02003737 case HCI_EV_IO_CAPA_REPLY:
3738 hci_io_capa_reply_evt(hdev, skb);
3739 break;
3740
Johan Hedberga5c29682011-02-19 12:05:57 -03003741 case HCI_EV_USER_CONFIRM_REQUEST:
3742 hci_user_confirm_request_evt(hdev, skb);
3743 break;
3744
Brian Gix1143d452011-11-23 08:28:34 -08003745 case HCI_EV_USER_PASSKEY_REQUEST:
3746 hci_user_passkey_request_evt(hdev, skb);
3747 break;
3748
Johan Hedberg92a25252012-09-06 18:39:26 +03003749 case HCI_EV_USER_PASSKEY_NOTIFY:
3750 hci_user_passkey_notify_evt(hdev, skb);
3751 break;
3752
3753 case HCI_EV_KEYPRESS_NOTIFY:
3754 hci_keypress_notify_evt(hdev, skb);
3755 break;
3756
Marcel Holtmann04936842008-07-14 20:13:48 +02003757 case HCI_EV_SIMPLE_PAIR_COMPLETE:
3758 hci_simple_pair_complete_evt(hdev, skb);
3759 break;
3760
Marcel Holtmann41a96212008-07-14 20:13:48 +02003761 case HCI_EV_REMOTE_HOST_FEATURES:
3762 hci_remote_host_features_evt(hdev, skb);
3763 break;
3764
Ville Tervofcd89c02011-02-10 22:38:47 -03003765 case HCI_EV_LE_META:
3766 hci_le_meta_evt(hdev, skb);
3767 break;
3768
Andrei Emeltchenko9495b2e2012-09-27 17:26:22 +03003769 case HCI_EV_CHANNEL_SELECTED:
3770 hci_chan_selected_evt(hdev, skb);
3771 break;
3772
Szymon Janc2763eda2011-03-22 13:12:22 +01003773 case HCI_EV_REMOTE_OOB_DATA_REQUEST:
3774 hci_remote_oob_data_request_evt(hdev, skb);
3775 break;
3776
Andrei Emeltchenkod5e91192012-10-25 15:20:44 +03003777 case HCI_EV_PHY_LINK_COMPLETE:
3778 hci_phy_link_complete_evt(hdev, skb);
3779 break;
3780
Andrei Emeltchenko27695fb2012-10-25 15:20:45 +03003781 case HCI_EV_LOGICAL_LINK_COMPLETE:
3782 hci_loglink_complete_evt(hdev, skb);
3783 break;
3784
Andrei Emeltchenko606e2a12012-10-31 15:46:31 +02003785 case HCI_EV_DISCONN_LOGICAL_LINK_COMPLETE:
3786 hci_disconn_loglink_complete_evt(hdev, skb);
3787 break;
3788
Andrei Emeltchenko9eef6b32012-10-31 15:46:32 +02003789 case HCI_EV_DISCONN_PHY_LINK_COMPLETE:
3790 hci_disconn_phylink_complete_evt(hdev, skb);
3791 break;
3792
Andrei Emeltchenko25e89e92012-01-04 12:41:58 +02003793 case HCI_EV_NUM_COMP_BLOCKS:
3794 hci_num_comp_blocks_evt(hdev, skb);
3795 break;
3796
Marcel Holtmanna9de9242007-10-20 13:33:56 +02003797 default:
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +03003798 BT_DBG("%s event 0x%2.2x", hdev->name, event);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003799 break;
3800 }
3801
3802 kfree_skb(skb);
3803 hdev->stat.evt_rx++;
3804}