blob: 9f5c5f244502ef3cad289c8477fb05ad3990f37e [file] [log] [blame]
YOSHIFUJI Hideaki8e87d142007-02-09 23:24:33 +09001/*
Linus Torvalds1da177e2005-04-16 15:20:36 -07002 BlueZ - Bluetooth protocol stack for Linux
Ron Shaffer2d0a0342010-05-28 11:53:46 -04003 Copyright (c) 2000-2001, 2010, Code Aurora Forum. All rights reserved.
Linus Torvalds1da177e2005-04-16 15:20:36 -07004
5 Written 2000,2001 by Maxim Krasnyansky <maxk@qualcomm.com>
6
7 This program is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License version 2 as
9 published by the Free Software Foundation;
10
11 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
12 OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
13 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF THIRD PARTY RIGHTS.
14 IN NO EVENT SHALL THE COPYRIGHT HOLDER(S) AND AUTHOR(S) BE LIABLE FOR ANY
YOSHIFUJI Hideaki8e87d142007-02-09 23:24:33 +090015 CLAIM, OR ANY SPECIAL INDIRECT OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES
16 WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
17 ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
Linus Torvalds1da177e2005-04-16 15:20:36 -070018 OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
19
YOSHIFUJI Hideaki8e87d142007-02-09 23:24:33 +090020 ALL LIABILITY, INCLUDING LIABILITY FOR INFRINGEMENT OF ANY PATENTS,
21 COPYRIGHTS, TRADEMARKS OR OTHER RIGHTS, RELATING TO USE OF THIS
Linus Torvalds1da177e2005-04-16 15:20:36 -070022 SOFTWARE IS DISCLAIMED.
23*/
24
25/* Bluetooth HCI event handling. */
26
Linus Torvalds1da177e2005-04-16 15:20:36 -070027#include <asm/unaligned.h>
28
29#include <net/bluetooth/bluetooth.h>
30#include <net/bluetooth/hci_core.h>
Mikel Astizf0d6a0e2012-08-09 09:52:30 +020031#include <net/bluetooth/mgmt.h>
Andrei Emeltchenko8e2a0d92012-09-27 17:26:08 +030032#include <net/bluetooth/a2mp.h>
Andrei Emeltchenko903e4542012-09-27 17:26:09 +030033#include <net/bluetooth/amp.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070034
Linus Torvalds1da177e2005-04-16 15:20:36 -070035/* Handle HCI Event packets */
36
Marcel Holtmanna9de9242007-10-20 13:33:56 +020037static void hci_cc_inquiry_cancel(struct hci_dev *hdev, struct sk_buff *skb)
Linus Torvalds1da177e2005-04-16 15:20:36 -070038{
Marcel Holtmanna9de9242007-10-20 13:33:56 +020039 __u8 status = *((__u8 *) skb->data);
Linus Torvalds1da177e2005-04-16 15:20:36 -070040
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +030041 BT_DBG("%s status 0x%2.2x", hdev->name, status);
Linus Torvalds1da177e2005-04-16 15:20:36 -070042
Andre Guedese6d465c2011-11-09 17:14:26 -030043 if (status) {
44 hci_dev_lock(hdev);
45 mgmt_stop_discovery_failed(hdev, status);
46 hci_dev_unlock(hdev);
Marcel Holtmanna9de9242007-10-20 13:33:56 +020047 return;
Andre Guedese6d465c2011-11-09 17:14:26 -030048 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070049
Andre Guedes89352e72011-11-04 14:16:53 -030050 clear_bit(HCI_INQUIRY, &hdev->flags);
51
Johan Hedberg56e5cb82011-11-08 20:40:16 +020052 hci_dev_lock(hdev);
Johan Hedbergff9ef572012-01-04 14:23:45 +020053 hci_discovery_set_state(hdev, DISCOVERY_STOPPED);
Johan Hedberg56e5cb82011-11-08 20:40:16 +020054 hci_dev_unlock(hdev);
Marcel Holtmann6bd57412006-11-18 22:14:22 +010055
Johan Hedberg23bb5762010-12-21 23:01:27 +020056 hci_req_complete(hdev, HCI_OP_INQUIRY_CANCEL, status);
Marcel Holtmann6bd57412006-11-18 22:14:22 +010057
Marcel Holtmanna9de9242007-10-20 13:33:56 +020058 hci_conn_check_pending(hdev);
Linus Torvalds1da177e2005-04-16 15:20:36 -070059}
60
Andre Guedes4d934832012-03-21 00:03:35 -030061static void hci_cc_periodic_inq(struct hci_dev *hdev, struct sk_buff *skb)
62{
63 __u8 status = *((__u8 *) skb->data);
64
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +030065 BT_DBG("%s status 0x%2.2x", hdev->name, status);
Andre Guedesae854a72012-03-21 00:03:36 -030066
67 if (status)
68 return;
69
70 set_bit(HCI_PERIODIC_INQ, &hdev->dev_flags);
Andre Guedes4d934832012-03-21 00:03:35 -030071}
72
Marcel Holtmanna9de9242007-10-20 13:33:56 +020073static void hci_cc_exit_periodic_inq(struct hci_dev *hdev, struct sk_buff *skb)
Linus Torvalds1da177e2005-04-16 15:20:36 -070074{
Marcel Holtmanna9de9242007-10-20 13:33:56 +020075 __u8 status = *((__u8 *) skb->data);
76
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +030077 BT_DBG("%s status 0x%2.2x", hdev->name, status);
Marcel Holtmanna9de9242007-10-20 13:33:56 +020078
79 if (status)
80 return;
81
Andre Guedesae854a72012-03-21 00:03:36 -030082 clear_bit(HCI_PERIODIC_INQ, &hdev->dev_flags);
83
Marcel Holtmanna9de9242007-10-20 13:33:56 +020084 hci_conn_check_pending(hdev);
85}
86
Gustavo Padovan807deac2012-05-17 00:36:24 -030087static void hci_cc_remote_name_req_cancel(struct hci_dev *hdev,
88 struct sk_buff *skb)
Marcel Holtmanna9de9242007-10-20 13:33:56 +020089{
90 BT_DBG("%s", hdev->name);
91}
92
93static void hci_cc_role_discovery(struct hci_dev *hdev, struct sk_buff *skb)
94{
95 struct hci_rp_role_discovery *rp = (void *) skb->data;
Linus Torvalds1da177e2005-04-16 15:20:36 -070096 struct hci_conn *conn;
Linus Torvalds1da177e2005-04-16 15:20:36 -070097
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +030098 BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
Linus Torvalds1da177e2005-04-16 15:20:36 -070099
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200100 if (rp->status)
101 return;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700102
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200103 hci_dev_lock(hdev);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700104
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200105 conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(rp->handle));
106 if (conn) {
107 if (rp->role)
108 conn->link_mode &= ~HCI_LM_MASTER;
109 else
110 conn->link_mode |= HCI_LM_MASTER;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700111 }
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200112
113 hci_dev_unlock(hdev);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700114}
115
Marcel Holtmanne4e8e372008-07-14 20:13:47 +0200116static void hci_cc_read_link_policy(struct hci_dev *hdev, struct sk_buff *skb)
117{
118 struct hci_rp_read_link_policy *rp = (void *) skb->data;
119 struct hci_conn *conn;
120
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +0300121 BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
Marcel Holtmanne4e8e372008-07-14 20:13:47 +0200122
123 if (rp->status)
124 return;
125
126 hci_dev_lock(hdev);
127
128 conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(rp->handle));
129 if (conn)
130 conn->link_policy = __le16_to_cpu(rp->policy);
131
132 hci_dev_unlock(hdev);
133}
134
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200135static void hci_cc_write_link_policy(struct hci_dev *hdev, struct sk_buff *skb)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700136{
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200137 struct hci_rp_write_link_policy *rp = (void *) skb->data;
138 struct hci_conn *conn;
139 void *sent;
140
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +0300141 BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200142
143 if (rp->status)
144 return;
145
146 sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_LINK_POLICY);
147 if (!sent)
148 return;
149
150 hci_dev_lock(hdev);
151
152 conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(rp->handle));
Marcel Holtmanne4e8e372008-07-14 20:13:47 +0200153 if (conn)
Harvey Harrison83985312008-05-02 16:25:46 -0700154 conn->link_policy = get_unaligned_le16(sent + 2);
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200155
156 hci_dev_unlock(hdev);
157}
158
Gustavo Padovan807deac2012-05-17 00:36:24 -0300159static void hci_cc_read_def_link_policy(struct hci_dev *hdev,
160 struct sk_buff *skb)
Marcel Holtmanne4e8e372008-07-14 20:13:47 +0200161{
162 struct hci_rp_read_def_link_policy *rp = (void *) skb->data;
163
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +0300164 BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
Marcel Holtmanne4e8e372008-07-14 20:13:47 +0200165
166 if (rp->status)
167 return;
168
169 hdev->link_policy = __le16_to_cpu(rp->policy);
170}
171
Gustavo Padovan807deac2012-05-17 00:36:24 -0300172static void hci_cc_write_def_link_policy(struct hci_dev *hdev,
173 struct sk_buff *skb)
Marcel Holtmanne4e8e372008-07-14 20:13:47 +0200174{
175 __u8 status = *((__u8 *) skb->data);
176 void *sent;
177
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +0300178 BT_DBG("%s status 0x%2.2x", hdev->name, status);
Marcel Holtmanne4e8e372008-07-14 20:13:47 +0200179
180 sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_DEF_LINK_POLICY);
181 if (!sent)
182 return;
183
184 if (!status)
185 hdev->link_policy = get_unaligned_le16(sent);
186
Johan Hedberg23bb5762010-12-21 23:01:27 +0200187 hci_req_complete(hdev, HCI_OP_WRITE_DEF_LINK_POLICY, status);
Marcel Holtmanne4e8e372008-07-14 20:13:47 +0200188}
189
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200190static void hci_cc_reset(struct hci_dev *hdev, struct sk_buff *skb)
191{
192 __u8 status = *((__u8 *) skb->data);
193
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +0300194 BT_DBG("%s status 0x%2.2x", hdev->name, status);
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200195
Gustavo F. Padovan10572132011-03-16 15:36:29 -0300196 clear_bit(HCI_RESET, &hdev->flags);
197
Johan Hedberg23bb5762010-12-21 23:01:27 +0200198 hci_req_complete(hdev, HCI_OP_RESET, status);
Andre Guedesd23264a2011-11-25 20:53:38 -0300199
Johan Hedberga297e972012-02-21 17:55:47 +0200200 /* Reset all non-persistent flags */
Andre Guedesae854a72012-03-21 00:03:36 -0300201 hdev->dev_flags &= ~(BIT(HCI_LE_SCAN) | BIT(HCI_PENDING_CLASS) |
202 BIT(HCI_PERIODIC_INQ));
Andre Guedes69775ff2012-02-23 16:50:05 +0200203
204 hdev->discovery.state = DISCOVERY_STOPPED;
Johan Hedbergbbaf4442012-11-08 01:22:59 +0100205 hdev->inq_tx_power = HCI_TX_POWER_INVALID;
206 hdev->adv_tx_power = HCI_TX_POWER_INVALID;
Johan Hedberg3f0f5242012-11-08 01:23:00 +0100207
208 memset(hdev->adv_data, 0, sizeof(hdev->adv_data));
209 hdev->adv_data_len = 0;
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200210}
211
212static void hci_cc_write_local_name(struct hci_dev *hdev, struct sk_buff *skb)
213{
214 __u8 status = *((__u8 *) skb->data);
215 void *sent;
216
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +0300217 BT_DBG("%s status 0x%2.2x", hdev->name, status);
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200218
219 sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_LOCAL_NAME);
220 if (!sent)
221 return;
222
Johan Hedberg56e5cb82011-11-08 20:40:16 +0200223 hci_dev_lock(hdev);
224
Johan Hedbergf51d5b22012-02-22 18:17:32 +0200225 if (test_bit(HCI_MGMT, &hdev->dev_flags))
226 mgmt_set_local_name_complete(hdev, sent, status);
Johan Hedberg28cc7bd2012-02-22 21:06:55 +0200227 else if (!status)
228 memcpy(hdev->dev_name, sent, HCI_MAX_NAME_LENGTH);
Johan Hedbergf51d5b22012-02-22 18:17:32 +0200229
Johan Hedberg56e5cb82011-11-08 20:40:16 +0200230 hci_dev_unlock(hdev);
Johan Hedberg3159d382012-02-24 13:47:56 +0200231
Johan Hedberg3f0f5242012-11-08 01:23:00 +0100232 if (!status && !test_bit(HCI_INIT, &hdev->flags))
233 hci_update_ad(hdev);
234
Johan Hedberg3159d382012-02-24 13:47:56 +0200235 hci_req_complete(hdev, HCI_OP_WRITE_LOCAL_NAME, status);
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200236}
237
238static void hci_cc_read_local_name(struct hci_dev *hdev, struct sk_buff *skb)
239{
240 struct hci_rp_read_local_name *rp = (void *) skb->data;
241
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +0300242 BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200243
244 if (rp->status)
245 return;
246
Johan Hedbergdb99b5f2012-02-22 20:14:22 +0200247 if (test_bit(HCI_SETUP, &hdev->dev_flags))
248 memcpy(hdev->dev_name, rp->name, HCI_MAX_NAME_LENGTH);
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200249}
250
251static void hci_cc_write_auth_enable(struct hci_dev *hdev, struct sk_buff *skb)
252{
253 __u8 status = *((__u8 *) skb->data);
254 void *sent;
255
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +0300256 BT_DBG("%s status 0x%2.2x", hdev->name, status);
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200257
258 sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_AUTH_ENABLE);
259 if (!sent)
260 return;
261
262 if (!status) {
263 __u8 param = *((__u8 *) sent);
264
265 if (param == AUTH_ENABLED)
266 set_bit(HCI_AUTH, &hdev->flags);
267 else
268 clear_bit(HCI_AUTH, &hdev->flags);
269 }
270
Johan Hedberg33ef95e2012-02-16 23:56:27 +0200271 if (test_bit(HCI_MGMT, &hdev->dev_flags))
272 mgmt_auth_enable_complete(hdev, status);
273
Johan Hedberg23bb5762010-12-21 23:01:27 +0200274 hci_req_complete(hdev, HCI_OP_WRITE_AUTH_ENABLE, status);
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200275}
276
277static void hci_cc_write_encrypt_mode(struct hci_dev *hdev, struct sk_buff *skb)
278{
279 __u8 status = *((__u8 *) skb->data);
280 void *sent;
281
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +0300282 BT_DBG("%s status 0x%2.2x", hdev->name, status);
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200283
284 sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_ENCRYPT_MODE);
285 if (!sent)
286 return;
287
288 if (!status) {
289 __u8 param = *((__u8 *) sent);
290
291 if (param)
292 set_bit(HCI_ENCRYPT, &hdev->flags);
293 else
294 clear_bit(HCI_ENCRYPT, &hdev->flags);
295 }
296
Johan Hedberg23bb5762010-12-21 23:01:27 +0200297 hci_req_complete(hdev, HCI_OP_WRITE_ENCRYPT_MODE, status);
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200298}
299
300static void hci_cc_write_scan_enable(struct hci_dev *hdev, struct sk_buff *skb)
301{
Johan Hedberg36f7fc72011-11-04 00:17:45 +0200302 __u8 param, status = *((__u8 *) skb->data);
303 int old_pscan, old_iscan;
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200304 void *sent;
305
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +0300306 BT_DBG("%s status 0x%2.2x", hdev->name, status);
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200307
308 sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_SCAN_ENABLE);
309 if (!sent)
310 return;
311
Johan Hedberg36f7fc72011-11-04 00:17:45 +0200312 param = *((__u8 *) sent);
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200313
Johan Hedberg56e5cb82011-11-08 20:40:16 +0200314 hci_dev_lock(hdev);
315
Mikel Astizfa1bd912012-08-09 09:52:29 +0200316 if (status) {
Johan Hedberg744cf192011-11-08 20:40:14 +0200317 mgmt_write_scan_failed(hdev, param, status);
Johan Hedberg2d7cee52011-11-07 22:16:03 +0200318 hdev->discov_timeout = 0;
319 goto done;
320 }
321
Johan Hedberg36f7fc72011-11-04 00:17:45 +0200322 old_pscan = test_and_clear_bit(HCI_PSCAN, &hdev->flags);
323 old_iscan = test_and_clear_bit(HCI_ISCAN, &hdev->flags);
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200324
Johan Hedberg36f7fc72011-11-04 00:17:45 +0200325 if (param & SCAN_INQUIRY) {
326 set_bit(HCI_ISCAN, &hdev->flags);
327 if (!old_iscan)
Johan Hedberg744cf192011-11-08 20:40:14 +0200328 mgmt_discoverable(hdev, 1);
Johan Hedberg16ab91a2011-11-07 22:16:02 +0200329 if (hdev->discov_timeout > 0) {
330 int to = msecs_to_jiffies(hdev->discov_timeout * 1000);
331 queue_delayed_work(hdev->workqueue, &hdev->discov_off,
Gustavo Padovan807deac2012-05-17 00:36:24 -0300332 to);
Johan Hedberg16ab91a2011-11-07 22:16:02 +0200333 }
Johan Hedberg36f7fc72011-11-04 00:17:45 +0200334 } else if (old_iscan)
Johan Hedberg744cf192011-11-08 20:40:14 +0200335 mgmt_discoverable(hdev, 0);
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200336
Johan Hedberg36f7fc72011-11-04 00:17:45 +0200337 if (param & SCAN_PAGE) {
338 set_bit(HCI_PSCAN, &hdev->flags);
339 if (!old_pscan)
Johan Hedberg744cf192011-11-08 20:40:14 +0200340 mgmt_connectable(hdev, 1);
Johan Hedberg36f7fc72011-11-04 00:17:45 +0200341 } else if (old_pscan)
Johan Hedberg744cf192011-11-08 20:40:14 +0200342 mgmt_connectable(hdev, 0);
Johan Hedberg36f7fc72011-11-04 00:17:45 +0200343
344done:
Johan Hedberg56e5cb82011-11-08 20:40:16 +0200345 hci_dev_unlock(hdev);
Johan Hedberg23bb5762010-12-21 23:01:27 +0200346 hci_req_complete(hdev, HCI_OP_WRITE_SCAN_ENABLE, status);
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200347}
348
349static void hci_cc_read_class_of_dev(struct hci_dev *hdev, struct sk_buff *skb)
350{
351 struct hci_rp_read_class_of_dev *rp = (void *) skb->data;
352
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +0300353 BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200354
355 if (rp->status)
356 return;
357
358 memcpy(hdev->dev_class, rp->dev_class, 3);
359
360 BT_DBG("%s class 0x%.2x%.2x%.2x", hdev->name,
Gustavo Padovan807deac2012-05-17 00:36:24 -0300361 hdev->dev_class[2], hdev->dev_class[1], hdev->dev_class[0]);
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200362}
363
364static void hci_cc_write_class_of_dev(struct hci_dev *hdev, struct sk_buff *skb)
365{
366 __u8 status = *((__u8 *) skb->data);
367 void *sent;
368
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +0300369 BT_DBG("%s status 0x%2.2x", hdev->name, status);
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200370
371 sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_CLASS_OF_DEV);
372 if (!sent)
373 return;
374
Marcel Holtmann7f9a9032012-02-22 18:38:01 +0100375 hci_dev_lock(hdev);
376
377 if (status == 0)
378 memcpy(hdev->dev_class, sent, 3);
379
380 if (test_bit(HCI_MGMT, &hdev->dev_flags))
381 mgmt_set_class_of_dev_complete(hdev, sent, status);
382
383 hci_dev_unlock(hdev);
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200384}
385
386static void hci_cc_read_voice_setting(struct hci_dev *hdev, struct sk_buff *skb)
387{
388 struct hci_rp_read_voice_setting *rp = (void *) skb->data;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700389 __u16 setting;
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200390
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +0300391 BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200392
393 if (rp->status)
394 return;
395
396 setting = __le16_to_cpu(rp->voice_setting);
397
Marcel Holtmannf383f272008-07-14 20:13:47 +0200398 if (hdev->voice_setting == setting)
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200399 return;
400
401 hdev->voice_setting = setting;
402
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +0300403 BT_DBG("%s voice setting 0x%4.4x", hdev->name, setting);
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200404
Gustavo F. Padovan3c547112011-12-14 22:58:44 -0200405 if (hdev->notify)
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200406 hdev->notify(hdev, HCI_NOTIFY_VOICE_SETTING);
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200407}
408
Gustavo Padovan8fc9ced2012-05-23 04:04:21 -0300409static void hci_cc_write_voice_setting(struct hci_dev *hdev,
410 struct sk_buff *skb)
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200411{
412 __u8 status = *((__u8 *) skb->data);
Marcel Holtmannf383f272008-07-14 20:13:47 +0200413 __u16 setting;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700414 void *sent;
415
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +0300416 BT_DBG("%s status 0x%2.2x", hdev->name, status);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700417
Marcel Holtmannf383f272008-07-14 20:13:47 +0200418 if (status)
419 return;
420
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200421 sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_VOICE_SETTING);
422 if (!sent)
423 return;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700424
Marcel Holtmannf383f272008-07-14 20:13:47 +0200425 setting = get_unaligned_le16(sent);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700426
Marcel Holtmannf383f272008-07-14 20:13:47 +0200427 if (hdev->voice_setting == setting)
428 return;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700429
Marcel Holtmannf383f272008-07-14 20:13:47 +0200430 hdev->voice_setting = setting;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700431
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +0300432 BT_DBG("%s voice setting 0x%4.4x", hdev->name, setting);
Marcel Holtmannf383f272008-07-14 20:13:47 +0200433
Gustavo F. Padovan3c547112011-12-14 22:58:44 -0200434 if (hdev->notify)
Marcel Holtmannf383f272008-07-14 20:13:47 +0200435 hdev->notify(hdev, HCI_NOTIFY_VOICE_SETTING);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700436}
437
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200438static void hci_cc_host_buffer_size(struct hci_dev *hdev, struct sk_buff *skb)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700439{
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200440 __u8 status = *((__u8 *) skb->data);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700441
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +0300442 BT_DBG("%s status 0x%2.2x", hdev->name, status);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700443
Johan Hedberg23bb5762010-12-21 23:01:27 +0200444 hci_req_complete(hdev, HCI_OP_HOST_BUFFER_SIZE, status);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700445}
446
Marcel Holtmann333140b2008-07-14 20:13:48 +0200447static void hci_cc_write_ssp_mode(struct hci_dev *hdev, struct sk_buff *skb)
448{
449 __u8 status = *((__u8 *) skb->data);
Johan Hedberg5ed8eb22012-10-25 00:09:51 +0300450 struct hci_cp_write_ssp_mode *sent;
Marcel Holtmann333140b2008-07-14 20:13:48 +0200451
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +0300452 BT_DBG("%s status 0x%2.2x", hdev->name, status);
Marcel Holtmann333140b2008-07-14 20:13:48 +0200453
Marcel Holtmann333140b2008-07-14 20:13:48 +0200454 sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_SSP_MODE);
455 if (!sent)
456 return;
457
Johan Hedberg5ed8eb22012-10-25 00:09:51 +0300458 if (!status) {
459 if (sent->mode)
460 hdev->host_features[0] |= LMP_HOST_SSP;
461 else
462 hdev->host_features[0] &= ~LMP_HOST_SSP;
463 }
464
Johan Hedberged2c4ee2012-02-17 00:56:28 +0200465 if (test_bit(HCI_MGMT, &hdev->dev_flags))
Johan Hedberg5ed8eb22012-10-25 00:09:51 +0300466 mgmt_ssp_enable_complete(hdev, sent->mode, status);
Johan Hedbergc0ecddc2012-02-22 12:38:31 +0200467 else if (!status) {
Johan Hedberg5ed8eb22012-10-25 00:09:51 +0300468 if (sent->mode)
Johan Hedbergc0ecddc2012-02-22 12:38:31 +0200469 set_bit(HCI_SSP_ENABLED, &hdev->dev_flags);
470 else
471 clear_bit(HCI_SSP_ENABLED, &hdev->dev_flags);
472 }
Marcel Holtmann333140b2008-07-14 20:13:48 +0200473}
474
Johan Hedbergd5859e22011-01-25 01:19:58 +0200475static u8 hci_get_inquiry_mode(struct hci_dev *hdev)
476{
Johan Hedberg976eb202012-10-24 21:12:01 +0300477 if (lmp_ext_inq_capable(hdev))
Johan Hedbergd5859e22011-01-25 01:19:58 +0200478 return 2;
479
Johan Hedberg976eb202012-10-24 21:12:01 +0300480 if (lmp_inq_rssi_capable(hdev))
Johan Hedbergd5859e22011-01-25 01:19:58 +0200481 return 1;
482
483 if (hdev->manufacturer == 11 && hdev->hci_rev == 0x00 &&
Gustavo Padovan807deac2012-05-17 00:36:24 -0300484 hdev->lmp_subver == 0x0757)
Johan Hedbergd5859e22011-01-25 01:19:58 +0200485 return 1;
486
487 if (hdev->manufacturer == 15) {
488 if (hdev->hci_rev == 0x03 && hdev->lmp_subver == 0x6963)
489 return 1;
490 if (hdev->hci_rev == 0x09 && hdev->lmp_subver == 0x6963)
491 return 1;
492 if (hdev->hci_rev == 0x00 && hdev->lmp_subver == 0x6965)
493 return 1;
494 }
495
496 if (hdev->manufacturer == 31 && hdev->hci_rev == 0x2005 &&
Gustavo Padovan807deac2012-05-17 00:36:24 -0300497 hdev->lmp_subver == 0x1805)
Johan Hedbergd5859e22011-01-25 01:19:58 +0200498 return 1;
499
500 return 0;
501}
502
503static void hci_setup_inquiry_mode(struct hci_dev *hdev)
504{
505 u8 mode;
506
507 mode = hci_get_inquiry_mode(hdev);
508
509 hci_send_cmd(hdev, HCI_OP_WRITE_INQUIRY_MODE, 1, &mode);
510}
511
512static void hci_setup_event_mask(struct hci_dev *hdev)
513{
514 /* The second byte is 0xff instead of 0x9f (two reserved bits
515 * disabled) since a Broadcom 1.2 dongle doesn't respond to the
516 * command otherwise */
517 u8 events[8] = { 0xff, 0xff, 0xfb, 0xff, 0x00, 0x00, 0x00, 0x00 };
518
Ville Tervo6de6c182011-05-27 11:16:21 +0300519 /* CSR 1.1 dongles does not accept any bitfield so don't try to set
520 * any event mask for pre 1.2 devices */
Andrei Emeltchenko5a13b092011-12-01 14:33:28 +0200521 if (hdev->hci_ver < BLUETOOTH_VER_1_2)
Ville Tervo6de6c182011-05-27 11:16:21 +0300522 return;
523
Johan Hedberge1171e82012-10-19 20:57:45 +0300524 if (lmp_bredr_capable(hdev)) {
525 events[4] |= 0x01; /* Flow Specification Complete */
526 events[4] |= 0x02; /* Inquiry Result with RSSI */
527 events[4] |= 0x04; /* Read Remote Extended Features Complete */
528 events[5] |= 0x08; /* Synchronous Connection Complete */
529 events[5] |= 0x10; /* Synchronous Connection Changed */
530 }
Johan Hedbergd5859e22011-01-25 01:19:58 +0200531
Johan Hedberg976eb202012-10-24 21:12:01 +0300532 if (lmp_inq_rssi_capable(hdev))
Johan Hedberga24299e2012-04-26 09:47:46 +0300533 events[4] |= 0x02; /* Inquiry Result with RSSI */
Johan Hedbergd5859e22011-01-25 01:19:58 +0200534
Andre Guedes999dcd12012-07-24 15:03:52 -0300535 if (lmp_sniffsubr_capable(hdev))
Johan Hedbergd5859e22011-01-25 01:19:58 +0200536 events[5] |= 0x20; /* Sniff Subrating */
537
Johan Hedberg976eb202012-10-24 21:12:01 +0300538 if (lmp_pause_enc_capable(hdev))
Johan Hedbergd5859e22011-01-25 01:19:58 +0200539 events[5] |= 0x80; /* Encryption Key Refresh Complete */
540
Johan Hedberg976eb202012-10-24 21:12:01 +0300541 if (lmp_ext_inq_capable(hdev))
Johan Hedbergd5859e22011-01-25 01:19:58 +0200542 events[5] |= 0x40; /* Extended Inquiry Result */
543
Andre Guedesc58e8102012-07-24 15:03:53 -0300544 if (lmp_no_flush_capable(hdev))
Johan Hedbergd5859e22011-01-25 01:19:58 +0200545 events[7] |= 0x01; /* Enhanced Flush Complete */
546
Johan Hedberg976eb202012-10-24 21:12:01 +0300547 if (lmp_lsto_capable(hdev))
Johan Hedbergd5859e22011-01-25 01:19:58 +0200548 events[6] |= 0x80; /* Link Supervision Timeout Changed */
549
Andre Guedes9a1a1992012-07-24 15:03:48 -0300550 if (lmp_ssp_capable(hdev)) {
Johan Hedbergd5859e22011-01-25 01:19:58 +0200551 events[6] |= 0x01; /* IO Capability Request */
552 events[6] |= 0x02; /* IO Capability Response */
553 events[6] |= 0x04; /* User Confirmation Request */
554 events[6] |= 0x08; /* User Passkey Request */
555 events[6] |= 0x10; /* Remote OOB Data Request */
556 events[6] |= 0x20; /* Simple Pairing Complete */
557 events[7] |= 0x04; /* User Passkey Notification */
558 events[7] |= 0x08; /* Keypress Notification */
559 events[7] |= 0x10; /* Remote Host Supported
560 * Features Notification */
561 }
562
Andre Guedesc383ddc2012-07-24 15:03:47 -0300563 if (lmp_le_capable(hdev))
Johan Hedbergd5859e22011-01-25 01:19:58 +0200564 events[7] |= 0x20; /* LE Meta-Event */
565
566 hci_send_cmd(hdev, HCI_OP_SET_EVENT_MASK, sizeof(events), events);
Johan Hedberge36b04c2012-10-19 20:57:47 +0300567
568 if (lmp_le_capable(hdev)) {
569 memset(events, 0, sizeof(events));
570 events[0] = 0x1f;
571 hci_send_cmd(hdev, HCI_OP_LE_SET_EVENT_MASK,
572 sizeof(events), events);
573 }
Johan Hedbergd5859e22011-01-25 01:19:58 +0200574}
575
Gustavo Padovan4611dfa2012-10-24 11:18:41 -0200576static void bredr_setup(struct hci_dev *hdev)
Johan Hedberge1171e82012-10-19 20:57:45 +0300577{
578 struct hci_cp_delete_stored_link_key cp;
579 __le16 param;
580 __u8 flt_type;
581
582 /* Read Buffer Size (ACL mtu, max pkt, etc.) */
583 hci_send_cmd(hdev, HCI_OP_READ_BUFFER_SIZE, 0, NULL);
584
585 /* Read Class of Device */
586 hci_send_cmd(hdev, HCI_OP_READ_CLASS_OF_DEV, 0, NULL);
587
588 /* Read Local Name */
589 hci_send_cmd(hdev, HCI_OP_READ_LOCAL_NAME, 0, NULL);
590
591 /* Read Voice Setting */
592 hci_send_cmd(hdev, HCI_OP_READ_VOICE_SETTING, 0, NULL);
593
594 /* Clear Event Filters */
595 flt_type = HCI_FLT_CLEAR_ALL;
596 hci_send_cmd(hdev, HCI_OP_SET_EVENT_FLT, 1, &flt_type);
597
598 /* Connection accept timeout ~20 secs */
599 param = __constant_cpu_to_le16(0x7d00);
600 hci_send_cmd(hdev, HCI_OP_WRITE_CA_TIMEOUT, 2, &param);
601
602 bacpy(&cp.bdaddr, BDADDR_ANY);
603 cp.delete_all = 1;
604 hci_send_cmd(hdev, HCI_OP_DELETE_STORED_LINK_KEY, sizeof(cp), &cp);
605}
606
Gustavo Padovan4611dfa2012-10-24 11:18:41 -0200607static void le_setup(struct hci_dev *hdev)
Johan Hedberge1171e82012-10-19 20:57:45 +0300608{
609 /* Read LE Buffer Size */
610 hci_send_cmd(hdev, HCI_OP_LE_READ_BUFFER_SIZE, 0, NULL);
Johan Hedberg8fa19092012-10-19 20:57:49 +0300611
612 /* Read LE Advertising Channel TX Power */
613 hci_send_cmd(hdev, HCI_OP_LE_READ_ADV_TX_POWER, 0, NULL);
Johan Hedberge1171e82012-10-19 20:57:45 +0300614}
615
Johan Hedbergd5859e22011-01-25 01:19:58 +0200616static void hci_setup(struct hci_dev *hdev)
617{
Andrei Emeltchenkoe61ef4992011-12-19 16:31:27 +0200618 if (hdev->dev_type != HCI_BREDR)
619 return;
620
Johan Hedberge1171e82012-10-19 20:57:45 +0300621 /* Read BD Address */
622 hci_send_cmd(hdev, HCI_OP_READ_BD_ADDR, 0, NULL);
623
624 if (lmp_bredr_capable(hdev))
Gustavo Padovan4611dfa2012-10-24 11:18:41 -0200625 bredr_setup(hdev);
Johan Hedberge1171e82012-10-19 20:57:45 +0300626
627 if (lmp_le_capable(hdev))
Gustavo Padovan4611dfa2012-10-24 11:18:41 -0200628 le_setup(hdev);
Johan Hedberge1171e82012-10-19 20:57:45 +0300629
Johan Hedbergd5859e22011-01-25 01:19:58 +0200630 hci_setup_event_mask(hdev);
631
Andrei Emeltchenkod095c1e2011-12-01 14:33:27 +0200632 if (hdev->hci_ver > BLUETOOTH_VER_1_1)
Johan Hedbergd5859e22011-01-25 01:19:58 +0200633 hci_send_cmd(hdev, HCI_OP_READ_LOCAL_COMMANDS, 0, NULL);
634
Gustavo Padovan6d3c7302012-05-24 03:36:37 -0300635 if (lmp_ssp_capable(hdev)) {
Johan Hedberg54d04db2012-02-22 15:47:48 +0200636 if (test_bit(HCI_SSP_ENABLED, &hdev->dev_flags)) {
637 u8 mode = 0x01;
638 hci_send_cmd(hdev, HCI_OP_WRITE_SSP_MODE,
Gustavo F. Padovan04124682012-03-08 01:25:00 -0300639 sizeof(mode), &mode);
Johan Hedberg54d04db2012-02-22 15:47:48 +0200640 } else {
641 struct hci_cp_write_eir cp;
642
643 memset(hdev->eir, 0, sizeof(hdev->eir));
644 memset(&cp, 0, sizeof(cp));
645
646 hci_send_cmd(hdev, HCI_OP_WRITE_EIR, sizeof(cp), &cp);
647 }
Johan Hedbergd5859e22011-01-25 01:19:58 +0200648 }
649
Johan Hedberg976eb202012-10-24 21:12:01 +0300650 if (lmp_inq_rssi_capable(hdev))
Johan Hedbergd5859e22011-01-25 01:19:58 +0200651 hci_setup_inquiry_mode(hdev);
652
Johan Hedberg976eb202012-10-24 21:12:01 +0300653 if (lmp_inq_tx_pwr_capable(hdev))
Johan Hedbergd5859e22011-01-25 01:19:58 +0200654 hci_send_cmd(hdev, HCI_OP_READ_INQ_RSP_TX_POWER, 0, NULL);
Andre Guedes971e3a42011-06-30 19:20:52 -0300655
Johan Hedberg976eb202012-10-24 21:12:01 +0300656 if (lmp_ext_feat_capable(hdev)) {
Andre Guedes971e3a42011-06-30 19:20:52 -0300657 struct hci_cp_read_local_ext_features cp;
658
659 cp.page = 0x01;
Gustavo F. Padovan04124682012-03-08 01:25:00 -0300660 hci_send_cmd(hdev, HCI_OP_READ_LOCAL_EXT_FEATURES, sizeof(cp),
661 &cp);
Andre Guedes971e3a42011-06-30 19:20:52 -0300662 }
Andre Guedese6100a22011-06-30 19:20:54 -0300663
Johan Hedberg47990ea2012-02-22 11:58:37 +0200664 if (test_bit(HCI_LINK_SECURITY, &hdev->dev_flags)) {
665 u8 enable = 1;
Gustavo F. Padovan04124682012-03-08 01:25:00 -0300666 hci_send_cmd(hdev, HCI_OP_WRITE_AUTH_ENABLE, sizeof(enable),
667 &enable);
Johan Hedberg47990ea2012-02-22 11:58:37 +0200668 }
Johan Hedbergd5859e22011-01-25 01:19:58 +0200669}
670
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200671static void hci_cc_read_local_version(struct hci_dev *hdev, struct sk_buff *skb)
672{
673 struct hci_rp_read_local_version *rp = (void *) skb->data;
674
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +0300675 BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200676
677 if (rp->status)
Andrei Emeltchenko28b8df72012-02-24 12:45:44 +0200678 goto done;
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200679
680 hdev->hci_ver = rp->hci_ver;
Marcel Holtmanne4e8e372008-07-14 20:13:47 +0200681 hdev->hci_rev = __le16_to_cpu(rp->hci_rev);
Johan Hedbergd5859e22011-01-25 01:19:58 +0200682 hdev->lmp_ver = rp->lmp_ver;
Marcel Holtmanne4e8e372008-07-14 20:13:47 +0200683 hdev->manufacturer = __le16_to_cpu(rp->manufacturer);
Johan Hedbergd5859e22011-01-25 01:19:58 +0200684 hdev->lmp_subver = __le16_to_cpu(rp->lmp_subver);
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200685
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +0300686 BT_DBG("%s manufacturer 0x%4.4x hci ver %d:%d", hdev->name,
Gustavo Padovan807deac2012-05-17 00:36:24 -0300687 hdev->manufacturer, hdev->hci_ver, hdev->hci_rev);
Johan Hedbergd5859e22011-01-25 01:19:58 +0200688
689 if (test_bit(HCI_INIT, &hdev->flags))
690 hci_setup(hdev);
Andrei Emeltchenko28b8df72012-02-24 12:45:44 +0200691
692done:
693 hci_req_complete(hdev, HCI_OP_READ_LOCAL_VERSION, rp->status);
Johan Hedbergd5859e22011-01-25 01:19:58 +0200694}
695
696static void hci_setup_link_policy(struct hci_dev *hdev)
697{
Andrei Emeltchenko035100c2012-03-12 15:59:32 +0200698 struct hci_cp_write_def_link_policy cp;
Johan Hedbergd5859e22011-01-25 01:19:58 +0200699 u16 link_policy = 0;
700
Andre Guedes9f92ebf2012-07-24 15:03:50 -0300701 if (lmp_rswitch_capable(hdev))
Johan Hedbergd5859e22011-01-25 01:19:58 +0200702 link_policy |= HCI_LP_RSWITCH;
Johan Hedberg976eb202012-10-24 21:12:01 +0300703 if (lmp_hold_capable(hdev))
Johan Hedbergd5859e22011-01-25 01:19:58 +0200704 link_policy |= HCI_LP_HOLD;
Andre Guedes6eded102012-07-24 15:03:51 -0300705 if (lmp_sniff_capable(hdev))
Johan Hedbergd5859e22011-01-25 01:19:58 +0200706 link_policy |= HCI_LP_SNIFF;
Johan Hedberg976eb202012-10-24 21:12:01 +0300707 if (lmp_park_capable(hdev))
Johan Hedbergd5859e22011-01-25 01:19:58 +0200708 link_policy |= HCI_LP_PARK;
709
Andrei Emeltchenko035100c2012-03-12 15:59:32 +0200710 cp.policy = cpu_to_le16(link_policy);
711 hci_send_cmd(hdev, HCI_OP_WRITE_DEF_LINK_POLICY, sizeof(cp), &cp);
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200712}
713
Gustavo Padovan8fc9ced2012-05-23 04:04:21 -0300714static void hci_cc_read_local_commands(struct hci_dev *hdev,
715 struct sk_buff *skb)
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200716{
717 struct hci_rp_read_local_commands *rp = (void *) skb->data;
718
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +0300719 BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200720
721 if (rp->status)
Johan Hedbergd5859e22011-01-25 01:19:58 +0200722 goto done;
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200723
724 memcpy(hdev->commands, rp->commands, sizeof(hdev->commands));
Johan Hedbergd5859e22011-01-25 01:19:58 +0200725
726 if (test_bit(HCI_INIT, &hdev->flags) && (hdev->commands[5] & 0x10))
727 hci_setup_link_policy(hdev);
728
729done:
730 hci_req_complete(hdev, HCI_OP_READ_LOCAL_COMMANDS, rp->status);
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200731}
732
Gustavo Padovan8fc9ced2012-05-23 04:04:21 -0300733static void hci_cc_read_local_features(struct hci_dev *hdev,
734 struct sk_buff *skb)
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200735{
736 struct hci_rp_read_local_features *rp = (void *) skb->data;
737
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +0300738 BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200739
740 if (rp->status)
741 return;
742
743 memcpy(hdev->features, rp->features, 8);
744
745 /* Adjust default settings according to features
746 * supported by device. */
747
748 if (hdev->features[0] & LMP_3SLOT)
749 hdev->pkt_type |= (HCI_DM3 | HCI_DH3);
750
751 if (hdev->features[0] & LMP_5SLOT)
752 hdev->pkt_type |= (HCI_DM5 | HCI_DH5);
753
754 if (hdev->features[1] & LMP_HV2) {
755 hdev->pkt_type |= (HCI_HV2);
756 hdev->esco_type |= (ESCO_HV2);
757 }
758
759 if (hdev->features[1] & LMP_HV3) {
760 hdev->pkt_type |= (HCI_HV3);
761 hdev->esco_type |= (ESCO_HV3);
762 }
763
Andre Guedes45db810f2012-07-24 15:03:49 -0300764 if (lmp_esco_capable(hdev))
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200765 hdev->esco_type |= (ESCO_EV3);
766
767 if (hdev->features[4] & LMP_EV4)
768 hdev->esco_type |= (ESCO_EV4);
769
770 if (hdev->features[4] & LMP_EV5)
771 hdev->esco_type |= (ESCO_EV5);
772
Marcel Holtmannefc76882009-02-06 09:13:37 +0100773 if (hdev->features[5] & LMP_EDR_ESCO_2M)
774 hdev->esco_type |= (ESCO_2EV3);
775
776 if (hdev->features[5] & LMP_EDR_ESCO_3M)
777 hdev->esco_type |= (ESCO_3EV3);
778
779 if (hdev->features[5] & LMP_EDR_3S_ESCO)
780 hdev->esco_type |= (ESCO_2EV5 | ESCO_3EV5);
781
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200782 BT_DBG("%s features 0x%.2x%.2x%.2x%.2x%.2x%.2x%.2x%.2x", hdev->name,
Gustavo Padovan807deac2012-05-17 00:36:24 -0300783 hdev->features[0], hdev->features[1],
784 hdev->features[2], hdev->features[3],
785 hdev->features[4], hdev->features[5],
786 hdev->features[6], hdev->features[7]);
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200787}
788
Johan Hedberg8f984df2012-02-28 01:07:22 +0200789static void hci_set_le_support(struct hci_dev *hdev)
790{
791 struct hci_cp_write_le_host_supported cp;
792
793 memset(&cp, 0, sizeof(cp));
794
Marcel Holtmann9d428202012-05-03 07:12:31 +0200795 if (test_bit(HCI_LE_ENABLED, &hdev->dev_flags)) {
Johan Hedberg8f984df2012-02-28 01:07:22 +0200796 cp.le = 1;
Johan Hedberg976eb202012-10-24 21:12:01 +0300797 cp.simul = !!lmp_le_br_capable(hdev);
Johan Hedberg8f984df2012-02-28 01:07:22 +0200798 }
799
Johan Hedberg976eb202012-10-24 21:12:01 +0300800 if (cp.le != !!lmp_host_le_capable(hdev))
Gustavo F. Padovan04124682012-03-08 01:25:00 -0300801 hci_send_cmd(hdev, HCI_OP_WRITE_LE_HOST_SUPPORTED, sizeof(cp),
802 &cp);
Johan Hedberg8f984df2012-02-28 01:07:22 +0200803}
804
Andre Guedes971e3a42011-06-30 19:20:52 -0300805static void hci_cc_read_local_ext_features(struct hci_dev *hdev,
Gustavo Padovan807deac2012-05-17 00:36:24 -0300806 struct sk_buff *skb)
Andre Guedes971e3a42011-06-30 19:20:52 -0300807{
808 struct hci_rp_read_local_ext_features *rp = (void *) skb->data;
809
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +0300810 BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
Andre Guedes971e3a42011-06-30 19:20:52 -0300811
812 if (rp->status)
Johan Hedberg8f984df2012-02-28 01:07:22 +0200813 goto done;
Andre Guedes971e3a42011-06-30 19:20:52 -0300814
Andre Guedesb5b32b62011-12-30 10:34:04 -0300815 switch (rp->page) {
816 case 0:
817 memcpy(hdev->features, rp->features, 8);
818 break;
819 case 1:
820 memcpy(hdev->host_features, rp->features, 8);
821 break;
822 }
Andre Guedes971e3a42011-06-30 19:20:52 -0300823
Andre Guedesc383ddc2012-07-24 15:03:47 -0300824 if (test_bit(HCI_INIT, &hdev->flags) && lmp_le_capable(hdev))
Johan Hedberg8f984df2012-02-28 01:07:22 +0200825 hci_set_le_support(hdev);
826
827done:
Andre Guedes971e3a42011-06-30 19:20:52 -0300828 hci_req_complete(hdev, HCI_OP_READ_LOCAL_EXT_FEATURES, rp->status);
829}
830
Andrei Emeltchenko1e89cff2011-11-24 14:52:02 +0200831static void hci_cc_read_flow_control_mode(struct hci_dev *hdev,
Gustavo Padovan807deac2012-05-17 00:36:24 -0300832 struct sk_buff *skb)
Andrei Emeltchenko1e89cff2011-11-24 14:52:02 +0200833{
834 struct hci_rp_read_flow_control_mode *rp = (void *) skb->data;
835
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +0300836 BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
Andrei Emeltchenko1e89cff2011-11-24 14:52:02 +0200837
838 if (rp->status)
839 return;
840
841 hdev->flow_ctl_mode = rp->mode;
842
843 hci_req_complete(hdev, HCI_OP_READ_FLOW_CONTROL_MODE, rp->status);
844}
845
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200846static void hci_cc_read_buffer_size(struct hci_dev *hdev, struct sk_buff *skb)
847{
848 struct hci_rp_read_buffer_size *rp = (void *) skb->data;
849
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +0300850 BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200851
852 if (rp->status)
853 return;
854
855 hdev->acl_mtu = __le16_to_cpu(rp->acl_mtu);
856 hdev->sco_mtu = rp->sco_mtu;
857 hdev->acl_pkts = __le16_to_cpu(rp->acl_max_pkt);
858 hdev->sco_pkts = __le16_to_cpu(rp->sco_max_pkt);
859
860 if (test_bit(HCI_QUIRK_FIXUP_BUFFER_SIZE, &hdev->quirks)) {
861 hdev->sco_mtu = 64;
862 hdev->sco_pkts = 8;
863 }
864
865 hdev->acl_cnt = hdev->acl_pkts;
866 hdev->sco_cnt = hdev->sco_pkts;
867
Gustavo Padovan807deac2012-05-17 00:36:24 -0300868 BT_DBG("%s acl mtu %d:%d sco mtu %d:%d", hdev->name, hdev->acl_mtu,
869 hdev->acl_pkts, hdev->sco_mtu, hdev->sco_pkts);
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200870}
871
872static void hci_cc_read_bd_addr(struct hci_dev *hdev, struct sk_buff *skb)
873{
874 struct hci_rp_read_bd_addr *rp = (void *) skb->data;
875
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +0300876 BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200877
878 if (!rp->status)
879 bacpy(&hdev->bdaddr, &rp->bdaddr);
880
Johan Hedberg23bb5762010-12-21 23:01:27 +0200881 hci_req_complete(hdev, HCI_OP_READ_BD_ADDR, rp->status);
882}
883
Andrei Emeltchenko350ee4c2011-12-07 15:56:51 +0200884static void hci_cc_read_data_block_size(struct hci_dev *hdev,
Gustavo Padovan807deac2012-05-17 00:36:24 -0300885 struct sk_buff *skb)
Andrei Emeltchenko350ee4c2011-12-07 15:56:51 +0200886{
887 struct hci_rp_read_data_block_size *rp = (void *) skb->data;
888
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +0300889 BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
Andrei Emeltchenko350ee4c2011-12-07 15:56:51 +0200890
891 if (rp->status)
892 return;
893
894 hdev->block_mtu = __le16_to_cpu(rp->max_acl_len);
895 hdev->block_len = __le16_to_cpu(rp->block_len);
896 hdev->num_blocks = __le16_to_cpu(rp->num_blocks);
897
898 hdev->block_cnt = hdev->num_blocks;
899
900 BT_DBG("%s blk mtu %d cnt %d len %d", hdev->name, hdev->block_mtu,
Gustavo Padovan807deac2012-05-17 00:36:24 -0300901 hdev->block_cnt, hdev->block_len);
Andrei Emeltchenko350ee4c2011-12-07 15:56:51 +0200902
903 hci_req_complete(hdev, HCI_OP_READ_DATA_BLOCK_SIZE, rp->status);
904}
905
Johan Hedberg23bb5762010-12-21 23:01:27 +0200906static void hci_cc_write_ca_timeout(struct hci_dev *hdev, struct sk_buff *skb)
907{
908 __u8 status = *((__u8 *) skb->data);
909
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +0300910 BT_DBG("%s status 0x%2.2x", hdev->name, status);
Johan Hedberg23bb5762010-12-21 23:01:27 +0200911
912 hci_req_complete(hdev, HCI_OP_WRITE_CA_TIMEOUT, status);
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200913}
914
Andrei Emeltchenko928abaa2011-10-12 10:53:57 +0300915static void hci_cc_read_local_amp_info(struct hci_dev *hdev,
Gustavo Padovan807deac2012-05-17 00:36:24 -0300916 struct sk_buff *skb)
Andrei Emeltchenko928abaa2011-10-12 10:53:57 +0300917{
918 struct hci_rp_read_local_amp_info *rp = (void *) skb->data;
919
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +0300920 BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
Andrei Emeltchenko928abaa2011-10-12 10:53:57 +0300921
922 if (rp->status)
Andrei Emeltchenko8e2a0d92012-09-27 17:26:08 +0300923 goto a2mp_rsp;
Andrei Emeltchenko928abaa2011-10-12 10:53:57 +0300924
925 hdev->amp_status = rp->amp_status;
926 hdev->amp_total_bw = __le32_to_cpu(rp->total_bw);
927 hdev->amp_max_bw = __le32_to_cpu(rp->max_bw);
928 hdev->amp_min_latency = __le32_to_cpu(rp->min_latency);
929 hdev->amp_max_pdu = __le32_to_cpu(rp->max_pdu);
930 hdev->amp_type = rp->amp_type;
931 hdev->amp_pal_cap = __le16_to_cpu(rp->pal_cap);
932 hdev->amp_assoc_size = __le16_to_cpu(rp->max_assoc_size);
933 hdev->amp_be_flush_to = __le32_to_cpu(rp->be_flush_to);
934 hdev->amp_max_flush_to = __le32_to_cpu(rp->max_flush_to);
935
936 hci_req_complete(hdev, HCI_OP_READ_LOCAL_AMP_INFO, rp->status);
Andrei Emeltchenko8e2a0d92012-09-27 17:26:08 +0300937
938a2mp_rsp:
939 a2mp_send_getinfo_rsp(hdev);
Andrei Emeltchenko928abaa2011-10-12 10:53:57 +0300940}
941
Andrei Emeltchenko903e4542012-09-27 17:26:09 +0300942static void hci_cc_read_local_amp_assoc(struct hci_dev *hdev,
943 struct sk_buff *skb)
944{
945 struct hci_rp_read_local_amp_assoc *rp = (void *) skb->data;
946 struct amp_assoc *assoc = &hdev->loc_assoc;
947 size_t rem_len, frag_len;
948
949 BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
950
951 if (rp->status)
952 goto a2mp_rsp;
953
954 frag_len = skb->len - sizeof(*rp);
955 rem_len = __le16_to_cpu(rp->rem_len);
956
957 if (rem_len > frag_len) {
Andrei Emeltchenko2e430be32012-09-28 14:44:23 +0300958 BT_DBG("frag_len %zu rem_len %zu", frag_len, rem_len);
Andrei Emeltchenko903e4542012-09-27 17:26:09 +0300959
960 memcpy(assoc->data + assoc->offset, rp->frag, frag_len);
961 assoc->offset += frag_len;
962
963 /* Read other fragments */
964 amp_read_loc_assoc_frag(hdev, rp->phy_handle);
965
966 return;
967 }
968
969 memcpy(assoc->data + assoc->offset, rp->frag, rem_len);
970 assoc->len = assoc->offset + rem_len;
971 assoc->offset = 0;
972
973a2mp_rsp:
974 /* Send A2MP Rsp when all fragments are received */
975 a2mp_send_getampassoc_rsp(hdev, rp->status);
Andrei Emeltchenko9495b2e2012-09-27 17:26:22 +0300976 a2mp_send_create_phy_link_req(hdev, rp->status);
Andrei Emeltchenko903e4542012-09-27 17:26:09 +0300977}
978
Johan Hedbergb0916ea2011-01-10 13:44:55 +0200979static void hci_cc_delete_stored_link_key(struct hci_dev *hdev,
Gustavo Padovan807deac2012-05-17 00:36:24 -0300980 struct sk_buff *skb)
Johan Hedbergb0916ea2011-01-10 13:44:55 +0200981{
982 __u8 status = *((__u8 *) skb->data);
983
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +0300984 BT_DBG("%s status 0x%2.2x", hdev->name, status);
Johan Hedbergb0916ea2011-01-10 13:44:55 +0200985
986 hci_req_complete(hdev, HCI_OP_DELETE_STORED_LINK_KEY, status);
987}
988
Johan Hedbergd5859e22011-01-25 01:19:58 +0200989static void hci_cc_set_event_mask(struct hci_dev *hdev, struct sk_buff *skb)
990{
991 __u8 status = *((__u8 *) skb->data);
992
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +0300993 BT_DBG("%s status 0x%2.2x", hdev->name, status);
Johan Hedbergd5859e22011-01-25 01:19:58 +0200994
995 hci_req_complete(hdev, HCI_OP_SET_EVENT_MASK, status);
996}
997
998static void hci_cc_write_inquiry_mode(struct hci_dev *hdev,
Gustavo Padovan807deac2012-05-17 00:36:24 -0300999 struct sk_buff *skb)
Johan Hedbergd5859e22011-01-25 01:19:58 +02001000{
1001 __u8 status = *((__u8 *) skb->data);
1002
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +03001003 BT_DBG("%s status 0x%2.2x", hdev->name, status);
Johan Hedbergd5859e22011-01-25 01:19:58 +02001004
1005 hci_req_complete(hdev, HCI_OP_WRITE_INQUIRY_MODE, status);
1006}
1007
1008static void hci_cc_read_inq_rsp_tx_power(struct hci_dev *hdev,
Gustavo Padovan807deac2012-05-17 00:36:24 -03001009 struct sk_buff *skb)
Johan Hedbergd5859e22011-01-25 01:19:58 +02001010{
Marcel Holtmann91c4e9b2012-03-11 19:27:21 -07001011 struct hci_rp_read_inq_rsp_tx_power *rp = (void *) skb->data;
Johan Hedbergd5859e22011-01-25 01:19:58 +02001012
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +03001013 BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
Johan Hedbergd5859e22011-01-25 01:19:58 +02001014
Marcel Holtmann91c4e9b2012-03-11 19:27:21 -07001015 if (!rp->status)
1016 hdev->inq_tx_power = rp->tx_power;
1017
1018 hci_req_complete(hdev, HCI_OP_READ_INQ_RSP_TX_POWER, rp->status);
Johan Hedbergd5859e22011-01-25 01:19:58 +02001019}
1020
1021static void hci_cc_set_event_flt(struct hci_dev *hdev, struct sk_buff *skb)
1022{
1023 __u8 status = *((__u8 *) skb->data);
1024
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +03001025 BT_DBG("%s status 0x%2.2x", hdev->name, status);
Johan Hedbergd5859e22011-01-25 01:19:58 +02001026
1027 hci_req_complete(hdev, HCI_OP_SET_EVENT_FLT, status);
1028}
1029
Johan Hedberg980e1a52011-01-22 06:10:07 +02001030static void hci_cc_pin_code_reply(struct hci_dev *hdev, struct sk_buff *skb)
1031{
1032 struct hci_rp_pin_code_reply *rp = (void *) skb->data;
1033 struct hci_cp_pin_code_reply *cp;
1034 struct hci_conn *conn;
1035
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +03001036 BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
Johan Hedberg980e1a52011-01-22 06:10:07 +02001037
Johan Hedberg56e5cb82011-11-08 20:40:16 +02001038 hci_dev_lock(hdev);
1039
Johan Hedberga8b2d5c2012-01-08 23:11:15 +02001040 if (test_bit(HCI_MGMT, &hdev->dev_flags))
Johan Hedberg744cf192011-11-08 20:40:14 +02001041 mgmt_pin_code_reply_complete(hdev, &rp->bdaddr, rp->status);
Johan Hedberg980e1a52011-01-22 06:10:07 +02001042
Mikel Astizfa1bd912012-08-09 09:52:29 +02001043 if (rp->status)
Johan Hedberg56e5cb82011-11-08 20:40:16 +02001044 goto unlock;
Johan Hedberg980e1a52011-01-22 06:10:07 +02001045
1046 cp = hci_sent_cmd_data(hdev, HCI_OP_PIN_CODE_REPLY);
1047 if (!cp)
Johan Hedberg56e5cb82011-11-08 20:40:16 +02001048 goto unlock;
Johan Hedberg980e1a52011-01-22 06:10:07 +02001049
1050 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &cp->bdaddr);
1051 if (conn)
1052 conn->pin_length = cp->pin_len;
Johan Hedberg56e5cb82011-11-08 20:40:16 +02001053
1054unlock:
1055 hci_dev_unlock(hdev);
Johan Hedberg980e1a52011-01-22 06:10:07 +02001056}
1057
1058static void hci_cc_pin_code_neg_reply(struct hci_dev *hdev, struct sk_buff *skb)
1059{
1060 struct hci_rp_pin_code_neg_reply *rp = (void *) skb->data;
1061
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +03001062 BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
Johan Hedberg980e1a52011-01-22 06:10:07 +02001063
Johan Hedberg56e5cb82011-11-08 20:40:16 +02001064 hci_dev_lock(hdev);
1065
Johan Hedberga8b2d5c2012-01-08 23:11:15 +02001066 if (test_bit(HCI_MGMT, &hdev->dev_flags))
Johan Hedberg744cf192011-11-08 20:40:14 +02001067 mgmt_pin_code_neg_reply_complete(hdev, &rp->bdaddr,
Gustavo Padovan807deac2012-05-17 00:36:24 -03001068 rp->status);
Johan Hedberg56e5cb82011-11-08 20:40:16 +02001069
1070 hci_dev_unlock(hdev);
Johan Hedberg980e1a52011-01-22 06:10:07 +02001071}
Johan Hedberg56e5cb82011-11-08 20:40:16 +02001072
Ville Tervo6ed58ec2011-02-10 22:38:48 -03001073static void hci_cc_le_read_buffer_size(struct hci_dev *hdev,
1074 struct sk_buff *skb)
1075{
1076 struct hci_rp_le_read_buffer_size *rp = (void *) skb->data;
1077
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +03001078 BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
Ville Tervo6ed58ec2011-02-10 22:38:48 -03001079
1080 if (rp->status)
1081 return;
1082
1083 hdev->le_mtu = __le16_to_cpu(rp->le_mtu);
1084 hdev->le_pkts = rp->le_max_pkt;
1085
1086 hdev->le_cnt = hdev->le_pkts;
1087
1088 BT_DBG("%s le mtu %d:%d", hdev->name, hdev->le_mtu, hdev->le_pkts);
1089
1090 hci_req_complete(hdev, HCI_OP_LE_READ_BUFFER_SIZE, rp->status);
1091}
Johan Hedberg980e1a52011-01-22 06:10:07 +02001092
Johan Hedberg8fa19092012-10-19 20:57:49 +03001093static void hci_cc_le_read_adv_tx_power(struct hci_dev *hdev,
1094 struct sk_buff *skb)
1095{
1096 struct hci_rp_le_read_adv_tx_power *rp = (void *) skb->data;
1097
1098 BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
1099
Johan Hedberg3f0f5242012-11-08 01:23:00 +01001100 if (!rp->status) {
Johan Hedberg8fa19092012-10-19 20:57:49 +03001101 hdev->adv_tx_power = rp->tx_power;
Johan Hedberg3f0f5242012-11-08 01:23:00 +01001102 if (!test_bit(HCI_INIT, &hdev->flags))
1103 hci_update_ad(hdev);
1104 }
Johan Hedberg8fa19092012-10-19 20:57:49 +03001105
1106 hci_req_complete(hdev, HCI_OP_LE_READ_ADV_TX_POWER, rp->status);
1107}
1108
Johan Hedberge36b04c2012-10-19 20:57:47 +03001109static void hci_cc_le_set_event_mask(struct hci_dev *hdev, struct sk_buff *skb)
1110{
1111 __u8 status = *((__u8 *) skb->data);
1112
1113 BT_DBG("%s status 0x%2.2x", hdev->name, status);
1114
1115 hci_req_complete(hdev, HCI_OP_LE_SET_EVENT_MASK, status);
1116}
1117
Johan Hedberga5c29682011-02-19 12:05:57 -03001118static void hci_cc_user_confirm_reply(struct hci_dev *hdev, struct sk_buff *skb)
1119{
1120 struct hci_rp_user_confirm_reply *rp = (void *) skb->data;
1121
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +03001122 BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
Johan Hedberga5c29682011-02-19 12:05:57 -03001123
Johan Hedberg56e5cb82011-11-08 20:40:16 +02001124 hci_dev_lock(hdev);
1125
Johan Hedberga8b2d5c2012-01-08 23:11:15 +02001126 if (test_bit(HCI_MGMT, &hdev->dev_flags))
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001127 mgmt_user_confirm_reply_complete(hdev, &rp->bdaddr, ACL_LINK, 0,
1128 rp->status);
Johan Hedberg56e5cb82011-11-08 20:40:16 +02001129
1130 hci_dev_unlock(hdev);
Johan Hedberga5c29682011-02-19 12:05:57 -03001131}
1132
1133static void hci_cc_user_confirm_neg_reply(struct hci_dev *hdev,
Gustavo Padovan807deac2012-05-17 00:36:24 -03001134 struct sk_buff *skb)
Johan Hedberga5c29682011-02-19 12:05:57 -03001135{
1136 struct hci_rp_user_confirm_reply *rp = (void *) skb->data;
1137
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +03001138 BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
Johan Hedberga5c29682011-02-19 12:05:57 -03001139
Johan Hedberg56e5cb82011-11-08 20:40:16 +02001140 hci_dev_lock(hdev);
1141
Johan Hedberga8b2d5c2012-01-08 23:11:15 +02001142 if (test_bit(HCI_MGMT, &hdev->dev_flags))
Johan Hedberg744cf192011-11-08 20:40:14 +02001143 mgmt_user_confirm_neg_reply_complete(hdev, &rp->bdaddr,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001144 ACL_LINK, 0, rp->status);
Johan Hedberg56e5cb82011-11-08 20:40:16 +02001145
1146 hci_dev_unlock(hdev);
Johan Hedberga5c29682011-02-19 12:05:57 -03001147}
1148
Brian Gix1143d452011-11-23 08:28:34 -08001149static void hci_cc_user_passkey_reply(struct hci_dev *hdev, struct sk_buff *skb)
1150{
1151 struct hci_rp_user_confirm_reply *rp = (void *) skb->data;
1152
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +03001153 BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
Brian Gix1143d452011-11-23 08:28:34 -08001154
1155 hci_dev_lock(hdev);
1156
Johan Hedberga8b2d5c2012-01-08 23:11:15 +02001157 if (test_bit(HCI_MGMT, &hdev->dev_flags))
Johan Hedberg272d90d2012-02-09 15:26:12 +02001158 mgmt_user_passkey_reply_complete(hdev, &rp->bdaddr, ACL_LINK,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001159 0, rp->status);
Brian Gix1143d452011-11-23 08:28:34 -08001160
1161 hci_dev_unlock(hdev);
1162}
1163
1164static void hci_cc_user_passkey_neg_reply(struct hci_dev *hdev,
Gustavo Padovan807deac2012-05-17 00:36:24 -03001165 struct sk_buff *skb)
Brian Gix1143d452011-11-23 08:28:34 -08001166{
1167 struct hci_rp_user_confirm_reply *rp = (void *) skb->data;
1168
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +03001169 BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
Brian Gix1143d452011-11-23 08:28:34 -08001170
1171 hci_dev_lock(hdev);
1172
Johan Hedberga8b2d5c2012-01-08 23:11:15 +02001173 if (test_bit(HCI_MGMT, &hdev->dev_flags))
Brian Gix1143d452011-11-23 08:28:34 -08001174 mgmt_user_passkey_neg_reply_complete(hdev, &rp->bdaddr,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001175 ACL_LINK, 0, rp->status);
Brian Gix1143d452011-11-23 08:28:34 -08001176
1177 hci_dev_unlock(hdev);
1178}
1179
Szymon Jancc35938b2011-03-22 13:12:21 +01001180static void hci_cc_read_local_oob_data_reply(struct hci_dev *hdev,
Gustavo Padovan807deac2012-05-17 00:36:24 -03001181 struct sk_buff *skb)
Szymon Jancc35938b2011-03-22 13:12:21 +01001182{
1183 struct hci_rp_read_local_oob_data *rp = (void *) skb->data;
1184
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +03001185 BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
Szymon Jancc35938b2011-03-22 13:12:21 +01001186
Johan Hedberg56e5cb82011-11-08 20:40:16 +02001187 hci_dev_lock(hdev);
Johan Hedberg744cf192011-11-08 20:40:14 +02001188 mgmt_read_local_oob_data_reply_complete(hdev, rp->hash,
Szymon Jancc35938b2011-03-22 13:12:21 +01001189 rp->randomizer, rp->status);
Johan Hedberg56e5cb82011-11-08 20:40:16 +02001190 hci_dev_unlock(hdev);
Szymon Jancc35938b2011-03-22 13:12:21 +01001191}
1192
Johan Hedbergc1d5dc42012-11-08 01:23:01 +01001193static void hci_cc_le_set_adv_enable(struct hci_dev *hdev, struct sk_buff *skb)
1194{
1195 __u8 *sent, status = *((__u8 *) skb->data);
1196
1197 BT_DBG("%s status 0x%2.2x", hdev->name, status);
1198
1199 sent = hci_sent_cmd_data(hdev, HCI_OP_LE_SET_ADV_ENABLE);
1200 if (!sent)
1201 return;
1202
1203 hci_dev_lock(hdev);
1204
1205 if (!status) {
1206 if (*sent)
1207 set_bit(HCI_LE_PERIPHERAL, &hdev->dev_flags);
1208 else
1209 clear_bit(HCI_LE_PERIPHERAL, &hdev->dev_flags);
1210 }
1211
1212 hci_dev_unlock(hdev);
1213
1214 if (!test_bit(HCI_INIT, &hdev->flags))
1215 hci_update_ad(hdev);
1216
1217 hci_req_complete(hdev, HCI_OP_LE_SET_ADV_ENABLE, status);
1218}
1219
Andre Guedes07f7fa52011-12-02 21:13:31 +09001220static void hci_cc_le_set_scan_param(struct hci_dev *hdev, struct sk_buff *skb)
1221{
1222 __u8 status = *((__u8 *) skb->data);
1223
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +03001224 BT_DBG("%s status 0x%2.2x", hdev->name, status);
Andre Guedes7ba8b4b2012-02-03 17:47:59 -03001225
1226 hci_req_complete(hdev, HCI_OP_LE_SET_SCAN_PARAM, status);
Andre Guedes3fd24152012-02-03 17:48:01 -03001227
1228 if (status) {
1229 hci_dev_lock(hdev);
1230 mgmt_start_discovery_failed(hdev, status);
1231 hci_dev_unlock(hdev);
1232 return;
1233 }
Andre Guedes07f7fa52011-12-02 21:13:31 +09001234}
1235
Andre Guedeseb9d91f2011-05-26 16:23:52 -03001236static void hci_cc_le_set_scan_enable(struct hci_dev *hdev,
Gustavo Padovan807deac2012-05-17 00:36:24 -03001237 struct sk_buff *skb)
Andre Guedeseb9d91f2011-05-26 16:23:52 -03001238{
1239 struct hci_cp_le_set_scan_enable *cp;
1240 __u8 status = *((__u8 *) skb->data);
1241
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +03001242 BT_DBG("%s status 0x%2.2x", hdev->name, status);
Andre Guedeseb9d91f2011-05-26 16:23:52 -03001243
Andre Guedeseb9d91f2011-05-26 16:23:52 -03001244 cp = hci_sent_cmd_data(hdev, HCI_OP_LE_SET_SCAN_ENABLE);
1245 if (!cp)
1246 return;
1247
Andrei Emeltchenko68a8aea2011-12-19 16:14:18 +02001248 switch (cp->enable) {
1249 case LE_SCANNING_ENABLED:
Andre Guedes7ba8b4b2012-02-03 17:47:59 -03001250 hci_req_complete(hdev, HCI_OP_LE_SET_SCAN_ENABLE, status);
1251
Andre Guedes3fd24152012-02-03 17:48:01 -03001252 if (status) {
1253 hci_dev_lock(hdev);
1254 mgmt_start_discovery_failed(hdev, status);
1255 hci_dev_unlock(hdev);
Andre Guedes7ba8b4b2012-02-03 17:47:59 -03001256 return;
Andre Guedes3fd24152012-02-03 17:48:01 -03001257 }
Andre Guedes7ba8b4b2012-02-03 17:47:59 -03001258
Andre Guedesd23264a2011-11-25 20:53:38 -03001259 set_bit(HCI_LE_SCAN, &hdev->dev_flags);
1260
Andre Guedesa8f13c82011-09-09 18:56:24 -03001261 hci_dev_lock(hdev);
Andre Guedes343f9352012-02-17 20:39:37 -03001262 hci_discovery_set_state(hdev, DISCOVERY_FINDING);
Andre Guedesa8f13c82011-09-09 18:56:24 -03001263 hci_dev_unlock(hdev);
Andrei Emeltchenko68a8aea2011-12-19 16:14:18 +02001264 break;
1265
1266 case LE_SCANNING_DISABLED:
Andre Guedesc9ecc482012-03-15 16:52:08 -03001267 if (status) {
1268 hci_dev_lock(hdev);
1269 mgmt_stop_discovery_failed(hdev, status);
1270 hci_dev_unlock(hdev);
Andre Guedes7ba8b4b2012-02-03 17:47:59 -03001271 return;
Andre Guedesc9ecc482012-03-15 16:52:08 -03001272 }
Andre Guedes7ba8b4b2012-02-03 17:47:59 -03001273
Andre Guedesd23264a2011-11-25 20:53:38 -03001274 clear_bit(HCI_LE_SCAN, &hdev->dev_flags);
1275
Andre Guedesbc3dd332012-03-06 19:37:06 -03001276 if (hdev->discovery.type == DISCOV_TYPE_INTERLEAVED &&
1277 hdev->discovery.state == DISCOVERY_FINDING) {
Andre Guedes5e0452c2012-02-17 20:39:38 -03001278 mgmt_interleaved_discovery(hdev);
1279 } else {
1280 hci_dev_lock(hdev);
1281 hci_discovery_set_state(hdev, DISCOVERY_STOPPED);
1282 hci_dev_unlock(hdev);
1283 }
1284
Andrei Emeltchenko68a8aea2011-12-19 16:14:18 +02001285 break;
1286
1287 default:
1288 BT_ERR("Used reserved LE_Scan_Enable param %d", cp->enable);
1289 break;
Andre Guedes35815082011-05-26 16:23:53 -03001290 }
Andre Guedeseb9d91f2011-05-26 16:23:52 -03001291}
1292
Vinicius Costa Gomesa7a595f2011-06-09 18:50:47 -03001293static void hci_cc_le_ltk_reply(struct hci_dev *hdev, struct sk_buff *skb)
1294{
1295 struct hci_rp_le_ltk_reply *rp = (void *) skb->data;
1296
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +03001297 BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
Vinicius Costa Gomesa7a595f2011-06-09 18:50:47 -03001298
1299 if (rp->status)
1300 return;
1301
1302 hci_req_complete(hdev, HCI_OP_LE_LTK_REPLY, rp->status);
1303}
1304
1305static void hci_cc_le_ltk_neg_reply(struct hci_dev *hdev, struct sk_buff *skb)
1306{
1307 struct hci_rp_le_ltk_neg_reply *rp = (void *) skb->data;
1308
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +03001309 BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
Vinicius Costa Gomesa7a595f2011-06-09 18:50:47 -03001310
1311 if (rp->status)
1312 return;
1313
1314 hci_req_complete(hdev, HCI_OP_LE_LTK_NEG_REPLY, rp->status);
1315}
1316
Gustavo Padovan6039aa72012-05-23 04:04:18 -03001317static void hci_cc_write_le_host_supported(struct hci_dev *hdev,
1318 struct sk_buff *skb)
Andre Guedesf9b49302011-06-30 19:20:53 -03001319{
Johan Hedberg06199cf2012-02-22 16:37:11 +02001320 struct hci_cp_write_le_host_supported *sent;
Andre Guedesf9b49302011-06-30 19:20:53 -03001321 __u8 status = *((__u8 *) skb->data);
1322
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +03001323 BT_DBG("%s status 0x%2.2x", hdev->name, status);
Andre Guedesf9b49302011-06-30 19:20:53 -03001324
Johan Hedberg06199cf2012-02-22 16:37:11 +02001325 sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_LE_HOST_SUPPORTED);
Johan Hedberg8f984df2012-02-28 01:07:22 +02001326 if (!sent)
Andre Guedesf9b49302011-06-30 19:20:53 -03001327 return;
1328
Johan Hedberg8f984df2012-02-28 01:07:22 +02001329 if (!status) {
1330 if (sent->le)
1331 hdev->host_features[0] |= LMP_HOST_LE;
1332 else
1333 hdev->host_features[0] &= ~LMP_HOST_LE;
Johan Hedberg53b2caa2012-10-24 21:11:59 +03001334
1335 if (sent->simul)
1336 hdev->host_features[0] |= LMP_HOST_LE_BREDR;
1337 else
1338 hdev->host_features[0] &= ~LMP_HOST_LE_BREDR;
Johan Hedberg8f984df2012-02-28 01:07:22 +02001339 }
1340
1341 if (test_bit(HCI_MGMT, &hdev->dev_flags) &&
Gustavo Padovan807deac2012-05-17 00:36:24 -03001342 !test_bit(HCI_INIT, &hdev->flags))
Johan Hedberg8f984df2012-02-28 01:07:22 +02001343 mgmt_le_enable_complete(hdev, sent->le, status);
1344
1345 hci_req_complete(hdev, HCI_OP_WRITE_LE_HOST_SUPPORTED, status);
Andre Guedesf9b49302011-06-30 19:20:53 -03001346}
1347
Andrei Emeltchenko93c284e2012-09-27 17:26:20 +03001348static void hci_cc_write_remote_amp_assoc(struct hci_dev *hdev,
1349 struct sk_buff *skb)
1350{
1351 struct hci_rp_write_remote_amp_assoc *rp = (void *) skb->data;
1352
1353 BT_DBG("%s status 0x%2.2x phy_handle 0x%2.2x",
1354 hdev->name, rp->status, rp->phy_handle);
1355
1356 if (rp->status)
1357 return;
1358
1359 amp_write_rem_assoc_continue(hdev, rp->phy_handle);
1360}
1361
Gustavo Padovan6039aa72012-05-23 04:04:18 -03001362static void hci_cs_inquiry(struct hci_dev *hdev, __u8 status)
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001363{
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +03001364 BT_DBG("%s status 0x%2.2x", hdev->name, status);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001365
1366 if (status) {
Johan Hedberg23bb5762010-12-21 23:01:27 +02001367 hci_req_complete(hdev, HCI_OP_INQUIRY, status);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001368 hci_conn_check_pending(hdev);
Johan Hedberg56e5cb82011-11-08 20:40:16 +02001369 hci_dev_lock(hdev);
Johan Hedberga8b2d5c2012-01-08 23:11:15 +02001370 if (test_bit(HCI_MGMT, &hdev->dev_flags))
Andre Guedes7a135102011-11-09 17:14:25 -03001371 mgmt_start_discovery_failed(hdev, status);
Johan Hedberg56e5cb82011-11-08 20:40:16 +02001372 hci_dev_unlock(hdev);
Johan Hedberg314b2382011-04-27 10:29:57 -04001373 return;
1374 }
1375
Andre Guedes89352e72011-11-04 14:16:53 -03001376 set_bit(HCI_INQUIRY, &hdev->flags);
1377
Johan Hedberg56e5cb82011-11-08 20:40:16 +02001378 hci_dev_lock(hdev);
Andre Guedes343f9352012-02-17 20:39:37 -03001379 hci_discovery_set_state(hdev, DISCOVERY_FINDING);
Johan Hedberg56e5cb82011-11-08 20:40:16 +02001380 hci_dev_unlock(hdev);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001381}
1382
Gustavo Padovan6039aa72012-05-23 04:04:18 -03001383static void hci_cs_create_conn(struct hci_dev *hdev, __u8 status)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001384{
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001385 struct hci_cp_create_conn *cp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001386 struct hci_conn *conn;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001387
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +03001388 BT_DBG("%s status 0x%2.2x", hdev->name, status);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001389
1390 cp = hci_sent_cmd_data(hdev, HCI_OP_CREATE_CONN);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001391 if (!cp)
1392 return;
1393
1394 hci_dev_lock(hdev);
1395
1396 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &cp->bdaddr);
1397
Andrei Emeltchenko6ed93dc2012-09-25 12:49:43 +03001398 BT_DBG("%s bdaddr %pMR hcon %p", hdev->name, &cp->bdaddr, conn);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001399
1400 if (status) {
1401 if (conn && conn->state == BT_CONNECT) {
Marcel Holtmann4c67bc72006-10-15 17:30:56 +02001402 if (status != 0x0c || conn->attempt > 2) {
1403 conn->state = BT_CLOSED;
1404 hci_proto_connect_cfm(conn, status);
1405 hci_conn_del(conn);
1406 } else
1407 conn->state = BT_CONNECT2;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001408 }
1409 } else {
1410 if (!conn) {
1411 conn = hci_conn_add(hdev, ACL_LINK, &cp->bdaddr);
1412 if (conn) {
Johan Hedberga0c808b2012-01-16 09:49:58 +02001413 conn->out = true;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001414 conn->link_mode |= HCI_LM_MASTER;
1415 } else
Gustavo F. Padovan893ef972010-07-18 15:13:37 -03001416 BT_ERR("No memory for new connection");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001417 }
1418 }
1419
1420 hci_dev_unlock(hdev);
1421}
1422
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001423static void hci_cs_add_sco(struct hci_dev *hdev, __u8 status)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001424{
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001425 struct hci_cp_add_sco *cp;
1426 struct hci_conn *acl, *sco;
1427 __u16 handle;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001428
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +03001429 BT_DBG("%s status 0x%2.2x", hdev->name, status);
Marcel Holtmannb6a0dc82007-10-20 14:55:10 +02001430
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001431 if (!status)
1432 return;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001433
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001434 cp = hci_sent_cmd_data(hdev, HCI_OP_ADD_SCO);
1435 if (!cp)
1436 return;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001437
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001438 handle = __le16_to_cpu(cp->handle);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001439
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +03001440 BT_DBG("%s handle 0x%4.4x", hdev->name, handle);
Marcel Holtmann6bd57412006-11-18 22:14:22 +01001441
1442 hci_dev_lock(hdev);
1443
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001444 acl = hci_conn_hash_lookup_handle(hdev, handle);
Andrei Emeltchenko5a08ecc2011-01-11 17:20:20 +02001445 if (acl) {
1446 sco = acl->link;
1447 if (sco) {
1448 sco->state = BT_CLOSED;
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001449
Andrei Emeltchenko5a08ecc2011-01-11 17:20:20 +02001450 hci_proto_connect_cfm(sco, status);
1451 hci_conn_del(sco);
1452 }
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001453 }
Marcel Holtmann6bd57412006-11-18 22:14:22 +01001454
1455 hci_dev_unlock(hdev);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001456}
1457
Marcel Holtmannf8558552008-07-14 20:13:49 +02001458static void hci_cs_auth_requested(struct hci_dev *hdev, __u8 status)
1459{
1460 struct hci_cp_auth_requested *cp;
1461 struct hci_conn *conn;
1462
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +03001463 BT_DBG("%s status 0x%2.2x", hdev->name, status);
Marcel Holtmannf8558552008-07-14 20:13:49 +02001464
1465 if (!status)
1466 return;
1467
1468 cp = hci_sent_cmd_data(hdev, HCI_OP_AUTH_REQUESTED);
1469 if (!cp)
1470 return;
1471
1472 hci_dev_lock(hdev);
1473
1474 conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(cp->handle));
1475 if (conn) {
1476 if (conn->state == BT_CONFIG) {
1477 hci_proto_connect_cfm(conn, status);
1478 hci_conn_put(conn);
1479 }
1480 }
1481
1482 hci_dev_unlock(hdev);
1483}
1484
1485static void hci_cs_set_conn_encrypt(struct hci_dev *hdev, __u8 status)
1486{
1487 struct hci_cp_set_conn_encrypt *cp;
1488 struct hci_conn *conn;
1489
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +03001490 BT_DBG("%s status 0x%2.2x", hdev->name, status);
Marcel Holtmannf8558552008-07-14 20:13:49 +02001491
1492 if (!status)
1493 return;
1494
1495 cp = hci_sent_cmd_data(hdev, HCI_OP_SET_CONN_ENCRYPT);
1496 if (!cp)
1497 return;
1498
1499 hci_dev_lock(hdev);
1500
1501 conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(cp->handle));
1502 if (conn) {
1503 if (conn->state == BT_CONFIG) {
1504 hci_proto_connect_cfm(conn, status);
1505 hci_conn_put(conn);
1506 }
1507 }
1508
1509 hci_dev_unlock(hdev);
1510}
1511
Johan Hedberg127178d2010-11-18 22:22:29 +02001512static int hci_outgoing_auth_needed(struct hci_dev *hdev,
Gustavo Padovan807deac2012-05-17 00:36:24 -03001513 struct hci_conn *conn)
Johan Hedberg392599b2010-11-18 22:22:28 +02001514{
Johan Hedberg392599b2010-11-18 22:22:28 +02001515 if (conn->state != BT_CONFIG || !conn->out)
1516 return 0;
1517
Johan Hedberg765c2a92011-01-19 12:06:52 +05301518 if (conn->pending_sec_level == BT_SECURITY_SDP)
Johan Hedberg392599b2010-11-18 22:22:28 +02001519 return 0;
1520
1521 /* Only request authentication for SSP connections or non-SSP
Vinicius Costa Gomese9bf2bf2011-09-02 14:51:20 -03001522 * devices with sec_level HIGH or if MITM protection is requested */
Gustavo Padovan807deac2012-05-17 00:36:24 -03001523 if (!hci_conn_ssp_enabled(conn) && !(conn->auth_type & 0x01) &&
1524 conn->pending_sec_level != BT_SECURITY_HIGH)
Johan Hedberg392599b2010-11-18 22:22:28 +02001525 return 0;
1526
Johan Hedberg392599b2010-11-18 22:22:28 +02001527 return 1;
1528}
1529
Gustavo Padovan6039aa72012-05-23 04:04:18 -03001530static int hci_resolve_name(struct hci_dev *hdev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001531 struct inquiry_entry *e)
Johan Hedberg30dc78e2012-01-04 15:44:20 +02001532{
1533 struct hci_cp_remote_name_req cp;
1534
1535 memset(&cp, 0, sizeof(cp));
1536
1537 bacpy(&cp.bdaddr, &e->data.bdaddr);
1538 cp.pscan_rep_mode = e->data.pscan_rep_mode;
1539 cp.pscan_mode = e->data.pscan_mode;
1540 cp.clock_offset = e->data.clock_offset;
1541
1542 return hci_send_cmd(hdev, HCI_OP_REMOTE_NAME_REQ, sizeof(cp), &cp);
1543}
1544
Johan Hedbergb644ba32012-01-17 21:48:47 +02001545static bool hci_resolve_next_name(struct hci_dev *hdev)
Johan Hedberg30dc78e2012-01-04 15:44:20 +02001546{
1547 struct discovery_state *discov = &hdev->discovery;
1548 struct inquiry_entry *e;
1549
Johan Hedbergb644ba32012-01-17 21:48:47 +02001550 if (list_empty(&discov->resolve))
1551 return false;
1552
1553 e = hci_inquiry_cache_lookup_resolve(hdev, BDADDR_ANY, NAME_NEEDED);
Ram Malovanyc8100892012-07-19 10:26:09 +03001554 if (!e)
1555 return false;
1556
Johan Hedbergb644ba32012-01-17 21:48:47 +02001557 if (hci_resolve_name(hdev, e) == 0) {
1558 e->name_state = NAME_PENDING;
1559 return true;
1560 }
1561
1562 return false;
1563}
1564
1565static void hci_check_pending_name(struct hci_dev *hdev, struct hci_conn *conn,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001566 bdaddr_t *bdaddr, u8 *name, u8 name_len)
Johan Hedbergb644ba32012-01-17 21:48:47 +02001567{
1568 struct discovery_state *discov = &hdev->discovery;
1569 struct inquiry_entry *e;
1570
1571 if (conn && !test_and_set_bit(HCI_CONN_MGMT_CONNECTED, &conn->flags))
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001572 mgmt_device_connected(hdev, bdaddr, ACL_LINK, 0x00, 0, name,
1573 name_len, conn->dev_class);
Johan Hedbergb644ba32012-01-17 21:48:47 +02001574
1575 if (discov->state == DISCOVERY_STOPPED)
1576 return;
1577
Johan Hedberg30dc78e2012-01-04 15:44:20 +02001578 if (discov->state == DISCOVERY_STOPPING)
1579 goto discov_complete;
1580
1581 if (discov->state != DISCOVERY_RESOLVING)
1582 return;
1583
1584 e = hci_inquiry_cache_lookup_resolve(hdev, bdaddr, NAME_PENDING);
Ram Malovany7cc83802012-07-19 10:26:10 +03001585 /* If the device was not found in a list of found devices names of which
1586 * are pending. there is no need to continue resolving a next name as it
1587 * will be done upon receiving another Remote Name Request Complete
1588 * Event */
1589 if (!e)
1590 return;
1591
1592 list_del(&e->list);
1593 if (name) {
Johan Hedberg30dc78e2012-01-04 15:44:20 +02001594 e->name_state = NAME_KNOWN;
Ram Malovany7cc83802012-07-19 10:26:10 +03001595 mgmt_remote_name(hdev, bdaddr, ACL_LINK, 0x00,
1596 e->data.rssi, name, name_len);
Ram Malovanyc3e7c0d2012-07-19 10:26:11 +03001597 } else {
1598 e->name_state = NAME_NOT_KNOWN;
Johan Hedberg30dc78e2012-01-04 15:44:20 +02001599 }
1600
Johan Hedbergb644ba32012-01-17 21:48:47 +02001601 if (hci_resolve_next_name(hdev))
Johan Hedberg30dc78e2012-01-04 15:44:20 +02001602 return;
Johan Hedberg30dc78e2012-01-04 15:44:20 +02001603
1604discov_complete:
1605 hci_discovery_set_state(hdev, DISCOVERY_STOPPED);
1606}
1607
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001608static void hci_cs_remote_name_req(struct hci_dev *hdev, __u8 status)
1609{
Johan Hedberg127178d2010-11-18 22:22:29 +02001610 struct hci_cp_remote_name_req *cp;
1611 struct hci_conn *conn;
1612
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +03001613 BT_DBG("%s status 0x%2.2x", hdev->name, status);
Johan Hedberg127178d2010-11-18 22:22:29 +02001614
1615 /* If successful wait for the name req complete event before
1616 * checking for the need to do authentication */
1617 if (!status)
1618 return;
1619
1620 cp = hci_sent_cmd_data(hdev, HCI_OP_REMOTE_NAME_REQ);
1621 if (!cp)
1622 return;
1623
1624 hci_dev_lock(hdev);
1625
1626 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &cp->bdaddr);
Johan Hedbergb644ba32012-01-17 21:48:47 +02001627
1628 if (test_bit(HCI_MGMT, &hdev->dev_flags))
1629 hci_check_pending_name(hdev, conn, &cp->bdaddr, NULL, 0);
1630
Johan Hedberg79c6c702011-04-28 11:28:55 -07001631 if (!conn)
1632 goto unlock;
1633
1634 if (!hci_outgoing_auth_needed(hdev, conn))
1635 goto unlock;
1636
Johan Hedberg51a8efd2012-01-16 06:10:31 +02001637 if (!test_and_set_bit(HCI_CONN_AUTH_PEND, &conn->flags)) {
Johan Hedberg127178d2010-11-18 22:22:29 +02001638 struct hci_cp_auth_requested cp;
1639 cp.handle = __cpu_to_le16(conn->handle);
1640 hci_send_cmd(hdev, HCI_OP_AUTH_REQUESTED, sizeof(cp), &cp);
1641 }
1642
Johan Hedberg79c6c702011-04-28 11:28:55 -07001643unlock:
Johan Hedberg127178d2010-11-18 22:22:29 +02001644 hci_dev_unlock(hdev);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001645}
1646
Marcel Holtmann769be972008-07-14 20:13:49 +02001647static void hci_cs_read_remote_features(struct hci_dev *hdev, __u8 status)
1648{
1649 struct hci_cp_read_remote_features *cp;
1650 struct hci_conn *conn;
1651
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +03001652 BT_DBG("%s status 0x%2.2x", hdev->name, status);
Marcel Holtmann769be972008-07-14 20:13:49 +02001653
1654 if (!status)
1655 return;
1656
1657 cp = hci_sent_cmd_data(hdev, HCI_OP_READ_REMOTE_FEATURES);
1658 if (!cp)
1659 return;
1660
1661 hci_dev_lock(hdev);
1662
1663 conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(cp->handle));
1664 if (conn) {
1665 if (conn->state == BT_CONFIG) {
Marcel Holtmann769be972008-07-14 20:13:49 +02001666 hci_proto_connect_cfm(conn, status);
1667 hci_conn_put(conn);
1668 }
1669 }
1670
1671 hci_dev_unlock(hdev);
1672}
1673
1674static void hci_cs_read_remote_ext_features(struct hci_dev *hdev, __u8 status)
1675{
1676 struct hci_cp_read_remote_ext_features *cp;
1677 struct hci_conn *conn;
1678
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +03001679 BT_DBG("%s status 0x%2.2x", hdev->name, status);
Marcel Holtmann769be972008-07-14 20:13:49 +02001680
1681 if (!status)
1682 return;
1683
1684 cp = hci_sent_cmd_data(hdev, HCI_OP_READ_REMOTE_EXT_FEATURES);
1685 if (!cp)
1686 return;
1687
1688 hci_dev_lock(hdev);
1689
1690 conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(cp->handle));
1691 if (conn) {
1692 if (conn->state == BT_CONFIG) {
Marcel Holtmann769be972008-07-14 20:13:49 +02001693 hci_proto_connect_cfm(conn, status);
1694 hci_conn_put(conn);
1695 }
1696 }
1697
1698 hci_dev_unlock(hdev);
1699}
1700
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001701static void hci_cs_setup_sync_conn(struct hci_dev *hdev, __u8 status)
1702{
Marcel Holtmannb6a0dc82007-10-20 14:55:10 +02001703 struct hci_cp_setup_sync_conn *cp;
1704 struct hci_conn *acl, *sco;
1705 __u16 handle;
1706
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +03001707 BT_DBG("%s status 0x%2.2x", hdev->name, status);
Marcel Holtmannb6a0dc82007-10-20 14:55:10 +02001708
1709 if (!status)
1710 return;
1711
1712 cp = hci_sent_cmd_data(hdev, HCI_OP_SETUP_SYNC_CONN);
1713 if (!cp)
1714 return;
1715
1716 handle = __le16_to_cpu(cp->handle);
1717
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +03001718 BT_DBG("%s handle 0x%4.4x", hdev->name, handle);
Marcel Holtmannb6a0dc82007-10-20 14:55:10 +02001719
1720 hci_dev_lock(hdev);
1721
1722 acl = hci_conn_hash_lookup_handle(hdev, handle);
Andrei Emeltchenko5a08ecc2011-01-11 17:20:20 +02001723 if (acl) {
1724 sco = acl->link;
1725 if (sco) {
1726 sco->state = BT_CLOSED;
Marcel Holtmannb6a0dc82007-10-20 14:55:10 +02001727
Andrei Emeltchenko5a08ecc2011-01-11 17:20:20 +02001728 hci_proto_connect_cfm(sco, status);
1729 hci_conn_del(sco);
1730 }
Marcel Holtmannb6a0dc82007-10-20 14:55:10 +02001731 }
1732
1733 hci_dev_unlock(hdev);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001734}
1735
1736static void hci_cs_sniff_mode(struct hci_dev *hdev, __u8 status)
1737{
1738 struct hci_cp_sniff_mode *cp;
1739 struct hci_conn *conn;
1740
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +03001741 BT_DBG("%s status 0x%2.2x", hdev->name, status);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001742
1743 if (!status)
1744 return;
1745
1746 cp = hci_sent_cmd_data(hdev, HCI_OP_SNIFF_MODE);
1747 if (!cp)
1748 return;
1749
1750 hci_dev_lock(hdev);
1751
1752 conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(cp->handle));
Marcel Holtmanne73439d2010-07-26 10:06:00 -04001753 if (conn) {
Johan Hedberg51a8efd2012-01-16 06:10:31 +02001754 clear_bit(HCI_CONN_MODE_CHANGE_PEND, &conn->flags);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001755
Johan Hedberg51a8efd2012-01-16 06:10:31 +02001756 if (test_and_clear_bit(HCI_CONN_SCO_SETUP_PEND, &conn->flags))
Marcel Holtmanne73439d2010-07-26 10:06:00 -04001757 hci_sco_setup(conn, status);
1758 }
1759
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001760 hci_dev_unlock(hdev);
1761}
1762
1763static void hci_cs_exit_sniff_mode(struct hci_dev *hdev, __u8 status)
1764{
1765 struct hci_cp_exit_sniff_mode *cp;
1766 struct hci_conn *conn;
1767
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +03001768 BT_DBG("%s status 0x%2.2x", hdev->name, status);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001769
1770 if (!status)
1771 return;
1772
1773 cp = hci_sent_cmd_data(hdev, HCI_OP_EXIT_SNIFF_MODE);
1774 if (!cp)
1775 return;
1776
1777 hci_dev_lock(hdev);
1778
1779 conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(cp->handle));
Marcel Holtmanne73439d2010-07-26 10:06:00 -04001780 if (conn) {
Johan Hedberg51a8efd2012-01-16 06:10:31 +02001781 clear_bit(HCI_CONN_MODE_CHANGE_PEND, &conn->flags);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001782
Johan Hedberg51a8efd2012-01-16 06:10:31 +02001783 if (test_and_clear_bit(HCI_CONN_SCO_SETUP_PEND, &conn->flags))
Marcel Holtmanne73439d2010-07-26 10:06:00 -04001784 hci_sco_setup(conn, status);
1785 }
1786
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001787 hci_dev_unlock(hdev);
1788}
1789
Johan Hedberg88c3df12012-02-09 14:27:38 +02001790static void hci_cs_disconnect(struct hci_dev *hdev, u8 status)
1791{
1792 struct hci_cp_disconnect *cp;
1793 struct hci_conn *conn;
1794
1795 if (!status)
1796 return;
1797
1798 cp = hci_sent_cmd_data(hdev, HCI_OP_DISCONNECT);
1799 if (!cp)
1800 return;
1801
1802 hci_dev_lock(hdev);
1803
1804 conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(cp->handle));
1805 if (conn)
1806 mgmt_disconnect_failed(hdev, &conn->dst, conn->type,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001807 conn->dst_type, status);
Johan Hedberg88c3df12012-02-09 14:27:38 +02001808
1809 hci_dev_unlock(hdev);
1810}
1811
Ville Tervofcd89c02011-02-10 22:38:47 -03001812static void hci_cs_le_create_conn(struct hci_dev *hdev, __u8 status)
1813{
Ville Tervofcd89c02011-02-10 22:38:47 -03001814 struct hci_conn *conn;
1815
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +03001816 BT_DBG("%s status 0x%2.2x", hdev->name, status);
Ville Tervofcd89c02011-02-10 22:38:47 -03001817
Ville Tervofcd89c02011-02-10 22:38:47 -03001818 if (status) {
Andre Guedesf00a06a2012-07-27 15:10:13 -03001819 hci_dev_lock(hdev);
Ville Tervofcd89c02011-02-10 22:38:47 -03001820
Andre Guedes0c95ab72012-07-27 15:10:14 -03001821 conn = hci_conn_hash_lookup_state(hdev, LE_LINK, BT_CONNECT);
Andre Guedesf00a06a2012-07-27 15:10:13 -03001822 if (!conn) {
1823 hci_dev_unlock(hdev);
1824 return;
1825 }
1826
Andrei Emeltchenko6ed93dc2012-09-25 12:49:43 +03001827 BT_DBG("%s bdaddr %pMR conn %p", hdev->name, &conn->dst, conn);
Andre Guedesf00a06a2012-07-27 15:10:13 -03001828
1829 conn->state = BT_CLOSED;
Andre Guedes0c95ab72012-07-27 15:10:14 -03001830 mgmt_connect_failed(hdev, &conn->dst, conn->type,
Andre Guedesf00a06a2012-07-27 15:10:13 -03001831 conn->dst_type, status);
1832 hci_proto_connect_cfm(conn, status);
1833 hci_conn_del(conn);
1834
1835 hci_dev_unlock(hdev);
1836 }
Ville Tervofcd89c02011-02-10 22:38:47 -03001837}
1838
Vinicius Costa Gomesa7a595f2011-06-09 18:50:47 -03001839static void hci_cs_le_start_enc(struct hci_dev *hdev, u8 status)
1840{
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +03001841 BT_DBG("%s status 0x%2.2x", hdev->name, status);
Vinicius Costa Gomesa7a595f2011-06-09 18:50:47 -03001842}
1843
Andrei Emeltchenkoa02226d2012-09-27 17:26:19 +03001844static void hci_cs_create_phylink(struct hci_dev *hdev, u8 status)
1845{
Andrei Emeltchenko93c284e2012-09-27 17:26:20 +03001846 struct hci_cp_create_phy_link *cp;
1847
Andrei Emeltchenkoa02226d2012-09-27 17:26:19 +03001848 BT_DBG("%s status 0x%2.2x", hdev->name, status);
Andrei Emeltchenko93c284e2012-09-27 17:26:20 +03001849
Andrei Emeltchenko93c284e2012-09-27 17:26:20 +03001850 cp = hci_sent_cmd_data(hdev, HCI_OP_CREATE_PHY_LINK);
1851 if (!cp)
1852 return;
1853
Andrei Emeltchenkoe58917b2012-10-31 15:46:33 +02001854 hci_dev_lock(hdev);
1855
1856 if (status) {
1857 struct hci_conn *hcon;
1858
1859 hcon = hci_conn_hash_lookup_handle(hdev, cp->phy_handle);
1860 if (hcon)
1861 hci_conn_del(hcon);
1862 } else {
1863 amp_write_remote_assoc(hdev, cp->phy_handle);
1864 }
1865
1866 hci_dev_unlock(hdev);
Andrei Emeltchenkoa02226d2012-09-27 17:26:19 +03001867}
1868
Andrei Emeltchenko0b26ab92012-09-27 17:26:24 +03001869static void hci_cs_accept_phylink(struct hci_dev *hdev, u8 status)
1870{
1871 struct hci_cp_accept_phy_link *cp;
1872
1873 BT_DBG("%s status 0x%2.2x", hdev->name, status);
1874
1875 if (status)
1876 return;
1877
1878 cp = hci_sent_cmd_data(hdev, HCI_OP_ACCEPT_PHY_LINK);
1879 if (!cp)
1880 return;
1881
1882 amp_write_remote_assoc(hdev, cp->phy_handle);
1883}
1884
Andrei Emeltchenko5ce66b52012-10-31 15:46:30 +02001885static void hci_cs_create_logical_link(struct hci_dev *hdev, u8 status)
1886{
1887 BT_DBG("%s status 0x%2.2x", hdev->name, status);
1888}
1889
Gustavo Padovan6039aa72012-05-23 04:04:18 -03001890static void hci_inquiry_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001891{
1892 __u8 status = *((__u8 *) skb->data);
Johan Hedberg30dc78e2012-01-04 15:44:20 +02001893 struct discovery_state *discov = &hdev->discovery;
1894 struct inquiry_entry *e;
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001895
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +03001896 BT_DBG("%s status 0x%2.2x", hdev->name, status);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001897
Johan Hedberg23bb5762010-12-21 23:01:27 +02001898 hci_req_complete(hdev, HCI_OP_INQUIRY, status);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001899
1900 hci_conn_check_pending(hdev);
Andre Guedes89352e72011-11-04 14:16:53 -03001901
1902 if (!test_and_clear_bit(HCI_INQUIRY, &hdev->flags))
1903 return;
1904
Johan Hedberga8b2d5c2012-01-08 23:11:15 +02001905 if (!test_bit(HCI_MGMT, &hdev->dev_flags))
Johan Hedberg30dc78e2012-01-04 15:44:20 +02001906 return;
1907
Johan Hedberg56e5cb82011-11-08 20:40:16 +02001908 hci_dev_lock(hdev);
Johan Hedberg30dc78e2012-01-04 15:44:20 +02001909
Andre Guedes343f9352012-02-17 20:39:37 -03001910 if (discov->state != DISCOVERY_FINDING)
Johan Hedberg30dc78e2012-01-04 15:44:20 +02001911 goto unlock;
1912
1913 if (list_empty(&discov->resolve)) {
1914 hci_discovery_set_state(hdev, DISCOVERY_STOPPED);
1915 goto unlock;
1916 }
1917
1918 e = hci_inquiry_cache_lookup_resolve(hdev, BDADDR_ANY, NAME_NEEDED);
1919 if (e && hci_resolve_name(hdev, e) == 0) {
1920 e->name_state = NAME_PENDING;
1921 hci_discovery_set_state(hdev, DISCOVERY_RESOLVING);
1922 } else {
1923 hci_discovery_set_state(hdev, DISCOVERY_STOPPED);
1924 }
1925
1926unlock:
Johan Hedberg56e5cb82011-11-08 20:40:16 +02001927 hci_dev_unlock(hdev);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001928}
1929
Gustavo Padovan6039aa72012-05-23 04:04:18 -03001930static void hci_inquiry_result_evt(struct hci_dev *hdev, struct sk_buff *skb)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001931{
Marcel Holtmann45bb4bf2005-08-09 20:27:49 -07001932 struct inquiry_data data;
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001933 struct inquiry_info *info = (void *) (skb->data + 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001934 int num_rsp = *((__u8 *) skb->data);
1935
1936 BT_DBG("%s num_rsp %d", hdev->name, num_rsp);
1937
Marcel Holtmann45bb4bf2005-08-09 20:27:49 -07001938 if (!num_rsp)
1939 return;
1940
Andre Guedes1519cc12012-03-21 00:03:38 -03001941 if (test_bit(HCI_PERIODIC_INQ, &hdev->dev_flags))
1942 return;
1943
Linus Torvalds1da177e2005-04-16 15:20:36 -07001944 hci_dev_lock(hdev);
Marcel Holtmann45bb4bf2005-08-09 20:27:49 -07001945
Johan Hedberge17acd42011-03-30 23:57:16 +03001946 for (; num_rsp; num_rsp--, info++) {
Johan Hedberg388fc8f2012-02-23 00:38:59 +02001947 bool name_known, ssp;
Johan Hedberg31754052012-01-04 13:39:52 +02001948
Linus Torvalds1da177e2005-04-16 15:20:36 -07001949 bacpy(&data.bdaddr, &info->bdaddr);
1950 data.pscan_rep_mode = info->pscan_rep_mode;
1951 data.pscan_period_mode = info->pscan_period_mode;
1952 data.pscan_mode = info->pscan_mode;
1953 memcpy(data.dev_class, info->dev_class, 3);
1954 data.clock_offset = info->clock_offset;
1955 data.rssi = 0x00;
Marcel Holtmann41a96212008-07-14 20:13:48 +02001956 data.ssp_mode = 0x00;
Johan Hedberg31754052012-01-04 13:39:52 +02001957
Johan Hedberg388fc8f2012-02-23 00:38:59 +02001958 name_known = hci_inquiry_cache_update(hdev, &data, false, &ssp);
Johan Hedberg48264f02011-11-09 13:58:58 +02001959 mgmt_device_found(hdev, &info->bdaddr, ACL_LINK, 0x00,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001960 info->dev_class, 0, !name_known, ssp, NULL,
1961 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001962 }
Marcel Holtmann45bb4bf2005-08-09 20:27:49 -07001963
Linus Torvalds1da177e2005-04-16 15:20:36 -07001964 hci_dev_unlock(hdev);
1965}
1966
Gustavo Padovan6039aa72012-05-23 04:04:18 -03001967static void hci_conn_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001968{
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001969 struct hci_ev_conn_complete *ev = (void *) skb->data;
1970 struct hci_conn *conn;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001971
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001972 BT_DBG("%s", hdev->name);
Marcel Holtmann45bb4bf2005-08-09 20:27:49 -07001973
Linus Torvalds1da177e2005-04-16 15:20:36 -07001974 hci_dev_lock(hdev);
Marcel Holtmann45bb4bf2005-08-09 20:27:49 -07001975
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001976 conn = hci_conn_hash_lookup_ba(hdev, ev->link_type, &ev->bdaddr);
Marcel Holtmann94992372009-04-19 19:30:03 +02001977 if (!conn) {
1978 if (ev->link_type != SCO_LINK)
1979 goto unlock;
1980
1981 conn = hci_conn_hash_lookup_ba(hdev, ESCO_LINK, &ev->bdaddr);
1982 if (!conn)
1983 goto unlock;
1984
1985 conn->type = SCO_LINK;
1986 }
Marcel Holtmann45bb4bf2005-08-09 20:27:49 -07001987
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001988 if (!ev->status) {
1989 conn->handle = __le16_to_cpu(ev->handle);
Marcel Holtmann769be972008-07-14 20:13:49 +02001990
1991 if (conn->type == ACL_LINK) {
1992 conn->state = BT_CONFIG;
1993 hci_conn_hold(conn);
Szymon Janca9ea3ed2012-07-19 14:46:08 +02001994
1995 if (!conn->out && !hci_conn_ssp_enabled(conn) &&
1996 !hci_find_link_key(hdev, &ev->bdaddr))
1997 conn->disc_timeout = HCI_PAIRING_TIMEOUT;
1998 else
1999 conn->disc_timeout = HCI_DISCONN_TIMEOUT;
Marcel Holtmann769be972008-07-14 20:13:49 +02002000 } else
2001 conn->state = BT_CONNECTED;
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002002
Marcel Holtmann9eba32b2009-08-22 14:19:26 -07002003 hci_conn_hold_device(conn);
Marcel Holtmann7d0db0a2008-07-14 20:13:51 +02002004 hci_conn_add_sysfs(conn);
2005
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002006 if (test_bit(HCI_AUTH, &hdev->flags))
2007 conn->link_mode |= HCI_LM_AUTH;
2008
2009 if (test_bit(HCI_ENCRYPT, &hdev->flags))
2010 conn->link_mode |= HCI_LM_ENCRYPT;
2011
2012 /* Get remote features */
2013 if (conn->type == ACL_LINK) {
2014 struct hci_cp_read_remote_features cp;
2015 cp.handle = ev->handle;
Marcel Holtmann769be972008-07-14 20:13:49 +02002016 hci_send_cmd(hdev, HCI_OP_READ_REMOTE_FEATURES,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002017 sizeof(cp), &cp);
Marcel Holtmann45bb4bf2005-08-09 20:27:49 -07002018 }
Marcel Holtmann45bb4bf2005-08-09 20:27:49 -07002019
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002020 /* Set packet type for incoming connection */
Andrei Emeltchenkod095c1e2011-12-01 14:33:27 +02002021 if (!conn->out && hdev->hci_ver < BLUETOOTH_VER_2_0) {
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002022 struct hci_cp_change_conn_ptype cp;
2023 cp.handle = ev->handle;
Marcel Holtmanna8746412008-07-14 20:13:46 +02002024 cp.pkt_type = cpu_to_le16(conn->pkt_type);
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002025 hci_send_cmd(hdev, HCI_OP_CHANGE_CONN_PTYPE, sizeof(cp),
2026 &cp);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002027 }
Johan Hedberg17d5c042011-01-22 06:09:08 +02002028 } else {
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002029 conn->state = BT_CLOSED;
Johan Hedberg17d5c042011-01-22 06:09:08 +02002030 if (conn->type == ACL_LINK)
Johan Hedberg744cf192011-11-08 20:40:14 +02002031 mgmt_connect_failed(hdev, &ev->bdaddr, conn->type,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002032 conn->dst_type, ev->status);
Johan Hedberg17d5c042011-01-22 06:09:08 +02002033 }
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002034
Marcel Holtmanne73439d2010-07-26 10:06:00 -04002035 if (conn->type == ACL_LINK)
2036 hci_sco_setup(conn, ev->status);
Marcel Holtmann45bb4bf2005-08-09 20:27:49 -07002037
Marcel Holtmann769be972008-07-14 20:13:49 +02002038 if (ev->status) {
2039 hci_proto_connect_cfm(conn, ev->status);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002040 hci_conn_del(conn);
Marcel Holtmannc89b6e62009-01-15 21:57:03 +01002041 } else if (ev->link_type != ACL_LINK)
2042 hci_proto_connect_cfm(conn, ev->status);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002043
2044unlock:
Linus Torvalds1da177e2005-04-16 15:20:36 -07002045 hci_dev_unlock(hdev);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002046
2047 hci_conn_check_pending(hdev);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002048}
2049
Gustavo Padovan6039aa72012-05-23 04:04:18 -03002050static void hci_conn_request_evt(struct hci_dev *hdev, struct sk_buff *skb)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002051{
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002052 struct hci_ev_conn_request *ev = (void *) skb->data;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002053 int mask = hdev->link_mode;
2054
Andrei Emeltchenko6ed93dc2012-09-25 12:49:43 +03002055 BT_DBG("%s bdaddr %pMR type 0x%x", hdev->name, &ev->bdaddr,
Gustavo Padovan807deac2012-05-17 00:36:24 -03002056 ev->link_type);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002057
2058 mask |= hci_proto_connect_ind(hdev, &ev->bdaddr, ev->link_type);
2059
Szymon Janc138d22e2011-02-17 16:44:23 +01002060 if ((mask & HCI_LM_ACCEPT) &&
Gustavo Padovan807deac2012-05-17 00:36:24 -03002061 !hci_blacklist_lookup(hdev, &ev->bdaddr)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002062 /* Connection accepted */
Marcel Holtmannc7bdd502008-07-14 20:13:47 +02002063 struct inquiry_entry *ie;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002064 struct hci_conn *conn;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002065
2066 hci_dev_lock(hdev);
Marcel Holtmannb6a0dc82007-10-20 14:55:10 +02002067
Andrei Emeltchenkocc11b9c2010-11-22 13:21:37 +02002068 ie = hci_inquiry_cache_lookup(hdev, &ev->bdaddr);
2069 if (ie)
Marcel Holtmannc7bdd502008-07-14 20:13:47 +02002070 memcpy(ie->data.dev_class, ev->dev_class, 3);
2071
Gustavo Padovan8fc9ced2012-05-23 04:04:21 -03002072 conn = hci_conn_hash_lookup_ba(hdev, ev->link_type,
2073 &ev->bdaddr);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002074 if (!conn) {
Andrei Emeltchenkocc11b9c2010-11-22 13:21:37 +02002075 conn = hci_conn_add(hdev, ev->link_type, &ev->bdaddr);
2076 if (!conn) {
Gustavo F. Padovan893ef972010-07-18 15:13:37 -03002077 BT_ERR("No memory for new connection");
Linus Torvalds1da177e2005-04-16 15:20:36 -07002078 hci_dev_unlock(hdev);
2079 return;
2080 }
2081 }
Marcel Holtmannb6a0dc82007-10-20 14:55:10 +02002082
Linus Torvalds1da177e2005-04-16 15:20:36 -07002083 memcpy(conn->dev_class, ev->dev_class, 3);
2084 conn->state = BT_CONNECT;
Marcel Holtmannb6a0dc82007-10-20 14:55:10 +02002085
Linus Torvalds1da177e2005-04-16 15:20:36 -07002086 hci_dev_unlock(hdev);
2087
Marcel Holtmannb6a0dc82007-10-20 14:55:10 +02002088 if (ev->link_type == ACL_LINK || !lmp_esco_capable(hdev)) {
2089 struct hci_cp_accept_conn_req cp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002090
Marcel Holtmannb6a0dc82007-10-20 14:55:10 +02002091 bacpy(&cp.bdaddr, &ev->bdaddr);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002092
Marcel Holtmannb6a0dc82007-10-20 14:55:10 +02002093 if (lmp_rswitch_capable(hdev) && (mask & HCI_LM_MASTER))
2094 cp.role = 0x00; /* Become master */
2095 else
2096 cp.role = 0x01; /* Remain slave */
2097
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002098 hci_send_cmd(hdev, HCI_OP_ACCEPT_CONN_REQ, sizeof(cp),
2099 &cp);
Marcel Holtmannb6a0dc82007-10-20 14:55:10 +02002100 } else {
2101 struct hci_cp_accept_sync_conn_req cp;
2102
2103 bacpy(&cp.bdaddr, &ev->bdaddr);
Marcel Holtmanna8746412008-07-14 20:13:46 +02002104 cp.pkt_type = cpu_to_le16(conn->pkt_type);
Marcel Holtmannb6a0dc82007-10-20 14:55:10 +02002105
Andrei Emeltchenko82781e62012-05-25 11:38:27 +03002106 cp.tx_bandwidth = __constant_cpu_to_le32(0x00001f40);
2107 cp.rx_bandwidth = __constant_cpu_to_le32(0x00001f40);
2108 cp.max_latency = __constant_cpu_to_le16(0xffff);
Marcel Holtmannb6a0dc82007-10-20 14:55:10 +02002109 cp.content_format = cpu_to_le16(hdev->voice_setting);
2110 cp.retrans_effort = 0xff;
2111
2112 hci_send_cmd(hdev, HCI_OP_ACCEPT_SYNC_CONN_REQ,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002113 sizeof(cp), &cp);
Marcel Holtmannb6a0dc82007-10-20 14:55:10 +02002114 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002115 } else {
2116 /* Connection rejected */
2117 struct hci_cp_reject_conn_req cp;
2118
2119 bacpy(&cp.bdaddr, &ev->bdaddr);
Andrei Emeltchenko9f5a0d72011-11-07 14:20:25 +02002120 cp.reason = HCI_ERROR_REJ_BAD_ADDR;
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002121 hci_send_cmd(hdev, HCI_OP_REJECT_CONN_REQ, sizeof(cp), &cp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002122 }
2123}
2124
Mikel Astizf0d6a0e2012-08-09 09:52:30 +02002125static u8 hci_to_mgmt_reason(u8 err)
2126{
2127 switch (err) {
2128 case HCI_ERROR_CONNECTION_TIMEOUT:
2129 return MGMT_DEV_DISCONN_TIMEOUT;
2130 case HCI_ERROR_REMOTE_USER_TERM:
2131 case HCI_ERROR_REMOTE_LOW_RESOURCES:
2132 case HCI_ERROR_REMOTE_POWER_OFF:
2133 return MGMT_DEV_DISCONN_REMOTE;
2134 case HCI_ERROR_LOCAL_HOST_TERM:
2135 return MGMT_DEV_DISCONN_LOCAL_HOST;
2136 default:
2137 return MGMT_DEV_DISCONN_UNKNOWN;
2138 }
2139}
2140
Gustavo Padovan6039aa72012-05-23 04:04:18 -03002141static void hci_disconn_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002142{
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002143 struct hci_ev_disconn_complete *ev = (void *) skb->data;
Marcel Holtmann04837f62006-07-03 10:02:33 +02002144 struct hci_conn *conn;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002145
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +03002146 BT_DBG("%s status 0x%2.2x", hdev->name, ev->status);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002147
Linus Torvalds1da177e2005-04-16 15:20:36 -07002148 hci_dev_lock(hdev);
2149
Marcel Holtmann04837f62006-07-03 10:02:33 +02002150 conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
Johan Hedbergf7520542011-01-20 12:34:39 +02002151 if (!conn)
2152 goto unlock;
Marcel Holtmann7d0db0a2008-07-14 20:13:51 +02002153
Johan Hedberg37d9ef72011-11-10 15:54:39 +02002154 if (ev->status == 0)
2155 conn->state = BT_CLOSED;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002156
Johan Hedbergb644ba32012-01-17 21:48:47 +02002157 if (test_and_clear_bit(HCI_CONN_MGMT_CONNECTED, &conn->flags) &&
Gustavo Padovan807deac2012-05-17 00:36:24 -03002158 (conn->type == ACL_LINK || conn->type == LE_LINK)) {
Mikel Astizf0d6a0e2012-08-09 09:52:30 +02002159 if (ev->status) {
Johan Hedberg88c3df12012-02-09 14:27:38 +02002160 mgmt_disconnect_failed(hdev, &conn->dst, conn->type,
Gustavo Padovan807deac2012-05-17 00:36:24 -03002161 conn->dst_type, ev->status);
Mikel Astizf0d6a0e2012-08-09 09:52:30 +02002162 } else {
2163 u8 reason = hci_to_mgmt_reason(ev->reason);
2164
Johan Hedbergafc747a2012-01-15 18:11:07 +02002165 mgmt_device_disconnected(hdev, &conn->dst, conn->type,
Mikel Astizf0d6a0e2012-08-09 09:52:30 +02002166 conn->dst_type, reason);
2167 }
Johan Hedberg37d9ef72011-11-10 15:54:39 +02002168 }
Johan Hedbergf7520542011-01-20 12:34:39 +02002169
Johan Hedberg37d9ef72011-11-10 15:54:39 +02002170 if (ev->status == 0) {
Vishal Agarwal6ec5bca2012-04-16 14:44:44 +05302171 if (conn->type == ACL_LINK && conn->flush_key)
2172 hci_remove_link_key(hdev, &conn->dst);
Johan Hedberg37d9ef72011-11-10 15:54:39 +02002173 hci_proto_disconn_cfm(conn, ev->reason);
2174 hci_conn_del(conn);
2175 }
Johan Hedbergf7520542011-01-20 12:34:39 +02002176
2177unlock:
Linus Torvalds1da177e2005-04-16 15:20:36 -07002178 hci_dev_unlock(hdev);
2179}
2180
Gustavo Padovan6039aa72012-05-23 04:04:18 -03002181static void hci_auth_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002182{
2183 struct hci_ev_auth_complete *ev = (void *) skb->data;
2184 struct hci_conn *conn;
2185
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +03002186 BT_DBG("%s status 0x%2.2x", hdev->name, ev->status);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002187
2188 hci_dev_lock(hdev);
2189
2190 conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
Waldemar Rymarkiewiczd7556e22011-05-31 15:49:26 +02002191 if (!conn)
2192 goto unlock;
2193
2194 if (!ev->status) {
Johan Hedbergaa64a8b2012-01-18 21:33:12 +02002195 if (!hci_conn_ssp_enabled(conn) &&
Gustavo Padovan807deac2012-05-17 00:36:24 -03002196 test_bit(HCI_CONN_REAUTH_PEND, &conn->flags)) {
Waldemar Rymarkiewiczd7556e22011-05-31 15:49:26 +02002197 BT_INFO("re-auth of legacy device is not possible.");
Johan Hedberg2a611692011-02-19 12:06:00 -03002198 } else {
Waldemar Rymarkiewiczd7556e22011-05-31 15:49:26 +02002199 conn->link_mode |= HCI_LM_AUTH;
2200 conn->sec_level = conn->pending_sec_level;
Johan Hedberg2a611692011-02-19 12:06:00 -03002201 }
Waldemar Rymarkiewiczd7556e22011-05-31 15:49:26 +02002202 } else {
Johan Hedbergbab73cb2012-02-09 16:07:29 +02002203 mgmt_auth_failed(hdev, &conn->dst, conn->type, conn->dst_type,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002204 ev->status);
Waldemar Rymarkiewiczd7556e22011-05-31 15:49:26 +02002205 }
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002206
Johan Hedberg51a8efd2012-01-16 06:10:31 +02002207 clear_bit(HCI_CONN_AUTH_PEND, &conn->flags);
2208 clear_bit(HCI_CONN_REAUTH_PEND, &conn->flags);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002209
Waldemar Rymarkiewiczd7556e22011-05-31 15:49:26 +02002210 if (conn->state == BT_CONFIG) {
Johan Hedbergaa64a8b2012-01-18 21:33:12 +02002211 if (!ev->status && hci_conn_ssp_enabled(conn)) {
Waldemar Rymarkiewiczd7556e22011-05-31 15:49:26 +02002212 struct hci_cp_set_conn_encrypt cp;
2213 cp.handle = ev->handle;
2214 cp.encrypt = 0x01;
2215 hci_send_cmd(hdev, HCI_OP_SET_CONN_ENCRYPT, sizeof(cp),
Gustavo Padovan807deac2012-05-17 00:36:24 -03002216 &cp);
Marcel Holtmann052b30b2009-04-26 20:01:22 +02002217 } else {
Waldemar Rymarkiewiczd7556e22011-05-31 15:49:26 +02002218 conn->state = BT_CONNECTED;
2219 hci_proto_connect_cfm(conn, ev->status);
Marcel Holtmann052b30b2009-04-26 20:01:22 +02002220 hci_conn_put(conn);
2221 }
Waldemar Rymarkiewiczd7556e22011-05-31 15:49:26 +02002222 } else {
2223 hci_auth_cfm(conn, ev->status);
Marcel Holtmann052b30b2009-04-26 20:01:22 +02002224
Waldemar Rymarkiewiczd7556e22011-05-31 15:49:26 +02002225 hci_conn_hold(conn);
2226 conn->disc_timeout = HCI_DISCONN_TIMEOUT;
2227 hci_conn_put(conn);
2228 }
2229
Johan Hedberg51a8efd2012-01-16 06:10:31 +02002230 if (test_bit(HCI_CONN_ENCRYPT_PEND, &conn->flags)) {
Waldemar Rymarkiewiczd7556e22011-05-31 15:49:26 +02002231 if (!ev->status) {
2232 struct hci_cp_set_conn_encrypt cp;
2233 cp.handle = ev->handle;
2234 cp.encrypt = 0x01;
2235 hci_send_cmd(hdev, HCI_OP_SET_CONN_ENCRYPT, sizeof(cp),
Gustavo Padovan807deac2012-05-17 00:36:24 -03002236 &cp);
Waldemar Rymarkiewiczd7556e22011-05-31 15:49:26 +02002237 } else {
Johan Hedberg51a8efd2012-01-16 06:10:31 +02002238 clear_bit(HCI_CONN_ENCRYPT_PEND, &conn->flags);
Waldemar Rymarkiewiczd7556e22011-05-31 15:49:26 +02002239 hci_encrypt_cfm(conn, ev->status, 0x00);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002240 }
2241 }
2242
Waldemar Rymarkiewiczd7556e22011-05-31 15:49:26 +02002243unlock:
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002244 hci_dev_unlock(hdev);
2245}
2246
Gustavo Padovan6039aa72012-05-23 04:04:18 -03002247static void hci_remote_name_evt(struct hci_dev *hdev, struct sk_buff *skb)
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002248{
Johan Hedberg127178d2010-11-18 22:22:29 +02002249 struct hci_ev_remote_name *ev = (void *) skb->data;
2250 struct hci_conn *conn;
2251
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002252 BT_DBG("%s", hdev->name);
2253
2254 hci_conn_check_pending(hdev);
Johan Hedberg127178d2010-11-18 22:22:29 +02002255
2256 hci_dev_lock(hdev);
2257
2258 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
Johan Hedbergb644ba32012-01-17 21:48:47 +02002259
2260 if (!test_bit(HCI_MGMT, &hdev->dev_flags))
2261 goto check_auth;
2262
2263 if (ev->status == 0)
2264 hci_check_pending_name(hdev, conn, &ev->bdaddr, ev->name,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002265 strnlen(ev->name, HCI_MAX_NAME_LENGTH));
Johan Hedbergb644ba32012-01-17 21:48:47 +02002266 else
2267 hci_check_pending_name(hdev, conn, &ev->bdaddr, NULL, 0);
2268
2269check_auth:
Johan Hedberg79c6c702011-04-28 11:28:55 -07002270 if (!conn)
2271 goto unlock;
2272
2273 if (!hci_outgoing_auth_needed(hdev, conn))
2274 goto unlock;
2275
Johan Hedberg51a8efd2012-01-16 06:10:31 +02002276 if (!test_and_set_bit(HCI_CONN_AUTH_PEND, &conn->flags)) {
Johan Hedberg127178d2010-11-18 22:22:29 +02002277 struct hci_cp_auth_requested cp;
2278 cp.handle = __cpu_to_le16(conn->handle);
2279 hci_send_cmd(hdev, HCI_OP_AUTH_REQUESTED, sizeof(cp), &cp);
2280 }
2281
Johan Hedberg79c6c702011-04-28 11:28:55 -07002282unlock:
Johan Hedberg127178d2010-11-18 22:22:29 +02002283 hci_dev_unlock(hdev);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002284}
2285
Gustavo Padovan6039aa72012-05-23 04:04:18 -03002286static void hci_encrypt_change_evt(struct hci_dev *hdev, struct sk_buff *skb)
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002287{
2288 struct hci_ev_encrypt_change *ev = (void *) skb->data;
2289 struct hci_conn *conn;
2290
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +03002291 BT_DBG("%s status 0x%2.2x", hdev->name, ev->status);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002292
2293 hci_dev_lock(hdev);
2294
2295 conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
2296 if (conn) {
2297 if (!ev->status) {
Marcel Holtmannae293192008-07-14 20:13:45 +02002298 if (ev->encrypt) {
2299 /* Encryption implies authentication */
2300 conn->link_mode |= HCI_LM_AUTH;
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002301 conn->link_mode |= HCI_LM_ENCRYPT;
Vinicius Costa Gomesda85e5e2011-06-09 18:50:53 -03002302 conn->sec_level = conn->pending_sec_level;
Marcel Holtmannae293192008-07-14 20:13:45 +02002303 } else
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002304 conn->link_mode &= ~HCI_LM_ENCRYPT;
2305 }
2306
Johan Hedberg51a8efd2012-01-16 06:10:31 +02002307 clear_bit(HCI_CONN_ENCRYPT_PEND, &conn->flags);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002308
Gustavo Padovana7d77232012-05-13 03:20:07 -03002309 if (ev->status && conn->state == BT_CONNECTED) {
Gustavo Padovand839c812012-05-16 12:17:12 -03002310 hci_acl_disconn(conn, HCI_ERROR_AUTH_FAILURE);
Gustavo Padovana7d77232012-05-13 03:20:07 -03002311 hci_conn_put(conn);
2312 goto unlock;
2313 }
2314
Marcel Holtmannf8558552008-07-14 20:13:49 +02002315 if (conn->state == BT_CONFIG) {
2316 if (!ev->status)
2317 conn->state = BT_CONNECTED;
2318
2319 hci_proto_connect_cfm(conn, ev->status);
2320 hci_conn_put(conn);
2321 } else
2322 hci_encrypt_cfm(conn, ev->status, ev->encrypt);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002323 }
2324
Gustavo Padovana7d77232012-05-13 03:20:07 -03002325unlock:
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002326 hci_dev_unlock(hdev);
2327}
2328
Gustavo Padovan6039aa72012-05-23 04:04:18 -03002329static void hci_change_link_key_complete_evt(struct hci_dev *hdev,
2330 struct sk_buff *skb)
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002331{
2332 struct hci_ev_change_link_key_complete *ev = (void *) skb->data;
2333 struct hci_conn *conn;
2334
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +03002335 BT_DBG("%s status 0x%2.2x", hdev->name, ev->status);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002336
2337 hci_dev_lock(hdev);
2338
2339 conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
2340 if (conn) {
2341 if (!ev->status)
2342 conn->link_mode |= HCI_LM_SECURE;
2343
Johan Hedberg51a8efd2012-01-16 06:10:31 +02002344 clear_bit(HCI_CONN_AUTH_PEND, &conn->flags);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002345
2346 hci_key_change_cfm(conn, ev->status);
2347 }
2348
2349 hci_dev_unlock(hdev);
2350}
2351
Gustavo Padovan6039aa72012-05-23 04:04:18 -03002352static void hci_remote_features_evt(struct hci_dev *hdev,
2353 struct sk_buff *skb)
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002354{
2355 struct hci_ev_remote_features *ev = (void *) skb->data;
2356 struct hci_conn *conn;
2357
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +03002358 BT_DBG("%s status 0x%2.2x", hdev->name, ev->status);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002359
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002360 hci_dev_lock(hdev);
2361
2362 conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
Johan Hedbergccd556f2010-11-10 17:11:51 +02002363 if (!conn)
2364 goto unlock;
Marcel Holtmann769be972008-07-14 20:13:49 +02002365
Johan Hedbergccd556f2010-11-10 17:11:51 +02002366 if (!ev->status)
2367 memcpy(conn->features, ev->features, 8);
2368
2369 if (conn->state != BT_CONFIG)
2370 goto unlock;
2371
2372 if (!ev->status && lmp_ssp_capable(hdev) && lmp_ssp_capable(conn)) {
2373 struct hci_cp_read_remote_ext_features cp;
2374 cp.handle = ev->handle;
2375 cp.page = 0x01;
2376 hci_send_cmd(hdev, HCI_OP_READ_REMOTE_EXT_FEATURES,
Gustavo Padovan807deac2012-05-17 00:36:24 -03002377 sizeof(cp), &cp);
Johan Hedberg392599b2010-11-18 22:22:28 +02002378 goto unlock;
2379 }
2380
Johan Hedberg671267b2012-05-12 16:11:50 -03002381 if (!ev->status && !test_bit(HCI_CONN_MGMT_CONNECTED, &conn->flags)) {
Johan Hedberg127178d2010-11-18 22:22:29 +02002382 struct hci_cp_remote_name_req cp;
2383 memset(&cp, 0, sizeof(cp));
2384 bacpy(&cp.bdaddr, &conn->dst);
2385 cp.pscan_rep_mode = 0x02;
2386 hci_send_cmd(hdev, HCI_OP_REMOTE_NAME_REQ, sizeof(cp), &cp);
Johan Hedbergb644ba32012-01-17 21:48:47 +02002387 } else if (!test_and_set_bit(HCI_CONN_MGMT_CONNECTED, &conn->flags))
2388 mgmt_device_connected(hdev, &conn->dst, conn->type,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002389 conn->dst_type, 0, NULL, 0,
2390 conn->dev_class);
Johan Hedberg392599b2010-11-18 22:22:28 +02002391
Johan Hedberg127178d2010-11-18 22:22:29 +02002392 if (!hci_outgoing_auth_needed(hdev, conn)) {
Johan Hedbergccd556f2010-11-10 17:11:51 +02002393 conn->state = BT_CONNECTED;
2394 hci_proto_connect_cfm(conn, ev->status);
2395 hci_conn_put(conn);
Marcel Holtmann769be972008-07-14 20:13:49 +02002396 }
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002397
Johan Hedbergccd556f2010-11-10 17:11:51 +02002398unlock:
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002399 hci_dev_unlock(hdev);
2400}
2401
Gustavo Padovan6039aa72012-05-23 04:04:18 -03002402static void hci_remote_version_evt(struct hci_dev *hdev, struct sk_buff *skb)
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002403{
2404 BT_DBG("%s", hdev->name);
2405}
2406
Gustavo Padovan6039aa72012-05-23 04:04:18 -03002407static void hci_qos_setup_complete_evt(struct hci_dev *hdev,
2408 struct sk_buff *skb)
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002409{
2410 BT_DBG("%s", hdev->name);
2411}
2412
Gustavo Padovan6039aa72012-05-23 04:04:18 -03002413static void hci_cmd_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002414{
2415 struct hci_ev_cmd_complete *ev = (void *) skb->data;
2416 __u16 opcode;
2417
2418 skb_pull(skb, sizeof(*ev));
2419
2420 opcode = __le16_to_cpu(ev->opcode);
2421
2422 switch (opcode) {
2423 case HCI_OP_INQUIRY_CANCEL:
2424 hci_cc_inquiry_cancel(hdev, skb);
2425 break;
2426
Andre Guedes4d934832012-03-21 00:03:35 -03002427 case HCI_OP_PERIODIC_INQ:
2428 hci_cc_periodic_inq(hdev, skb);
2429 break;
2430
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002431 case HCI_OP_EXIT_PERIODIC_INQ:
2432 hci_cc_exit_periodic_inq(hdev, skb);
2433 break;
2434
2435 case HCI_OP_REMOTE_NAME_REQ_CANCEL:
2436 hci_cc_remote_name_req_cancel(hdev, skb);
2437 break;
2438
2439 case HCI_OP_ROLE_DISCOVERY:
2440 hci_cc_role_discovery(hdev, skb);
2441 break;
2442
Marcel Holtmanne4e8e372008-07-14 20:13:47 +02002443 case HCI_OP_READ_LINK_POLICY:
2444 hci_cc_read_link_policy(hdev, skb);
2445 break;
2446
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002447 case HCI_OP_WRITE_LINK_POLICY:
2448 hci_cc_write_link_policy(hdev, skb);
2449 break;
2450
Marcel Holtmanne4e8e372008-07-14 20:13:47 +02002451 case HCI_OP_READ_DEF_LINK_POLICY:
2452 hci_cc_read_def_link_policy(hdev, skb);
2453 break;
2454
2455 case HCI_OP_WRITE_DEF_LINK_POLICY:
2456 hci_cc_write_def_link_policy(hdev, skb);
2457 break;
2458
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002459 case HCI_OP_RESET:
2460 hci_cc_reset(hdev, skb);
2461 break;
2462
2463 case HCI_OP_WRITE_LOCAL_NAME:
2464 hci_cc_write_local_name(hdev, skb);
2465 break;
2466
2467 case HCI_OP_READ_LOCAL_NAME:
2468 hci_cc_read_local_name(hdev, skb);
2469 break;
2470
2471 case HCI_OP_WRITE_AUTH_ENABLE:
2472 hci_cc_write_auth_enable(hdev, skb);
2473 break;
2474
2475 case HCI_OP_WRITE_ENCRYPT_MODE:
2476 hci_cc_write_encrypt_mode(hdev, skb);
2477 break;
2478
2479 case HCI_OP_WRITE_SCAN_ENABLE:
2480 hci_cc_write_scan_enable(hdev, skb);
2481 break;
2482
2483 case HCI_OP_READ_CLASS_OF_DEV:
2484 hci_cc_read_class_of_dev(hdev, skb);
2485 break;
2486
2487 case HCI_OP_WRITE_CLASS_OF_DEV:
2488 hci_cc_write_class_of_dev(hdev, skb);
2489 break;
2490
2491 case HCI_OP_READ_VOICE_SETTING:
2492 hci_cc_read_voice_setting(hdev, skb);
2493 break;
2494
2495 case HCI_OP_WRITE_VOICE_SETTING:
2496 hci_cc_write_voice_setting(hdev, skb);
2497 break;
2498
2499 case HCI_OP_HOST_BUFFER_SIZE:
2500 hci_cc_host_buffer_size(hdev, skb);
2501 break;
2502
Marcel Holtmann333140b2008-07-14 20:13:48 +02002503 case HCI_OP_WRITE_SSP_MODE:
2504 hci_cc_write_ssp_mode(hdev, skb);
2505 break;
2506
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002507 case HCI_OP_READ_LOCAL_VERSION:
2508 hci_cc_read_local_version(hdev, skb);
2509 break;
2510
2511 case HCI_OP_READ_LOCAL_COMMANDS:
2512 hci_cc_read_local_commands(hdev, skb);
2513 break;
2514
2515 case HCI_OP_READ_LOCAL_FEATURES:
2516 hci_cc_read_local_features(hdev, skb);
2517 break;
2518
Andre Guedes971e3a42011-06-30 19:20:52 -03002519 case HCI_OP_READ_LOCAL_EXT_FEATURES:
2520 hci_cc_read_local_ext_features(hdev, skb);
2521 break;
2522
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002523 case HCI_OP_READ_BUFFER_SIZE:
2524 hci_cc_read_buffer_size(hdev, skb);
2525 break;
2526
2527 case HCI_OP_READ_BD_ADDR:
2528 hci_cc_read_bd_addr(hdev, skb);
2529 break;
2530
Andrei Emeltchenko350ee4c2011-12-07 15:56:51 +02002531 case HCI_OP_READ_DATA_BLOCK_SIZE:
2532 hci_cc_read_data_block_size(hdev, skb);
2533 break;
2534
Johan Hedberg23bb5762010-12-21 23:01:27 +02002535 case HCI_OP_WRITE_CA_TIMEOUT:
2536 hci_cc_write_ca_timeout(hdev, skb);
2537 break;
2538
Andrei Emeltchenko1e89cff2011-11-24 14:52:02 +02002539 case HCI_OP_READ_FLOW_CONTROL_MODE:
2540 hci_cc_read_flow_control_mode(hdev, skb);
2541 break;
2542
Andrei Emeltchenko928abaa2011-10-12 10:53:57 +03002543 case HCI_OP_READ_LOCAL_AMP_INFO:
2544 hci_cc_read_local_amp_info(hdev, skb);
2545 break;
2546
Andrei Emeltchenko903e4542012-09-27 17:26:09 +03002547 case HCI_OP_READ_LOCAL_AMP_ASSOC:
2548 hci_cc_read_local_amp_assoc(hdev, skb);
2549 break;
2550
Johan Hedbergb0916ea2011-01-10 13:44:55 +02002551 case HCI_OP_DELETE_STORED_LINK_KEY:
2552 hci_cc_delete_stored_link_key(hdev, skb);
2553 break;
2554
Johan Hedbergd5859e22011-01-25 01:19:58 +02002555 case HCI_OP_SET_EVENT_MASK:
2556 hci_cc_set_event_mask(hdev, skb);
2557 break;
2558
2559 case HCI_OP_WRITE_INQUIRY_MODE:
2560 hci_cc_write_inquiry_mode(hdev, skb);
2561 break;
2562
2563 case HCI_OP_READ_INQ_RSP_TX_POWER:
2564 hci_cc_read_inq_rsp_tx_power(hdev, skb);
2565 break;
2566
2567 case HCI_OP_SET_EVENT_FLT:
2568 hci_cc_set_event_flt(hdev, skb);
2569 break;
2570
Johan Hedberg980e1a52011-01-22 06:10:07 +02002571 case HCI_OP_PIN_CODE_REPLY:
2572 hci_cc_pin_code_reply(hdev, skb);
2573 break;
2574
2575 case HCI_OP_PIN_CODE_NEG_REPLY:
2576 hci_cc_pin_code_neg_reply(hdev, skb);
2577 break;
2578
Szymon Jancc35938b2011-03-22 13:12:21 +01002579 case HCI_OP_READ_LOCAL_OOB_DATA:
2580 hci_cc_read_local_oob_data_reply(hdev, skb);
2581 break;
2582
Ville Tervo6ed58ec2011-02-10 22:38:48 -03002583 case HCI_OP_LE_READ_BUFFER_SIZE:
2584 hci_cc_le_read_buffer_size(hdev, skb);
2585 break;
2586
Johan Hedberg8fa19092012-10-19 20:57:49 +03002587 case HCI_OP_LE_READ_ADV_TX_POWER:
2588 hci_cc_le_read_adv_tx_power(hdev, skb);
2589 break;
2590
Johan Hedberge36b04c2012-10-19 20:57:47 +03002591 case HCI_OP_LE_SET_EVENT_MASK:
2592 hci_cc_le_set_event_mask(hdev, skb);
2593 break;
2594
Johan Hedberga5c29682011-02-19 12:05:57 -03002595 case HCI_OP_USER_CONFIRM_REPLY:
2596 hci_cc_user_confirm_reply(hdev, skb);
2597 break;
2598
2599 case HCI_OP_USER_CONFIRM_NEG_REPLY:
2600 hci_cc_user_confirm_neg_reply(hdev, skb);
2601 break;
2602
Brian Gix1143d452011-11-23 08:28:34 -08002603 case HCI_OP_USER_PASSKEY_REPLY:
2604 hci_cc_user_passkey_reply(hdev, skb);
2605 break;
2606
2607 case HCI_OP_USER_PASSKEY_NEG_REPLY:
2608 hci_cc_user_passkey_neg_reply(hdev, skb);
Szymon Janc16cde992012-04-13 12:32:42 +02002609 break;
Andre Guedes07f7fa52011-12-02 21:13:31 +09002610
2611 case HCI_OP_LE_SET_SCAN_PARAM:
2612 hci_cc_le_set_scan_param(hdev, skb);
Brian Gix1143d452011-11-23 08:28:34 -08002613 break;
2614
Johan Hedbergc1d5dc42012-11-08 01:23:01 +01002615 case HCI_OP_LE_SET_ADV_ENABLE:
2616 hci_cc_le_set_adv_enable(hdev, skb);
2617 break;
2618
Andre Guedeseb9d91f2011-05-26 16:23:52 -03002619 case HCI_OP_LE_SET_SCAN_ENABLE:
2620 hci_cc_le_set_scan_enable(hdev, skb);
2621 break;
2622
Vinicius Costa Gomesa7a595f2011-06-09 18:50:47 -03002623 case HCI_OP_LE_LTK_REPLY:
2624 hci_cc_le_ltk_reply(hdev, skb);
2625 break;
2626
2627 case HCI_OP_LE_LTK_NEG_REPLY:
2628 hci_cc_le_ltk_neg_reply(hdev, skb);
2629 break;
2630
Andre Guedesf9b49302011-06-30 19:20:53 -03002631 case HCI_OP_WRITE_LE_HOST_SUPPORTED:
2632 hci_cc_write_le_host_supported(hdev, skb);
2633 break;
2634
Andrei Emeltchenko93c284e2012-09-27 17:26:20 +03002635 case HCI_OP_WRITE_REMOTE_AMP_ASSOC:
2636 hci_cc_write_remote_amp_assoc(hdev, skb);
2637 break;
2638
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002639 default:
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +03002640 BT_DBG("%s opcode 0x%4.4x", hdev->name, opcode);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002641 break;
2642 }
2643
Ville Tervo6bd32322011-02-16 16:32:41 +02002644 if (ev->opcode != HCI_OP_NOP)
2645 del_timer(&hdev->cmd_timer);
2646
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002647 if (ev->ncmd) {
2648 atomic_set(&hdev->cmd_cnt, 1);
2649 if (!skb_queue_empty(&hdev->cmd_q))
Gustavo F. Padovanc347b762011-12-14 23:53:47 -02002650 queue_work(hdev->workqueue, &hdev->cmd_work);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002651 }
2652}
2653
Gustavo Padovan6039aa72012-05-23 04:04:18 -03002654static void hci_cmd_status_evt(struct hci_dev *hdev, struct sk_buff *skb)
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002655{
2656 struct hci_ev_cmd_status *ev = (void *) skb->data;
2657 __u16 opcode;
2658
2659 skb_pull(skb, sizeof(*ev));
2660
2661 opcode = __le16_to_cpu(ev->opcode);
2662
2663 switch (opcode) {
2664 case HCI_OP_INQUIRY:
2665 hci_cs_inquiry(hdev, ev->status);
2666 break;
2667
2668 case HCI_OP_CREATE_CONN:
2669 hci_cs_create_conn(hdev, ev->status);
2670 break;
2671
2672 case HCI_OP_ADD_SCO:
2673 hci_cs_add_sco(hdev, ev->status);
2674 break;
2675
Marcel Holtmannf8558552008-07-14 20:13:49 +02002676 case HCI_OP_AUTH_REQUESTED:
2677 hci_cs_auth_requested(hdev, ev->status);
2678 break;
2679
2680 case HCI_OP_SET_CONN_ENCRYPT:
2681 hci_cs_set_conn_encrypt(hdev, ev->status);
2682 break;
2683
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002684 case HCI_OP_REMOTE_NAME_REQ:
2685 hci_cs_remote_name_req(hdev, ev->status);
2686 break;
2687
Marcel Holtmann769be972008-07-14 20:13:49 +02002688 case HCI_OP_READ_REMOTE_FEATURES:
2689 hci_cs_read_remote_features(hdev, ev->status);
2690 break;
2691
2692 case HCI_OP_READ_REMOTE_EXT_FEATURES:
2693 hci_cs_read_remote_ext_features(hdev, ev->status);
2694 break;
2695
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002696 case HCI_OP_SETUP_SYNC_CONN:
2697 hci_cs_setup_sync_conn(hdev, ev->status);
2698 break;
2699
2700 case HCI_OP_SNIFF_MODE:
2701 hci_cs_sniff_mode(hdev, ev->status);
2702 break;
2703
2704 case HCI_OP_EXIT_SNIFF_MODE:
2705 hci_cs_exit_sniff_mode(hdev, ev->status);
2706 break;
2707
Johan Hedberg8962ee72011-01-20 12:40:27 +02002708 case HCI_OP_DISCONNECT:
Johan Hedberg88c3df12012-02-09 14:27:38 +02002709 hci_cs_disconnect(hdev, ev->status);
Johan Hedberg8962ee72011-01-20 12:40:27 +02002710 break;
2711
Ville Tervofcd89c02011-02-10 22:38:47 -03002712 case HCI_OP_LE_CREATE_CONN:
2713 hci_cs_le_create_conn(hdev, ev->status);
2714 break;
2715
Vinicius Costa Gomesa7a595f2011-06-09 18:50:47 -03002716 case HCI_OP_LE_START_ENC:
2717 hci_cs_le_start_enc(hdev, ev->status);
2718 break;
2719
Andrei Emeltchenkoa02226d2012-09-27 17:26:19 +03002720 case HCI_OP_CREATE_PHY_LINK:
2721 hci_cs_create_phylink(hdev, ev->status);
2722 break;
2723
Andrei Emeltchenko0b26ab92012-09-27 17:26:24 +03002724 case HCI_OP_ACCEPT_PHY_LINK:
2725 hci_cs_accept_phylink(hdev, ev->status);
2726 break;
2727
Andrei Emeltchenko5ce66b52012-10-31 15:46:30 +02002728 case HCI_OP_CREATE_LOGICAL_LINK:
2729 hci_cs_create_logical_link(hdev, ev->status);
2730 break;
2731
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002732 default:
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +03002733 BT_DBG("%s opcode 0x%4.4x", hdev->name, opcode);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002734 break;
2735 }
2736
Ville Tervo6bd32322011-02-16 16:32:41 +02002737 if (ev->opcode != HCI_OP_NOP)
2738 del_timer(&hdev->cmd_timer);
2739
Gustavo F. Padovan10572132011-03-16 15:36:29 -03002740 if (ev->ncmd && !test_bit(HCI_RESET, &hdev->flags)) {
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002741 atomic_set(&hdev->cmd_cnt, 1);
2742 if (!skb_queue_empty(&hdev->cmd_q))
Gustavo F. Padovanc347b762011-12-14 23:53:47 -02002743 queue_work(hdev->workqueue, &hdev->cmd_work);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002744 }
2745}
2746
Gustavo Padovan6039aa72012-05-23 04:04:18 -03002747static void hci_role_change_evt(struct hci_dev *hdev, struct sk_buff *skb)
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002748{
2749 struct hci_ev_role_change *ev = (void *) skb->data;
2750 struct hci_conn *conn;
2751
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +03002752 BT_DBG("%s status 0x%2.2x", hdev->name, ev->status);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002753
2754 hci_dev_lock(hdev);
2755
2756 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
2757 if (conn) {
2758 if (!ev->status) {
2759 if (ev->role)
2760 conn->link_mode &= ~HCI_LM_MASTER;
2761 else
2762 conn->link_mode |= HCI_LM_MASTER;
2763 }
2764
Johan Hedberg51a8efd2012-01-16 06:10:31 +02002765 clear_bit(HCI_CONN_RSWITCH_PEND, &conn->flags);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002766
2767 hci_role_switch_cfm(conn, ev->status, ev->role);
2768 }
2769
2770 hci_dev_unlock(hdev);
2771}
2772
Gustavo Padovan6039aa72012-05-23 04:04:18 -03002773static void hci_num_comp_pkts_evt(struct hci_dev *hdev, struct sk_buff *skb)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002774{
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002775 struct hci_ev_num_comp_pkts *ev = (void *) skb->data;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002776 int i;
2777
Andrei Emeltchenko32ac5b92011-12-19 16:31:29 +02002778 if (hdev->flow_ctl_mode != HCI_FLOW_CTL_MODE_PACKET_BASED) {
2779 BT_ERR("Wrong event for mode %d", hdev->flow_ctl_mode);
2780 return;
2781 }
2782
Andrei Emeltchenkoc5993de2011-12-30 12:07:47 +02002783 if (skb->len < sizeof(*ev) || skb->len < sizeof(*ev) +
Gustavo Padovan807deac2012-05-17 00:36:24 -03002784 ev->num_hndl * sizeof(struct hci_comp_pkts_info)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002785 BT_DBG("%s bad parameters", hdev->name);
2786 return;
2787 }
2788
Andrei Emeltchenkoc5993de2011-12-30 12:07:47 +02002789 BT_DBG("%s num_hndl %d", hdev->name, ev->num_hndl);
2790
Andrei Emeltchenko613a1c02011-12-19 16:31:30 +02002791 for (i = 0; i < ev->num_hndl; i++) {
2792 struct hci_comp_pkts_info *info = &ev->handles[i];
Linus Torvalds1da177e2005-04-16 15:20:36 -07002793 struct hci_conn *conn;
2794 __u16 handle, count;
2795
Andrei Emeltchenko613a1c02011-12-19 16:31:30 +02002796 handle = __le16_to_cpu(info->handle);
2797 count = __le16_to_cpu(info->count);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002798
2799 conn = hci_conn_hash_lookup_handle(hdev, handle);
Andrei Emeltchenkof4280912011-12-07 15:56:52 +02002800 if (!conn)
2801 continue;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002802
Andrei Emeltchenkof4280912011-12-07 15:56:52 +02002803 conn->sent -= count;
2804
2805 switch (conn->type) {
2806 case ACL_LINK:
2807 hdev->acl_cnt += count;
2808 if (hdev->acl_cnt > hdev->acl_pkts)
2809 hdev->acl_cnt = hdev->acl_pkts;
2810 break;
2811
2812 case LE_LINK:
2813 if (hdev->le_pkts) {
2814 hdev->le_cnt += count;
2815 if (hdev->le_cnt > hdev->le_pkts)
2816 hdev->le_cnt = hdev->le_pkts;
2817 } else {
Andrei Emeltchenko70f230202010-12-01 16:58:25 +02002818 hdev->acl_cnt += count;
2819 if (hdev->acl_cnt > hdev->acl_pkts)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002820 hdev->acl_cnt = hdev->acl_pkts;
2821 }
Andrei Emeltchenkof4280912011-12-07 15:56:52 +02002822 break;
2823
2824 case SCO_LINK:
2825 hdev->sco_cnt += count;
2826 if (hdev->sco_cnt > hdev->sco_pkts)
2827 hdev->sco_cnt = hdev->sco_pkts;
2828 break;
2829
2830 default:
2831 BT_ERR("Unknown type %d conn %p", conn->type, conn);
2832 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002833 }
2834 }
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002835
Gustavo F. Padovan3eff45e2011-12-15 00:50:02 -02002836 queue_work(hdev->workqueue, &hdev->tx_work);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002837}
2838
Andrei Emeltchenko76ef7cf2012-10-10 17:38:29 +03002839static struct hci_conn *__hci_conn_lookup_handle(struct hci_dev *hdev,
2840 __u16 handle)
2841{
2842 struct hci_chan *chan;
2843
2844 switch (hdev->dev_type) {
2845 case HCI_BREDR:
2846 return hci_conn_hash_lookup_handle(hdev, handle);
2847 case HCI_AMP:
2848 chan = hci_chan_lookup_handle(hdev, handle);
2849 if (chan)
2850 return chan->conn;
2851 break;
2852 default:
2853 BT_ERR("%s unknown dev_type %d", hdev->name, hdev->dev_type);
2854 break;
2855 }
2856
2857 return NULL;
2858}
2859
Gustavo Padovan6039aa72012-05-23 04:04:18 -03002860static void hci_num_comp_blocks_evt(struct hci_dev *hdev, struct sk_buff *skb)
Andrei Emeltchenko25e89e92012-01-04 12:41:58 +02002861{
2862 struct hci_ev_num_comp_blocks *ev = (void *) skb->data;
2863 int i;
2864
2865 if (hdev->flow_ctl_mode != HCI_FLOW_CTL_MODE_BLOCK_BASED) {
2866 BT_ERR("Wrong event for mode %d", hdev->flow_ctl_mode);
2867 return;
2868 }
2869
2870 if (skb->len < sizeof(*ev) || skb->len < sizeof(*ev) +
Gustavo Padovan807deac2012-05-17 00:36:24 -03002871 ev->num_hndl * sizeof(struct hci_comp_blocks_info)) {
Andrei Emeltchenko25e89e92012-01-04 12:41:58 +02002872 BT_DBG("%s bad parameters", hdev->name);
2873 return;
2874 }
2875
2876 BT_DBG("%s num_blocks %d num_hndl %d", hdev->name, ev->num_blocks,
Gustavo Padovan807deac2012-05-17 00:36:24 -03002877 ev->num_hndl);
Andrei Emeltchenko25e89e92012-01-04 12:41:58 +02002878
2879 for (i = 0; i < ev->num_hndl; i++) {
2880 struct hci_comp_blocks_info *info = &ev->handles[i];
Andrei Emeltchenko76ef7cf2012-10-10 17:38:29 +03002881 struct hci_conn *conn = NULL;
Andrei Emeltchenko25e89e92012-01-04 12:41:58 +02002882 __u16 handle, block_count;
2883
2884 handle = __le16_to_cpu(info->handle);
2885 block_count = __le16_to_cpu(info->blocks);
2886
Andrei Emeltchenko76ef7cf2012-10-10 17:38:29 +03002887 conn = __hci_conn_lookup_handle(hdev, handle);
Andrei Emeltchenko25e89e92012-01-04 12:41:58 +02002888 if (!conn)
2889 continue;
2890
2891 conn->sent -= block_count;
2892
2893 switch (conn->type) {
2894 case ACL_LINK:
Andrei Emeltchenkobd1eb662012-10-10 17:38:30 +03002895 case AMP_LINK:
Andrei Emeltchenko25e89e92012-01-04 12:41:58 +02002896 hdev->block_cnt += block_count;
2897 if (hdev->block_cnt > hdev->num_blocks)
2898 hdev->block_cnt = hdev->num_blocks;
2899 break;
2900
2901 default:
2902 BT_ERR("Unknown type %d conn %p", conn->type, conn);
2903 break;
2904 }
2905 }
2906
2907 queue_work(hdev->workqueue, &hdev->tx_work);
2908}
2909
Gustavo Padovan6039aa72012-05-23 04:04:18 -03002910static void hci_mode_change_evt(struct hci_dev *hdev, struct sk_buff *skb)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002911{
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002912 struct hci_ev_mode_change *ev = (void *) skb->data;
Marcel Holtmann04837f62006-07-03 10:02:33 +02002913 struct hci_conn *conn;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002914
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +03002915 BT_DBG("%s status 0x%2.2x", hdev->name, ev->status);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002916
2917 hci_dev_lock(hdev);
2918
Marcel Holtmann04837f62006-07-03 10:02:33 +02002919 conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
2920 if (conn) {
2921 conn->mode = ev->mode;
2922 conn->interval = __le16_to_cpu(ev->interval);
2923
Gustavo Padovan8fc9ced2012-05-23 04:04:21 -03002924 if (!test_and_clear_bit(HCI_CONN_MODE_CHANGE_PEND,
2925 &conn->flags)) {
Marcel Holtmann04837f62006-07-03 10:02:33 +02002926 if (conn->mode == HCI_CM_ACTIVE)
Johan Hedberg58a681e2012-01-16 06:47:28 +02002927 set_bit(HCI_CONN_POWER_SAVE, &conn->flags);
Marcel Holtmann04837f62006-07-03 10:02:33 +02002928 else
Johan Hedberg58a681e2012-01-16 06:47:28 +02002929 clear_bit(HCI_CONN_POWER_SAVE, &conn->flags);
Marcel Holtmann04837f62006-07-03 10:02:33 +02002930 }
Marcel Holtmanne73439d2010-07-26 10:06:00 -04002931
Johan Hedberg51a8efd2012-01-16 06:10:31 +02002932 if (test_and_clear_bit(HCI_CONN_SCO_SETUP_PEND, &conn->flags))
Marcel Holtmanne73439d2010-07-26 10:06:00 -04002933 hci_sco_setup(conn, ev->status);
Marcel Holtmann04837f62006-07-03 10:02:33 +02002934 }
2935
2936 hci_dev_unlock(hdev);
2937}
2938
Gustavo Padovan6039aa72012-05-23 04:04:18 -03002939static void hci_pin_code_request_evt(struct hci_dev *hdev, struct sk_buff *skb)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002940{
Marcel Holtmann052b30b2009-04-26 20:01:22 +02002941 struct hci_ev_pin_code_req *ev = (void *) skb->data;
2942 struct hci_conn *conn;
2943
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002944 BT_DBG("%s", hdev->name);
Marcel Holtmann052b30b2009-04-26 20:01:22 +02002945
2946 hci_dev_lock(hdev);
2947
2948 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
Waldemar Rymarkiewiczb6f98042011-09-23 10:01:30 +02002949 if (!conn)
2950 goto unlock;
2951
2952 if (conn->state == BT_CONNECTED) {
Marcel Holtmann052b30b2009-04-26 20:01:22 +02002953 hci_conn_hold(conn);
2954 conn->disc_timeout = HCI_PAIRING_TIMEOUT;
2955 hci_conn_put(conn);
2956 }
2957
Johan Hedberga8b2d5c2012-01-08 23:11:15 +02002958 if (!test_bit(HCI_PAIRABLE, &hdev->dev_flags))
Johan Hedberg03b555e2011-01-04 15:40:05 +02002959 hci_send_cmd(hdev, HCI_OP_PIN_CODE_NEG_REPLY,
Gustavo Padovan807deac2012-05-17 00:36:24 -03002960 sizeof(ev->bdaddr), &ev->bdaddr);
Johan Hedberga8b2d5c2012-01-08 23:11:15 +02002961 else if (test_bit(HCI_MGMT, &hdev->dev_flags)) {
Waldemar Rymarkiewicza770bb52011-04-28 12:07:59 +02002962 u8 secure;
2963
2964 if (conn->pending_sec_level == BT_SECURITY_HIGH)
2965 secure = 1;
2966 else
2967 secure = 0;
2968
Johan Hedberg744cf192011-11-08 20:40:14 +02002969 mgmt_pin_code_request(hdev, &ev->bdaddr, secure);
Waldemar Rymarkiewicza770bb52011-04-28 12:07:59 +02002970 }
Johan Hedberg980e1a52011-01-22 06:10:07 +02002971
Waldemar Rymarkiewiczb6f98042011-09-23 10:01:30 +02002972unlock:
Marcel Holtmann052b30b2009-04-26 20:01:22 +02002973 hci_dev_unlock(hdev);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002974}
2975
Gustavo Padovan6039aa72012-05-23 04:04:18 -03002976static void hci_link_key_request_evt(struct hci_dev *hdev, struct sk_buff *skb)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002977{
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002978 struct hci_ev_link_key_req *ev = (void *) skb->data;
2979 struct hci_cp_link_key_reply cp;
2980 struct hci_conn *conn;
2981 struct link_key *key;
2982
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002983 BT_DBG("%s", hdev->name);
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002984
Johan Hedberga8b2d5c2012-01-08 23:11:15 +02002985 if (!test_bit(HCI_LINK_KEYS, &hdev->dev_flags))
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002986 return;
2987
2988 hci_dev_lock(hdev);
2989
2990 key = hci_find_link_key(hdev, &ev->bdaddr);
2991 if (!key) {
Andrei Emeltchenko6ed93dc2012-09-25 12:49:43 +03002992 BT_DBG("%s link key not found for %pMR", hdev->name,
2993 &ev->bdaddr);
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002994 goto not_found;
2995 }
2996
Andrei Emeltchenko6ed93dc2012-09-25 12:49:43 +03002997 BT_DBG("%s found key type %u for %pMR", hdev->name, key->type,
2998 &ev->bdaddr);
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002999
Johan Hedberga8b2d5c2012-01-08 23:11:15 +02003000 if (!test_bit(HCI_DEBUG_KEYS, &hdev->dev_flags) &&
Gustavo Padovan807deac2012-05-17 00:36:24 -03003001 key->type == HCI_LK_DEBUG_COMBINATION) {
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02003002 BT_DBG("%s ignoring debug key", hdev->name);
3003 goto not_found;
3004 }
3005
3006 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
Waldemar Rymarkiewicz60b83f52011-04-28 12:07:56 +02003007 if (conn) {
3008 if (key->type == HCI_LK_UNAUTH_COMBINATION &&
Gustavo Padovan807deac2012-05-17 00:36:24 -03003009 conn->auth_type != 0xff && (conn->auth_type & 0x01)) {
Waldemar Rymarkiewicz60b83f52011-04-28 12:07:56 +02003010 BT_DBG("%s ignoring unauthenticated key", hdev->name);
3011 goto not_found;
3012 }
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02003013
Waldemar Rymarkiewicz60b83f52011-04-28 12:07:56 +02003014 if (key->type == HCI_LK_COMBINATION && key->pin_len < 16 &&
Gustavo Padovan807deac2012-05-17 00:36:24 -03003015 conn->pending_sec_level == BT_SECURITY_HIGH) {
Gustavo Padovan8fc9ced2012-05-23 04:04:21 -03003016 BT_DBG("%s ignoring key unauthenticated for high security",
3017 hdev->name);
Waldemar Rymarkiewicz60b83f52011-04-28 12:07:56 +02003018 goto not_found;
3019 }
3020
3021 conn->key_type = key->type;
3022 conn->pin_length = key->pin_len;
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02003023 }
3024
3025 bacpy(&cp.bdaddr, &ev->bdaddr);
Andrei Emeltchenko9b3b4462012-05-23 11:31:20 +03003026 memcpy(cp.link_key, key->val, HCI_LINK_KEY_SIZE);
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02003027
3028 hci_send_cmd(hdev, HCI_OP_LINK_KEY_REPLY, sizeof(cp), &cp);
3029
3030 hci_dev_unlock(hdev);
3031
3032 return;
3033
3034not_found:
3035 hci_send_cmd(hdev, HCI_OP_LINK_KEY_NEG_REPLY, 6, &ev->bdaddr);
3036 hci_dev_unlock(hdev);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003037}
3038
Gustavo Padovan6039aa72012-05-23 04:04:18 -03003039static void hci_link_key_notify_evt(struct hci_dev *hdev, struct sk_buff *skb)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003040{
Marcel Holtmann052b30b2009-04-26 20:01:22 +02003041 struct hci_ev_link_key_notify *ev = (void *) skb->data;
3042 struct hci_conn *conn;
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02003043 u8 pin_len = 0;
Marcel Holtmann052b30b2009-04-26 20:01:22 +02003044
Marcel Holtmanna9de9242007-10-20 13:33:56 +02003045 BT_DBG("%s", hdev->name);
Marcel Holtmann052b30b2009-04-26 20:01:22 +02003046
3047 hci_dev_lock(hdev);
3048
3049 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
3050 if (conn) {
3051 hci_conn_hold(conn);
3052 conn->disc_timeout = HCI_DISCONN_TIMEOUT;
Johan Hedberg980e1a52011-01-22 06:10:07 +02003053 pin_len = conn->pin_length;
Waldemar Rymarkiewicz13d39312011-04-28 12:07:55 +02003054
3055 if (ev->key_type != HCI_LK_CHANGED_COMBINATION)
3056 conn->key_type = ev->key_type;
3057
Marcel Holtmann052b30b2009-04-26 20:01:22 +02003058 hci_conn_put(conn);
3059 }
3060
Johan Hedberga8b2d5c2012-01-08 23:11:15 +02003061 if (test_bit(HCI_LINK_KEYS, &hdev->dev_flags))
Johan Hedbergd25e28a2011-04-28 11:28:59 -07003062 hci_add_link_key(hdev, conn, 1, &ev->bdaddr, ev->link_key,
Gustavo Padovan807deac2012-05-17 00:36:24 -03003063 ev->key_type, pin_len);
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02003064
Marcel Holtmann052b30b2009-04-26 20:01:22 +02003065 hci_dev_unlock(hdev);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003066}
3067
Gustavo Padovan6039aa72012-05-23 04:04:18 -03003068static void hci_clock_offset_evt(struct hci_dev *hdev, struct sk_buff *skb)
Marcel Holtmann04837f62006-07-03 10:02:33 +02003069{
Marcel Holtmanna9de9242007-10-20 13:33:56 +02003070 struct hci_ev_clock_offset *ev = (void *) skb->data;
Marcel Holtmann04837f62006-07-03 10:02:33 +02003071 struct hci_conn *conn;
3072
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +03003073 BT_DBG("%s status 0x%2.2x", hdev->name, ev->status);
Marcel Holtmann04837f62006-07-03 10:02:33 +02003074
3075 hci_dev_lock(hdev);
3076
3077 conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
Linus Torvalds1da177e2005-04-16 15:20:36 -07003078 if (conn && !ev->status) {
3079 struct inquiry_entry *ie;
3080
Andrei Emeltchenkocc11b9c2010-11-22 13:21:37 +02003081 ie = hci_inquiry_cache_lookup(hdev, &conn->dst);
3082 if (ie) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003083 ie->data.clock_offset = ev->clock_offset;
3084 ie->timestamp = jiffies;
3085 }
3086 }
3087
3088 hci_dev_unlock(hdev);
3089}
3090
Gustavo Padovan6039aa72012-05-23 04:04:18 -03003091static void hci_pkt_type_change_evt(struct hci_dev *hdev, struct sk_buff *skb)
Marcel Holtmanna8746412008-07-14 20:13:46 +02003092{
3093 struct hci_ev_pkt_type_change *ev = (void *) skb->data;
3094 struct hci_conn *conn;
3095
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +03003096 BT_DBG("%s status 0x%2.2x", hdev->name, ev->status);
Marcel Holtmanna8746412008-07-14 20:13:46 +02003097
3098 hci_dev_lock(hdev);
3099
3100 conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
3101 if (conn && !ev->status)
3102 conn->pkt_type = __le16_to_cpu(ev->pkt_type);
3103
3104 hci_dev_unlock(hdev);
3105}
3106
Gustavo Padovan6039aa72012-05-23 04:04:18 -03003107static void hci_pscan_rep_mode_evt(struct hci_dev *hdev, struct sk_buff *skb)
Marcel Holtmann85a1e932005-08-09 20:28:02 -07003108{
Marcel Holtmanna9de9242007-10-20 13:33:56 +02003109 struct hci_ev_pscan_rep_mode *ev = (void *) skb->data;
Marcel Holtmann85a1e932005-08-09 20:28:02 -07003110 struct inquiry_entry *ie;
3111
3112 BT_DBG("%s", hdev->name);
3113
3114 hci_dev_lock(hdev);
3115
Andrei Emeltchenkocc11b9c2010-11-22 13:21:37 +02003116 ie = hci_inquiry_cache_lookup(hdev, &ev->bdaddr);
3117 if (ie) {
Marcel Holtmann85a1e932005-08-09 20:28:02 -07003118 ie->data.pscan_rep_mode = ev->pscan_rep_mode;
3119 ie->timestamp = jiffies;
3120 }
3121
3122 hci_dev_unlock(hdev);
3123}
3124
Gustavo Padovan6039aa72012-05-23 04:04:18 -03003125static void hci_inquiry_result_with_rssi_evt(struct hci_dev *hdev,
3126 struct sk_buff *skb)
Marcel Holtmanna9de9242007-10-20 13:33:56 +02003127{
3128 struct inquiry_data data;
3129 int num_rsp = *((__u8 *) skb->data);
Johan Hedberg388fc8f2012-02-23 00:38:59 +02003130 bool name_known, ssp;
Marcel Holtmanna9de9242007-10-20 13:33:56 +02003131
3132 BT_DBG("%s num_rsp %d", hdev->name, num_rsp);
3133
3134 if (!num_rsp)
3135 return;
3136
Andre Guedes1519cc12012-03-21 00:03:38 -03003137 if (test_bit(HCI_PERIODIC_INQ, &hdev->dev_flags))
3138 return;
3139
Marcel Holtmanna9de9242007-10-20 13:33:56 +02003140 hci_dev_lock(hdev);
3141
3142 if ((skb->len - 1) / num_rsp != sizeof(struct inquiry_info_with_rssi)) {
Szymon Janc138d22e2011-02-17 16:44:23 +01003143 struct inquiry_info_with_rssi_and_pscan_mode *info;
3144 info = (void *) (skb->data + 1);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02003145
Johan Hedberge17acd42011-03-30 23:57:16 +03003146 for (; num_rsp; num_rsp--, info++) {
Marcel Holtmanna9de9242007-10-20 13:33:56 +02003147 bacpy(&data.bdaddr, &info->bdaddr);
3148 data.pscan_rep_mode = info->pscan_rep_mode;
3149 data.pscan_period_mode = info->pscan_period_mode;
3150 data.pscan_mode = info->pscan_mode;
3151 memcpy(data.dev_class, info->dev_class, 3);
3152 data.clock_offset = info->clock_offset;
3153 data.rssi = info->rssi;
Marcel Holtmann41a96212008-07-14 20:13:48 +02003154 data.ssp_mode = 0x00;
Johan Hedberg31754052012-01-04 13:39:52 +02003155
3156 name_known = hci_inquiry_cache_update(hdev, &data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003157 false, &ssp);
Johan Hedberg48264f02011-11-09 13:58:58 +02003158 mgmt_device_found(hdev, &info->bdaddr, ACL_LINK, 0x00,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003159 info->dev_class, info->rssi,
3160 !name_known, ssp, NULL, 0);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02003161 }
3162 } else {
3163 struct inquiry_info_with_rssi *info = (void *) (skb->data + 1);
3164
Johan Hedberge17acd42011-03-30 23:57:16 +03003165 for (; num_rsp; num_rsp--, info++) {
Marcel Holtmanna9de9242007-10-20 13:33:56 +02003166 bacpy(&data.bdaddr, &info->bdaddr);
3167 data.pscan_rep_mode = info->pscan_rep_mode;
3168 data.pscan_period_mode = info->pscan_period_mode;
3169 data.pscan_mode = 0x00;
3170 memcpy(data.dev_class, info->dev_class, 3);
3171 data.clock_offset = info->clock_offset;
3172 data.rssi = info->rssi;
Marcel Holtmann41a96212008-07-14 20:13:48 +02003173 data.ssp_mode = 0x00;
Johan Hedberg31754052012-01-04 13:39:52 +02003174 name_known = hci_inquiry_cache_update(hdev, &data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003175 false, &ssp);
Johan Hedberg48264f02011-11-09 13:58:58 +02003176 mgmt_device_found(hdev, &info->bdaddr, ACL_LINK, 0x00,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003177 info->dev_class, info->rssi,
3178 !name_known, ssp, NULL, 0);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02003179 }
3180 }
3181
3182 hci_dev_unlock(hdev);
3183}
3184
Gustavo Padovan6039aa72012-05-23 04:04:18 -03003185static void hci_remote_ext_features_evt(struct hci_dev *hdev,
3186 struct sk_buff *skb)
Marcel Holtmanna9de9242007-10-20 13:33:56 +02003187{
Marcel Holtmann41a96212008-07-14 20:13:48 +02003188 struct hci_ev_remote_ext_features *ev = (void *) skb->data;
3189 struct hci_conn *conn;
3190
Marcel Holtmanna9de9242007-10-20 13:33:56 +02003191 BT_DBG("%s", hdev->name);
Marcel Holtmann41a96212008-07-14 20:13:48 +02003192
Marcel Holtmann41a96212008-07-14 20:13:48 +02003193 hci_dev_lock(hdev);
3194
3195 conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
Johan Hedbergccd556f2010-11-10 17:11:51 +02003196 if (!conn)
3197 goto unlock;
Marcel Holtmann41a96212008-07-14 20:13:48 +02003198
Johan Hedbergccd556f2010-11-10 17:11:51 +02003199 if (!ev->status && ev->page == 0x01) {
3200 struct inquiry_entry *ie;
Marcel Holtmann41a96212008-07-14 20:13:48 +02003201
Andrei Emeltchenkocc11b9c2010-11-22 13:21:37 +02003202 ie = hci_inquiry_cache_lookup(hdev, &conn->dst);
3203 if (ie)
Johan Hedberg02b7cc62012-02-28 02:28:43 +02003204 ie->data.ssp_mode = (ev->features[0] & LMP_HOST_SSP);
Marcel Holtmann769be972008-07-14 20:13:49 +02003205
Johan Hedberg02b7cc62012-02-28 02:28:43 +02003206 if (ev->features[0] & LMP_HOST_SSP)
Johan Hedberg58a681e2012-01-16 06:47:28 +02003207 set_bit(HCI_CONN_SSP_ENABLED, &conn->flags);
Marcel Holtmann41a96212008-07-14 20:13:48 +02003208 }
3209
Johan Hedbergccd556f2010-11-10 17:11:51 +02003210 if (conn->state != BT_CONFIG)
3211 goto unlock;
3212
Johan Hedberg671267b2012-05-12 16:11:50 -03003213 if (!ev->status && !test_bit(HCI_CONN_MGMT_CONNECTED, &conn->flags)) {
Johan Hedberg127178d2010-11-18 22:22:29 +02003214 struct hci_cp_remote_name_req cp;
3215 memset(&cp, 0, sizeof(cp));
3216 bacpy(&cp.bdaddr, &conn->dst);
3217 cp.pscan_rep_mode = 0x02;
3218 hci_send_cmd(hdev, HCI_OP_REMOTE_NAME_REQ, sizeof(cp), &cp);
Johan Hedbergb644ba32012-01-17 21:48:47 +02003219 } else if (!test_and_set_bit(HCI_CONN_MGMT_CONNECTED, &conn->flags))
3220 mgmt_device_connected(hdev, &conn->dst, conn->type,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003221 conn->dst_type, 0, NULL, 0,
3222 conn->dev_class);
Johan Hedberg392599b2010-11-18 22:22:28 +02003223
Johan Hedberg127178d2010-11-18 22:22:29 +02003224 if (!hci_outgoing_auth_needed(hdev, conn)) {
Johan Hedbergccd556f2010-11-10 17:11:51 +02003225 conn->state = BT_CONNECTED;
3226 hci_proto_connect_cfm(conn, ev->status);
3227 hci_conn_put(conn);
3228 }
3229
3230unlock:
Marcel Holtmann41a96212008-07-14 20:13:48 +02003231 hci_dev_unlock(hdev);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02003232}
3233
Gustavo Padovan6039aa72012-05-23 04:04:18 -03003234static void hci_sync_conn_complete_evt(struct hci_dev *hdev,
3235 struct sk_buff *skb)
Marcel Holtmanna9de9242007-10-20 13:33:56 +02003236{
Marcel Holtmannb6a0dc82007-10-20 14:55:10 +02003237 struct hci_ev_sync_conn_complete *ev = (void *) skb->data;
3238 struct hci_conn *conn;
3239
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +03003240 BT_DBG("%s status 0x%2.2x", hdev->name, ev->status);
Marcel Holtmannb6a0dc82007-10-20 14:55:10 +02003241
3242 hci_dev_lock(hdev);
3243
3244 conn = hci_conn_hash_lookup_ba(hdev, ev->link_type, &ev->bdaddr);
Marcel Holtmann9dc0a3a2008-07-14 20:13:46 +02003245 if (!conn) {
3246 if (ev->link_type == ESCO_LINK)
3247 goto unlock;
3248
3249 conn = hci_conn_hash_lookup_ba(hdev, ESCO_LINK, &ev->bdaddr);
3250 if (!conn)
3251 goto unlock;
3252
3253 conn->type = SCO_LINK;
3254 }
Marcel Holtmannb6a0dc82007-10-20 14:55:10 +02003255
Marcel Holtmann732547f2009-04-19 19:14:14 +02003256 switch (ev->status) {
3257 case 0x00:
Marcel Holtmannb6a0dc82007-10-20 14:55:10 +02003258 conn->handle = __le16_to_cpu(ev->handle);
3259 conn->state = BT_CONNECTED;
Marcel Holtmann7d0db0a2008-07-14 20:13:51 +02003260
Marcel Holtmann9eba32b2009-08-22 14:19:26 -07003261 hci_conn_hold_device(conn);
Marcel Holtmann7d0db0a2008-07-14 20:13:51 +02003262 hci_conn_add_sysfs(conn);
Marcel Holtmann732547f2009-04-19 19:14:14 +02003263 break;
3264
Stephen Coe705e5712010-02-16 11:29:44 -05003265 case 0x11: /* Unsupported Feature or Parameter Value */
Marcel Holtmann732547f2009-04-19 19:14:14 +02003266 case 0x1c: /* SCO interval rejected */
Nick Pelly1038a002010-02-03 11:42:26 -08003267 case 0x1a: /* Unsupported Remote Feature */
Marcel Holtmann732547f2009-04-19 19:14:14 +02003268 case 0x1f: /* Unspecified error */
3269 if (conn->out && conn->attempt < 2) {
3270 conn->pkt_type = (hdev->esco_type & SCO_ESCO_MASK) |
3271 (hdev->esco_type & EDR_ESCO_MASK);
3272 hci_setup_sync(conn, conn->link->handle);
3273 goto unlock;
3274 }
3275 /* fall through */
3276
3277 default:
Marcel Holtmannb6a0dc82007-10-20 14:55:10 +02003278 conn->state = BT_CLOSED;
Marcel Holtmann732547f2009-04-19 19:14:14 +02003279 break;
3280 }
Marcel Holtmannb6a0dc82007-10-20 14:55:10 +02003281
3282 hci_proto_connect_cfm(conn, ev->status);
3283 if (ev->status)
3284 hci_conn_del(conn);
3285
3286unlock:
3287 hci_dev_unlock(hdev);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02003288}
3289
Gustavo Padovan6039aa72012-05-23 04:04:18 -03003290static void hci_sync_conn_changed_evt(struct hci_dev *hdev, struct sk_buff *skb)
Marcel Holtmanna9de9242007-10-20 13:33:56 +02003291{
3292 BT_DBG("%s", hdev->name);
3293}
3294
Gustavo Padovan6039aa72012-05-23 04:04:18 -03003295static void hci_sniff_subrate_evt(struct hci_dev *hdev, struct sk_buff *skb)
Marcel Holtmann04837f62006-07-03 10:02:33 +02003296{
Marcel Holtmanna9de9242007-10-20 13:33:56 +02003297 struct hci_ev_sniff_subrate *ev = (void *) skb->data;
Marcel Holtmann04837f62006-07-03 10:02:33 +02003298
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +03003299 BT_DBG("%s status 0x%2.2x", hdev->name, ev->status);
Marcel Holtmann04837f62006-07-03 10:02:33 +02003300}
3301
Gustavo Padovan6039aa72012-05-23 04:04:18 -03003302static void hci_extended_inquiry_result_evt(struct hci_dev *hdev,
3303 struct sk_buff *skb)
Marcel Holtmanna9de9242007-10-20 13:33:56 +02003304{
3305 struct inquiry_data data;
3306 struct extended_inquiry_info *info = (void *) (skb->data + 1);
3307 int num_rsp = *((__u8 *) skb->data);
Vishal Agarwal9d939d92012-04-26 19:19:56 +05303308 size_t eir_len;
Marcel Holtmanna9de9242007-10-20 13:33:56 +02003309
3310 BT_DBG("%s num_rsp %d", hdev->name, num_rsp);
3311
3312 if (!num_rsp)
3313 return;
3314
Andre Guedes1519cc12012-03-21 00:03:38 -03003315 if (test_bit(HCI_PERIODIC_INQ, &hdev->dev_flags))
3316 return;
3317
Marcel Holtmanna9de9242007-10-20 13:33:56 +02003318 hci_dev_lock(hdev);
3319
Johan Hedberge17acd42011-03-30 23:57:16 +03003320 for (; num_rsp; num_rsp--, info++) {
Johan Hedberg388fc8f2012-02-23 00:38:59 +02003321 bool name_known, ssp;
Johan Hedberg561aafb2012-01-04 13:31:59 +02003322
Marcel Holtmanna9de9242007-10-20 13:33:56 +02003323 bacpy(&data.bdaddr, &info->bdaddr);
Szymon Janc138d22e2011-02-17 16:44:23 +01003324 data.pscan_rep_mode = info->pscan_rep_mode;
3325 data.pscan_period_mode = info->pscan_period_mode;
3326 data.pscan_mode = 0x00;
Marcel Holtmanna9de9242007-10-20 13:33:56 +02003327 memcpy(data.dev_class, info->dev_class, 3);
Szymon Janc138d22e2011-02-17 16:44:23 +01003328 data.clock_offset = info->clock_offset;
3329 data.rssi = info->rssi;
Marcel Holtmann41a96212008-07-14 20:13:48 +02003330 data.ssp_mode = 0x01;
Johan Hedberg561aafb2012-01-04 13:31:59 +02003331
Johan Hedberga8b2d5c2012-01-08 23:11:15 +02003332 if (test_bit(HCI_MGMT, &hdev->dev_flags))
Johan Hedberg4ddb1932012-01-15 20:04:43 +02003333 name_known = eir_has_data_type(info->data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003334 sizeof(info->data),
3335 EIR_NAME_COMPLETE);
Johan Hedberg561aafb2012-01-04 13:31:59 +02003336 else
3337 name_known = true;
3338
Johan Hedberg388fc8f2012-02-23 00:38:59 +02003339 name_known = hci_inquiry_cache_update(hdev, &data, name_known,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003340 &ssp);
Vishal Agarwal9d939d92012-04-26 19:19:56 +05303341 eir_len = eir_get_length(info->data, sizeof(info->data));
Johan Hedberg48264f02011-11-09 13:58:58 +02003342 mgmt_device_found(hdev, &info->bdaddr, ACL_LINK, 0x00,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003343 info->dev_class, info->rssi, !name_known,
Vishal Agarwal9d939d92012-04-26 19:19:56 +05303344 ssp, info->data, eir_len);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02003345 }
3346
3347 hci_dev_unlock(hdev);
3348}
3349
Johan Hedberg1c2e0042012-06-08 23:31:13 +08003350static void hci_key_refresh_complete_evt(struct hci_dev *hdev,
3351 struct sk_buff *skb)
3352{
3353 struct hci_ev_key_refresh_complete *ev = (void *) skb->data;
3354 struct hci_conn *conn;
3355
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +03003356 BT_DBG("%s status 0x%2.2x handle 0x%4.4x", hdev->name, ev->status,
Johan Hedberg1c2e0042012-06-08 23:31:13 +08003357 __le16_to_cpu(ev->handle));
3358
3359 hci_dev_lock(hdev);
3360
3361 conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
3362 if (!conn)
3363 goto unlock;
3364
3365 if (!ev->status)
3366 conn->sec_level = conn->pending_sec_level;
3367
3368 clear_bit(HCI_CONN_ENCRYPT_PEND, &conn->flags);
3369
3370 if (ev->status && conn->state == BT_CONNECTED) {
3371 hci_acl_disconn(conn, HCI_ERROR_AUTH_FAILURE);
3372 hci_conn_put(conn);
3373 goto unlock;
3374 }
3375
3376 if (conn->state == BT_CONFIG) {
3377 if (!ev->status)
3378 conn->state = BT_CONNECTED;
3379
3380 hci_proto_connect_cfm(conn, ev->status);
3381 hci_conn_put(conn);
3382 } else {
3383 hci_auth_cfm(conn, ev->status);
3384
3385 hci_conn_hold(conn);
3386 conn->disc_timeout = HCI_DISCONN_TIMEOUT;
3387 hci_conn_put(conn);
3388 }
3389
3390unlock:
3391 hci_dev_unlock(hdev);
3392}
3393
Gustavo Padovan6039aa72012-05-23 04:04:18 -03003394static u8 hci_get_auth_req(struct hci_conn *conn)
Johan Hedberg17fa4b92011-01-25 13:28:33 +02003395{
3396 /* If remote requests dedicated bonding follow that lead */
3397 if (conn->remote_auth == 0x02 || conn->remote_auth == 0x03) {
3398 /* If both remote and local IO capabilities allow MITM
3399 * protection then require it, otherwise don't */
3400 if (conn->remote_cap == 0x03 || conn->io_capability == 0x03)
3401 return 0x02;
3402 else
3403 return 0x03;
3404 }
3405
3406 /* If remote requests no-bonding follow that lead */
3407 if (conn->remote_auth == 0x00 || conn->remote_auth == 0x01)
Waldemar Rymarkiewicz58797bf2011-04-28 12:07:58 +02003408 return conn->remote_auth | (conn->auth_type & 0x01);
Johan Hedberg17fa4b92011-01-25 13:28:33 +02003409
3410 return conn->auth_type;
3411}
3412
Gustavo Padovan6039aa72012-05-23 04:04:18 -03003413static void hci_io_capa_request_evt(struct hci_dev *hdev, struct sk_buff *skb)
Marcel Holtmann04936842008-07-14 20:13:48 +02003414{
3415 struct hci_ev_io_capa_request *ev = (void *) skb->data;
3416 struct hci_conn *conn;
3417
3418 BT_DBG("%s", hdev->name);
3419
3420 hci_dev_lock(hdev);
3421
3422 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
Johan Hedberg03b555e2011-01-04 15:40:05 +02003423 if (!conn)
3424 goto unlock;
Marcel Holtmann04936842008-07-14 20:13:48 +02003425
Johan Hedberg03b555e2011-01-04 15:40:05 +02003426 hci_conn_hold(conn);
3427
Johan Hedberga8b2d5c2012-01-08 23:11:15 +02003428 if (!test_bit(HCI_MGMT, &hdev->dev_flags))
Johan Hedberg03b555e2011-01-04 15:40:05 +02003429 goto unlock;
3430
Johan Hedberga8b2d5c2012-01-08 23:11:15 +02003431 if (test_bit(HCI_PAIRABLE, &hdev->dev_flags) ||
Gustavo Padovan807deac2012-05-17 00:36:24 -03003432 (conn->remote_auth & ~0x01) == HCI_AT_NO_BONDING) {
Johan Hedberg17fa4b92011-01-25 13:28:33 +02003433 struct hci_cp_io_capability_reply cp;
3434
3435 bacpy(&cp.bdaddr, &ev->bdaddr);
Hemant Gupta7a7f1e72012-01-16 13:34:29 +05303436 /* Change the IO capability from KeyboardDisplay
3437 * to DisplayYesNo as it is not supported by BT spec. */
3438 cp.capability = (conn->io_capability == 0x04) ?
3439 0x01 : conn->io_capability;
Johan Hedberg7cbc9bd2011-04-28 11:29:04 -07003440 conn->auth_type = hci_get_auth_req(conn);
3441 cp.authentication = conn->auth_type;
Johan Hedberg17fa4b92011-01-25 13:28:33 +02003442
Gustavo Padovan8fc9ced2012-05-23 04:04:21 -03003443 if (hci_find_remote_oob_data(hdev, &conn->dst) &&
3444 (conn->out || test_bit(HCI_CONN_REMOTE_OOB, &conn->flags)))
Szymon Jancce85ee12011-03-22 13:12:23 +01003445 cp.oob_data = 0x01;
3446 else
3447 cp.oob_data = 0x00;
3448
Johan Hedberg17fa4b92011-01-25 13:28:33 +02003449 hci_send_cmd(hdev, HCI_OP_IO_CAPABILITY_REPLY,
Gustavo Padovan807deac2012-05-17 00:36:24 -03003450 sizeof(cp), &cp);
Johan Hedberg03b555e2011-01-04 15:40:05 +02003451 } else {
3452 struct hci_cp_io_capability_neg_reply cp;
3453
3454 bacpy(&cp.bdaddr, &ev->bdaddr);
Andrei Emeltchenko9f5a0d72011-11-07 14:20:25 +02003455 cp.reason = HCI_ERROR_PAIRING_NOT_ALLOWED;
Johan Hedberg03b555e2011-01-04 15:40:05 +02003456
3457 hci_send_cmd(hdev, HCI_OP_IO_CAPABILITY_NEG_REPLY,
Gustavo Padovan807deac2012-05-17 00:36:24 -03003458 sizeof(cp), &cp);
Johan Hedberg03b555e2011-01-04 15:40:05 +02003459 }
3460
3461unlock:
3462 hci_dev_unlock(hdev);
3463}
3464
Gustavo Padovan6039aa72012-05-23 04:04:18 -03003465static void hci_io_capa_reply_evt(struct hci_dev *hdev, struct sk_buff *skb)
Johan Hedberg03b555e2011-01-04 15:40:05 +02003466{
3467 struct hci_ev_io_capa_reply *ev = (void *) skb->data;
3468 struct hci_conn *conn;
3469
3470 BT_DBG("%s", hdev->name);
3471
3472 hci_dev_lock(hdev);
3473
3474 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
3475 if (!conn)
3476 goto unlock;
3477
Johan Hedberg03b555e2011-01-04 15:40:05 +02003478 conn->remote_cap = ev->capability;
Johan Hedberg03b555e2011-01-04 15:40:05 +02003479 conn->remote_auth = ev->authentication;
Johan Hedberg58a681e2012-01-16 06:47:28 +02003480 if (ev->oob_data)
3481 set_bit(HCI_CONN_REMOTE_OOB, &conn->flags);
Johan Hedberg03b555e2011-01-04 15:40:05 +02003482
3483unlock:
Marcel Holtmann04936842008-07-14 20:13:48 +02003484 hci_dev_unlock(hdev);
3485}
3486
Gustavo Padovan6039aa72012-05-23 04:04:18 -03003487static void hci_user_confirm_request_evt(struct hci_dev *hdev,
3488 struct sk_buff *skb)
Johan Hedberga5c29682011-02-19 12:05:57 -03003489{
3490 struct hci_ev_user_confirm_req *ev = (void *) skb->data;
Johan Hedberg55bc1a32011-04-28 11:28:56 -07003491 int loc_mitm, rem_mitm, confirm_hint = 0;
Johan Hedberg7a828902011-04-28 11:28:53 -07003492 struct hci_conn *conn;
Johan Hedberga5c29682011-02-19 12:05:57 -03003493
3494 BT_DBG("%s", hdev->name);
3495
3496 hci_dev_lock(hdev);
3497
Johan Hedberga8b2d5c2012-01-08 23:11:15 +02003498 if (!test_bit(HCI_MGMT, &hdev->dev_flags))
Johan Hedberg7a828902011-04-28 11:28:53 -07003499 goto unlock;
Johan Hedberga5c29682011-02-19 12:05:57 -03003500
Johan Hedberg7a828902011-04-28 11:28:53 -07003501 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
3502 if (!conn)
3503 goto unlock;
3504
3505 loc_mitm = (conn->auth_type & 0x01);
3506 rem_mitm = (conn->remote_auth & 0x01);
3507
3508 /* If we require MITM but the remote device can't provide that
3509 * (it has NoInputNoOutput) then reject the confirmation
3510 * request. The only exception is when we're dedicated bonding
3511 * initiators (connect_cfm_cb set) since then we always have the MITM
3512 * bit set. */
3513 if (!conn->connect_cfm_cb && loc_mitm && conn->remote_cap == 0x03) {
3514 BT_DBG("Rejecting request: remote device can't provide MITM");
3515 hci_send_cmd(hdev, HCI_OP_USER_CONFIRM_NEG_REPLY,
Gustavo Padovan807deac2012-05-17 00:36:24 -03003516 sizeof(ev->bdaddr), &ev->bdaddr);
Johan Hedberg7a828902011-04-28 11:28:53 -07003517 goto unlock;
3518 }
3519
3520 /* If no side requires MITM protection; auto-accept */
3521 if ((!loc_mitm || conn->remote_cap == 0x03) &&
Gustavo Padovan807deac2012-05-17 00:36:24 -03003522 (!rem_mitm || conn->io_capability == 0x03)) {
Johan Hedberg55bc1a32011-04-28 11:28:56 -07003523
3524 /* If we're not the initiators request authorization to
3525 * proceed from user space (mgmt_user_confirm with
3526 * confirm_hint set to 1). */
Johan Hedberg51a8efd2012-01-16 06:10:31 +02003527 if (!test_bit(HCI_CONN_AUTH_PEND, &conn->flags)) {
Johan Hedberg55bc1a32011-04-28 11:28:56 -07003528 BT_DBG("Confirming auto-accept as acceptor");
3529 confirm_hint = 1;
3530 goto confirm;
3531 }
3532
Johan Hedberg9f616562011-04-28 11:28:54 -07003533 BT_DBG("Auto-accept of user confirmation with %ums delay",
Gustavo Padovan807deac2012-05-17 00:36:24 -03003534 hdev->auto_accept_delay);
Johan Hedberg9f616562011-04-28 11:28:54 -07003535
3536 if (hdev->auto_accept_delay > 0) {
3537 int delay = msecs_to_jiffies(hdev->auto_accept_delay);
3538 mod_timer(&conn->auto_accept_timer, jiffies + delay);
3539 goto unlock;
3540 }
3541
Johan Hedberg7a828902011-04-28 11:28:53 -07003542 hci_send_cmd(hdev, HCI_OP_USER_CONFIRM_REPLY,
Gustavo Padovan807deac2012-05-17 00:36:24 -03003543 sizeof(ev->bdaddr), &ev->bdaddr);
Johan Hedberg7a828902011-04-28 11:28:53 -07003544 goto unlock;
3545 }
3546
Johan Hedberg55bc1a32011-04-28 11:28:56 -07003547confirm:
Johan Hedberg272d90d2012-02-09 15:26:12 +02003548 mgmt_user_confirm_request(hdev, &ev->bdaddr, ACL_LINK, 0, ev->passkey,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003549 confirm_hint);
Johan Hedberg7a828902011-04-28 11:28:53 -07003550
3551unlock:
Johan Hedberga5c29682011-02-19 12:05:57 -03003552 hci_dev_unlock(hdev);
3553}
3554
Gustavo Padovan6039aa72012-05-23 04:04:18 -03003555static void hci_user_passkey_request_evt(struct hci_dev *hdev,
3556 struct sk_buff *skb)
Brian Gix1143d452011-11-23 08:28:34 -08003557{
3558 struct hci_ev_user_passkey_req *ev = (void *) skb->data;
3559
3560 BT_DBG("%s", hdev->name);
3561
Johan Hedberga8b2d5c2012-01-08 23:11:15 +02003562 if (test_bit(HCI_MGMT, &hdev->dev_flags))
Johan Hedberg272d90d2012-02-09 15:26:12 +02003563 mgmt_user_passkey_request(hdev, &ev->bdaddr, ACL_LINK, 0);
Brian Gix1143d452011-11-23 08:28:34 -08003564}
3565
Johan Hedberg92a25252012-09-06 18:39:26 +03003566static void hci_user_passkey_notify_evt(struct hci_dev *hdev,
3567 struct sk_buff *skb)
3568{
3569 struct hci_ev_user_passkey_notify *ev = (void *) skb->data;
3570 struct hci_conn *conn;
3571
3572 BT_DBG("%s", hdev->name);
3573
3574 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
3575 if (!conn)
3576 return;
3577
3578 conn->passkey_notify = __le32_to_cpu(ev->passkey);
3579 conn->passkey_entered = 0;
3580
3581 if (test_bit(HCI_MGMT, &hdev->dev_flags))
3582 mgmt_user_passkey_notify(hdev, &conn->dst, conn->type,
3583 conn->dst_type, conn->passkey_notify,
3584 conn->passkey_entered);
3585}
3586
3587static void hci_keypress_notify_evt(struct hci_dev *hdev, struct sk_buff *skb)
3588{
3589 struct hci_ev_keypress_notify *ev = (void *) skb->data;
3590 struct hci_conn *conn;
3591
3592 BT_DBG("%s", hdev->name);
3593
3594 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
3595 if (!conn)
3596 return;
3597
3598 switch (ev->type) {
3599 case HCI_KEYPRESS_STARTED:
3600 conn->passkey_entered = 0;
3601 return;
3602
3603 case HCI_KEYPRESS_ENTERED:
3604 conn->passkey_entered++;
3605 break;
3606
3607 case HCI_KEYPRESS_ERASED:
3608 conn->passkey_entered--;
3609 break;
3610
3611 case HCI_KEYPRESS_CLEARED:
3612 conn->passkey_entered = 0;
3613 break;
3614
3615 case HCI_KEYPRESS_COMPLETED:
3616 return;
3617 }
3618
3619 if (test_bit(HCI_MGMT, &hdev->dev_flags))
3620 mgmt_user_passkey_notify(hdev, &conn->dst, conn->type,
3621 conn->dst_type, conn->passkey_notify,
3622 conn->passkey_entered);
3623}
3624
Gustavo Padovan6039aa72012-05-23 04:04:18 -03003625static void hci_simple_pair_complete_evt(struct hci_dev *hdev,
3626 struct sk_buff *skb)
Marcel Holtmann04936842008-07-14 20:13:48 +02003627{
3628 struct hci_ev_simple_pair_complete *ev = (void *) skb->data;
3629 struct hci_conn *conn;
3630
3631 BT_DBG("%s", hdev->name);
3632
3633 hci_dev_lock(hdev);
3634
3635 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
Johan Hedberg2a611692011-02-19 12:06:00 -03003636 if (!conn)
3637 goto unlock;
Marcel Holtmann04936842008-07-14 20:13:48 +02003638
Johan Hedberg2a611692011-02-19 12:06:00 -03003639 /* To avoid duplicate auth_failed events to user space we check
3640 * the HCI_CONN_AUTH_PEND flag which will be set if we
3641 * initiated the authentication. A traditional auth_complete
3642 * event gets always produced as initiator and is also mapped to
3643 * the mgmt_auth_failed event */
Mikel Astizfa1bd912012-08-09 09:52:29 +02003644 if (!test_bit(HCI_CONN_AUTH_PEND, &conn->flags) && ev->status)
Johan Hedbergbab73cb2012-02-09 16:07:29 +02003645 mgmt_auth_failed(hdev, &conn->dst, conn->type, conn->dst_type,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003646 ev->status);
Johan Hedberg2a611692011-02-19 12:06:00 -03003647
3648 hci_conn_put(conn);
3649
3650unlock:
Marcel Holtmann04936842008-07-14 20:13:48 +02003651 hci_dev_unlock(hdev);
3652}
3653
Gustavo Padovan6039aa72012-05-23 04:04:18 -03003654static void hci_remote_host_features_evt(struct hci_dev *hdev,
3655 struct sk_buff *skb)
Marcel Holtmann41a96212008-07-14 20:13:48 +02003656{
3657 struct hci_ev_remote_host_features *ev = (void *) skb->data;
3658 struct inquiry_entry *ie;
3659
3660 BT_DBG("%s", hdev->name);
3661
3662 hci_dev_lock(hdev);
3663
Andrei Emeltchenkocc11b9c2010-11-22 13:21:37 +02003664 ie = hci_inquiry_cache_lookup(hdev, &ev->bdaddr);
3665 if (ie)
Johan Hedberg02b7cc62012-02-28 02:28:43 +02003666 ie->data.ssp_mode = (ev->features[0] & LMP_HOST_SSP);
Marcel Holtmann41a96212008-07-14 20:13:48 +02003667
3668 hci_dev_unlock(hdev);
3669}
3670
Gustavo Padovan6039aa72012-05-23 04:04:18 -03003671static void hci_remote_oob_data_request_evt(struct hci_dev *hdev,
3672 struct sk_buff *skb)
Szymon Janc2763eda2011-03-22 13:12:22 +01003673{
3674 struct hci_ev_remote_oob_data_request *ev = (void *) skb->data;
3675 struct oob_data *data;
3676
3677 BT_DBG("%s", hdev->name);
3678
3679 hci_dev_lock(hdev);
3680
Johan Hedberga8b2d5c2012-01-08 23:11:15 +02003681 if (!test_bit(HCI_MGMT, &hdev->dev_flags))
Szymon Jance1ba1f12011-04-06 13:01:59 +02003682 goto unlock;
3683
Szymon Janc2763eda2011-03-22 13:12:22 +01003684 data = hci_find_remote_oob_data(hdev, &ev->bdaddr);
3685 if (data) {
3686 struct hci_cp_remote_oob_data_reply cp;
3687
3688 bacpy(&cp.bdaddr, &ev->bdaddr);
3689 memcpy(cp.hash, data->hash, sizeof(cp.hash));
3690 memcpy(cp.randomizer, data->randomizer, sizeof(cp.randomizer));
3691
3692 hci_send_cmd(hdev, HCI_OP_REMOTE_OOB_DATA_REPLY, sizeof(cp),
Gustavo Padovan807deac2012-05-17 00:36:24 -03003693 &cp);
Szymon Janc2763eda2011-03-22 13:12:22 +01003694 } else {
3695 struct hci_cp_remote_oob_data_neg_reply cp;
3696
3697 bacpy(&cp.bdaddr, &ev->bdaddr);
3698 hci_send_cmd(hdev, HCI_OP_REMOTE_OOB_DATA_NEG_REPLY, sizeof(cp),
Gustavo Padovan807deac2012-05-17 00:36:24 -03003699 &cp);
Szymon Janc2763eda2011-03-22 13:12:22 +01003700 }
3701
Szymon Jance1ba1f12011-04-06 13:01:59 +02003702unlock:
Szymon Janc2763eda2011-03-22 13:12:22 +01003703 hci_dev_unlock(hdev);
3704}
3705
Andrei Emeltchenkod5e91192012-10-25 15:20:44 +03003706static void hci_phy_link_complete_evt(struct hci_dev *hdev,
3707 struct sk_buff *skb)
3708{
3709 struct hci_ev_phy_link_complete *ev = (void *) skb->data;
3710 struct hci_conn *hcon, *bredr_hcon;
3711
3712 BT_DBG("%s handle 0x%2.2x status 0x%2.2x", hdev->name, ev->phy_handle,
3713 ev->status);
3714
3715 hci_dev_lock(hdev);
3716
3717 hcon = hci_conn_hash_lookup_handle(hdev, ev->phy_handle);
3718 if (!hcon) {
3719 hci_dev_unlock(hdev);
3720 return;
3721 }
3722
3723 if (ev->status) {
3724 hci_conn_del(hcon);
3725 hci_dev_unlock(hdev);
3726 return;
3727 }
3728
3729 bredr_hcon = hcon->amp_mgr->l2cap_conn->hcon;
3730
3731 hcon->state = BT_CONNECTED;
3732 bacpy(&hcon->dst, &bredr_hcon->dst);
3733
3734 hci_conn_hold(hcon);
3735 hcon->disc_timeout = HCI_DISCONN_TIMEOUT;
3736 hci_conn_put(hcon);
3737
3738 hci_conn_hold_device(hcon);
3739 hci_conn_add_sysfs(hcon);
3740
Andrei Emeltchenkocf70ff22012-10-31 15:46:36 +02003741 amp_physical_cfm(bredr_hcon, hcon);
3742
Andrei Emeltchenkod5e91192012-10-25 15:20:44 +03003743 hci_dev_unlock(hdev);
Andrei Emeltchenkod5e91192012-10-25 15:20:44 +03003744}
3745
Andrei Emeltchenko27695fb2012-10-25 15:20:45 +03003746static void hci_loglink_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
3747{
3748 struct hci_ev_logical_link_complete *ev = (void *) skb->data;
3749 struct hci_conn *hcon;
3750 struct hci_chan *hchan;
3751 struct amp_mgr *mgr;
3752
3753 BT_DBG("%s log_handle 0x%4.4x phy_handle 0x%2.2x status 0x%2.2x",
3754 hdev->name, le16_to_cpu(ev->handle), ev->phy_handle,
3755 ev->status);
3756
3757 hcon = hci_conn_hash_lookup_handle(hdev, ev->phy_handle);
3758 if (!hcon)
3759 return;
3760
3761 /* Create AMP hchan */
3762 hchan = hci_chan_create(hcon);
3763 if (!hchan)
3764 return;
3765
3766 hchan->handle = le16_to_cpu(ev->handle);
3767
3768 BT_DBG("hcon %p mgr %p hchan %p", hcon, hcon->amp_mgr, hchan);
3769
3770 mgr = hcon->amp_mgr;
3771 if (mgr && mgr->bredr_chan) {
3772 struct l2cap_chan *bredr_chan = mgr->bredr_chan;
3773
3774 l2cap_chan_lock(bredr_chan);
3775
3776 bredr_chan->conn->mtu = hdev->block_mtu;
3777 l2cap_logical_cfm(bredr_chan, hchan, 0);
3778 hci_conn_hold(hcon);
3779
3780 l2cap_chan_unlock(bredr_chan);
3781 }
3782}
3783
Andrei Emeltchenko606e2a12012-10-31 15:46:31 +02003784static void hci_disconn_loglink_complete_evt(struct hci_dev *hdev,
3785 struct sk_buff *skb)
3786{
3787 struct hci_ev_disconn_logical_link_complete *ev = (void *) skb->data;
3788 struct hci_chan *hchan;
3789
3790 BT_DBG("%s log handle 0x%4.4x status 0x%2.2x", hdev->name,
3791 le16_to_cpu(ev->handle), ev->status);
3792
3793 if (ev->status)
3794 return;
3795
3796 hci_dev_lock(hdev);
3797
3798 hchan = hci_chan_lookup_handle(hdev, le16_to_cpu(ev->handle));
3799 if (!hchan)
3800 goto unlock;
3801
3802 amp_destroy_logical_link(hchan, ev->reason);
3803
3804unlock:
3805 hci_dev_unlock(hdev);
3806}
3807
Andrei Emeltchenko9eef6b32012-10-31 15:46:32 +02003808static void hci_disconn_phylink_complete_evt(struct hci_dev *hdev,
3809 struct sk_buff *skb)
3810{
3811 struct hci_ev_disconn_phy_link_complete *ev = (void *) skb->data;
3812 struct hci_conn *hcon;
3813
3814 BT_DBG("%s status 0x%2.2x", hdev->name, ev->status);
3815
3816 if (ev->status)
3817 return;
3818
3819 hci_dev_lock(hdev);
3820
3821 hcon = hci_conn_hash_lookup_handle(hdev, ev->phy_handle);
3822 if (hcon) {
3823 hcon->state = BT_CLOSED;
3824 hci_conn_del(hcon);
3825 }
3826
3827 hci_dev_unlock(hdev);
3828}
3829
Gustavo Padovan6039aa72012-05-23 04:04:18 -03003830static void hci_le_conn_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
Ville Tervofcd89c02011-02-10 22:38:47 -03003831{
3832 struct hci_ev_le_conn_complete *ev = (void *) skb->data;
3833 struct hci_conn *conn;
3834
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +03003835 BT_DBG("%s status 0x%2.2x", hdev->name, ev->status);
Ville Tervofcd89c02011-02-10 22:38:47 -03003836
3837 hci_dev_lock(hdev);
3838
Andre Guedesb47a09b2012-07-27 15:10:15 -03003839 conn = hci_conn_hash_lookup_state(hdev, LE_LINK, BT_CONNECT);
Ville Tervob62f3282011-02-10 22:38:50 -03003840 if (!conn) {
3841 conn = hci_conn_add(hdev, LE_LINK, &ev->bdaddr);
3842 if (!conn) {
3843 BT_ERR("No memory for new connection");
Andre Guedes230fd162012-07-27 15:10:10 -03003844 goto unlock;
Ville Tervob62f3282011-02-10 22:38:50 -03003845 }
Andre Guedes29b79882011-05-31 14:20:54 -03003846
3847 conn->dst_type = ev->bdaddr_type;
Andre Guedesb9b343d2012-07-27 15:10:11 -03003848
3849 if (ev->role == LE_CONN_ROLE_MASTER) {
3850 conn->out = true;
3851 conn->link_mode |= HCI_LM_MASTER;
3852 }
Ville Tervob62f3282011-02-10 22:38:50 -03003853 }
Ville Tervofcd89c02011-02-10 22:38:47 -03003854
Andre Guedescd17dec2012-07-27 15:10:16 -03003855 if (ev->status) {
3856 mgmt_connect_failed(hdev, &conn->dst, conn->type,
3857 conn->dst_type, ev->status);
3858 hci_proto_connect_cfm(conn, ev->status);
3859 conn->state = BT_CLOSED;
3860 hci_conn_del(conn);
3861 goto unlock;
3862 }
3863
Johan Hedbergb644ba32012-01-17 21:48:47 +02003864 if (!test_and_set_bit(HCI_CONN_MGMT_CONNECTED, &conn->flags))
3865 mgmt_device_connected(hdev, &ev->bdaddr, conn->type,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003866 conn->dst_type, 0, NULL, 0, NULL);
Vinicius Costa Gomes83bc71b2011-05-06 18:41:43 -03003867
Vinicius Costa Gomes7b5c0d52011-06-09 18:50:50 -03003868 conn->sec_level = BT_SECURITY_LOW;
Ville Tervofcd89c02011-02-10 22:38:47 -03003869 conn->handle = __le16_to_cpu(ev->handle);
3870 conn->state = BT_CONNECTED;
3871
3872 hci_conn_hold_device(conn);
3873 hci_conn_add_sysfs(conn);
3874
3875 hci_proto_connect_cfm(conn, ev->status);
3876
3877unlock:
3878 hci_dev_unlock(hdev);
3879}
3880
Gustavo Padovan6039aa72012-05-23 04:04:18 -03003881static void hci_le_adv_report_evt(struct hci_dev *hdev, struct sk_buff *skb)
Andre Guedes9aa04c92011-05-26 16:23:51 -03003882{
Andre Guedese95beb42011-09-26 20:48:35 -03003883 u8 num_reports = skb->data[0];
3884 void *ptr = &skb->data[1];
Andre Guedes3c9e9192012-01-10 18:20:50 -03003885 s8 rssi;
Andre Guedes9aa04c92011-05-26 16:23:51 -03003886
3887 hci_dev_lock(hdev);
3888
Andre Guedese95beb42011-09-26 20:48:35 -03003889 while (num_reports--) {
3890 struct hci_ev_le_advertising_info *ev = ptr;
Andre Guedes9aa04c92011-05-26 16:23:51 -03003891
Andre Guedes3c9e9192012-01-10 18:20:50 -03003892 rssi = ev->data[ev->length];
3893 mgmt_device_found(hdev, &ev->bdaddr, LE_LINK, ev->bdaddr_type,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003894 NULL, rssi, 0, 1, ev->data, ev->length);
Andre Guedes3c9e9192012-01-10 18:20:50 -03003895
Andre Guedese95beb42011-09-26 20:48:35 -03003896 ptr += sizeof(*ev) + ev->length + 1;
Andre Guedes9aa04c92011-05-26 16:23:51 -03003897 }
3898
3899 hci_dev_unlock(hdev);
3900}
3901
Gustavo Padovan6039aa72012-05-23 04:04:18 -03003902static void hci_le_ltk_request_evt(struct hci_dev *hdev, struct sk_buff *skb)
Vinicius Costa Gomesa7a595f2011-06-09 18:50:47 -03003903{
3904 struct hci_ev_le_ltk_req *ev = (void *) skb->data;
3905 struct hci_cp_le_ltk_reply cp;
Vinicius Costa Gomesbea710f2011-07-07 18:59:37 -03003906 struct hci_cp_le_ltk_neg_reply neg;
Vinicius Costa Gomesa7a595f2011-06-09 18:50:47 -03003907 struct hci_conn *conn;
Vinicius Costa Gomesc9839a12012-02-02 21:08:01 -03003908 struct smp_ltk *ltk;
Vinicius Costa Gomesa7a595f2011-06-09 18:50:47 -03003909
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +03003910 BT_DBG("%s handle 0x%4.4x", hdev->name, __le16_to_cpu(ev->handle));
Vinicius Costa Gomesa7a595f2011-06-09 18:50:47 -03003911
3912 hci_dev_lock(hdev);
3913
3914 conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
Vinicius Costa Gomesbea710f2011-07-07 18:59:37 -03003915 if (conn == NULL)
3916 goto not_found;
Vinicius Costa Gomesa7a595f2011-06-09 18:50:47 -03003917
Vinicius Costa Gomesbea710f2011-07-07 18:59:37 -03003918 ltk = hci_find_ltk(hdev, ev->ediv, ev->random);
3919 if (ltk == NULL)
3920 goto not_found;
3921
3922 memcpy(cp.ltk, ltk->val, sizeof(ltk->val));
Vinicius Costa Gomesa7a595f2011-06-09 18:50:47 -03003923 cp.handle = cpu_to_le16(conn->handle);
Vinicius Costa Gomesc9839a12012-02-02 21:08:01 -03003924
3925 if (ltk->authenticated)
3926 conn->sec_level = BT_SECURITY_HIGH;
Vinicius Costa Gomesa7a595f2011-06-09 18:50:47 -03003927
3928 hci_send_cmd(hdev, HCI_OP_LE_LTK_REPLY, sizeof(cp), &cp);
3929
Vinicius Costa Gomesc9839a12012-02-02 21:08:01 -03003930 if (ltk->type & HCI_SMP_STK) {
3931 list_del(&ltk->list);
3932 kfree(ltk);
3933 }
3934
Vinicius Costa Gomesa7a595f2011-06-09 18:50:47 -03003935 hci_dev_unlock(hdev);
Vinicius Costa Gomesbea710f2011-07-07 18:59:37 -03003936
3937 return;
3938
3939not_found:
3940 neg.handle = ev->handle;
3941 hci_send_cmd(hdev, HCI_OP_LE_LTK_NEG_REPLY, sizeof(neg), &neg);
3942 hci_dev_unlock(hdev);
Vinicius Costa Gomesa7a595f2011-06-09 18:50:47 -03003943}
3944
Gustavo Padovan6039aa72012-05-23 04:04:18 -03003945static void hci_le_meta_evt(struct hci_dev *hdev, struct sk_buff *skb)
Ville Tervofcd89c02011-02-10 22:38:47 -03003946{
3947 struct hci_ev_le_meta *le_ev = (void *) skb->data;
3948
3949 skb_pull(skb, sizeof(*le_ev));
3950
3951 switch (le_ev->subevent) {
3952 case HCI_EV_LE_CONN_COMPLETE:
3953 hci_le_conn_complete_evt(hdev, skb);
3954 break;
3955
Andre Guedes9aa04c92011-05-26 16:23:51 -03003956 case HCI_EV_LE_ADVERTISING_REPORT:
3957 hci_le_adv_report_evt(hdev, skb);
3958 break;
3959
Vinicius Costa Gomesa7a595f2011-06-09 18:50:47 -03003960 case HCI_EV_LE_LTK_REQ:
3961 hci_le_ltk_request_evt(hdev, skb);
3962 break;
3963
Ville Tervofcd89c02011-02-10 22:38:47 -03003964 default:
3965 break;
3966 }
3967}
3968
Andrei Emeltchenko9495b2e2012-09-27 17:26:22 +03003969static void hci_chan_selected_evt(struct hci_dev *hdev, struct sk_buff *skb)
3970{
3971 struct hci_ev_channel_selected *ev = (void *) skb->data;
3972 struct hci_conn *hcon;
3973
3974 BT_DBG("%s handle 0x%2.2x", hdev->name, ev->phy_handle);
3975
3976 skb_pull(skb, sizeof(*ev));
3977
3978 hcon = hci_conn_hash_lookup_handle(hdev, ev->phy_handle);
3979 if (!hcon)
3980 return;
3981
3982 amp_read_loc_assoc_final_data(hdev, hcon);
3983}
3984
Linus Torvalds1da177e2005-04-16 15:20:36 -07003985void hci_event_packet(struct hci_dev *hdev, struct sk_buff *skb)
3986{
Marcel Holtmanna9de9242007-10-20 13:33:56 +02003987 struct hci_event_hdr *hdr = (void *) skb->data;
3988 __u8 event = hdr->evt;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003989
3990 skb_pull(skb, HCI_EVENT_HDR_SIZE);
3991
Marcel Holtmanna9de9242007-10-20 13:33:56 +02003992 switch (event) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003993 case HCI_EV_INQUIRY_COMPLETE:
3994 hci_inquiry_complete_evt(hdev, skb);
3995 break;
3996
3997 case HCI_EV_INQUIRY_RESULT:
3998 hci_inquiry_result_evt(hdev, skb);
3999 break;
4000
Marcel Holtmanna9de9242007-10-20 13:33:56 +02004001 case HCI_EV_CONN_COMPLETE:
4002 hci_conn_complete_evt(hdev, skb);
Marcel Holtmann21d9e302005-09-13 01:32:25 +02004003 break;
4004
Linus Torvalds1da177e2005-04-16 15:20:36 -07004005 case HCI_EV_CONN_REQUEST:
4006 hci_conn_request_evt(hdev, skb);
4007 break;
4008
Linus Torvalds1da177e2005-04-16 15:20:36 -07004009 case HCI_EV_DISCONN_COMPLETE:
4010 hci_disconn_complete_evt(hdev, skb);
4011 break;
4012
Linus Torvalds1da177e2005-04-16 15:20:36 -07004013 case HCI_EV_AUTH_COMPLETE:
4014 hci_auth_complete_evt(hdev, skb);
4015 break;
4016
Marcel Holtmanna9de9242007-10-20 13:33:56 +02004017 case HCI_EV_REMOTE_NAME:
4018 hci_remote_name_evt(hdev, skb);
4019 break;
4020
Linus Torvalds1da177e2005-04-16 15:20:36 -07004021 case HCI_EV_ENCRYPT_CHANGE:
4022 hci_encrypt_change_evt(hdev, skb);
4023 break;
4024
Marcel Holtmanna9de9242007-10-20 13:33:56 +02004025 case HCI_EV_CHANGE_LINK_KEY_COMPLETE:
4026 hci_change_link_key_complete_evt(hdev, skb);
4027 break;
4028
4029 case HCI_EV_REMOTE_FEATURES:
4030 hci_remote_features_evt(hdev, skb);
4031 break;
4032
4033 case HCI_EV_REMOTE_VERSION:
4034 hci_remote_version_evt(hdev, skb);
4035 break;
4036
4037 case HCI_EV_QOS_SETUP_COMPLETE:
4038 hci_qos_setup_complete_evt(hdev, skb);
4039 break;
4040
4041 case HCI_EV_CMD_COMPLETE:
4042 hci_cmd_complete_evt(hdev, skb);
4043 break;
4044
4045 case HCI_EV_CMD_STATUS:
4046 hci_cmd_status_evt(hdev, skb);
4047 break;
4048
4049 case HCI_EV_ROLE_CHANGE:
4050 hci_role_change_evt(hdev, skb);
4051 break;
4052
4053 case HCI_EV_NUM_COMP_PKTS:
4054 hci_num_comp_pkts_evt(hdev, skb);
4055 break;
4056
4057 case HCI_EV_MODE_CHANGE:
4058 hci_mode_change_evt(hdev, skb);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004059 break;
4060
4061 case HCI_EV_PIN_CODE_REQ:
4062 hci_pin_code_request_evt(hdev, skb);
4063 break;
4064
4065 case HCI_EV_LINK_KEY_REQ:
4066 hci_link_key_request_evt(hdev, skb);
4067 break;
4068
4069 case HCI_EV_LINK_KEY_NOTIFY:
4070 hci_link_key_notify_evt(hdev, skb);
4071 break;
4072
4073 case HCI_EV_CLOCK_OFFSET:
4074 hci_clock_offset_evt(hdev, skb);
4075 break;
4076
Marcel Holtmanna8746412008-07-14 20:13:46 +02004077 case HCI_EV_PKT_TYPE_CHANGE:
4078 hci_pkt_type_change_evt(hdev, skb);
4079 break;
4080
Marcel Holtmann85a1e932005-08-09 20:28:02 -07004081 case HCI_EV_PSCAN_REP_MODE:
4082 hci_pscan_rep_mode_evt(hdev, skb);
4083 break;
4084
Marcel Holtmanna9de9242007-10-20 13:33:56 +02004085 case HCI_EV_INQUIRY_RESULT_WITH_RSSI:
4086 hci_inquiry_result_with_rssi_evt(hdev, skb);
4087 break;
4088
4089 case HCI_EV_REMOTE_EXT_FEATURES:
4090 hci_remote_ext_features_evt(hdev, skb);
4091 break;
4092
4093 case HCI_EV_SYNC_CONN_COMPLETE:
4094 hci_sync_conn_complete_evt(hdev, skb);
4095 break;
4096
4097 case HCI_EV_SYNC_CONN_CHANGED:
4098 hci_sync_conn_changed_evt(hdev, skb);
4099 break;
4100
Marcel Holtmann04837f62006-07-03 10:02:33 +02004101 case HCI_EV_SNIFF_SUBRATE:
4102 hci_sniff_subrate_evt(hdev, skb);
4103 break;
4104
Marcel Holtmanna9de9242007-10-20 13:33:56 +02004105 case HCI_EV_EXTENDED_INQUIRY_RESULT:
4106 hci_extended_inquiry_result_evt(hdev, skb);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004107 break;
4108
Johan Hedberg1c2e0042012-06-08 23:31:13 +08004109 case HCI_EV_KEY_REFRESH_COMPLETE:
4110 hci_key_refresh_complete_evt(hdev, skb);
4111 break;
4112
Marcel Holtmann04936842008-07-14 20:13:48 +02004113 case HCI_EV_IO_CAPA_REQUEST:
4114 hci_io_capa_request_evt(hdev, skb);
4115 break;
4116
Johan Hedberg03b555e2011-01-04 15:40:05 +02004117 case HCI_EV_IO_CAPA_REPLY:
4118 hci_io_capa_reply_evt(hdev, skb);
4119 break;
4120
Johan Hedberga5c29682011-02-19 12:05:57 -03004121 case HCI_EV_USER_CONFIRM_REQUEST:
4122 hci_user_confirm_request_evt(hdev, skb);
4123 break;
4124
Brian Gix1143d452011-11-23 08:28:34 -08004125 case HCI_EV_USER_PASSKEY_REQUEST:
4126 hci_user_passkey_request_evt(hdev, skb);
4127 break;
4128
Johan Hedberg92a25252012-09-06 18:39:26 +03004129 case HCI_EV_USER_PASSKEY_NOTIFY:
4130 hci_user_passkey_notify_evt(hdev, skb);
4131 break;
4132
4133 case HCI_EV_KEYPRESS_NOTIFY:
4134 hci_keypress_notify_evt(hdev, skb);
4135 break;
4136
Marcel Holtmann04936842008-07-14 20:13:48 +02004137 case HCI_EV_SIMPLE_PAIR_COMPLETE:
4138 hci_simple_pair_complete_evt(hdev, skb);
4139 break;
4140
Marcel Holtmann41a96212008-07-14 20:13:48 +02004141 case HCI_EV_REMOTE_HOST_FEATURES:
4142 hci_remote_host_features_evt(hdev, skb);
4143 break;
4144
Ville Tervofcd89c02011-02-10 22:38:47 -03004145 case HCI_EV_LE_META:
4146 hci_le_meta_evt(hdev, skb);
4147 break;
4148
Andrei Emeltchenko9495b2e2012-09-27 17:26:22 +03004149 case HCI_EV_CHANNEL_SELECTED:
4150 hci_chan_selected_evt(hdev, skb);
4151 break;
4152
Szymon Janc2763eda2011-03-22 13:12:22 +01004153 case HCI_EV_REMOTE_OOB_DATA_REQUEST:
4154 hci_remote_oob_data_request_evt(hdev, skb);
4155 break;
4156
Andrei Emeltchenkod5e91192012-10-25 15:20:44 +03004157 case HCI_EV_PHY_LINK_COMPLETE:
4158 hci_phy_link_complete_evt(hdev, skb);
4159 break;
4160
Andrei Emeltchenko27695fb2012-10-25 15:20:45 +03004161 case HCI_EV_LOGICAL_LINK_COMPLETE:
4162 hci_loglink_complete_evt(hdev, skb);
4163 break;
4164
Andrei Emeltchenko606e2a12012-10-31 15:46:31 +02004165 case HCI_EV_DISCONN_LOGICAL_LINK_COMPLETE:
4166 hci_disconn_loglink_complete_evt(hdev, skb);
4167 break;
4168
Andrei Emeltchenko9eef6b32012-10-31 15:46:32 +02004169 case HCI_EV_DISCONN_PHY_LINK_COMPLETE:
4170 hci_disconn_phylink_complete_evt(hdev, skb);
4171 break;
4172
Andrei Emeltchenko25e89e92012-01-04 12:41:58 +02004173 case HCI_EV_NUM_COMP_BLOCKS:
4174 hci_num_comp_blocks_evt(hdev, skb);
4175 break;
4176
Marcel Holtmanna9de9242007-10-20 13:33:56 +02004177 default:
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +03004178 BT_DBG("%s event 0x%2.2x", hdev->name, event);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004179 break;
4180 }
4181
4182 kfree_skb(skb);
4183 hdev->stat.evt_rx++;
4184}