blob: 14e872aa0d2c7c0b045738dff5c5b09964b60617 [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
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200475static void hci_cc_read_local_version(struct hci_dev *hdev, struct sk_buff *skb)
476{
477 struct hci_rp_read_local_version *rp = (void *) skb->data;
478
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +0300479 BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200480
481 if (rp->status)
Andrei Emeltchenko28b8df72012-02-24 12:45:44 +0200482 goto done;
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200483
484 hdev->hci_ver = rp->hci_ver;
Marcel Holtmanne4e8e372008-07-14 20:13:47 +0200485 hdev->hci_rev = __le16_to_cpu(rp->hci_rev);
Johan Hedbergd5859e22011-01-25 01:19:58 +0200486 hdev->lmp_ver = rp->lmp_ver;
Marcel Holtmanne4e8e372008-07-14 20:13:47 +0200487 hdev->manufacturer = __le16_to_cpu(rp->manufacturer);
Johan Hedbergd5859e22011-01-25 01:19:58 +0200488 hdev->lmp_subver = __le16_to_cpu(rp->lmp_subver);
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200489
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +0300490 BT_DBG("%s manufacturer 0x%4.4x hci ver %d:%d", hdev->name,
Gustavo Padovan807deac2012-05-17 00:36:24 -0300491 hdev->manufacturer, hdev->hci_ver, hdev->hci_rev);
Johan Hedbergd5859e22011-01-25 01:19:58 +0200492
Andrei Emeltchenko28b8df72012-02-24 12:45:44 +0200493done:
494 hci_req_complete(hdev, HCI_OP_READ_LOCAL_VERSION, rp->status);
Johan Hedbergd5859e22011-01-25 01:19:58 +0200495}
496
Gustavo Padovan8fc9ced2012-05-23 04:04:21 -0300497static void hci_cc_read_local_commands(struct hci_dev *hdev,
498 struct sk_buff *skb)
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200499{
500 struct hci_rp_read_local_commands *rp = (void *) skb->data;
501
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +0300502 BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200503
Johan Hedberg2177bab2013-03-05 20:37:43 +0200504 if (!rp->status)
505 memcpy(hdev->commands, rp->commands, sizeof(hdev->commands));
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200506
Johan Hedbergd5859e22011-01-25 01:19:58 +0200507 hci_req_complete(hdev, HCI_OP_READ_LOCAL_COMMANDS, rp->status);
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200508}
509
Gustavo Padovan8fc9ced2012-05-23 04:04:21 -0300510static void hci_cc_read_local_features(struct hci_dev *hdev,
511 struct sk_buff *skb)
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200512{
513 struct hci_rp_read_local_features *rp = (void *) skb->data;
514
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +0300515 BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200516
517 if (rp->status)
518 return;
519
520 memcpy(hdev->features, rp->features, 8);
521
522 /* Adjust default settings according to features
523 * supported by device. */
524
525 if (hdev->features[0] & LMP_3SLOT)
526 hdev->pkt_type |= (HCI_DM3 | HCI_DH3);
527
528 if (hdev->features[0] & LMP_5SLOT)
529 hdev->pkt_type |= (HCI_DM5 | HCI_DH5);
530
531 if (hdev->features[1] & LMP_HV2) {
532 hdev->pkt_type |= (HCI_HV2);
533 hdev->esco_type |= (ESCO_HV2);
534 }
535
536 if (hdev->features[1] & LMP_HV3) {
537 hdev->pkt_type |= (HCI_HV3);
538 hdev->esco_type |= (ESCO_HV3);
539 }
540
Andre Guedes45db810f2012-07-24 15:03:49 -0300541 if (lmp_esco_capable(hdev))
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200542 hdev->esco_type |= (ESCO_EV3);
543
544 if (hdev->features[4] & LMP_EV4)
545 hdev->esco_type |= (ESCO_EV4);
546
547 if (hdev->features[4] & LMP_EV5)
548 hdev->esco_type |= (ESCO_EV5);
549
Marcel Holtmannefc76882009-02-06 09:13:37 +0100550 if (hdev->features[5] & LMP_EDR_ESCO_2M)
551 hdev->esco_type |= (ESCO_2EV3);
552
553 if (hdev->features[5] & LMP_EDR_ESCO_3M)
554 hdev->esco_type |= (ESCO_3EV3);
555
556 if (hdev->features[5] & LMP_EDR_3S_ESCO)
557 hdev->esco_type |= (ESCO_2EV5 | ESCO_3EV5);
558
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200559 BT_DBG("%s features 0x%.2x%.2x%.2x%.2x%.2x%.2x%.2x%.2x", hdev->name,
Gustavo Padovan807deac2012-05-17 00:36:24 -0300560 hdev->features[0], hdev->features[1],
561 hdev->features[2], hdev->features[3],
562 hdev->features[4], hdev->features[5],
563 hdev->features[6], hdev->features[7]);
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200564}
565
Andre Guedes971e3a42011-06-30 19:20:52 -0300566static void hci_cc_read_local_ext_features(struct hci_dev *hdev,
Gustavo Padovan807deac2012-05-17 00:36:24 -0300567 struct sk_buff *skb)
Andre Guedes971e3a42011-06-30 19:20:52 -0300568{
569 struct hci_rp_read_local_ext_features *rp = (void *) skb->data;
570
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +0300571 BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
Andre Guedes971e3a42011-06-30 19:20:52 -0300572
573 if (rp->status)
Johan Hedberg8f984df2012-02-28 01:07:22 +0200574 goto done;
Andre Guedes971e3a42011-06-30 19:20:52 -0300575
Andre Guedesb5b32b62011-12-30 10:34:04 -0300576 switch (rp->page) {
577 case 0:
578 memcpy(hdev->features, rp->features, 8);
579 break;
580 case 1:
581 memcpy(hdev->host_features, rp->features, 8);
582 break;
583 }
Andre Guedes971e3a42011-06-30 19:20:52 -0300584
Johan Hedberg8f984df2012-02-28 01:07:22 +0200585done:
Andre Guedes971e3a42011-06-30 19:20:52 -0300586 hci_req_complete(hdev, HCI_OP_READ_LOCAL_EXT_FEATURES, rp->status);
587}
588
Andrei Emeltchenko1e89cff2011-11-24 14:52:02 +0200589static void hci_cc_read_flow_control_mode(struct hci_dev *hdev,
Gustavo Padovan807deac2012-05-17 00:36:24 -0300590 struct sk_buff *skb)
Andrei Emeltchenko1e89cff2011-11-24 14:52:02 +0200591{
592 struct hci_rp_read_flow_control_mode *rp = (void *) skb->data;
593
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +0300594 BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
Andrei Emeltchenko1e89cff2011-11-24 14:52:02 +0200595
596 if (rp->status)
597 return;
598
599 hdev->flow_ctl_mode = rp->mode;
600
601 hci_req_complete(hdev, HCI_OP_READ_FLOW_CONTROL_MODE, rp->status);
602}
603
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200604static void hci_cc_read_buffer_size(struct hci_dev *hdev, struct sk_buff *skb)
605{
606 struct hci_rp_read_buffer_size *rp = (void *) skb->data;
607
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +0300608 BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200609
610 if (rp->status)
611 return;
612
613 hdev->acl_mtu = __le16_to_cpu(rp->acl_mtu);
614 hdev->sco_mtu = rp->sco_mtu;
615 hdev->acl_pkts = __le16_to_cpu(rp->acl_max_pkt);
616 hdev->sco_pkts = __le16_to_cpu(rp->sco_max_pkt);
617
618 if (test_bit(HCI_QUIRK_FIXUP_BUFFER_SIZE, &hdev->quirks)) {
619 hdev->sco_mtu = 64;
620 hdev->sco_pkts = 8;
621 }
622
623 hdev->acl_cnt = hdev->acl_pkts;
624 hdev->sco_cnt = hdev->sco_pkts;
625
Gustavo Padovan807deac2012-05-17 00:36:24 -0300626 BT_DBG("%s acl mtu %d:%d sco mtu %d:%d", hdev->name, hdev->acl_mtu,
627 hdev->acl_pkts, hdev->sco_mtu, hdev->sco_pkts);
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200628}
629
630static void hci_cc_read_bd_addr(struct hci_dev *hdev, struct sk_buff *skb)
631{
632 struct hci_rp_read_bd_addr *rp = (void *) skb->data;
633
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +0300634 BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200635
636 if (!rp->status)
637 bacpy(&hdev->bdaddr, &rp->bdaddr);
638
Johan Hedberg23bb5762010-12-21 23:01:27 +0200639 hci_req_complete(hdev, HCI_OP_READ_BD_ADDR, rp->status);
640}
641
Andrei Emeltchenko350ee4c2011-12-07 15:56:51 +0200642static void hci_cc_read_data_block_size(struct hci_dev *hdev,
Gustavo Padovan807deac2012-05-17 00:36:24 -0300643 struct sk_buff *skb)
Andrei Emeltchenko350ee4c2011-12-07 15:56:51 +0200644{
645 struct hci_rp_read_data_block_size *rp = (void *) skb->data;
646
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +0300647 BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
Andrei Emeltchenko350ee4c2011-12-07 15:56:51 +0200648
649 if (rp->status)
650 return;
651
652 hdev->block_mtu = __le16_to_cpu(rp->max_acl_len);
653 hdev->block_len = __le16_to_cpu(rp->block_len);
654 hdev->num_blocks = __le16_to_cpu(rp->num_blocks);
655
656 hdev->block_cnt = hdev->num_blocks;
657
658 BT_DBG("%s blk mtu %d cnt %d len %d", hdev->name, hdev->block_mtu,
Gustavo Padovan807deac2012-05-17 00:36:24 -0300659 hdev->block_cnt, hdev->block_len);
Andrei Emeltchenko350ee4c2011-12-07 15:56:51 +0200660
661 hci_req_complete(hdev, HCI_OP_READ_DATA_BLOCK_SIZE, rp->status);
662}
663
Johan Hedberg23bb5762010-12-21 23:01:27 +0200664static void hci_cc_write_ca_timeout(struct hci_dev *hdev, struct sk_buff *skb)
665{
666 __u8 status = *((__u8 *) skb->data);
667
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +0300668 BT_DBG("%s status 0x%2.2x", hdev->name, status);
Johan Hedberg23bb5762010-12-21 23:01:27 +0200669
670 hci_req_complete(hdev, HCI_OP_WRITE_CA_TIMEOUT, status);
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200671}
672
Andrei Emeltchenko928abaa2011-10-12 10:53:57 +0300673static void hci_cc_read_local_amp_info(struct hci_dev *hdev,
Gustavo Padovan807deac2012-05-17 00:36:24 -0300674 struct sk_buff *skb)
Andrei Emeltchenko928abaa2011-10-12 10:53:57 +0300675{
676 struct hci_rp_read_local_amp_info *rp = (void *) skb->data;
677
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +0300678 BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
Andrei Emeltchenko928abaa2011-10-12 10:53:57 +0300679
680 if (rp->status)
Andrei Emeltchenko8e2a0d92012-09-27 17:26:08 +0300681 goto a2mp_rsp;
Andrei Emeltchenko928abaa2011-10-12 10:53:57 +0300682
683 hdev->amp_status = rp->amp_status;
684 hdev->amp_total_bw = __le32_to_cpu(rp->total_bw);
685 hdev->amp_max_bw = __le32_to_cpu(rp->max_bw);
686 hdev->amp_min_latency = __le32_to_cpu(rp->min_latency);
687 hdev->amp_max_pdu = __le32_to_cpu(rp->max_pdu);
688 hdev->amp_type = rp->amp_type;
689 hdev->amp_pal_cap = __le16_to_cpu(rp->pal_cap);
690 hdev->amp_assoc_size = __le16_to_cpu(rp->max_assoc_size);
691 hdev->amp_be_flush_to = __le32_to_cpu(rp->be_flush_to);
692 hdev->amp_max_flush_to = __le32_to_cpu(rp->max_flush_to);
693
694 hci_req_complete(hdev, HCI_OP_READ_LOCAL_AMP_INFO, rp->status);
Andrei Emeltchenko8e2a0d92012-09-27 17:26:08 +0300695
696a2mp_rsp:
697 a2mp_send_getinfo_rsp(hdev);
Andrei Emeltchenko928abaa2011-10-12 10:53:57 +0300698}
699
Andrei Emeltchenko903e4542012-09-27 17:26:09 +0300700static void hci_cc_read_local_amp_assoc(struct hci_dev *hdev,
701 struct sk_buff *skb)
702{
703 struct hci_rp_read_local_amp_assoc *rp = (void *) skb->data;
704 struct amp_assoc *assoc = &hdev->loc_assoc;
705 size_t rem_len, frag_len;
706
707 BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
708
709 if (rp->status)
710 goto a2mp_rsp;
711
712 frag_len = skb->len - sizeof(*rp);
713 rem_len = __le16_to_cpu(rp->rem_len);
714
715 if (rem_len > frag_len) {
Andrei Emeltchenko2e430be32012-09-28 14:44:23 +0300716 BT_DBG("frag_len %zu rem_len %zu", frag_len, rem_len);
Andrei Emeltchenko903e4542012-09-27 17:26:09 +0300717
718 memcpy(assoc->data + assoc->offset, rp->frag, frag_len);
719 assoc->offset += frag_len;
720
721 /* Read other fragments */
722 amp_read_loc_assoc_frag(hdev, rp->phy_handle);
723
724 return;
725 }
726
727 memcpy(assoc->data + assoc->offset, rp->frag, rem_len);
728 assoc->len = assoc->offset + rem_len;
729 assoc->offset = 0;
730
731a2mp_rsp:
732 /* Send A2MP Rsp when all fragments are received */
733 a2mp_send_getampassoc_rsp(hdev, rp->status);
Andrei Emeltchenko9495b2e2012-09-27 17:26:22 +0300734 a2mp_send_create_phy_link_req(hdev, rp->status);
Andrei Emeltchenko903e4542012-09-27 17:26:09 +0300735}
736
Johan Hedbergb0916ea2011-01-10 13:44:55 +0200737static void hci_cc_delete_stored_link_key(struct hci_dev *hdev,
Gustavo Padovan807deac2012-05-17 00:36:24 -0300738 struct sk_buff *skb)
Johan Hedbergb0916ea2011-01-10 13:44:55 +0200739{
740 __u8 status = *((__u8 *) skb->data);
741
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +0300742 BT_DBG("%s status 0x%2.2x", hdev->name, status);
Johan Hedbergb0916ea2011-01-10 13:44:55 +0200743
744 hci_req_complete(hdev, HCI_OP_DELETE_STORED_LINK_KEY, status);
745}
746
Johan Hedbergd5859e22011-01-25 01:19:58 +0200747static void hci_cc_set_event_mask(struct hci_dev *hdev, struct sk_buff *skb)
748{
749 __u8 status = *((__u8 *) skb->data);
750
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +0300751 BT_DBG("%s status 0x%2.2x", hdev->name, status);
Johan Hedbergd5859e22011-01-25 01:19:58 +0200752
753 hci_req_complete(hdev, HCI_OP_SET_EVENT_MASK, status);
754}
755
756static void hci_cc_write_inquiry_mode(struct hci_dev *hdev,
Gustavo Padovan807deac2012-05-17 00:36:24 -0300757 struct sk_buff *skb)
Johan Hedbergd5859e22011-01-25 01:19:58 +0200758{
759 __u8 status = *((__u8 *) skb->data);
760
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +0300761 BT_DBG("%s status 0x%2.2x", hdev->name, status);
Johan Hedbergd5859e22011-01-25 01:19:58 +0200762
763 hci_req_complete(hdev, HCI_OP_WRITE_INQUIRY_MODE, status);
764}
765
766static void hci_cc_read_inq_rsp_tx_power(struct hci_dev *hdev,
Gustavo Padovan807deac2012-05-17 00:36:24 -0300767 struct sk_buff *skb)
Johan Hedbergd5859e22011-01-25 01:19:58 +0200768{
Marcel Holtmann91c4e9b2012-03-11 19:27:21 -0700769 struct hci_rp_read_inq_rsp_tx_power *rp = (void *) skb->data;
Johan Hedbergd5859e22011-01-25 01:19:58 +0200770
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +0300771 BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
Johan Hedbergd5859e22011-01-25 01:19:58 +0200772
Marcel Holtmann91c4e9b2012-03-11 19:27:21 -0700773 if (!rp->status)
774 hdev->inq_tx_power = rp->tx_power;
775
776 hci_req_complete(hdev, HCI_OP_READ_INQ_RSP_TX_POWER, rp->status);
Johan Hedbergd5859e22011-01-25 01:19:58 +0200777}
778
779static void hci_cc_set_event_flt(struct hci_dev *hdev, struct sk_buff *skb)
780{
781 __u8 status = *((__u8 *) skb->data);
782
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +0300783 BT_DBG("%s status 0x%2.2x", hdev->name, status);
Johan Hedbergd5859e22011-01-25 01:19:58 +0200784
785 hci_req_complete(hdev, HCI_OP_SET_EVENT_FLT, status);
786}
787
Johan Hedberg980e1a52011-01-22 06:10:07 +0200788static void hci_cc_pin_code_reply(struct hci_dev *hdev, struct sk_buff *skb)
789{
790 struct hci_rp_pin_code_reply *rp = (void *) skb->data;
791 struct hci_cp_pin_code_reply *cp;
792 struct hci_conn *conn;
793
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +0300794 BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
Johan Hedberg980e1a52011-01-22 06:10:07 +0200795
Johan Hedberg56e5cb82011-11-08 20:40:16 +0200796 hci_dev_lock(hdev);
797
Johan Hedberga8b2d5c2012-01-08 23:11:15 +0200798 if (test_bit(HCI_MGMT, &hdev->dev_flags))
Johan Hedberg744cf192011-11-08 20:40:14 +0200799 mgmt_pin_code_reply_complete(hdev, &rp->bdaddr, rp->status);
Johan Hedberg980e1a52011-01-22 06:10:07 +0200800
Mikel Astizfa1bd912012-08-09 09:52:29 +0200801 if (rp->status)
Johan Hedberg56e5cb82011-11-08 20:40:16 +0200802 goto unlock;
Johan Hedberg980e1a52011-01-22 06:10:07 +0200803
804 cp = hci_sent_cmd_data(hdev, HCI_OP_PIN_CODE_REPLY);
805 if (!cp)
Johan Hedberg56e5cb82011-11-08 20:40:16 +0200806 goto unlock;
Johan Hedberg980e1a52011-01-22 06:10:07 +0200807
808 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &cp->bdaddr);
809 if (conn)
810 conn->pin_length = cp->pin_len;
Johan Hedberg56e5cb82011-11-08 20:40:16 +0200811
812unlock:
813 hci_dev_unlock(hdev);
Johan Hedberg980e1a52011-01-22 06:10:07 +0200814}
815
816static void hci_cc_pin_code_neg_reply(struct hci_dev *hdev, struct sk_buff *skb)
817{
818 struct hci_rp_pin_code_neg_reply *rp = (void *) skb->data;
819
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +0300820 BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
Johan Hedberg980e1a52011-01-22 06:10:07 +0200821
Johan Hedberg56e5cb82011-11-08 20:40:16 +0200822 hci_dev_lock(hdev);
823
Johan Hedberga8b2d5c2012-01-08 23:11:15 +0200824 if (test_bit(HCI_MGMT, &hdev->dev_flags))
Johan Hedberg744cf192011-11-08 20:40:14 +0200825 mgmt_pin_code_neg_reply_complete(hdev, &rp->bdaddr,
Gustavo Padovan807deac2012-05-17 00:36:24 -0300826 rp->status);
Johan Hedberg56e5cb82011-11-08 20:40:16 +0200827
828 hci_dev_unlock(hdev);
Johan Hedberg980e1a52011-01-22 06:10:07 +0200829}
Johan Hedberg56e5cb82011-11-08 20:40:16 +0200830
Ville Tervo6ed58ec2011-02-10 22:38:48 -0300831static void hci_cc_le_read_buffer_size(struct hci_dev *hdev,
832 struct sk_buff *skb)
833{
834 struct hci_rp_le_read_buffer_size *rp = (void *) skb->data;
835
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +0300836 BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
Ville Tervo6ed58ec2011-02-10 22:38:48 -0300837
838 if (rp->status)
839 return;
840
841 hdev->le_mtu = __le16_to_cpu(rp->le_mtu);
842 hdev->le_pkts = rp->le_max_pkt;
843
844 hdev->le_cnt = hdev->le_pkts;
845
846 BT_DBG("%s le mtu %d:%d", hdev->name, hdev->le_mtu, hdev->le_pkts);
847
848 hci_req_complete(hdev, HCI_OP_LE_READ_BUFFER_SIZE, rp->status);
849}
Johan Hedberg980e1a52011-01-22 06:10:07 +0200850
Johan Hedberg60e77322013-01-22 14:01:59 +0200851static void hci_cc_le_read_local_features(struct hci_dev *hdev,
852 struct sk_buff *skb)
853{
854 struct hci_rp_le_read_local_features *rp = (void *) skb->data;
855
856 BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
857
858 if (!rp->status)
859 memcpy(hdev->le_features, rp->features, 8);
860
861 hci_req_complete(hdev, HCI_OP_LE_READ_LOCAL_FEATURES, rp->status);
862}
863
Johan Hedberg8fa19092012-10-19 20:57:49 +0300864static void hci_cc_le_read_adv_tx_power(struct hci_dev *hdev,
865 struct sk_buff *skb)
866{
867 struct hci_rp_le_read_adv_tx_power *rp = (void *) skb->data;
868
869 BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
870
Johan Hedberg3f0f5242012-11-08 01:23:00 +0100871 if (!rp->status) {
Johan Hedberg8fa19092012-10-19 20:57:49 +0300872 hdev->adv_tx_power = rp->tx_power;
Johan Hedberg3f0f5242012-11-08 01:23:00 +0100873 if (!test_bit(HCI_INIT, &hdev->flags))
874 hci_update_ad(hdev);
875 }
Johan Hedberg8fa19092012-10-19 20:57:49 +0300876
877 hci_req_complete(hdev, HCI_OP_LE_READ_ADV_TX_POWER, rp->status);
878}
879
Johan Hedberge36b04c2012-10-19 20:57:47 +0300880static void hci_cc_le_set_event_mask(struct hci_dev *hdev, struct sk_buff *skb)
881{
882 __u8 status = *((__u8 *) skb->data);
883
884 BT_DBG("%s status 0x%2.2x", hdev->name, status);
885
886 hci_req_complete(hdev, HCI_OP_LE_SET_EVENT_MASK, status);
887}
888
Johan Hedberga5c29682011-02-19 12:05:57 -0300889static void hci_cc_user_confirm_reply(struct hci_dev *hdev, struct sk_buff *skb)
890{
891 struct hci_rp_user_confirm_reply *rp = (void *) skb->data;
892
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +0300893 BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
Johan Hedberga5c29682011-02-19 12:05:57 -0300894
Johan Hedberg56e5cb82011-11-08 20:40:16 +0200895 hci_dev_lock(hdev);
896
Johan Hedberga8b2d5c2012-01-08 23:11:15 +0200897 if (test_bit(HCI_MGMT, &hdev->dev_flags))
Gustavo F. Padovan04124682012-03-08 01:25:00 -0300898 mgmt_user_confirm_reply_complete(hdev, &rp->bdaddr, ACL_LINK, 0,
899 rp->status);
Johan Hedberg56e5cb82011-11-08 20:40:16 +0200900
901 hci_dev_unlock(hdev);
Johan Hedberga5c29682011-02-19 12:05:57 -0300902}
903
904static void hci_cc_user_confirm_neg_reply(struct hci_dev *hdev,
Gustavo Padovan807deac2012-05-17 00:36:24 -0300905 struct sk_buff *skb)
Johan Hedberga5c29682011-02-19 12:05:57 -0300906{
907 struct hci_rp_user_confirm_reply *rp = (void *) skb->data;
908
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +0300909 BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
Johan Hedberga5c29682011-02-19 12:05:57 -0300910
Johan Hedberg56e5cb82011-11-08 20:40:16 +0200911 hci_dev_lock(hdev);
912
Johan Hedberga8b2d5c2012-01-08 23:11:15 +0200913 if (test_bit(HCI_MGMT, &hdev->dev_flags))
Johan Hedberg744cf192011-11-08 20:40:14 +0200914 mgmt_user_confirm_neg_reply_complete(hdev, &rp->bdaddr,
Gustavo F. Padovan04124682012-03-08 01:25:00 -0300915 ACL_LINK, 0, rp->status);
Johan Hedberg56e5cb82011-11-08 20:40:16 +0200916
917 hci_dev_unlock(hdev);
Johan Hedberga5c29682011-02-19 12:05:57 -0300918}
919
Brian Gix1143d452011-11-23 08:28:34 -0800920static void hci_cc_user_passkey_reply(struct hci_dev *hdev, struct sk_buff *skb)
921{
922 struct hci_rp_user_confirm_reply *rp = (void *) skb->data;
923
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +0300924 BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
Brian Gix1143d452011-11-23 08:28:34 -0800925
926 hci_dev_lock(hdev);
927
Johan Hedberga8b2d5c2012-01-08 23:11:15 +0200928 if (test_bit(HCI_MGMT, &hdev->dev_flags))
Johan Hedberg272d90d2012-02-09 15:26:12 +0200929 mgmt_user_passkey_reply_complete(hdev, &rp->bdaddr, ACL_LINK,
Gustavo F. Padovan04124682012-03-08 01:25:00 -0300930 0, rp->status);
Brian Gix1143d452011-11-23 08:28:34 -0800931
932 hci_dev_unlock(hdev);
933}
934
935static void hci_cc_user_passkey_neg_reply(struct hci_dev *hdev,
Gustavo Padovan807deac2012-05-17 00:36:24 -0300936 struct sk_buff *skb)
Brian Gix1143d452011-11-23 08:28:34 -0800937{
938 struct hci_rp_user_confirm_reply *rp = (void *) skb->data;
939
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +0300940 BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
Brian Gix1143d452011-11-23 08:28:34 -0800941
942 hci_dev_lock(hdev);
943
Johan Hedberga8b2d5c2012-01-08 23:11:15 +0200944 if (test_bit(HCI_MGMT, &hdev->dev_flags))
Brian Gix1143d452011-11-23 08:28:34 -0800945 mgmt_user_passkey_neg_reply_complete(hdev, &rp->bdaddr,
Gustavo F. Padovan04124682012-03-08 01:25:00 -0300946 ACL_LINK, 0, rp->status);
Brian Gix1143d452011-11-23 08:28:34 -0800947
948 hci_dev_unlock(hdev);
949}
950
Szymon Jancc35938b2011-03-22 13:12:21 +0100951static void hci_cc_read_local_oob_data_reply(struct hci_dev *hdev,
Gustavo Padovan807deac2012-05-17 00:36:24 -0300952 struct sk_buff *skb)
Szymon Jancc35938b2011-03-22 13:12:21 +0100953{
954 struct hci_rp_read_local_oob_data *rp = (void *) skb->data;
955
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +0300956 BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
Szymon Jancc35938b2011-03-22 13:12:21 +0100957
Johan Hedberg56e5cb82011-11-08 20:40:16 +0200958 hci_dev_lock(hdev);
Johan Hedberg744cf192011-11-08 20:40:14 +0200959 mgmt_read_local_oob_data_reply_complete(hdev, rp->hash,
Szymon Jancc35938b2011-03-22 13:12:21 +0100960 rp->randomizer, rp->status);
Johan Hedberg56e5cb82011-11-08 20:40:16 +0200961 hci_dev_unlock(hdev);
Szymon Jancc35938b2011-03-22 13:12:21 +0100962}
963
Johan Hedbergc1d5dc42012-11-08 01:23:01 +0100964static void hci_cc_le_set_adv_enable(struct hci_dev *hdev, struct sk_buff *skb)
965{
966 __u8 *sent, status = *((__u8 *) skb->data);
967
968 BT_DBG("%s status 0x%2.2x", hdev->name, status);
969
970 sent = hci_sent_cmd_data(hdev, HCI_OP_LE_SET_ADV_ENABLE);
971 if (!sent)
972 return;
973
974 hci_dev_lock(hdev);
975
976 if (!status) {
977 if (*sent)
978 set_bit(HCI_LE_PERIPHERAL, &hdev->dev_flags);
979 else
980 clear_bit(HCI_LE_PERIPHERAL, &hdev->dev_flags);
981 }
982
983 hci_dev_unlock(hdev);
984
985 if (!test_bit(HCI_INIT, &hdev->flags))
986 hci_update_ad(hdev);
987
988 hci_req_complete(hdev, HCI_OP_LE_SET_ADV_ENABLE, status);
989}
990
Andre Guedes07f7fa52011-12-02 21:13:31 +0900991static void hci_cc_le_set_scan_param(struct hci_dev *hdev, struct sk_buff *skb)
992{
993 __u8 status = *((__u8 *) skb->data);
994
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +0300995 BT_DBG("%s status 0x%2.2x", hdev->name, status);
Andre Guedes7ba8b4b2012-02-03 17:47:59 -0300996
997 hci_req_complete(hdev, HCI_OP_LE_SET_SCAN_PARAM, status);
Andre Guedes3fd24152012-02-03 17:48:01 -0300998
999 if (status) {
1000 hci_dev_lock(hdev);
1001 mgmt_start_discovery_failed(hdev, status);
1002 hci_dev_unlock(hdev);
1003 return;
1004 }
Andre Guedes07f7fa52011-12-02 21:13:31 +09001005}
1006
Andre Guedeseb9d91f2011-05-26 16:23:52 -03001007static void hci_cc_le_set_scan_enable(struct hci_dev *hdev,
Gustavo Padovan807deac2012-05-17 00:36:24 -03001008 struct sk_buff *skb)
Andre Guedeseb9d91f2011-05-26 16:23:52 -03001009{
1010 struct hci_cp_le_set_scan_enable *cp;
1011 __u8 status = *((__u8 *) skb->data);
1012
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +03001013 BT_DBG("%s status 0x%2.2x", hdev->name, status);
Andre Guedeseb9d91f2011-05-26 16:23:52 -03001014
Andre Guedeseb9d91f2011-05-26 16:23:52 -03001015 cp = hci_sent_cmd_data(hdev, HCI_OP_LE_SET_SCAN_ENABLE);
1016 if (!cp)
1017 return;
1018
Andrei Emeltchenko68a8aea2011-12-19 16:14:18 +02001019 switch (cp->enable) {
1020 case LE_SCANNING_ENABLED:
Andre Guedes7ba8b4b2012-02-03 17:47:59 -03001021 hci_req_complete(hdev, HCI_OP_LE_SET_SCAN_ENABLE, status);
1022
Andre Guedes3fd24152012-02-03 17:48:01 -03001023 if (status) {
1024 hci_dev_lock(hdev);
1025 mgmt_start_discovery_failed(hdev, status);
1026 hci_dev_unlock(hdev);
Andre Guedes7ba8b4b2012-02-03 17:47:59 -03001027 return;
Andre Guedes3fd24152012-02-03 17:48:01 -03001028 }
Andre Guedes7ba8b4b2012-02-03 17:47:59 -03001029
Andre Guedesd23264a2011-11-25 20:53:38 -03001030 set_bit(HCI_LE_SCAN, &hdev->dev_flags);
1031
Andre Guedesa8f13c82011-09-09 18:56:24 -03001032 hci_dev_lock(hdev);
Andre Guedes343f9352012-02-17 20:39:37 -03001033 hci_discovery_set_state(hdev, DISCOVERY_FINDING);
Andre Guedesa8f13c82011-09-09 18:56:24 -03001034 hci_dev_unlock(hdev);
Andrei Emeltchenko68a8aea2011-12-19 16:14:18 +02001035 break;
1036
1037 case LE_SCANNING_DISABLED:
Andre Guedesc9ecc482012-03-15 16:52:08 -03001038 if (status) {
1039 hci_dev_lock(hdev);
1040 mgmt_stop_discovery_failed(hdev, status);
1041 hci_dev_unlock(hdev);
Andre Guedes7ba8b4b2012-02-03 17:47:59 -03001042 return;
Andre Guedesc9ecc482012-03-15 16:52:08 -03001043 }
Andre Guedes7ba8b4b2012-02-03 17:47:59 -03001044
Andre Guedesd23264a2011-11-25 20:53:38 -03001045 clear_bit(HCI_LE_SCAN, &hdev->dev_flags);
1046
Andre Guedesbc3dd332012-03-06 19:37:06 -03001047 if (hdev->discovery.type == DISCOV_TYPE_INTERLEAVED &&
1048 hdev->discovery.state == DISCOVERY_FINDING) {
Andre Guedes5e0452c2012-02-17 20:39:38 -03001049 mgmt_interleaved_discovery(hdev);
1050 } else {
1051 hci_dev_lock(hdev);
1052 hci_discovery_set_state(hdev, DISCOVERY_STOPPED);
1053 hci_dev_unlock(hdev);
1054 }
1055
Andrei Emeltchenko68a8aea2011-12-19 16:14:18 +02001056 break;
1057
1058 default:
1059 BT_ERR("Used reserved LE_Scan_Enable param %d", cp->enable);
1060 break;
Andre Guedes35815082011-05-26 16:23:53 -03001061 }
Andre Guedeseb9d91f2011-05-26 16:23:52 -03001062}
1063
Johan Hedbergcf1d0812013-01-22 14:02:00 +02001064static void hci_cc_le_read_white_list_size(struct hci_dev *hdev,
1065 struct sk_buff *skb)
1066{
1067 struct hci_rp_le_read_white_list_size *rp = (void *) skb->data;
1068
1069 BT_DBG("%s status 0x%2.2x size %u", hdev->name, rp->status, rp->size);
1070
1071 if (!rp->status)
1072 hdev->le_white_list_size = rp->size;
1073
1074 hci_req_complete(hdev, HCI_OP_LE_READ_WHITE_LIST_SIZE, rp->status);
1075}
1076
Vinicius Costa Gomesa7a595f2011-06-09 18:50:47 -03001077static void hci_cc_le_ltk_reply(struct hci_dev *hdev, struct sk_buff *skb)
1078{
1079 struct hci_rp_le_ltk_reply *rp = (void *) skb->data;
1080
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +03001081 BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
Vinicius Costa Gomesa7a595f2011-06-09 18:50:47 -03001082
1083 if (rp->status)
1084 return;
1085
1086 hci_req_complete(hdev, HCI_OP_LE_LTK_REPLY, rp->status);
1087}
1088
1089static void hci_cc_le_ltk_neg_reply(struct hci_dev *hdev, struct sk_buff *skb)
1090{
1091 struct hci_rp_le_ltk_neg_reply *rp = (void *) skb->data;
1092
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +03001093 BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
Vinicius Costa Gomesa7a595f2011-06-09 18:50:47 -03001094
1095 if (rp->status)
1096 return;
1097
1098 hci_req_complete(hdev, HCI_OP_LE_LTK_NEG_REPLY, rp->status);
1099}
1100
Johan Hedberg9b008c02013-01-22 14:02:01 +02001101static void hci_cc_le_read_supported_states(struct hci_dev *hdev,
1102 struct sk_buff *skb)
1103{
1104 struct hci_rp_le_read_supported_states *rp = (void *) skb->data;
1105
1106 BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
1107
1108 if (!rp->status)
1109 memcpy(hdev->le_states, rp->le_states, 8);
1110
1111 hci_req_complete(hdev, HCI_OP_LE_READ_SUPPORTED_STATES, rp->status);
1112}
1113
Gustavo Padovan6039aa72012-05-23 04:04:18 -03001114static void hci_cc_write_le_host_supported(struct hci_dev *hdev,
1115 struct sk_buff *skb)
Andre Guedesf9b49302011-06-30 19:20:53 -03001116{
Johan Hedberg06199cf2012-02-22 16:37:11 +02001117 struct hci_cp_write_le_host_supported *sent;
Andre Guedesf9b49302011-06-30 19:20:53 -03001118 __u8 status = *((__u8 *) skb->data);
1119
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +03001120 BT_DBG("%s status 0x%2.2x", hdev->name, status);
Andre Guedesf9b49302011-06-30 19:20:53 -03001121
Johan Hedberg06199cf2012-02-22 16:37:11 +02001122 sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_LE_HOST_SUPPORTED);
Johan Hedberg8f984df2012-02-28 01:07:22 +02001123 if (!sent)
Andre Guedesf9b49302011-06-30 19:20:53 -03001124 return;
1125
Johan Hedberg8f984df2012-02-28 01:07:22 +02001126 if (!status) {
1127 if (sent->le)
1128 hdev->host_features[0] |= LMP_HOST_LE;
1129 else
1130 hdev->host_features[0] &= ~LMP_HOST_LE;
Johan Hedberg53b2caa2012-10-24 21:11:59 +03001131
1132 if (sent->simul)
1133 hdev->host_features[0] |= LMP_HOST_LE_BREDR;
1134 else
1135 hdev->host_features[0] &= ~LMP_HOST_LE_BREDR;
Johan Hedberg8f984df2012-02-28 01:07:22 +02001136 }
1137
1138 if (test_bit(HCI_MGMT, &hdev->dev_flags) &&
Gustavo Padovan807deac2012-05-17 00:36:24 -03001139 !test_bit(HCI_INIT, &hdev->flags))
Johan Hedberg8f984df2012-02-28 01:07:22 +02001140 mgmt_le_enable_complete(hdev, sent->le, status);
1141
1142 hci_req_complete(hdev, HCI_OP_WRITE_LE_HOST_SUPPORTED, status);
Andre Guedesf9b49302011-06-30 19:20:53 -03001143}
1144
Andrei Emeltchenko93c284e2012-09-27 17:26:20 +03001145static void hci_cc_write_remote_amp_assoc(struct hci_dev *hdev,
1146 struct sk_buff *skb)
1147{
1148 struct hci_rp_write_remote_amp_assoc *rp = (void *) skb->data;
1149
1150 BT_DBG("%s status 0x%2.2x phy_handle 0x%2.2x",
1151 hdev->name, rp->status, rp->phy_handle);
1152
1153 if (rp->status)
1154 return;
1155
1156 amp_write_rem_assoc_continue(hdev, rp->phy_handle);
1157}
1158
Gustavo Padovan6039aa72012-05-23 04:04:18 -03001159static void hci_cs_inquiry(struct hci_dev *hdev, __u8 status)
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001160{
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +03001161 BT_DBG("%s status 0x%2.2x", hdev->name, status);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001162
1163 if (status) {
Johan Hedberg23bb5762010-12-21 23:01:27 +02001164 hci_req_complete(hdev, HCI_OP_INQUIRY, status);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001165 hci_conn_check_pending(hdev);
Johan Hedberg56e5cb82011-11-08 20:40:16 +02001166 hci_dev_lock(hdev);
Johan Hedberga8b2d5c2012-01-08 23:11:15 +02001167 if (test_bit(HCI_MGMT, &hdev->dev_flags))
Andre Guedes7a135102011-11-09 17:14:25 -03001168 mgmt_start_discovery_failed(hdev, status);
Johan Hedberg56e5cb82011-11-08 20:40:16 +02001169 hci_dev_unlock(hdev);
Johan Hedberg314b2382011-04-27 10:29:57 -04001170 return;
1171 }
1172
Andre Guedes89352e72011-11-04 14:16:53 -03001173 set_bit(HCI_INQUIRY, &hdev->flags);
1174
Johan Hedberg56e5cb82011-11-08 20:40:16 +02001175 hci_dev_lock(hdev);
Andre Guedes343f9352012-02-17 20:39:37 -03001176 hci_discovery_set_state(hdev, DISCOVERY_FINDING);
Johan Hedberg56e5cb82011-11-08 20:40:16 +02001177 hci_dev_unlock(hdev);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001178}
1179
Gustavo Padovan6039aa72012-05-23 04:04:18 -03001180static void hci_cs_create_conn(struct hci_dev *hdev, __u8 status)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001181{
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001182 struct hci_cp_create_conn *cp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001183 struct hci_conn *conn;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001184
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +03001185 BT_DBG("%s status 0x%2.2x", hdev->name, status);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001186
1187 cp = hci_sent_cmd_data(hdev, HCI_OP_CREATE_CONN);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001188 if (!cp)
1189 return;
1190
1191 hci_dev_lock(hdev);
1192
1193 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &cp->bdaddr);
1194
Andrei Emeltchenko6ed93dc2012-09-25 12:49:43 +03001195 BT_DBG("%s bdaddr %pMR hcon %p", hdev->name, &cp->bdaddr, conn);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001196
1197 if (status) {
1198 if (conn && conn->state == BT_CONNECT) {
Marcel Holtmann4c67bc72006-10-15 17:30:56 +02001199 if (status != 0x0c || conn->attempt > 2) {
1200 conn->state = BT_CLOSED;
1201 hci_proto_connect_cfm(conn, status);
1202 hci_conn_del(conn);
1203 } else
1204 conn->state = BT_CONNECT2;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001205 }
1206 } else {
1207 if (!conn) {
1208 conn = hci_conn_add(hdev, ACL_LINK, &cp->bdaddr);
1209 if (conn) {
Johan Hedberga0c808b2012-01-16 09:49:58 +02001210 conn->out = true;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001211 conn->link_mode |= HCI_LM_MASTER;
1212 } else
Gustavo F. Padovan893ef972010-07-18 15:13:37 -03001213 BT_ERR("No memory for new connection");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001214 }
1215 }
1216
1217 hci_dev_unlock(hdev);
1218}
1219
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001220static void hci_cs_add_sco(struct hci_dev *hdev, __u8 status)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001221{
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001222 struct hci_cp_add_sco *cp;
1223 struct hci_conn *acl, *sco;
1224 __u16 handle;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001225
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +03001226 BT_DBG("%s status 0x%2.2x", hdev->name, status);
Marcel Holtmannb6a0dc82007-10-20 14:55:10 +02001227
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001228 if (!status)
1229 return;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001230
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001231 cp = hci_sent_cmd_data(hdev, HCI_OP_ADD_SCO);
1232 if (!cp)
1233 return;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001234
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001235 handle = __le16_to_cpu(cp->handle);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001236
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +03001237 BT_DBG("%s handle 0x%4.4x", hdev->name, handle);
Marcel Holtmann6bd57412006-11-18 22:14:22 +01001238
1239 hci_dev_lock(hdev);
1240
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001241 acl = hci_conn_hash_lookup_handle(hdev, handle);
Andrei Emeltchenko5a08ecc2011-01-11 17:20:20 +02001242 if (acl) {
1243 sco = acl->link;
1244 if (sco) {
1245 sco->state = BT_CLOSED;
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001246
Andrei Emeltchenko5a08ecc2011-01-11 17:20:20 +02001247 hci_proto_connect_cfm(sco, status);
1248 hci_conn_del(sco);
1249 }
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001250 }
Marcel Holtmann6bd57412006-11-18 22:14:22 +01001251
1252 hci_dev_unlock(hdev);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001253}
1254
Marcel Holtmannf8558552008-07-14 20:13:49 +02001255static void hci_cs_auth_requested(struct hci_dev *hdev, __u8 status)
1256{
1257 struct hci_cp_auth_requested *cp;
1258 struct hci_conn *conn;
1259
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +03001260 BT_DBG("%s status 0x%2.2x", hdev->name, status);
Marcel Holtmannf8558552008-07-14 20:13:49 +02001261
1262 if (!status)
1263 return;
1264
1265 cp = hci_sent_cmd_data(hdev, HCI_OP_AUTH_REQUESTED);
1266 if (!cp)
1267 return;
1268
1269 hci_dev_lock(hdev);
1270
1271 conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(cp->handle));
1272 if (conn) {
1273 if (conn->state == BT_CONFIG) {
1274 hci_proto_connect_cfm(conn, status);
1275 hci_conn_put(conn);
1276 }
1277 }
1278
1279 hci_dev_unlock(hdev);
1280}
1281
1282static void hci_cs_set_conn_encrypt(struct hci_dev *hdev, __u8 status)
1283{
1284 struct hci_cp_set_conn_encrypt *cp;
1285 struct hci_conn *conn;
1286
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +03001287 BT_DBG("%s status 0x%2.2x", hdev->name, status);
Marcel Holtmannf8558552008-07-14 20:13:49 +02001288
1289 if (!status)
1290 return;
1291
1292 cp = hci_sent_cmd_data(hdev, HCI_OP_SET_CONN_ENCRYPT);
1293 if (!cp)
1294 return;
1295
1296 hci_dev_lock(hdev);
1297
1298 conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(cp->handle));
1299 if (conn) {
1300 if (conn->state == BT_CONFIG) {
1301 hci_proto_connect_cfm(conn, status);
1302 hci_conn_put(conn);
1303 }
1304 }
1305
1306 hci_dev_unlock(hdev);
1307}
1308
Johan Hedberg127178d2010-11-18 22:22:29 +02001309static int hci_outgoing_auth_needed(struct hci_dev *hdev,
Gustavo Padovan807deac2012-05-17 00:36:24 -03001310 struct hci_conn *conn)
Johan Hedberg392599b2010-11-18 22:22:28 +02001311{
Johan Hedberg392599b2010-11-18 22:22:28 +02001312 if (conn->state != BT_CONFIG || !conn->out)
1313 return 0;
1314
Johan Hedberg765c2a92011-01-19 12:06:52 +05301315 if (conn->pending_sec_level == BT_SECURITY_SDP)
Johan Hedberg392599b2010-11-18 22:22:28 +02001316 return 0;
1317
1318 /* Only request authentication for SSP connections or non-SSP
Vinicius Costa Gomese9bf2bf2011-09-02 14:51:20 -03001319 * devices with sec_level HIGH or if MITM protection is requested */
Gustavo Padovan807deac2012-05-17 00:36:24 -03001320 if (!hci_conn_ssp_enabled(conn) && !(conn->auth_type & 0x01) &&
1321 conn->pending_sec_level != BT_SECURITY_HIGH)
Johan Hedberg392599b2010-11-18 22:22:28 +02001322 return 0;
1323
Johan Hedberg392599b2010-11-18 22:22:28 +02001324 return 1;
1325}
1326
Gustavo Padovan6039aa72012-05-23 04:04:18 -03001327static int hci_resolve_name(struct hci_dev *hdev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001328 struct inquiry_entry *e)
Johan Hedberg30dc78e2012-01-04 15:44:20 +02001329{
1330 struct hci_cp_remote_name_req cp;
1331
1332 memset(&cp, 0, sizeof(cp));
1333
1334 bacpy(&cp.bdaddr, &e->data.bdaddr);
1335 cp.pscan_rep_mode = e->data.pscan_rep_mode;
1336 cp.pscan_mode = e->data.pscan_mode;
1337 cp.clock_offset = e->data.clock_offset;
1338
1339 return hci_send_cmd(hdev, HCI_OP_REMOTE_NAME_REQ, sizeof(cp), &cp);
1340}
1341
Johan Hedbergb644ba32012-01-17 21:48:47 +02001342static bool hci_resolve_next_name(struct hci_dev *hdev)
Johan Hedberg30dc78e2012-01-04 15:44:20 +02001343{
1344 struct discovery_state *discov = &hdev->discovery;
1345 struct inquiry_entry *e;
1346
Johan Hedbergb644ba32012-01-17 21:48:47 +02001347 if (list_empty(&discov->resolve))
1348 return false;
1349
1350 e = hci_inquiry_cache_lookup_resolve(hdev, BDADDR_ANY, NAME_NEEDED);
Ram Malovanyc8100892012-07-19 10:26:09 +03001351 if (!e)
1352 return false;
1353
Johan Hedbergb644ba32012-01-17 21:48:47 +02001354 if (hci_resolve_name(hdev, e) == 0) {
1355 e->name_state = NAME_PENDING;
1356 return true;
1357 }
1358
1359 return false;
1360}
1361
1362static void hci_check_pending_name(struct hci_dev *hdev, struct hci_conn *conn,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001363 bdaddr_t *bdaddr, u8 *name, u8 name_len)
Johan Hedbergb644ba32012-01-17 21:48:47 +02001364{
1365 struct discovery_state *discov = &hdev->discovery;
1366 struct inquiry_entry *e;
1367
1368 if (conn && !test_and_set_bit(HCI_CONN_MGMT_CONNECTED, &conn->flags))
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001369 mgmt_device_connected(hdev, bdaddr, ACL_LINK, 0x00, 0, name,
1370 name_len, conn->dev_class);
Johan Hedbergb644ba32012-01-17 21:48:47 +02001371
1372 if (discov->state == DISCOVERY_STOPPED)
1373 return;
1374
Johan Hedberg30dc78e2012-01-04 15:44:20 +02001375 if (discov->state == DISCOVERY_STOPPING)
1376 goto discov_complete;
1377
1378 if (discov->state != DISCOVERY_RESOLVING)
1379 return;
1380
1381 e = hci_inquiry_cache_lookup_resolve(hdev, bdaddr, NAME_PENDING);
Ram Malovany7cc83802012-07-19 10:26:10 +03001382 /* If the device was not found in a list of found devices names of which
1383 * are pending. there is no need to continue resolving a next name as it
1384 * will be done upon receiving another Remote Name Request Complete
1385 * Event */
1386 if (!e)
1387 return;
1388
1389 list_del(&e->list);
1390 if (name) {
Johan Hedberg30dc78e2012-01-04 15:44:20 +02001391 e->name_state = NAME_KNOWN;
Ram Malovany7cc83802012-07-19 10:26:10 +03001392 mgmt_remote_name(hdev, bdaddr, ACL_LINK, 0x00,
1393 e->data.rssi, name, name_len);
Ram Malovanyc3e7c0d2012-07-19 10:26:11 +03001394 } else {
1395 e->name_state = NAME_NOT_KNOWN;
Johan Hedberg30dc78e2012-01-04 15:44:20 +02001396 }
1397
Johan Hedbergb644ba32012-01-17 21:48:47 +02001398 if (hci_resolve_next_name(hdev))
Johan Hedberg30dc78e2012-01-04 15:44:20 +02001399 return;
Johan Hedberg30dc78e2012-01-04 15:44:20 +02001400
1401discov_complete:
1402 hci_discovery_set_state(hdev, DISCOVERY_STOPPED);
1403}
1404
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001405static void hci_cs_remote_name_req(struct hci_dev *hdev, __u8 status)
1406{
Johan Hedberg127178d2010-11-18 22:22:29 +02001407 struct hci_cp_remote_name_req *cp;
1408 struct hci_conn *conn;
1409
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +03001410 BT_DBG("%s status 0x%2.2x", hdev->name, status);
Johan Hedberg127178d2010-11-18 22:22:29 +02001411
1412 /* If successful wait for the name req complete event before
1413 * checking for the need to do authentication */
1414 if (!status)
1415 return;
1416
1417 cp = hci_sent_cmd_data(hdev, HCI_OP_REMOTE_NAME_REQ);
1418 if (!cp)
1419 return;
1420
1421 hci_dev_lock(hdev);
1422
1423 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &cp->bdaddr);
Johan Hedbergb644ba32012-01-17 21:48:47 +02001424
1425 if (test_bit(HCI_MGMT, &hdev->dev_flags))
1426 hci_check_pending_name(hdev, conn, &cp->bdaddr, NULL, 0);
1427
Johan Hedberg79c6c702011-04-28 11:28:55 -07001428 if (!conn)
1429 goto unlock;
1430
1431 if (!hci_outgoing_auth_needed(hdev, conn))
1432 goto unlock;
1433
Johan Hedberg51a8efd2012-01-16 06:10:31 +02001434 if (!test_and_set_bit(HCI_CONN_AUTH_PEND, &conn->flags)) {
Johan Hedberg127178d2010-11-18 22:22:29 +02001435 struct hci_cp_auth_requested cp;
1436 cp.handle = __cpu_to_le16(conn->handle);
1437 hci_send_cmd(hdev, HCI_OP_AUTH_REQUESTED, sizeof(cp), &cp);
1438 }
1439
Johan Hedberg79c6c702011-04-28 11:28:55 -07001440unlock:
Johan Hedberg127178d2010-11-18 22:22:29 +02001441 hci_dev_unlock(hdev);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001442}
1443
Marcel Holtmann769be972008-07-14 20:13:49 +02001444static void hci_cs_read_remote_features(struct hci_dev *hdev, __u8 status)
1445{
1446 struct hci_cp_read_remote_features *cp;
1447 struct hci_conn *conn;
1448
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +03001449 BT_DBG("%s status 0x%2.2x", hdev->name, status);
Marcel Holtmann769be972008-07-14 20:13:49 +02001450
1451 if (!status)
1452 return;
1453
1454 cp = hci_sent_cmd_data(hdev, HCI_OP_READ_REMOTE_FEATURES);
1455 if (!cp)
1456 return;
1457
1458 hci_dev_lock(hdev);
1459
1460 conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(cp->handle));
1461 if (conn) {
1462 if (conn->state == BT_CONFIG) {
Marcel Holtmann769be972008-07-14 20:13:49 +02001463 hci_proto_connect_cfm(conn, status);
1464 hci_conn_put(conn);
1465 }
1466 }
1467
1468 hci_dev_unlock(hdev);
1469}
1470
1471static void hci_cs_read_remote_ext_features(struct hci_dev *hdev, __u8 status)
1472{
1473 struct hci_cp_read_remote_ext_features *cp;
1474 struct hci_conn *conn;
1475
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +03001476 BT_DBG("%s status 0x%2.2x", hdev->name, status);
Marcel Holtmann769be972008-07-14 20:13:49 +02001477
1478 if (!status)
1479 return;
1480
1481 cp = hci_sent_cmd_data(hdev, HCI_OP_READ_REMOTE_EXT_FEATURES);
1482 if (!cp)
1483 return;
1484
1485 hci_dev_lock(hdev);
1486
1487 conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(cp->handle));
1488 if (conn) {
1489 if (conn->state == BT_CONFIG) {
Marcel Holtmann769be972008-07-14 20:13:49 +02001490 hci_proto_connect_cfm(conn, status);
1491 hci_conn_put(conn);
1492 }
1493 }
1494
1495 hci_dev_unlock(hdev);
1496}
1497
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001498static void hci_cs_setup_sync_conn(struct hci_dev *hdev, __u8 status)
1499{
Marcel Holtmannb6a0dc82007-10-20 14:55:10 +02001500 struct hci_cp_setup_sync_conn *cp;
1501 struct hci_conn *acl, *sco;
1502 __u16 handle;
1503
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +03001504 BT_DBG("%s status 0x%2.2x", hdev->name, status);
Marcel Holtmannb6a0dc82007-10-20 14:55:10 +02001505
1506 if (!status)
1507 return;
1508
1509 cp = hci_sent_cmd_data(hdev, HCI_OP_SETUP_SYNC_CONN);
1510 if (!cp)
1511 return;
1512
1513 handle = __le16_to_cpu(cp->handle);
1514
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +03001515 BT_DBG("%s handle 0x%4.4x", hdev->name, handle);
Marcel Holtmannb6a0dc82007-10-20 14:55:10 +02001516
1517 hci_dev_lock(hdev);
1518
1519 acl = hci_conn_hash_lookup_handle(hdev, handle);
Andrei Emeltchenko5a08ecc2011-01-11 17:20:20 +02001520 if (acl) {
1521 sco = acl->link;
1522 if (sco) {
1523 sco->state = BT_CLOSED;
Marcel Holtmannb6a0dc82007-10-20 14:55:10 +02001524
Andrei Emeltchenko5a08ecc2011-01-11 17:20:20 +02001525 hci_proto_connect_cfm(sco, status);
1526 hci_conn_del(sco);
1527 }
Marcel Holtmannb6a0dc82007-10-20 14:55:10 +02001528 }
1529
1530 hci_dev_unlock(hdev);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001531}
1532
1533static void hci_cs_sniff_mode(struct hci_dev *hdev, __u8 status)
1534{
1535 struct hci_cp_sniff_mode *cp;
1536 struct hci_conn *conn;
1537
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +03001538 BT_DBG("%s status 0x%2.2x", hdev->name, status);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001539
1540 if (!status)
1541 return;
1542
1543 cp = hci_sent_cmd_data(hdev, HCI_OP_SNIFF_MODE);
1544 if (!cp)
1545 return;
1546
1547 hci_dev_lock(hdev);
1548
1549 conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(cp->handle));
Marcel Holtmanne73439d2010-07-26 10:06:00 -04001550 if (conn) {
Johan Hedberg51a8efd2012-01-16 06:10:31 +02001551 clear_bit(HCI_CONN_MODE_CHANGE_PEND, &conn->flags);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001552
Johan Hedberg51a8efd2012-01-16 06:10:31 +02001553 if (test_and_clear_bit(HCI_CONN_SCO_SETUP_PEND, &conn->flags))
Marcel Holtmanne73439d2010-07-26 10:06:00 -04001554 hci_sco_setup(conn, status);
1555 }
1556
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001557 hci_dev_unlock(hdev);
1558}
1559
1560static void hci_cs_exit_sniff_mode(struct hci_dev *hdev, __u8 status)
1561{
1562 struct hci_cp_exit_sniff_mode *cp;
1563 struct hci_conn *conn;
1564
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +03001565 BT_DBG("%s status 0x%2.2x", hdev->name, status);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001566
1567 if (!status)
1568 return;
1569
1570 cp = hci_sent_cmd_data(hdev, HCI_OP_EXIT_SNIFF_MODE);
1571 if (!cp)
1572 return;
1573
1574 hci_dev_lock(hdev);
1575
1576 conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(cp->handle));
Marcel Holtmanne73439d2010-07-26 10:06:00 -04001577 if (conn) {
Johan Hedberg51a8efd2012-01-16 06:10:31 +02001578 clear_bit(HCI_CONN_MODE_CHANGE_PEND, &conn->flags);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001579
Johan Hedberg51a8efd2012-01-16 06:10:31 +02001580 if (test_and_clear_bit(HCI_CONN_SCO_SETUP_PEND, &conn->flags))
Marcel Holtmanne73439d2010-07-26 10:06:00 -04001581 hci_sco_setup(conn, status);
1582 }
1583
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001584 hci_dev_unlock(hdev);
1585}
1586
Johan Hedberg88c3df12012-02-09 14:27:38 +02001587static void hci_cs_disconnect(struct hci_dev *hdev, u8 status)
1588{
1589 struct hci_cp_disconnect *cp;
1590 struct hci_conn *conn;
1591
1592 if (!status)
1593 return;
1594
1595 cp = hci_sent_cmd_data(hdev, HCI_OP_DISCONNECT);
1596 if (!cp)
1597 return;
1598
1599 hci_dev_lock(hdev);
1600
1601 conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(cp->handle));
1602 if (conn)
1603 mgmt_disconnect_failed(hdev, &conn->dst, conn->type,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001604 conn->dst_type, status);
Johan Hedberg88c3df12012-02-09 14:27:38 +02001605
1606 hci_dev_unlock(hdev);
1607}
1608
Ville Tervofcd89c02011-02-10 22:38:47 -03001609static void hci_cs_le_create_conn(struct hci_dev *hdev, __u8 status)
1610{
Ville Tervofcd89c02011-02-10 22:38:47 -03001611 struct hci_conn *conn;
1612
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +03001613 BT_DBG("%s status 0x%2.2x", hdev->name, status);
Ville Tervofcd89c02011-02-10 22:38:47 -03001614
Ville Tervofcd89c02011-02-10 22:38:47 -03001615 if (status) {
Andre Guedesf00a06a2012-07-27 15:10:13 -03001616 hci_dev_lock(hdev);
Ville Tervofcd89c02011-02-10 22:38:47 -03001617
Andre Guedes0c95ab72012-07-27 15:10:14 -03001618 conn = hci_conn_hash_lookup_state(hdev, LE_LINK, BT_CONNECT);
Andre Guedesf00a06a2012-07-27 15:10:13 -03001619 if (!conn) {
1620 hci_dev_unlock(hdev);
1621 return;
1622 }
1623
Andrei Emeltchenko6ed93dc2012-09-25 12:49:43 +03001624 BT_DBG("%s bdaddr %pMR conn %p", hdev->name, &conn->dst, conn);
Andre Guedesf00a06a2012-07-27 15:10:13 -03001625
1626 conn->state = BT_CLOSED;
Andre Guedes0c95ab72012-07-27 15:10:14 -03001627 mgmt_connect_failed(hdev, &conn->dst, conn->type,
Andre Guedesf00a06a2012-07-27 15:10:13 -03001628 conn->dst_type, status);
1629 hci_proto_connect_cfm(conn, status);
1630 hci_conn_del(conn);
1631
1632 hci_dev_unlock(hdev);
1633 }
Ville Tervofcd89c02011-02-10 22:38:47 -03001634}
1635
Vinicius Costa Gomesa7a595f2011-06-09 18:50:47 -03001636static void hci_cs_le_start_enc(struct hci_dev *hdev, u8 status)
1637{
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +03001638 BT_DBG("%s status 0x%2.2x", hdev->name, status);
Vinicius Costa Gomesa7a595f2011-06-09 18:50:47 -03001639}
1640
Andrei Emeltchenkoa02226d2012-09-27 17:26:19 +03001641static void hci_cs_create_phylink(struct hci_dev *hdev, u8 status)
1642{
Andrei Emeltchenko93c284e2012-09-27 17:26:20 +03001643 struct hci_cp_create_phy_link *cp;
1644
Andrei Emeltchenkoa02226d2012-09-27 17:26:19 +03001645 BT_DBG("%s status 0x%2.2x", hdev->name, status);
Andrei Emeltchenko93c284e2012-09-27 17:26:20 +03001646
Andrei Emeltchenko93c284e2012-09-27 17:26:20 +03001647 cp = hci_sent_cmd_data(hdev, HCI_OP_CREATE_PHY_LINK);
1648 if (!cp)
1649 return;
1650
Andrei Emeltchenkoe58917b2012-10-31 15:46:33 +02001651 hci_dev_lock(hdev);
1652
1653 if (status) {
1654 struct hci_conn *hcon;
1655
1656 hcon = hci_conn_hash_lookup_handle(hdev, cp->phy_handle);
1657 if (hcon)
1658 hci_conn_del(hcon);
1659 } else {
1660 amp_write_remote_assoc(hdev, cp->phy_handle);
1661 }
1662
1663 hci_dev_unlock(hdev);
Andrei Emeltchenkoa02226d2012-09-27 17:26:19 +03001664}
1665
Andrei Emeltchenko0b26ab92012-09-27 17:26:24 +03001666static void hci_cs_accept_phylink(struct hci_dev *hdev, u8 status)
1667{
1668 struct hci_cp_accept_phy_link *cp;
1669
1670 BT_DBG("%s status 0x%2.2x", hdev->name, status);
1671
1672 if (status)
1673 return;
1674
1675 cp = hci_sent_cmd_data(hdev, HCI_OP_ACCEPT_PHY_LINK);
1676 if (!cp)
1677 return;
1678
1679 amp_write_remote_assoc(hdev, cp->phy_handle);
1680}
1681
Andrei Emeltchenko5ce66b52012-10-31 15:46:30 +02001682static void hci_cs_create_logical_link(struct hci_dev *hdev, u8 status)
1683{
1684 BT_DBG("%s status 0x%2.2x", hdev->name, status);
1685}
1686
Gustavo Padovan6039aa72012-05-23 04:04:18 -03001687static void hci_inquiry_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001688{
1689 __u8 status = *((__u8 *) skb->data);
Johan Hedberg30dc78e2012-01-04 15:44:20 +02001690 struct discovery_state *discov = &hdev->discovery;
1691 struct inquiry_entry *e;
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001692
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +03001693 BT_DBG("%s status 0x%2.2x", hdev->name, status);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001694
Johan Hedberg23bb5762010-12-21 23:01:27 +02001695 hci_req_complete(hdev, HCI_OP_INQUIRY, status);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001696
1697 hci_conn_check_pending(hdev);
Andre Guedes89352e72011-11-04 14:16:53 -03001698
1699 if (!test_and_clear_bit(HCI_INQUIRY, &hdev->flags))
1700 return;
1701
Johan Hedberga8b2d5c2012-01-08 23:11:15 +02001702 if (!test_bit(HCI_MGMT, &hdev->dev_flags))
Johan Hedberg30dc78e2012-01-04 15:44:20 +02001703 return;
1704
Johan Hedberg56e5cb82011-11-08 20:40:16 +02001705 hci_dev_lock(hdev);
Johan Hedberg30dc78e2012-01-04 15:44:20 +02001706
Andre Guedes343f9352012-02-17 20:39:37 -03001707 if (discov->state != DISCOVERY_FINDING)
Johan Hedberg30dc78e2012-01-04 15:44:20 +02001708 goto unlock;
1709
1710 if (list_empty(&discov->resolve)) {
1711 hci_discovery_set_state(hdev, DISCOVERY_STOPPED);
1712 goto unlock;
1713 }
1714
1715 e = hci_inquiry_cache_lookup_resolve(hdev, BDADDR_ANY, NAME_NEEDED);
1716 if (e && hci_resolve_name(hdev, e) == 0) {
1717 e->name_state = NAME_PENDING;
1718 hci_discovery_set_state(hdev, DISCOVERY_RESOLVING);
1719 } else {
1720 hci_discovery_set_state(hdev, DISCOVERY_STOPPED);
1721 }
1722
1723unlock:
Johan Hedberg56e5cb82011-11-08 20:40:16 +02001724 hci_dev_unlock(hdev);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001725}
1726
Gustavo Padovan6039aa72012-05-23 04:04:18 -03001727static void hci_inquiry_result_evt(struct hci_dev *hdev, struct sk_buff *skb)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001728{
Marcel Holtmann45bb4bf2005-08-09 20:27:49 -07001729 struct inquiry_data data;
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001730 struct inquiry_info *info = (void *) (skb->data + 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001731 int num_rsp = *((__u8 *) skb->data);
1732
1733 BT_DBG("%s num_rsp %d", hdev->name, num_rsp);
1734
Marcel Holtmann45bb4bf2005-08-09 20:27:49 -07001735 if (!num_rsp)
1736 return;
1737
Andre Guedes1519cc12012-03-21 00:03:38 -03001738 if (test_bit(HCI_PERIODIC_INQ, &hdev->dev_flags))
1739 return;
1740
Linus Torvalds1da177e2005-04-16 15:20:36 -07001741 hci_dev_lock(hdev);
Marcel Holtmann45bb4bf2005-08-09 20:27:49 -07001742
Johan Hedberge17acd42011-03-30 23:57:16 +03001743 for (; num_rsp; num_rsp--, info++) {
Johan Hedberg388fc8f2012-02-23 00:38:59 +02001744 bool name_known, ssp;
Johan Hedberg31754052012-01-04 13:39:52 +02001745
Linus Torvalds1da177e2005-04-16 15:20:36 -07001746 bacpy(&data.bdaddr, &info->bdaddr);
1747 data.pscan_rep_mode = info->pscan_rep_mode;
1748 data.pscan_period_mode = info->pscan_period_mode;
1749 data.pscan_mode = info->pscan_mode;
1750 memcpy(data.dev_class, info->dev_class, 3);
1751 data.clock_offset = info->clock_offset;
1752 data.rssi = 0x00;
Marcel Holtmann41a96212008-07-14 20:13:48 +02001753 data.ssp_mode = 0x00;
Johan Hedberg31754052012-01-04 13:39:52 +02001754
Johan Hedberg388fc8f2012-02-23 00:38:59 +02001755 name_known = hci_inquiry_cache_update(hdev, &data, false, &ssp);
Johan Hedberg48264f02011-11-09 13:58:58 +02001756 mgmt_device_found(hdev, &info->bdaddr, ACL_LINK, 0x00,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001757 info->dev_class, 0, !name_known, ssp, NULL,
1758 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001759 }
Marcel Holtmann45bb4bf2005-08-09 20:27:49 -07001760
Linus Torvalds1da177e2005-04-16 15:20:36 -07001761 hci_dev_unlock(hdev);
1762}
1763
Gustavo Padovan6039aa72012-05-23 04:04:18 -03001764static void hci_conn_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001765{
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001766 struct hci_ev_conn_complete *ev = (void *) skb->data;
1767 struct hci_conn *conn;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001768
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001769 BT_DBG("%s", hdev->name);
Marcel Holtmann45bb4bf2005-08-09 20:27:49 -07001770
Linus Torvalds1da177e2005-04-16 15:20:36 -07001771 hci_dev_lock(hdev);
Marcel Holtmann45bb4bf2005-08-09 20:27:49 -07001772
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001773 conn = hci_conn_hash_lookup_ba(hdev, ev->link_type, &ev->bdaddr);
Marcel Holtmann94992372009-04-19 19:30:03 +02001774 if (!conn) {
1775 if (ev->link_type != SCO_LINK)
1776 goto unlock;
1777
1778 conn = hci_conn_hash_lookup_ba(hdev, ESCO_LINK, &ev->bdaddr);
1779 if (!conn)
1780 goto unlock;
1781
1782 conn->type = SCO_LINK;
1783 }
Marcel Holtmann45bb4bf2005-08-09 20:27:49 -07001784
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001785 if (!ev->status) {
1786 conn->handle = __le16_to_cpu(ev->handle);
Marcel Holtmann769be972008-07-14 20:13:49 +02001787
1788 if (conn->type == ACL_LINK) {
1789 conn->state = BT_CONFIG;
1790 hci_conn_hold(conn);
Szymon Janca9ea3ed2012-07-19 14:46:08 +02001791
1792 if (!conn->out && !hci_conn_ssp_enabled(conn) &&
1793 !hci_find_link_key(hdev, &ev->bdaddr))
1794 conn->disc_timeout = HCI_PAIRING_TIMEOUT;
1795 else
1796 conn->disc_timeout = HCI_DISCONN_TIMEOUT;
Marcel Holtmann769be972008-07-14 20:13:49 +02001797 } else
1798 conn->state = BT_CONNECTED;
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001799
Marcel Holtmann9eba32b2009-08-22 14:19:26 -07001800 hci_conn_hold_device(conn);
Marcel Holtmann7d0db0a2008-07-14 20:13:51 +02001801 hci_conn_add_sysfs(conn);
1802
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001803 if (test_bit(HCI_AUTH, &hdev->flags))
1804 conn->link_mode |= HCI_LM_AUTH;
1805
1806 if (test_bit(HCI_ENCRYPT, &hdev->flags))
1807 conn->link_mode |= HCI_LM_ENCRYPT;
1808
1809 /* Get remote features */
1810 if (conn->type == ACL_LINK) {
1811 struct hci_cp_read_remote_features cp;
1812 cp.handle = ev->handle;
Marcel Holtmann769be972008-07-14 20:13:49 +02001813 hci_send_cmd(hdev, HCI_OP_READ_REMOTE_FEATURES,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001814 sizeof(cp), &cp);
Marcel Holtmann45bb4bf2005-08-09 20:27:49 -07001815 }
Marcel Holtmann45bb4bf2005-08-09 20:27:49 -07001816
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001817 /* Set packet type for incoming connection */
Andrei Emeltchenkod095c1e2011-12-01 14:33:27 +02001818 if (!conn->out && hdev->hci_ver < BLUETOOTH_VER_2_0) {
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001819 struct hci_cp_change_conn_ptype cp;
1820 cp.handle = ev->handle;
Marcel Holtmanna8746412008-07-14 20:13:46 +02001821 cp.pkt_type = cpu_to_le16(conn->pkt_type);
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001822 hci_send_cmd(hdev, HCI_OP_CHANGE_CONN_PTYPE, sizeof(cp),
1823 &cp);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001824 }
Johan Hedberg17d5c042011-01-22 06:09:08 +02001825 } else {
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001826 conn->state = BT_CLOSED;
Johan Hedberg17d5c042011-01-22 06:09:08 +02001827 if (conn->type == ACL_LINK)
Johan Hedberg744cf192011-11-08 20:40:14 +02001828 mgmt_connect_failed(hdev, &ev->bdaddr, conn->type,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001829 conn->dst_type, ev->status);
Johan Hedberg17d5c042011-01-22 06:09:08 +02001830 }
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001831
Marcel Holtmanne73439d2010-07-26 10:06:00 -04001832 if (conn->type == ACL_LINK)
1833 hci_sco_setup(conn, ev->status);
Marcel Holtmann45bb4bf2005-08-09 20:27:49 -07001834
Marcel Holtmann769be972008-07-14 20:13:49 +02001835 if (ev->status) {
1836 hci_proto_connect_cfm(conn, ev->status);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001837 hci_conn_del(conn);
Marcel Holtmannc89b6e62009-01-15 21:57:03 +01001838 } else if (ev->link_type != ACL_LINK)
1839 hci_proto_connect_cfm(conn, ev->status);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001840
1841unlock:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001842 hci_dev_unlock(hdev);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001843
1844 hci_conn_check_pending(hdev);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001845}
1846
Frédéric Dalleau20714bf2012-11-21 10:51:12 +01001847void hci_conn_accept(struct hci_conn *conn, int mask)
1848{
1849 struct hci_dev *hdev = conn->hdev;
1850
1851 BT_DBG("conn %p", conn);
1852
1853 conn->state = BT_CONFIG;
1854
1855 if (!lmp_esco_capable(hdev)) {
1856 struct hci_cp_accept_conn_req cp;
1857
1858 bacpy(&cp.bdaddr, &conn->dst);
1859
1860 if (lmp_rswitch_capable(hdev) && (mask & HCI_LM_MASTER))
1861 cp.role = 0x00; /* Become master */
1862 else
1863 cp.role = 0x01; /* Remain slave */
1864
1865 hci_send_cmd(hdev, HCI_OP_ACCEPT_CONN_REQ, sizeof(cp), &cp);
1866 } else /* lmp_esco_capable(hdev)) */ {
1867 struct hci_cp_accept_sync_conn_req cp;
1868
1869 bacpy(&cp.bdaddr, &conn->dst);
1870 cp.pkt_type = cpu_to_le16(conn->pkt_type);
1871
1872 cp.tx_bandwidth = __constant_cpu_to_le32(0x00001f40);
1873 cp.rx_bandwidth = __constant_cpu_to_le32(0x00001f40);
1874 cp.max_latency = __constant_cpu_to_le16(0xffff);
1875 cp.content_format = cpu_to_le16(hdev->voice_setting);
1876 cp.retrans_effort = 0xff;
1877
1878 hci_send_cmd(hdev, HCI_OP_ACCEPT_SYNC_CONN_REQ,
1879 sizeof(cp), &cp);
1880 }
1881}
1882
Gustavo Padovan6039aa72012-05-23 04:04:18 -03001883static void hci_conn_request_evt(struct hci_dev *hdev, struct sk_buff *skb)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001884{
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001885 struct hci_ev_conn_request *ev = (void *) skb->data;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001886 int mask = hdev->link_mode;
Frédéric Dalleau20714bf2012-11-21 10:51:12 +01001887 __u8 flags = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001888
Andrei Emeltchenko6ed93dc2012-09-25 12:49:43 +03001889 BT_DBG("%s bdaddr %pMR type 0x%x", hdev->name, &ev->bdaddr,
Gustavo Padovan807deac2012-05-17 00:36:24 -03001890 ev->link_type);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001891
Frédéric Dalleau20714bf2012-11-21 10:51:12 +01001892 mask |= hci_proto_connect_ind(hdev, &ev->bdaddr, ev->link_type,
1893 &flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001894
Szymon Janc138d22e2011-02-17 16:44:23 +01001895 if ((mask & HCI_LM_ACCEPT) &&
Gustavo Padovan807deac2012-05-17 00:36:24 -03001896 !hci_blacklist_lookup(hdev, &ev->bdaddr)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001897 /* Connection accepted */
Marcel Holtmannc7bdd502008-07-14 20:13:47 +02001898 struct inquiry_entry *ie;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001899 struct hci_conn *conn;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001900
1901 hci_dev_lock(hdev);
Marcel Holtmannb6a0dc82007-10-20 14:55:10 +02001902
Andrei Emeltchenkocc11b9c2010-11-22 13:21:37 +02001903 ie = hci_inquiry_cache_lookup(hdev, &ev->bdaddr);
1904 if (ie)
Marcel Holtmannc7bdd502008-07-14 20:13:47 +02001905 memcpy(ie->data.dev_class, ev->dev_class, 3);
1906
Gustavo Padovan8fc9ced2012-05-23 04:04:21 -03001907 conn = hci_conn_hash_lookup_ba(hdev, ev->link_type,
1908 &ev->bdaddr);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001909 if (!conn) {
Andrei Emeltchenkocc11b9c2010-11-22 13:21:37 +02001910 conn = hci_conn_add(hdev, ev->link_type, &ev->bdaddr);
1911 if (!conn) {
Gustavo F. Padovan893ef972010-07-18 15:13:37 -03001912 BT_ERR("No memory for new connection");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001913 hci_dev_unlock(hdev);
1914 return;
1915 }
1916 }
Marcel Holtmannb6a0dc82007-10-20 14:55:10 +02001917
Linus Torvalds1da177e2005-04-16 15:20:36 -07001918 memcpy(conn->dev_class, ev->dev_class, 3);
Marcel Holtmannb6a0dc82007-10-20 14:55:10 +02001919
Linus Torvalds1da177e2005-04-16 15:20:36 -07001920 hci_dev_unlock(hdev);
1921
Frédéric Dalleau20714bf2012-11-21 10:51:12 +01001922 if (ev->link_type == ACL_LINK ||
1923 (!(flags & HCI_PROTO_DEFER) && !lmp_esco_capable(hdev))) {
Marcel Holtmannb6a0dc82007-10-20 14:55:10 +02001924 struct hci_cp_accept_conn_req cp;
Frédéric Dalleau20714bf2012-11-21 10:51:12 +01001925 conn->state = BT_CONNECT;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001926
Marcel Holtmannb6a0dc82007-10-20 14:55:10 +02001927 bacpy(&cp.bdaddr, &ev->bdaddr);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001928
Marcel Holtmannb6a0dc82007-10-20 14:55:10 +02001929 if (lmp_rswitch_capable(hdev) && (mask & HCI_LM_MASTER))
1930 cp.role = 0x00; /* Become master */
1931 else
1932 cp.role = 0x01; /* Remain slave */
1933
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001934 hci_send_cmd(hdev, HCI_OP_ACCEPT_CONN_REQ, sizeof(cp),
1935 &cp);
Frédéric Dalleau20714bf2012-11-21 10:51:12 +01001936 } else if (!(flags & HCI_PROTO_DEFER)) {
Marcel Holtmannb6a0dc82007-10-20 14:55:10 +02001937 struct hci_cp_accept_sync_conn_req cp;
Frédéric Dalleau20714bf2012-11-21 10:51:12 +01001938 conn->state = BT_CONNECT;
Marcel Holtmannb6a0dc82007-10-20 14:55:10 +02001939
1940 bacpy(&cp.bdaddr, &ev->bdaddr);
Marcel Holtmanna8746412008-07-14 20:13:46 +02001941 cp.pkt_type = cpu_to_le16(conn->pkt_type);
Marcel Holtmannb6a0dc82007-10-20 14:55:10 +02001942
Andrei Emeltchenko82781e62012-05-25 11:38:27 +03001943 cp.tx_bandwidth = __constant_cpu_to_le32(0x00001f40);
1944 cp.rx_bandwidth = __constant_cpu_to_le32(0x00001f40);
1945 cp.max_latency = __constant_cpu_to_le16(0xffff);
Marcel Holtmannb6a0dc82007-10-20 14:55:10 +02001946 cp.content_format = cpu_to_le16(hdev->voice_setting);
1947 cp.retrans_effort = 0xff;
1948
1949 hci_send_cmd(hdev, HCI_OP_ACCEPT_SYNC_CONN_REQ,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001950 sizeof(cp), &cp);
Frédéric Dalleau20714bf2012-11-21 10:51:12 +01001951 } else {
1952 conn->state = BT_CONNECT2;
1953 hci_proto_connect_cfm(conn, 0);
1954 hci_conn_put(conn);
Marcel Holtmannb6a0dc82007-10-20 14:55:10 +02001955 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001956 } else {
1957 /* Connection rejected */
1958 struct hci_cp_reject_conn_req cp;
1959
1960 bacpy(&cp.bdaddr, &ev->bdaddr);
Andrei Emeltchenko9f5a0d72011-11-07 14:20:25 +02001961 cp.reason = HCI_ERROR_REJ_BAD_ADDR;
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001962 hci_send_cmd(hdev, HCI_OP_REJECT_CONN_REQ, sizeof(cp), &cp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001963 }
1964}
1965
Mikel Astizf0d6a0e2012-08-09 09:52:30 +02001966static u8 hci_to_mgmt_reason(u8 err)
1967{
1968 switch (err) {
1969 case HCI_ERROR_CONNECTION_TIMEOUT:
1970 return MGMT_DEV_DISCONN_TIMEOUT;
1971 case HCI_ERROR_REMOTE_USER_TERM:
1972 case HCI_ERROR_REMOTE_LOW_RESOURCES:
1973 case HCI_ERROR_REMOTE_POWER_OFF:
1974 return MGMT_DEV_DISCONN_REMOTE;
1975 case HCI_ERROR_LOCAL_HOST_TERM:
1976 return MGMT_DEV_DISCONN_LOCAL_HOST;
1977 default:
1978 return MGMT_DEV_DISCONN_UNKNOWN;
1979 }
1980}
1981
Gustavo Padovan6039aa72012-05-23 04:04:18 -03001982static void hci_disconn_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001983{
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001984 struct hci_ev_disconn_complete *ev = (void *) skb->data;
Marcel Holtmann04837f62006-07-03 10:02:33 +02001985 struct hci_conn *conn;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001986
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +03001987 BT_DBG("%s status 0x%2.2x", hdev->name, ev->status);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001988
Linus Torvalds1da177e2005-04-16 15:20:36 -07001989 hci_dev_lock(hdev);
1990
Marcel Holtmann04837f62006-07-03 10:02:33 +02001991 conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
Johan Hedbergf7520542011-01-20 12:34:39 +02001992 if (!conn)
1993 goto unlock;
Marcel Holtmann7d0db0a2008-07-14 20:13:51 +02001994
Johan Hedberg37d9ef72011-11-10 15:54:39 +02001995 if (ev->status == 0)
1996 conn->state = BT_CLOSED;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001997
Johan Hedbergb644ba32012-01-17 21:48:47 +02001998 if (test_and_clear_bit(HCI_CONN_MGMT_CONNECTED, &conn->flags) &&
Gustavo Padovan807deac2012-05-17 00:36:24 -03001999 (conn->type == ACL_LINK || conn->type == LE_LINK)) {
Mikel Astizf0d6a0e2012-08-09 09:52:30 +02002000 if (ev->status) {
Johan Hedberg88c3df12012-02-09 14:27:38 +02002001 mgmt_disconnect_failed(hdev, &conn->dst, conn->type,
Gustavo Padovan807deac2012-05-17 00:36:24 -03002002 conn->dst_type, ev->status);
Mikel Astizf0d6a0e2012-08-09 09:52:30 +02002003 } else {
2004 u8 reason = hci_to_mgmt_reason(ev->reason);
2005
Johan Hedbergafc747a2012-01-15 18:11:07 +02002006 mgmt_device_disconnected(hdev, &conn->dst, conn->type,
Mikel Astizf0d6a0e2012-08-09 09:52:30 +02002007 conn->dst_type, reason);
2008 }
Johan Hedberg37d9ef72011-11-10 15:54:39 +02002009 }
Johan Hedbergf7520542011-01-20 12:34:39 +02002010
Johan Hedberg37d9ef72011-11-10 15:54:39 +02002011 if (ev->status == 0) {
Vishal Agarwal6ec5bca2012-04-16 14:44:44 +05302012 if (conn->type == ACL_LINK && conn->flush_key)
2013 hci_remove_link_key(hdev, &conn->dst);
Johan Hedberg37d9ef72011-11-10 15:54:39 +02002014 hci_proto_disconn_cfm(conn, ev->reason);
2015 hci_conn_del(conn);
2016 }
Johan Hedbergf7520542011-01-20 12:34:39 +02002017
2018unlock:
Linus Torvalds1da177e2005-04-16 15:20:36 -07002019 hci_dev_unlock(hdev);
2020}
2021
Gustavo Padovan6039aa72012-05-23 04:04:18 -03002022static void hci_auth_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002023{
2024 struct hci_ev_auth_complete *ev = (void *) skb->data;
2025 struct hci_conn *conn;
2026
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +03002027 BT_DBG("%s status 0x%2.2x", hdev->name, ev->status);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002028
2029 hci_dev_lock(hdev);
2030
2031 conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
Waldemar Rymarkiewiczd7556e22011-05-31 15:49:26 +02002032 if (!conn)
2033 goto unlock;
2034
2035 if (!ev->status) {
Johan Hedbergaa64a8b2012-01-18 21:33:12 +02002036 if (!hci_conn_ssp_enabled(conn) &&
Gustavo Padovan807deac2012-05-17 00:36:24 -03002037 test_bit(HCI_CONN_REAUTH_PEND, &conn->flags)) {
Waldemar Rymarkiewiczd7556e22011-05-31 15:49:26 +02002038 BT_INFO("re-auth of legacy device is not possible.");
Johan Hedberg2a611692011-02-19 12:06:00 -03002039 } else {
Waldemar Rymarkiewiczd7556e22011-05-31 15:49:26 +02002040 conn->link_mode |= HCI_LM_AUTH;
2041 conn->sec_level = conn->pending_sec_level;
Johan Hedberg2a611692011-02-19 12:06:00 -03002042 }
Waldemar Rymarkiewiczd7556e22011-05-31 15:49:26 +02002043 } else {
Johan Hedbergbab73cb2012-02-09 16:07:29 +02002044 mgmt_auth_failed(hdev, &conn->dst, conn->type, conn->dst_type,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002045 ev->status);
Waldemar Rymarkiewiczd7556e22011-05-31 15:49:26 +02002046 }
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002047
Johan Hedberg51a8efd2012-01-16 06:10:31 +02002048 clear_bit(HCI_CONN_AUTH_PEND, &conn->flags);
2049 clear_bit(HCI_CONN_REAUTH_PEND, &conn->flags);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002050
Waldemar Rymarkiewiczd7556e22011-05-31 15:49:26 +02002051 if (conn->state == BT_CONFIG) {
Johan Hedbergaa64a8b2012-01-18 21:33:12 +02002052 if (!ev->status && hci_conn_ssp_enabled(conn)) {
Waldemar Rymarkiewiczd7556e22011-05-31 15:49:26 +02002053 struct hci_cp_set_conn_encrypt cp;
2054 cp.handle = ev->handle;
2055 cp.encrypt = 0x01;
2056 hci_send_cmd(hdev, HCI_OP_SET_CONN_ENCRYPT, sizeof(cp),
Gustavo Padovan807deac2012-05-17 00:36:24 -03002057 &cp);
Marcel Holtmann052b30b2009-04-26 20:01:22 +02002058 } else {
Waldemar Rymarkiewiczd7556e22011-05-31 15:49:26 +02002059 conn->state = BT_CONNECTED;
2060 hci_proto_connect_cfm(conn, ev->status);
Marcel Holtmann052b30b2009-04-26 20:01:22 +02002061 hci_conn_put(conn);
2062 }
Waldemar Rymarkiewiczd7556e22011-05-31 15:49:26 +02002063 } else {
2064 hci_auth_cfm(conn, ev->status);
Marcel Holtmann052b30b2009-04-26 20:01:22 +02002065
Waldemar Rymarkiewiczd7556e22011-05-31 15:49:26 +02002066 hci_conn_hold(conn);
2067 conn->disc_timeout = HCI_DISCONN_TIMEOUT;
2068 hci_conn_put(conn);
2069 }
2070
Johan Hedberg51a8efd2012-01-16 06:10:31 +02002071 if (test_bit(HCI_CONN_ENCRYPT_PEND, &conn->flags)) {
Waldemar Rymarkiewiczd7556e22011-05-31 15:49:26 +02002072 if (!ev->status) {
2073 struct hci_cp_set_conn_encrypt cp;
2074 cp.handle = ev->handle;
2075 cp.encrypt = 0x01;
2076 hci_send_cmd(hdev, HCI_OP_SET_CONN_ENCRYPT, sizeof(cp),
Gustavo Padovan807deac2012-05-17 00:36:24 -03002077 &cp);
Waldemar Rymarkiewiczd7556e22011-05-31 15:49:26 +02002078 } else {
Johan Hedberg51a8efd2012-01-16 06:10:31 +02002079 clear_bit(HCI_CONN_ENCRYPT_PEND, &conn->flags);
Waldemar Rymarkiewiczd7556e22011-05-31 15:49:26 +02002080 hci_encrypt_cfm(conn, ev->status, 0x00);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002081 }
2082 }
2083
Waldemar Rymarkiewiczd7556e22011-05-31 15:49:26 +02002084unlock:
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002085 hci_dev_unlock(hdev);
2086}
2087
Gustavo Padovan6039aa72012-05-23 04:04:18 -03002088static void hci_remote_name_evt(struct hci_dev *hdev, struct sk_buff *skb)
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002089{
Johan Hedberg127178d2010-11-18 22:22:29 +02002090 struct hci_ev_remote_name *ev = (void *) skb->data;
2091 struct hci_conn *conn;
2092
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002093 BT_DBG("%s", hdev->name);
2094
2095 hci_conn_check_pending(hdev);
Johan Hedberg127178d2010-11-18 22:22:29 +02002096
2097 hci_dev_lock(hdev);
2098
2099 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
Johan Hedbergb644ba32012-01-17 21:48:47 +02002100
2101 if (!test_bit(HCI_MGMT, &hdev->dev_flags))
2102 goto check_auth;
2103
2104 if (ev->status == 0)
2105 hci_check_pending_name(hdev, conn, &ev->bdaddr, ev->name,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002106 strnlen(ev->name, HCI_MAX_NAME_LENGTH));
Johan Hedbergb644ba32012-01-17 21:48:47 +02002107 else
2108 hci_check_pending_name(hdev, conn, &ev->bdaddr, NULL, 0);
2109
2110check_auth:
Johan Hedberg79c6c702011-04-28 11:28:55 -07002111 if (!conn)
2112 goto unlock;
2113
2114 if (!hci_outgoing_auth_needed(hdev, conn))
2115 goto unlock;
2116
Johan Hedberg51a8efd2012-01-16 06:10:31 +02002117 if (!test_and_set_bit(HCI_CONN_AUTH_PEND, &conn->flags)) {
Johan Hedberg127178d2010-11-18 22:22:29 +02002118 struct hci_cp_auth_requested cp;
2119 cp.handle = __cpu_to_le16(conn->handle);
2120 hci_send_cmd(hdev, HCI_OP_AUTH_REQUESTED, sizeof(cp), &cp);
2121 }
2122
Johan Hedberg79c6c702011-04-28 11:28:55 -07002123unlock:
Johan Hedberg127178d2010-11-18 22:22:29 +02002124 hci_dev_unlock(hdev);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002125}
2126
Gustavo Padovan6039aa72012-05-23 04:04:18 -03002127static void hci_encrypt_change_evt(struct hci_dev *hdev, struct sk_buff *skb)
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002128{
2129 struct hci_ev_encrypt_change *ev = (void *) skb->data;
2130 struct hci_conn *conn;
2131
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +03002132 BT_DBG("%s status 0x%2.2x", hdev->name, ev->status);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002133
2134 hci_dev_lock(hdev);
2135
2136 conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
2137 if (conn) {
2138 if (!ev->status) {
Marcel Holtmannae293192008-07-14 20:13:45 +02002139 if (ev->encrypt) {
2140 /* Encryption implies authentication */
2141 conn->link_mode |= HCI_LM_AUTH;
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002142 conn->link_mode |= HCI_LM_ENCRYPT;
Vinicius Costa Gomesda85e5e2011-06-09 18:50:53 -03002143 conn->sec_level = conn->pending_sec_level;
Marcel Holtmannae293192008-07-14 20:13:45 +02002144 } else
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002145 conn->link_mode &= ~HCI_LM_ENCRYPT;
2146 }
2147
Johan Hedberg51a8efd2012-01-16 06:10:31 +02002148 clear_bit(HCI_CONN_ENCRYPT_PEND, &conn->flags);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002149
Gustavo Padovana7d77232012-05-13 03:20:07 -03002150 if (ev->status && conn->state == BT_CONNECTED) {
Andre Guedesbed71742013-01-30 11:50:56 -03002151 hci_disconnect(conn, HCI_ERROR_AUTH_FAILURE);
Gustavo Padovana7d77232012-05-13 03:20:07 -03002152 hci_conn_put(conn);
2153 goto unlock;
2154 }
2155
Marcel Holtmannf8558552008-07-14 20:13:49 +02002156 if (conn->state == BT_CONFIG) {
2157 if (!ev->status)
2158 conn->state = BT_CONNECTED;
2159
2160 hci_proto_connect_cfm(conn, ev->status);
2161 hci_conn_put(conn);
2162 } else
2163 hci_encrypt_cfm(conn, ev->status, ev->encrypt);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002164 }
2165
Gustavo Padovana7d77232012-05-13 03:20:07 -03002166unlock:
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002167 hci_dev_unlock(hdev);
2168}
2169
Gustavo Padovan6039aa72012-05-23 04:04:18 -03002170static void hci_change_link_key_complete_evt(struct hci_dev *hdev,
2171 struct sk_buff *skb)
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002172{
2173 struct hci_ev_change_link_key_complete *ev = (void *) skb->data;
2174 struct hci_conn *conn;
2175
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +03002176 BT_DBG("%s status 0x%2.2x", hdev->name, ev->status);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002177
2178 hci_dev_lock(hdev);
2179
2180 conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
2181 if (conn) {
2182 if (!ev->status)
2183 conn->link_mode |= HCI_LM_SECURE;
2184
Johan Hedberg51a8efd2012-01-16 06:10:31 +02002185 clear_bit(HCI_CONN_AUTH_PEND, &conn->flags);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002186
2187 hci_key_change_cfm(conn, ev->status);
2188 }
2189
2190 hci_dev_unlock(hdev);
2191}
2192
Gustavo Padovan6039aa72012-05-23 04:04:18 -03002193static void hci_remote_features_evt(struct hci_dev *hdev,
2194 struct sk_buff *skb)
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002195{
2196 struct hci_ev_remote_features *ev = (void *) skb->data;
2197 struct hci_conn *conn;
2198
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +03002199 BT_DBG("%s status 0x%2.2x", hdev->name, ev->status);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002200
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002201 hci_dev_lock(hdev);
2202
2203 conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
Johan Hedbergccd556f2010-11-10 17:11:51 +02002204 if (!conn)
2205 goto unlock;
Marcel Holtmann769be972008-07-14 20:13:49 +02002206
Johan Hedbergccd556f2010-11-10 17:11:51 +02002207 if (!ev->status)
2208 memcpy(conn->features, ev->features, 8);
2209
2210 if (conn->state != BT_CONFIG)
2211 goto unlock;
2212
2213 if (!ev->status && lmp_ssp_capable(hdev) && lmp_ssp_capable(conn)) {
2214 struct hci_cp_read_remote_ext_features cp;
2215 cp.handle = ev->handle;
2216 cp.page = 0x01;
2217 hci_send_cmd(hdev, HCI_OP_READ_REMOTE_EXT_FEATURES,
Gustavo Padovan807deac2012-05-17 00:36:24 -03002218 sizeof(cp), &cp);
Johan Hedberg392599b2010-11-18 22:22:28 +02002219 goto unlock;
2220 }
2221
Johan Hedberg671267b2012-05-12 16:11:50 -03002222 if (!ev->status && !test_bit(HCI_CONN_MGMT_CONNECTED, &conn->flags)) {
Johan Hedberg127178d2010-11-18 22:22:29 +02002223 struct hci_cp_remote_name_req cp;
2224 memset(&cp, 0, sizeof(cp));
2225 bacpy(&cp.bdaddr, &conn->dst);
2226 cp.pscan_rep_mode = 0x02;
2227 hci_send_cmd(hdev, HCI_OP_REMOTE_NAME_REQ, sizeof(cp), &cp);
Johan Hedbergb644ba32012-01-17 21:48:47 +02002228 } else if (!test_and_set_bit(HCI_CONN_MGMT_CONNECTED, &conn->flags))
2229 mgmt_device_connected(hdev, &conn->dst, conn->type,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002230 conn->dst_type, 0, NULL, 0,
2231 conn->dev_class);
Johan Hedberg392599b2010-11-18 22:22:28 +02002232
Johan Hedberg127178d2010-11-18 22:22:29 +02002233 if (!hci_outgoing_auth_needed(hdev, conn)) {
Johan Hedbergccd556f2010-11-10 17:11:51 +02002234 conn->state = BT_CONNECTED;
2235 hci_proto_connect_cfm(conn, ev->status);
2236 hci_conn_put(conn);
Marcel Holtmann769be972008-07-14 20:13:49 +02002237 }
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002238
Johan Hedbergccd556f2010-11-10 17:11:51 +02002239unlock:
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002240 hci_dev_unlock(hdev);
2241}
2242
Gustavo Padovan6039aa72012-05-23 04:04:18 -03002243static void hci_remote_version_evt(struct hci_dev *hdev, struct sk_buff *skb)
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002244{
2245 BT_DBG("%s", hdev->name);
2246}
2247
Gustavo Padovan6039aa72012-05-23 04:04:18 -03002248static void hci_qos_setup_complete_evt(struct hci_dev *hdev,
2249 struct sk_buff *skb)
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002250{
2251 BT_DBG("%s", hdev->name);
2252}
2253
Gustavo Padovan6039aa72012-05-23 04:04:18 -03002254static void hci_cmd_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002255{
2256 struct hci_ev_cmd_complete *ev = (void *) skb->data;
2257 __u16 opcode;
2258
2259 skb_pull(skb, sizeof(*ev));
2260
2261 opcode = __le16_to_cpu(ev->opcode);
2262
2263 switch (opcode) {
2264 case HCI_OP_INQUIRY_CANCEL:
2265 hci_cc_inquiry_cancel(hdev, skb);
2266 break;
2267
Andre Guedes4d934832012-03-21 00:03:35 -03002268 case HCI_OP_PERIODIC_INQ:
2269 hci_cc_periodic_inq(hdev, skb);
2270 break;
2271
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002272 case HCI_OP_EXIT_PERIODIC_INQ:
2273 hci_cc_exit_periodic_inq(hdev, skb);
2274 break;
2275
2276 case HCI_OP_REMOTE_NAME_REQ_CANCEL:
2277 hci_cc_remote_name_req_cancel(hdev, skb);
2278 break;
2279
2280 case HCI_OP_ROLE_DISCOVERY:
2281 hci_cc_role_discovery(hdev, skb);
2282 break;
2283
Marcel Holtmanne4e8e372008-07-14 20:13:47 +02002284 case HCI_OP_READ_LINK_POLICY:
2285 hci_cc_read_link_policy(hdev, skb);
2286 break;
2287
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002288 case HCI_OP_WRITE_LINK_POLICY:
2289 hci_cc_write_link_policy(hdev, skb);
2290 break;
2291
Marcel Holtmanne4e8e372008-07-14 20:13:47 +02002292 case HCI_OP_READ_DEF_LINK_POLICY:
2293 hci_cc_read_def_link_policy(hdev, skb);
2294 break;
2295
2296 case HCI_OP_WRITE_DEF_LINK_POLICY:
2297 hci_cc_write_def_link_policy(hdev, skb);
2298 break;
2299
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002300 case HCI_OP_RESET:
2301 hci_cc_reset(hdev, skb);
2302 break;
2303
2304 case HCI_OP_WRITE_LOCAL_NAME:
2305 hci_cc_write_local_name(hdev, skb);
2306 break;
2307
2308 case HCI_OP_READ_LOCAL_NAME:
2309 hci_cc_read_local_name(hdev, skb);
2310 break;
2311
2312 case HCI_OP_WRITE_AUTH_ENABLE:
2313 hci_cc_write_auth_enable(hdev, skb);
2314 break;
2315
2316 case HCI_OP_WRITE_ENCRYPT_MODE:
2317 hci_cc_write_encrypt_mode(hdev, skb);
2318 break;
2319
2320 case HCI_OP_WRITE_SCAN_ENABLE:
2321 hci_cc_write_scan_enable(hdev, skb);
2322 break;
2323
2324 case HCI_OP_READ_CLASS_OF_DEV:
2325 hci_cc_read_class_of_dev(hdev, skb);
2326 break;
2327
2328 case HCI_OP_WRITE_CLASS_OF_DEV:
2329 hci_cc_write_class_of_dev(hdev, skb);
2330 break;
2331
2332 case HCI_OP_READ_VOICE_SETTING:
2333 hci_cc_read_voice_setting(hdev, skb);
2334 break;
2335
2336 case HCI_OP_WRITE_VOICE_SETTING:
2337 hci_cc_write_voice_setting(hdev, skb);
2338 break;
2339
2340 case HCI_OP_HOST_BUFFER_SIZE:
2341 hci_cc_host_buffer_size(hdev, skb);
2342 break;
2343
Marcel Holtmann333140b2008-07-14 20:13:48 +02002344 case HCI_OP_WRITE_SSP_MODE:
2345 hci_cc_write_ssp_mode(hdev, skb);
2346 break;
2347
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002348 case HCI_OP_READ_LOCAL_VERSION:
2349 hci_cc_read_local_version(hdev, skb);
2350 break;
2351
2352 case HCI_OP_READ_LOCAL_COMMANDS:
2353 hci_cc_read_local_commands(hdev, skb);
2354 break;
2355
2356 case HCI_OP_READ_LOCAL_FEATURES:
2357 hci_cc_read_local_features(hdev, skb);
2358 break;
2359
Andre Guedes971e3a42011-06-30 19:20:52 -03002360 case HCI_OP_READ_LOCAL_EXT_FEATURES:
2361 hci_cc_read_local_ext_features(hdev, skb);
2362 break;
2363
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002364 case HCI_OP_READ_BUFFER_SIZE:
2365 hci_cc_read_buffer_size(hdev, skb);
2366 break;
2367
2368 case HCI_OP_READ_BD_ADDR:
2369 hci_cc_read_bd_addr(hdev, skb);
2370 break;
2371
Andrei Emeltchenko350ee4c2011-12-07 15:56:51 +02002372 case HCI_OP_READ_DATA_BLOCK_SIZE:
2373 hci_cc_read_data_block_size(hdev, skb);
2374 break;
2375
Johan Hedberg23bb5762010-12-21 23:01:27 +02002376 case HCI_OP_WRITE_CA_TIMEOUT:
2377 hci_cc_write_ca_timeout(hdev, skb);
2378 break;
2379
Andrei Emeltchenko1e89cff2011-11-24 14:52:02 +02002380 case HCI_OP_READ_FLOW_CONTROL_MODE:
2381 hci_cc_read_flow_control_mode(hdev, skb);
2382 break;
2383
Andrei Emeltchenko928abaa2011-10-12 10:53:57 +03002384 case HCI_OP_READ_LOCAL_AMP_INFO:
2385 hci_cc_read_local_amp_info(hdev, skb);
2386 break;
2387
Andrei Emeltchenko903e4542012-09-27 17:26:09 +03002388 case HCI_OP_READ_LOCAL_AMP_ASSOC:
2389 hci_cc_read_local_amp_assoc(hdev, skb);
2390 break;
2391
Johan Hedbergb0916ea2011-01-10 13:44:55 +02002392 case HCI_OP_DELETE_STORED_LINK_KEY:
2393 hci_cc_delete_stored_link_key(hdev, skb);
2394 break;
2395
Johan Hedbergd5859e22011-01-25 01:19:58 +02002396 case HCI_OP_SET_EVENT_MASK:
2397 hci_cc_set_event_mask(hdev, skb);
2398 break;
2399
2400 case HCI_OP_WRITE_INQUIRY_MODE:
2401 hci_cc_write_inquiry_mode(hdev, skb);
2402 break;
2403
2404 case HCI_OP_READ_INQ_RSP_TX_POWER:
2405 hci_cc_read_inq_rsp_tx_power(hdev, skb);
2406 break;
2407
2408 case HCI_OP_SET_EVENT_FLT:
2409 hci_cc_set_event_flt(hdev, skb);
2410 break;
2411
Johan Hedberg980e1a52011-01-22 06:10:07 +02002412 case HCI_OP_PIN_CODE_REPLY:
2413 hci_cc_pin_code_reply(hdev, skb);
2414 break;
2415
2416 case HCI_OP_PIN_CODE_NEG_REPLY:
2417 hci_cc_pin_code_neg_reply(hdev, skb);
2418 break;
2419
Szymon Jancc35938b2011-03-22 13:12:21 +01002420 case HCI_OP_READ_LOCAL_OOB_DATA:
2421 hci_cc_read_local_oob_data_reply(hdev, skb);
2422 break;
2423
Ville Tervo6ed58ec2011-02-10 22:38:48 -03002424 case HCI_OP_LE_READ_BUFFER_SIZE:
2425 hci_cc_le_read_buffer_size(hdev, skb);
2426 break;
2427
Johan Hedberg60e77322013-01-22 14:01:59 +02002428 case HCI_OP_LE_READ_LOCAL_FEATURES:
2429 hci_cc_le_read_local_features(hdev, skb);
2430 break;
2431
Johan Hedberg8fa19092012-10-19 20:57:49 +03002432 case HCI_OP_LE_READ_ADV_TX_POWER:
2433 hci_cc_le_read_adv_tx_power(hdev, skb);
2434 break;
2435
Johan Hedberge36b04c2012-10-19 20:57:47 +03002436 case HCI_OP_LE_SET_EVENT_MASK:
2437 hci_cc_le_set_event_mask(hdev, skb);
2438 break;
2439
Johan Hedberga5c29682011-02-19 12:05:57 -03002440 case HCI_OP_USER_CONFIRM_REPLY:
2441 hci_cc_user_confirm_reply(hdev, skb);
2442 break;
2443
2444 case HCI_OP_USER_CONFIRM_NEG_REPLY:
2445 hci_cc_user_confirm_neg_reply(hdev, skb);
2446 break;
2447
Brian Gix1143d452011-11-23 08:28:34 -08002448 case HCI_OP_USER_PASSKEY_REPLY:
2449 hci_cc_user_passkey_reply(hdev, skb);
2450 break;
2451
2452 case HCI_OP_USER_PASSKEY_NEG_REPLY:
2453 hci_cc_user_passkey_neg_reply(hdev, skb);
Szymon Janc16cde992012-04-13 12:32:42 +02002454 break;
Andre Guedes07f7fa52011-12-02 21:13:31 +09002455
2456 case HCI_OP_LE_SET_SCAN_PARAM:
2457 hci_cc_le_set_scan_param(hdev, skb);
Brian Gix1143d452011-11-23 08:28:34 -08002458 break;
2459
Johan Hedbergc1d5dc42012-11-08 01:23:01 +01002460 case HCI_OP_LE_SET_ADV_ENABLE:
2461 hci_cc_le_set_adv_enable(hdev, skb);
2462 break;
2463
Andre Guedeseb9d91f2011-05-26 16:23:52 -03002464 case HCI_OP_LE_SET_SCAN_ENABLE:
2465 hci_cc_le_set_scan_enable(hdev, skb);
2466 break;
2467
Johan Hedbergcf1d0812013-01-22 14:02:00 +02002468 case HCI_OP_LE_READ_WHITE_LIST_SIZE:
2469 hci_cc_le_read_white_list_size(hdev, skb);
2470 break;
2471
Vinicius Costa Gomesa7a595f2011-06-09 18:50:47 -03002472 case HCI_OP_LE_LTK_REPLY:
2473 hci_cc_le_ltk_reply(hdev, skb);
2474 break;
2475
2476 case HCI_OP_LE_LTK_NEG_REPLY:
2477 hci_cc_le_ltk_neg_reply(hdev, skb);
2478 break;
2479
Johan Hedberg9b008c02013-01-22 14:02:01 +02002480 case HCI_OP_LE_READ_SUPPORTED_STATES:
2481 hci_cc_le_read_supported_states(hdev, skb);
2482 break;
2483
Andre Guedesf9b49302011-06-30 19:20:53 -03002484 case HCI_OP_WRITE_LE_HOST_SUPPORTED:
2485 hci_cc_write_le_host_supported(hdev, skb);
2486 break;
2487
Andrei Emeltchenko93c284e2012-09-27 17:26:20 +03002488 case HCI_OP_WRITE_REMOTE_AMP_ASSOC:
2489 hci_cc_write_remote_amp_assoc(hdev, skb);
2490 break;
2491
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002492 default:
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +03002493 BT_DBG("%s opcode 0x%4.4x", hdev->name, opcode);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002494 break;
2495 }
2496
Ville Tervo6bd32322011-02-16 16:32:41 +02002497 if (ev->opcode != HCI_OP_NOP)
2498 del_timer(&hdev->cmd_timer);
2499
Szymon Jancdbccd792012-12-11 08:51:19 +01002500 if (ev->ncmd && !test_bit(HCI_RESET, &hdev->flags)) {
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002501 atomic_set(&hdev->cmd_cnt, 1);
2502 if (!skb_queue_empty(&hdev->cmd_q))
Gustavo F. Padovanc347b762011-12-14 23:53:47 -02002503 queue_work(hdev->workqueue, &hdev->cmd_work);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002504 }
2505}
2506
Gustavo Padovan6039aa72012-05-23 04:04:18 -03002507static void hci_cmd_status_evt(struct hci_dev *hdev, struct sk_buff *skb)
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002508{
2509 struct hci_ev_cmd_status *ev = (void *) skb->data;
2510 __u16 opcode;
2511
2512 skb_pull(skb, sizeof(*ev));
2513
2514 opcode = __le16_to_cpu(ev->opcode);
2515
2516 switch (opcode) {
2517 case HCI_OP_INQUIRY:
2518 hci_cs_inquiry(hdev, ev->status);
2519 break;
2520
2521 case HCI_OP_CREATE_CONN:
2522 hci_cs_create_conn(hdev, ev->status);
2523 break;
2524
2525 case HCI_OP_ADD_SCO:
2526 hci_cs_add_sco(hdev, ev->status);
2527 break;
2528
Marcel Holtmannf8558552008-07-14 20:13:49 +02002529 case HCI_OP_AUTH_REQUESTED:
2530 hci_cs_auth_requested(hdev, ev->status);
2531 break;
2532
2533 case HCI_OP_SET_CONN_ENCRYPT:
2534 hci_cs_set_conn_encrypt(hdev, ev->status);
2535 break;
2536
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002537 case HCI_OP_REMOTE_NAME_REQ:
2538 hci_cs_remote_name_req(hdev, ev->status);
2539 break;
2540
Marcel Holtmann769be972008-07-14 20:13:49 +02002541 case HCI_OP_READ_REMOTE_FEATURES:
2542 hci_cs_read_remote_features(hdev, ev->status);
2543 break;
2544
2545 case HCI_OP_READ_REMOTE_EXT_FEATURES:
2546 hci_cs_read_remote_ext_features(hdev, ev->status);
2547 break;
2548
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002549 case HCI_OP_SETUP_SYNC_CONN:
2550 hci_cs_setup_sync_conn(hdev, ev->status);
2551 break;
2552
2553 case HCI_OP_SNIFF_MODE:
2554 hci_cs_sniff_mode(hdev, ev->status);
2555 break;
2556
2557 case HCI_OP_EXIT_SNIFF_MODE:
2558 hci_cs_exit_sniff_mode(hdev, ev->status);
2559 break;
2560
Johan Hedberg8962ee72011-01-20 12:40:27 +02002561 case HCI_OP_DISCONNECT:
Johan Hedberg88c3df12012-02-09 14:27:38 +02002562 hci_cs_disconnect(hdev, ev->status);
Johan Hedberg8962ee72011-01-20 12:40:27 +02002563 break;
2564
Ville Tervofcd89c02011-02-10 22:38:47 -03002565 case HCI_OP_LE_CREATE_CONN:
2566 hci_cs_le_create_conn(hdev, ev->status);
2567 break;
2568
Vinicius Costa Gomesa7a595f2011-06-09 18:50:47 -03002569 case HCI_OP_LE_START_ENC:
2570 hci_cs_le_start_enc(hdev, ev->status);
2571 break;
2572
Andrei Emeltchenkoa02226d2012-09-27 17:26:19 +03002573 case HCI_OP_CREATE_PHY_LINK:
2574 hci_cs_create_phylink(hdev, ev->status);
2575 break;
2576
Andrei Emeltchenko0b26ab92012-09-27 17:26:24 +03002577 case HCI_OP_ACCEPT_PHY_LINK:
2578 hci_cs_accept_phylink(hdev, ev->status);
2579 break;
2580
Andrei Emeltchenko5ce66b52012-10-31 15:46:30 +02002581 case HCI_OP_CREATE_LOGICAL_LINK:
2582 hci_cs_create_logical_link(hdev, ev->status);
2583 break;
2584
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002585 default:
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +03002586 BT_DBG("%s opcode 0x%4.4x", hdev->name, opcode);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002587 break;
2588 }
2589
Ville Tervo6bd32322011-02-16 16:32:41 +02002590 if (ev->opcode != HCI_OP_NOP)
2591 del_timer(&hdev->cmd_timer);
2592
Gustavo F. Padovan10572132011-03-16 15:36:29 -03002593 if (ev->ncmd && !test_bit(HCI_RESET, &hdev->flags)) {
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002594 atomic_set(&hdev->cmd_cnt, 1);
2595 if (!skb_queue_empty(&hdev->cmd_q))
Gustavo F. Padovanc347b762011-12-14 23:53:47 -02002596 queue_work(hdev->workqueue, &hdev->cmd_work);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002597 }
2598}
2599
Gustavo Padovan6039aa72012-05-23 04:04:18 -03002600static void hci_role_change_evt(struct hci_dev *hdev, struct sk_buff *skb)
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002601{
2602 struct hci_ev_role_change *ev = (void *) skb->data;
2603 struct hci_conn *conn;
2604
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +03002605 BT_DBG("%s status 0x%2.2x", hdev->name, ev->status);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002606
2607 hci_dev_lock(hdev);
2608
2609 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
2610 if (conn) {
2611 if (!ev->status) {
2612 if (ev->role)
2613 conn->link_mode &= ~HCI_LM_MASTER;
2614 else
2615 conn->link_mode |= HCI_LM_MASTER;
2616 }
2617
Johan Hedberg51a8efd2012-01-16 06:10:31 +02002618 clear_bit(HCI_CONN_RSWITCH_PEND, &conn->flags);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002619
2620 hci_role_switch_cfm(conn, ev->status, ev->role);
2621 }
2622
2623 hci_dev_unlock(hdev);
2624}
2625
Gustavo Padovan6039aa72012-05-23 04:04:18 -03002626static void hci_num_comp_pkts_evt(struct hci_dev *hdev, struct sk_buff *skb)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002627{
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002628 struct hci_ev_num_comp_pkts *ev = (void *) skb->data;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002629 int i;
2630
Andrei Emeltchenko32ac5b92011-12-19 16:31:29 +02002631 if (hdev->flow_ctl_mode != HCI_FLOW_CTL_MODE_PACKET_BASED) {
2632 BT_ERR("Wrong event for mode %d", hdev->flow_ctl_mode);
2633 return;
2634 }
2635
Andrei Emeltchenkoc5993de2011-12-30 12:07:47 +02002636 if (skb->len < sizeof(*ev) || skb->len < sizeof(*ev) +
Gustavo Padovan807deac2012-05-17 00:36:24 -03002637 ev->num_hndl * sizeof(struct hci_comp_pkts_info)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002638 BT_DBG("%s bad parameters", hdev->name);
2639 return;
2640 }
2641
Andrei Emeltchenkoc5993de2011-12-30 12:07:47 +02002642 BT_DBG("%s num_hndl %d", hdev->name, ev->num_hndl);
2643
Andrei Emeltchenko613a1c02011-12-19 16:31:30 +02002644 for (i = 0; i < ev->num_hndl; i++) {
2645 struct hci_comp_pkts_info *info = &ev->handles[i];
Linus Torvalds1da177e2005-04-16 15:20:36 -07002646 struct hci_conn *conn;
2647 __u16 handle, count;
2648
Andrei Emeltchenko613a1c02011-12-19 16:31:30 +02002649 handle = __le16_to_cpu(info->handle);
2650 count = __le16_to_cpu(info->count);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002651
2652 conn = hci_conn_hash_lookup_handle(hdev, handle);
Andrei Emeltchenkof4280912011-12-07 15:56:52 +02002653 if (!conn)
2654 continue;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002655
Andrei Emeltchenkof4280912011-12-07 15:56:52 +02002656 conn->sent -= count;
2657
2658 switch (conn->type) {
2659 case ACL_LINK:
2660 hdev->acl_cnt += count;
2661 if (hdev->acl_cnt > hdev->acl_pkts)
2662 hdev->acl_cnt = hdev->acl_pkts;
2663 break;
2664
2665 case LE_LINK:
2666 if (hdev->le_pkts) {
2667 hdev->le_cnt += count;
2668 if (hdev->le_cnt > hdev->le_pkts)
2669 hdev->le_cnt = hdev->le_pkts;
2670 } else {
Andrei Emeltchenko70f230202010-12-01 16:58:25 +02002671 hdev->acl_cnt += count;
2672 if (hdev->acl_cnt > hdev->acl_pkts)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002673 hdev->acl_cnt = hdev->acl_pkts;
2674 }
Andrei Emeltchenkof4280912011-12-07 15:56:52 +02002675 break;
2676
2677 case SCO_LINK:
2678 hdev->sco_cnt += count;
2679 if (hdev->sco_cnt > hdev->sco_pkts)
2680 hdev->sco_cnt = hdev->sco_pkts;
2681 break;
2682
2683 default:
2684 BT_ERR("Unknown type %d conn %p", conn->type, conn);
2685 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002686 }
2687 }
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002688
Gustavo F. Padovan3eff45e2011-12-15 00:50:02 -02002689 queue_work(hdev->workqueue, &hdev->tx_work);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002690}
2691
Andrei Emeltchenko76ef7cf2012-10-10 17:38:29 +03002692static struct hci_conn *__hci_conn_lookup_handle(struct hci_dev *hdev,
2693 __u16 handle)
2694{
2695 struct hci_chan *chan;
2696
2697 switch (hdev->dev_type) {
2698 case HCI_BREDR:
2699 return hci_conn_hash_lookup_handle(hdev, handle);
2700 case HCI_AMP:
2701 chan = hci_chan_lookup_handle(hdev, handle);
2702 if (chan)
2703 return chan->conn;
2704 break;
2705 default:
2706 BT_ERR("%s unknown dev_type %d", hdev->name, hdev->dev_type);
2707 break;
2708 }
2709
2710 return NULL;
2711}
2712
Gustavo Padovan6039aa72012-05-23 04:04:18 -03002713static void hci_num_comp_blocks_evt(struct hci_dev *hdev, struct sk_buff *skb)
Andrei Emeltchenko25e89e92012-01-04 12:41:58 +02002714{
2715 struct hci_ev_num_comp_blocks *ev = (void *) skb->data;
2716 int i;
2717
2718 if (hdev->flow_ctl_mode != HCI_FLOW_CTL_MODE_BLOCK_BASED) {
2719 BT_ERR("Wrong event for mode %d", hdev->flow_ctl_mode);
2720 return;
2721 }
2722
2723 if (skb->len < sizeof(*ev) || skb->len < sizeof(*ev) +
Gustavo Padovan807deac2012-05-17 00:36:24 -03002724 ev->num_hndl * sizeof(struct hci_comp_blocks_info)) {
Andrei Emeltchenko25e89e92012-01-04 12:41:58 +02002725 BT_DBG("%s bad parameters", hdev->name);
2726 return;
2727 }
2728
2729 BT_DBG("%s num_blocks %d num_hndl %d", hdev->name, ev->num_blocks,
Gustavo Padovan807deac2012-05-17 00:36:24 -03002730 ev->num_hndl);
Andrei Emeltchenko25e89e92012-01-04 12:41:58 +02002731
2732 for (i = 0; i < ev->num_hndl; i++) {
2733 struct hci_comp_blocks_info *info = &ev->handles[i];
Andrei Emeltchenko76ef7cf2012-10-10 17:38:29 +03002734 struct hci_conn *conn = NULL;
Andrei Emeltchenko25e89e92012-01-04 12:41:58 +02002735 __u16 handle, block_count;
2736
2737 handle = __le16_to_cpu(info->handle);
2738 block_count = __le16_to_cpu(info->blocks);
2739
Andrei Emeltchenko76ef7cf2012-10-10 17:38:29 +03002740 conn = __hci_conn_lookup_handle(hdev, handle);
Andrei Emeltchenko25e89e92012-01-04 12:41:58 +02002741 if (!conn)
2742 continue;
2743
2744 conn->sent -= block_count;
2745
2746 switch (conn->type) {
2747 case ACL_LINK:
Andrei Emeltchenkobd1eb662012-10-10 17:38:30 +03002748 case AMP_LINK:
Andrei Emeltchenko25e89e92012-01-04 12:41:58 +02002749 hdev->block_cnt += block_count;
2750 if (hdev->block_cnt > hdev->num_blocks)
2751 hdev->block_cnt = hdev->num_blocks;
2752 break;
2753
2754 default:
2755 BT_ERR("Unknown type %d conn %p", conn->type, conn);
2756 break;
2757 }
2758 }
2759
2760 queue_work(hdev->workqueue, &hdev->tx_work);
2761}
2762
Gustavo Padovan6039aa72012-05-23 04:04:18 -03002763static void hci_mode_change_evt(struct hci_dev *hdev, struct sk_buff *skb)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002764{
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002765 struct hci_ev_mode_change *ev = (void *) skb->data;
Marcel Holtmann04837f62006-07-03 10:02:33 +02002766 struct hci_conn *conn;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002767
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +03002768 BT_DBG("%s status 0x%2.2x", hdev->name, ev->status);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002769
2770 hci_dev_lock(hdev);
2771
Marcel Holtmann04837f62006-07-03 10:02:33 +02002772 conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
2773 if (conn) {
2774 conn->mode = ev->mode;
2775 conn->interval = __le16_to_cpu(ev->interval);
2776
Gustavo Padovan8fc9ced2012-05-23 04:04:21 -03002777 if (!test_and_clear_bit(HCI_CONN_MODE_CHANGE_PEND,
2778 &conn->flags)) {
Marcel Holtmann04837f62006-07-03 10:02:33 +02002779 if (conn->mode == HCI_CM_ACTIVE)
Johan Hedberg58a681e2012-01-16 06:47:28 +02002780 set_bit(HCI_CONN_POWER_SAVE, &conn->flags);
Marcel Holtmann04837f62006-07-03 10:02:33 +02002781 else
Johan Hedberg58a681e2012-01-16 06:47:28 +02002782 clear_bit(HCI_CONN_POWER_SAVE, &conn->flags);
Marcel Holtmann04837f62006-07-03 10:02:33 +02002783 }
Marcel Holtmanne73439d2010-07-26 10:06:00 -04002784
Johan Hedberg51a8efd2012-01-16 06:10:31 +02002785 if (test_and_clear_bit(HCI_CONN_SCO_SETUP_PEND, &conn->flags))
Marcel Holtmanne73439d2010-07-26 10:06:00 -04002786 hci_sco_setup(conn, ev->status);
Marcel Holtmann04837f62006-07-03 10:02:33 +02002787 }
2788
2789 hci_dev_unlock(hdev);
2790}
2791
Gustavo Padovan6039aa72012-05-23 04:04:18 -03002792static void hci_pin_code_request_evt(struct hci_dev *hdev, struct sk_buff *skb)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002793{
Marcel Holtmann052b30b2009-04-26 20:01:22 +02002794 struct hci_ev_pin_code_req *ev = (void *) skb->data;
2795 struct hci_conn *conn;
2796
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002797 BT_DBG("%s", hdev->name);
Marcel Holtmann052b30b2009-04-26 20:01:22 +02002798
2799 hci_dev_lock(hdev);
2800
2801 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
Waldemar Rymarkiewiczb6f98042011-09-23 10:01:30 +02002802 if (!conn)
2803 goto unlock;
2804
2805 if (conn->state == BT_CONNECTED) {
Marcel Holtmann052b30b2009-04-26 20:01:22 +02002806 hci_conn_hold(conn);
2807 conn->disc_timeout = HCI_PAIRING_TIMEOUT;
2808 hci_conn_put(conn);
2809 }
2810
Johan Hedberga8b2d5c2012-01-08 23:11:15 +02002811 if (!test_bit(HCI_PAIRABLE, &hdev->dev_flags))
Johan Hedberg03b555e2011-01-04 15:40:05 +02002812 hci_send_cmd(hdev, HCI_OP_PIN_CODE_NEG_REPLY,
Gustavo Padovan807deac2012-05-17 00:36:24 -03002813 sizeof(ev->bdaddr), &ev->bdaddr);
Johan Hedberga8b2d5c2012-01-08 23:11:15 +02002814 else if (test_bit(HCI_MGMT, &hdev->dev_flags)) {
Waldemar Rymarkiewicza770bb52011-04-28 12:07:59 +02002815 u8 secure;
2816
2817 if (conn->pending_sec_level == BT_SECURITY_HIGH)
2818 secure = 1;
2819 else
2820 secure = 0;
2821
Johan Hedberg744cf192011-11-08 20:40:14 +02002822 mgmt_pin_code_request(hdev, &ev->bdaddr, secure);
Waldemar Rymarkiewicza770bb52011-04-28 12:07:59 +02002823 }
Johan Hedberg980e1a52011-01-22 06:10:07 +02002824
Waldemar Rymarkiewiczb6f98042011-09-23 10:01:30 +02002825unlock:
Marcel Holtmann052b30b2009-04-26 20:01:22 +02002826 hci_dev_unlock(hdev);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002827}
2828
Gustavo Padovan6039aa72012-05-23 04:04:18 -03002829static void hci_link_key_request_evt(struct hci_dev *hdev, struct sk_buff *skb)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002830{
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002831 struct hci_ev_link_key_req *ev = (void *) skb->data;
2832 struct hci_cp_link_key_reply cp;
2833 struct hci_conn *conn;
2834 struct link_key *key;
2835
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002836 BT_DBG("%s", hdev->name);
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002837
Johan Hedberga8b2d5c2012-01-08 23:11:15 +02002838 if (!test_bit(HCI_LINK_KEYS, &hdev->dev_flags))
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002839 return;
2840
2841 hci_dev_lock(hdev);
2842
2843 key = hci_find_link_key(hdev, &ev->bdaddr);
2844 if (!key) {
Andrei Emeltchenko6ed93dc2012-09-25 12:49:43 +03002845 BT_DBG("%s link key not found for %pMR", hdev->name,
2846 &ev->bdaddr);
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002847 goto not_found;
2848 }
2849
Andrei Emeltchenko6ed93dc2012-09-25 12:49:43 +03002850 BT_DBG("%s found key type %u for %pMR", hdev->name, key->type,
2851 &ev->bdaddr);
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002852
Johan Hedberga8b2d5c2012-01-08 23:11:15 +02002853 if (!test_bit(HCI_DEBUG_KEYS, &hdev->dev_flags) &&
Gustavo Padovan807deac2012-05-17 00:36:24 -03002854 key->type == HCI_LK_DEBUG_COMBINATION) {
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002855 BT_DBG("%s ignoring debug key", hdev->name);
2856 goto not_found;
2857 }
2858
2859 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
Waldemar Rymarkiewicz60b83f52011-04-28 12:07:56 +02002860 if (conn) {
2861 if (key->type == HCI_LK_UNAUTH_COMBINATION &&
Gustavo Padovan807deac2012-05-17 00:36:24 -03002862 conn->auth_type != 0xff && (conn->auth_type & 0x01)) {
Waldemar Rymarkiewicz60b83f52011-04-28 12:07:56 +02002863 BT_DBG("%s ignoring unauthenticated key", hdev->name);
2864 goto not_found;
2865 }
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002866
Waldemar Rymarkiewicz60b83f52011-04-28 12:07:56 +02002867 if (key->type == HCI_LK_COMBINATION && key->pin_len < 16 &&
Gustavo Padovan807deac2012-05-17 00:36:24 -03002868 conn->pending_sec_level == BT_SECURITY_HIGH) {
Gustavo Padovan8fc9ced2012-05-23 04:04:21 -03002869 BT_DBG("%s ignoring key unauthenticated for high security",
2870 hdev->name);
Waldemar Rymarkiewicz60b83f52011-04-28 12:07:56 +02002871 goto not_found;
2872 }
2873
2874 conn->key_type = key->type;
2875 conn->pin_length = key->pin_len;
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002876 }
2877
2878 bacpy(&cp.bdaddr, &ev->bdaddr);
Andrei Emeltchenko9b3b4462012-05-23 11:31:20 +03002879 memcpy(cp.link_key, key->val, HCI_LINK_KEY_SIZE);
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002880
2881 hci_send_cmd(hdev, HCI_OP_LINK_KEY_REPLY, sizeof(cp), &cp);
2882
2883 hci_dev_unlock(hdev);
2884
2885 return;
2886
2887not_found:
2888 hci_send_cmd(hdev, HCI_OP_LINK_KEY_NEG_REPLY, 6, &ev->bdaddr);
2889 hci_dev_unlock(hdev);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002890}
2891
Gustavo Padovan6039aa72012-05-23 04:04:18 -03002892static void hci_link_key_notify_evt(struct hci_dev *hdev, struct sk_buff *skb)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002893{
Marcel Holtmann052b30b2009-04-26 20:01:22 +02002894 struct hci_ev_link_key_notify *ev = (void *) skb->data;
2895 struct hci_conn *conn;
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002896 u8 pin_len = 0;
Marcel Holtmann052b30b2009-04-26 20:01:22 +02002897
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002898 BT_DBG("%s", hdev->name);
Marcel Holtmann052b30b2009-04-26 20:01:22 +02002899
2900 hci_dev_lock(hdev);
2901
2902 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
2903 if (conn) {
2904 hci_conn_hold(conn);
2905 conn->disc_timeout = HCI_DISCONN_TIMEOUT;
Johan Hedberg980e1a52011-01-22 06:10:07 +02002906 pin_len = conn->pin_length;
Waldemar Rymarkiewicz13d39312011-04-28 12:07:55 +02002907
2908 if (ev->key_type != HCI_LK_CHANGED_COMBINATION)
2909 conn->key_type = ev->key_type;
2910
Marcel Holtmann052b30b2009-04-26 20:01:22 +02002911 hci_conn_put(conn);
2912 }
2913
Johan Hedberga8b2d5c2012-01-08 23:11:15 +02002914 if (test_bit(HCI_LINK_KEYS, &hdev->dev_flags))
Johan Hedbergd25e28a2011-04-28 11:28:59 -07002915 hci_add_link_key(hdev, conn, 1, &ev->bdaddr, ev->link_key,
Gustavo Padovan807deac2012-05-17 00:36:24 -03002916 ev->key_type, pin_len);
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002917
Marcel Holtmann052b30b2009-04-26 20:01:22 +02002918 hci_dev_unlock(hdev);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002919}
2920
Gustavo Padovan6039aa72012-05-23 04:04:18 -03002921static void hci_clock_offset_evt(struct hci_dev *hdev, struct sk_buff *skb)
Marcel Holtmann04837f62006-07-03 10:02:33 +02002922{
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002923 struct hci_ev_clock_offset *ev = (void *) skb->data;
Marcel Holtmann04837f62006-07-03 10:02:33 +02002924 struct hci_conn *conn;
2925
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +03002926 BT_DBG("%s status 0x%2.2x", hdev->name, ev->status);
Marcel Holtmann04837f62006-07-03 10:02:33 +02002927
2928 hci_dev_lock(hdev);
2929
2930 conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
Linus Torvalds1da177e2005-04-16 15:20:36 -07002931 if (conn && !ev->status) {
2932 struct inquiry_entry *ie;
2933
Andrei Emeltchenkocc11b9c2010-11-22 13:21:37 +02002934 ie = hci_inquiry_cache_lookup(hdev, &conn->dst);
2935 if (ie) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002936 ie->data.clock_offset = ev->clock_offset;
2937 ie->timestamp = jiffies;
2938 }
2939 }
2940
2941 hci_dev_unlock(hdev);
2942}
2943
Gustavo Padovan6039aa72012-05-23 04:04:18 -03002944static void hci_pkt_type_change_evt(struct hci_dev *hdev, struct sk_buff *skb)
Marcel Holtmanna8746412008-07-14 20:13:46 +02002945{
2946 struct hci_ev_pkt_type_change *ev = (void *) skb->data;
2947 struct hci_conn *conn;
2948
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +03002949 BT_DBG("%s status 0x%2.2x", hdev->name, ev->status);
Marcel Holtmanna8746412008-07-14 20:13:46 +02002950
2951 hci_dev_lock(hdev);
2952
2953 conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
2954 if (conn && !ev->status)
2955 conn->pkt_type = __le16_to_cpu(ev->pkt_type);
2956
2957 hci_dev_unlock(hdev);
2958}
2959
Gustavo Padovan6039aa72012-05-23 04:04:18 -03002960static void hci_pscan_rep_mode_evt(struct hci_dev *hdev, struct sk_buff *skb)
Marcel Holtmann85a1e932005-08-09 20:28:02 -07002961{
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002962 struct hci_ev_pscan_rep_mode *ev = (void *) skb->data;
Marcel Holtmann85a1e932005-08-09 20:28:02 -07002963 struct inquiry_entry *ie;
2964
2965 BT_DBG("%s", hdev->name);
2966
2967 hci_dev_lock(hdev);
2968
Andrei Emeltchenkocc11b9c2010-11-22 13:21:37 +02002969 ie = hci_inquiry_cache_lookup(hdev, &ev->bdaddr);
2970 if (ie) {
Marcel Holtmann85a1e932005-08-09 20:28:02 -07002971 ie->data.pscan_rep_mode = ev->pscan_rep_mode;
2972 ie->timestamp = jiffies;
2973 }
2974
2975 hci_dev_unlock(hdev);
2976}
2977
Gustavo Padovan6039aa72012-05-23 04:04:18 -03002978static void hci_inquiry_result_with_rssi_evt(struct hci_dev *hdev,
2979 struct sk_buff *skb)
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002980{
2981 struct inquiry_data data;
2982 int num_rsp = *((__u8 *) skb->data);
Johan Hedberg388fc8f2012-02-23 00:38:59 +02002983 bool name_known, ssp;
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002984
2985 BT_DBG("%s num_rsp %d", hdev->name, num_rsp);
2986
2987 if (!num_rsp)
2988 return;
2989
Andre Guedes1519cc12012-03-21 00:03:38 -03002990 if (test_bit(HCI_PERIODIC_INQ, &hdev->dev_flags))
2991 return;
2992
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002993 hci_dev_lock(hdev);
2994
2995 if ((skb->len - 1) / num_rsp != sizeof(struct inquiry_info_with_rssi)) {
Szymon Janc138d22e2011-02-17 16:44:23 +01002996 struct inquiry_info_with_rssi_and_pscan_mode *info;
2997 info = (void *) (skb->data + 1);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002998
Johan Hedberge17acd42011-03-30 23:57:16 +03002999 for (; num_rsp; num_rsp--, info++) {
Marcel Holtmanna9de9242007-10-20 13:33:56 +02003000 bacpy(&data.bdaddr, &info->bdaddr);
3001 data.pscan_rep_mode = info->pscan_rep_mode;
3002 data.pscan_period_mode = info->pscan_period_mode;
3003 data.pscan_mode = info->pscan_mode;
3004 memcpy(data.dev_class, info->dev_class, 3);
3005 data.clock_offset = info->clock_offset;
3006 data.rssi = info->rssi;
Marcel Holtmann41a96212008-07-14 20:13:48 +02003007 data.ssp_mode = 0x00;
Johan Hedberg31754052012-01-04 13:39:52 +02003008
3009 name_known = hci_inquiry_cache_update(hdev, &data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003010 false, &ssp);
Johan Hedberg48264f02011-11-09 13:58:58 +02003011 mgmt_device_found(hdev, &info->bdaddr, ACL_LINK, 0x00,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003012 info->dev_class, info->rssi,
3013 !name_known, ssp, NULL, 0);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02003014 }
3015 } else {
3016 struct inquiry_info_with_rssi *info = (void *) (skb->data + 1);
3017
Johan Hedberge17acd42011-03-30 23:57:16 +03003018 for (; num_rsp; num_rsp--, info++) {
Marcel Holtmanna9de9242007-10-20 13:33:56 +02003019 bacpy(&data.bdaddr, &info->bdaddr);
3020 data.pscan_rep_mode = info->pscan_rep_mode;
3021 data.pscan_period_mode = info->pscan_period_mode;
3022 data.pscan_mode = 0x00;
3023 memcpy(data.dev_class, info->dev_class, 3);
3024 data.clock_offset = info->clock_offset;
3025 data.rssi = info->rssi;
Marcel Holtmann41a96212008-07-14 20:13:48 +02003026 data.ssp_mode = 0x00;
Johan Hedberg31754052012-01-04 13:39:52 +02003027 name_known = hci_inquiry_cache_update(hdev, &data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003028 false, &ssp);
Johan Hedberg48264f02011-11-09 13:58:58 +02003029 mgmt_device_found(hdev, &info->bdaddr, ACL_LINK, 0x00,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003030 info->dev_class, info->rssi,
3031 !name_known, ssp, NULL, 0);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02003032 }
3033 }
3034
3035 hci_dev_unlock(hdev);
3036}
3037
Gustavo Padovan6039aa72012-05-23 04:04:18 -03003038static void hci_remote_ext_features_evt(struct hci_dev *hdev,
3039 struct sk_buff *skb)
Marcel Holtmanna9de9242007-10-20 13:33:56 +02003040{
Marcel Holtmann41a96212008-07-14 20:13:48 +02003041 struct hci_ev_remote_ext_features *ev = (void *) skb->data;
3042 struct hci_conn *conn;
3043
Marcel Holtmanna9de9242007-10-20 13:33:56 +02003044 BT_DBG("%s", hdev->name);
Marcel Holtmann41a96212008-07-14 20:13:48 +02003045
Marcel Holtmann41a96212008-07-14 20:13:48 +02003046 hci_dev_lock(hdev);
3047
3048 conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
Johan Hedbergccd556f2010-11-10 17:11:51 +02003049 if (!conn)
3050 goto unlock;
Marcel Holtmann41a96212008-07-14 20:13:48 +02003051
Johan Hedbergccd556f2010-11-10 17:11:51 +02003052 if (!ev->status && ev->page == 0x01) {
3053 struct inquiry_entry *ie;
Marcel Holtmann41a96212008-07-14 20:13:48 +02003054
Andrei Emeltchenkocc11b9c2010-11-22 13:21:37 +02003055 ie = hci_inquiry_cache_lookup(hdev, &conn->dst);
3056 if (ie)
Johan Hedberg02b7cc62012-02-28 02:28:43 +02003057 ie->data.ssp_mode = (ev->features[0] & LMP_HOST_SSP);
Marcel Holtmann769be972008-07-14 20:13:49 +02003058
Johan Hedberg02b7cc62012-02-28 02:28:43 +02003059 if (ev->features[0] & LMP_HOST_SSP)
Johan Hedberg58a681e2012-01-16 06:47:28 +02003060 set_bit(HCI_CONN_SSP_ENABLED, &conn->flags);
Marcel Holtmann41a96212008-07-14 20:13:48 +02003061 }
3062
Johan Hedbergccd556f2010-11-10 17:11:51 +02003063 if (conn->state != BT_CONFIG)
3064 goto unlock;
3065
Johan Hedberg671267b2012-05-12 16:11:50 -03003066 if (!ev->status && !test_bit(HCI_CONN_MGMT_CONNECTED, &conn->flags)) {
Johan Hedberg127178d2010-11-18 22:22:29 +02003067 struct hci_cp_remote_name_req cp;
3068 memset(&cp, 0, sizeof(cp));
3069 bacpy(&cp.bdaddr, &conn->dst);
3070 cp.pscan_rep_mode = 0x02;
3071 hci_send_cmd(hdev, HCI_OP_REMOTE_NAME_REQ, sizeof(cp), &cp);
Johan Hedbergb644ba32012-01-17 21:48:47 +02003072 } else if (!test_and_set_bit(HCI_CONN_MGMT_CONNECTED, &conn->flags))
3073 mgmt_device_connected(hdev, &conn->dst, conn->type,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003074 conn->dst_type, 0, NULL, 0,
3075 conn->dev_class);
Johan Hedberg392599b2010-11-18 22:22:28 +02003076
Johan Hedberg127178d2010-11-18 22:22:29 +02003077 if (!hci_outgoing_auth_needed(hdev, conn)) {
Johan Hedbergccd556f2010-11-10 17:11:51 +02003078 conn->state = BT_CONNECTED;
3079 hci_proto_connect_cfm(conn, ev->status);
3080 hci_conn_put(conn);
3081 }
3082
3083unlock:
Marcel Holtmann41a96212008-07-14 20:13:48 +02003084 hci_dev_unlock(hdev);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02003085}
3086
Gustavo Padovan6039aa72012-05-23 04:04:18 -03003087static void hci_sync_conn_complete_evt(struct hci_dev *hdev,
3088 struct sk_buff *skb)
Marcel Holtmanna9de9242007-10-20 13:33:56 +02003089{
Marcel Holtmannb6a0dc82007-10-20 14:55:10 +02003090 struct hci_ev_sync_conn_complete *ev = (void *) skb->data;
3091 struct hci_conn *conn;
3092
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +03003093 BT_DBG("%s status 0x%2.2x", hdev->name, ev->status);
Marcel Holtmannb6a0dc82007-10-20 14:55:10 +02003094
3095 hci_dev_lock(hdev);
3096
3097 conn = hci_conn_hash_lookup_ba(hdev, ev->link_type, &ev->bdaddr);
Marcel Holtmann9dc0a3a2008-07-14 20:13:46 +02003098 if (!conn) {
3099 if (ev->link_type == ESCO_LINK)
3100 goto unlock;
3101
3102 conn = hci_conn_hash_lookup_ba(hdev, ESCO_LINK, &ev->bdaddr);
3103 if (!conn)
3104 goto unlock;
3105
3106 conn->type = SCO_LINK;
3107 }
Marcel Holtmannb6a0dc82007-10-20 14:55:10 +02003108
Marcel Holtmann732547f2009-04-19 19:14:14 +02003109 switch (ev->status) {
3110 case 0x00:
Marcel Holtmannb6a0dc82007-10-20 14:55:10 +02003111 conn->handle = __le16_to_cpu(ev->handle);
3112 conn->state = BT_CONNECTED;
Marcel Holtmann7d0db0a2008-07-14 20:13:51 +02003113
Marcel Holtmann9eba32b2009-08-22 14:19:26 -07003114 hci_conn_hold_device(conn);
Marcel Holtmann7d0db0a2008-07-14 20:13:51 +02003115 hci_conn_add_sysfs(conn);
Marcel Holtmann732547f2009-04-19 19:14:14 +02003116 break;
3117
Stephen Coe705e5712010-02-16 11:29:44 -05003118 case 0x11: /* Unsupported Feature or Parameter Value */
Marcel Holtmann732547f2009-04-19 19:14:14 +02003119 case 0x1c: /* SCO interval rejected */
Nick Pelly1038a002010-02-03 11:42:26 -08003120 case 0x1a: /* Unsupported Remote Feature */
Marcel Holtmann732547f2009-04-19 19:14:14 +02003121 case 0x1f: /* Unspecified error */
3122 if (conn->out && conn->attempt < 2) {
3123 conn->pkt_type = (hdev->esco_type & SCO_ESCO_MASK) |
3124 (hdev->esco_type & EDR_ESCO_MASK);
3125 hci_setup_sync(conn, conn->link->handle);
3126 goto unlock;
3127 }
3128 /* fall through */
3129
3130 default:
Marcel Holtmannb6a0dc82007-10-20 14:55:10 +02003131 conn->state = BT_CLOSED;
Marcel Holtmann732547f2009-04-19 19:14:14 +02003132 break;
3133 }
Marcel Holtmannb6a0dc82007-10-20 14:55:10 +02003134
3135 hci_proto_connect_cfm(conn, ev->status);
3136 if (ev->status)
3137 hci_conn_del(conn);
3138
3139unlock:
3140 hci_dev_unlock(hdev);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02003141}
3142
Gustavo Padovan6039aa72012-05-23 04:04:18 -03003143static void hci_sync_conn_changed_evt(struct hci_dev *hdev, struct sk_buff *skb)
Marcel Holtmanna9de9242007-10-20 13:33:56 +02003144{
3145 BT_DBG("%s", hdev->name);
3146}
3147
Gustavo Padovan6039aa72012-05-23 04:04:18 -03003148static void hci_sniff_subrate_evt(struct hci_dev *hdev, struct sk_buff *skb)
Marcel Holtmann04837f62006-07-03 10:02:33 +02003149{
Marcel Holtmanna9de9242007-10-20 13:33:56 +02003150 struct hci_ev_sniff_subrate *ev = (void *) skb->data;
Marcel Holtmann04837f62006-07-03 10:02:33 +02003151
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +03003152 BT_DBG("%s status 0x%2.2x", hdev->name, ev->status);
Marcel Holtmann04837f62006-07-03 10:02:33 +02003153}
3154
Gustavo Padovan6039aa72012-05-23 04:04:18 -03003155static void hci_extended_inquiry_result_evt(struct hci_dev *hdev,
3156 struct sk_buff *skb)
Marcel Holtmanna9de9242007-10-20 13:33:56 +02003157{
3158 struct inquiry_data data;
3159 struct extended_inquiry_info *info = (void *) (skb->data + 1);
3160 int num_rsp = *((__u8 *) skb->data);
Vishal Agarwal9d939d92012-04-26 19:19:56 +05303161 size_t eir_len;
Marcel Holtmanna9de9242007-10-20 13:33:56 +02003162
3163 BT_DBG("%s num_rsp %d", hdev->name, num_rsp);
3164
3165 if (!num_rsp)
3166 return;
3167
Andre Guedes1519cc12012-03-21 00:03:38 -03003168 if (test_bit(HCI_PERIODIC_INQ, &hdev->dev_flags))
3169 return;
3170
Marcel Holtmanna9de9242007-10-20 13:33:56 +02003171 hci_dev_lock(hdev);
3172
Johan Hedberge17acd42011-03-30 23:57:16 +03003173 for (; num_rsp; num_rsp--, info++) {
Johan Hedberg388fc8f2012-02-23 00:38:59 +02003174 bool name_known, ssp;
Johan Hedberg561aafb2012-01-04 13:31:59 +02003175
Marcel Holtmanna9de9242007-10-20 13:33:56 +02003176 bacpy(&data.bdaddr, &info->bdaddr);
Szymon Janc138d22e2011-02-17 16:44:23 +01003177 data.pscan_rep_mode = info->pscan_rep_mode;
3178 data.pscan_period_mode = info->pscan_period_mode;
3179 data.pscan_mode = 0x00;
Marcel Holtmanna9de9242007-10-20 13:33:56 +02003180 memcpy(data.dev_class, info->dev_class, 3);
Szymon Janc138d22e2011-02-17 16:44:23 +01003181 data.clock_offset = info->clock_offset;
3182 data.rssi = info->rssi;
Marcel Holtmann41a96212008-07-14 20:13:48 +02003183 data.ssp_mode = 0x01;
Johan Hedberg561aafb2012-01-04 13:31:59 +02003184
Johan Hedberga8b2d5c2012-01-08 23:11:15 +02003185 if (test_bit(HCI_MGMT, &hdev->dev_flags))
Johan Hedberg4ddb1932012-01-15 20:04:43 +02003186 name_known = eir_has_data_type(info->data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003187 sizeof(info->data),
3188 EIR_NAME_COMPLETE);
Johan Hedberg561aafb2012-01-04 13:31:59 +02003189 else
3190 name_known = true;
3191
Johan Hedberg388fc8f2012-02-23 00:38:59 +02003192 name_known = hci_inquiry_cache_update(hdev, &data, name_known,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003193 &ssp);
Vishal Agarwal9d939d92012-04-26 19:19:56 +05303194 eir_len = eir_get_length(info->data, sizeof(info->data));
Johan Hedberg48264f02011-11-09 13:58:58 +02003195 mgmt_device_found(hdev, &info->bdaddr, ACL_LINK, 0x00,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003196 info->dev_class, info->rssi, !name_known,
Vishal Agarwal9d939d92012-04-26 19:19:56 +05303197 ssp, info->data, eir_len);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02003198 }
3199
3200 hci_dev_unlock(hdev);
3201}
3202
Johan Hedberg1c2e0042012-06-08 23:31:13 +08003203static void hci_key_refresh_complete_evt(struct hci_dev *hdev,
3204 struct sk_buff *skb)
3205{
3206 struct hci_ev_key_refresh_complete *ev = (void *) skb->data;
3207 struct hci_conn *conn;
3208
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +03003209 BT_DBG("%s status 0x%2.2x handle 0x%4.4x", hdev->name, ev->status,
Johan Hedberg1c2e0042012-06-08 23:31:13 +08003210 __le16_to_cpu(ev->handle));
3211
3212 hci_dev_lock(hdev);
3213
3214 conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
3215 if (!conn)
3216 goto unlock;
3217
3218 if (!ev->status)
3219 conn->sec_level = conn->pending_sec_level;
3220
3221 clear_bit(HCI_CONN_ENCRYPT_PEND, &conn->flags);
3222
3223 if (ev->status && conn->state == BT_CONNECTED) {
Andre Guedesbed71742013-01-30 11:50:56 -03003224 hci_disconnect(conn, HCI_ERROR_AUTH_FAILURE);
Johan Hedberg1c2e0042012-06-08 23:31:13 +08003225 hci_conn_put(conn);
3226 goto unlock;
3227 }
3228
3229 if (conn->state == BT_CONFIG) {
3230 if (!ev->status)
3231 conn->state = BT_CONNECTED;
3232
3233 hci_proto_connect_cfm(conn, ev->status);
3234 hci_conn_put(conn);
3235 } else {
3236 hci_auth_cfm(conn, ev->status);
3237
3238 hci_conn_hold(conn);
3239 conn->disc_timeout = HCI_DISCONN_TIMEOUT;
3240 hci_conn_put(conn);
3241 }
3242
3243unlock:
3244 hci_dev_unlock(hdev);
3245}
3246
Gustavo Padovan6039aa72012-05-23 04:04:18 -03003247static u8 hci_get_auth_req(struct hci_conn *conn)
Johan Hedberg17fa4b92011-01-25 13:28:33 +02003248{
3249 /* If remote requests dedicated bonding follow that lead */
3250 if (conn->remote_auth == 0x02 || conn->remote_auth == 0x03) {
3251 /* If both remote and local IO capabilities allow MITM
3252 * protection then require it, otherwise don't */
3253 if (conn->remote_cap == 0x03 || conn->io_capability == 0x03)
3254 return 0x02;
3255 else
3256 return 0x03;
3257 }
3258
3259 /* If remote requests no-bonding follow that lead */
3260 if (conn->remote_auth == 0x00 || conn->remote_auth == 0x01)
Waldemar Rymarkiewicz58797bf2011-04-28 12:07:58 +02003261 return conn->remote_auth | (conn->auth_type & 0x01);
Johan Hedberg17fa4b92011-01-25 13:28:33 +02003262
3263 return conn->auth_type;
3264}
3265
Gustavo Padovan6039aa72012-05-23 04:04:18 -03003266static void hci_io_capa_request_evt(struct hci_dev *hdev, struct sk_buff *skb)
Marcel Holtmann04936842008-07-14 20:13:48 +02003267{
3268 struct hci_ev_io_capa_request *ev = (void *) skb->data;
3269 struct hci_conn *conn;
3270
3271 BT_DBG("%s", hdev->name);
3272
3273 hci_dev_lock(hdev);
3274
3275 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
Johan Hedberg03b555e2011-01-04 15:40:05 +02003276 if (!conn)
3277 goto unlock;
Marcel Holtmann04936842008-07-14 20:13:48 +02003278
Johan Hedberg03b555e2011-01-04 15:40:05 +02003279 hci_conn_hold(conn);
3280
Johan Hedberga8b2d5c2012-01-08 23:11:15 +02003281 if (!test_bit(HCI_MGMT, &hdev->dev_flags))
Johan Hedberg03b555e2011-01-04 15:40:05 +02003282 goto unlock;
3283
Johan Hedberga8b2d5c2012-01-08 23:11:15 +02003284 if (test_bit(HCI_PAIRABLE, &hdev->dev_flags) ||
Gustavo Padovan807deac2012-05-17 00:36:24 -03003285 (conn->remote_auth & ~0x01) == HCI_AT_NO_BONDING) {
Johan Hedberg17fa4b92011-01-25 13:28:33 +02003286 struct hci_cp_io_capability_reply cp;
3287
3288 bacpy(&cp.bdaddr, &ev->bdaddr);
Hemant Gupta7a7f1e72012-01-16 13:34:29 +05303289 /* Change the IO capability from KeyboardDisplay
3290 * to DisplayYesNo as it is not supported by BT spec. */
3291 cp.capability = (conn->io_capability == 0x04) ?
3292 0x01 : conn->io_capability;
Johan Hedberg7cbc9bd2011-04-28 11:29:04 -07003293 conn->auth_type = hci_get_auth_req(conn);
3294 cp.authentication = conn->auth_type;
Johan Hedberg17fa4b92011-01-25 13:28:33 +02003295
Gustavo Padovan8fc9ced2012-05-23 04:04:21 -03003296 if (hci_find_remote_oob_data(hdev, &conn->dst) &&
3297 (conn->out || test_bit(HCI_CONN_REMOTE_OOB, &conn->flags)))
Szymon Jancce85ee12011-03-22 13:12:23 +01003298 cp.oob_data = 0x01;
3299 else
3300 cp.oob_data = 0x00;
3301
Johan Hedberg17fa4b92011-01-25 13:28:33 +02003302 hci_send_cmd(hdev, HCI_OP_IO_CAPABILITY_REPLY,
Gustavo Padovan807deac2012-05-17 00:36:24 -03003303 sizeof(cp), &cp);
Johan Hedberg03b555e2011-01-04 15:40:05 +02003304 } else {
3305 struct hci_cp_io_capability_neg_reply cp;
3306
3307 bacpy(&cp.bdaddr, &ev->bdaddr);
Andrei Emeltchenko9f5a0d72011-11-07 14:20:25 +02003308 cp.reason = HCI_ERROR_PAIRING_NOT_ALLOWED;
Johan Hedberg03b555e2011-01-04 15:40:05 +02003309
3310 hci_send_cmd(hdev, HCI_OP_IO_CAPABILITY_NEG_REPLY,
Gustavo Padovan807deac2012-05-17 00:36:24 -03003311 sizeof(cp), &cp);
Johan Hedberg03b555e2011-01-04 15:40:05 +02003312 }
3313
3314unlock:
3315 hci_dev_unlock(hdev);
3316}
3317
Gustavo Padovan6039aa72012-05-23 04:04:18 -03003318static void hci_io_capa_reply_evt(struct hci_dev *hdev, struct sk_buff *skb)
Johan Hedberg03b555e2011-01-04 15:40:05 +02003319{
3320 struct hci_ev_io_capa_reply *ev = (void *) skb->data;
3321 struct hci_conn *conn;
3322
3323 BT_DBG("%s", hdev->name);
3324
3325 hci_dev_lock(hdev);
3326
3327 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
3328 if (!conn)
3329 goto unlock;
3330
Johan Hedberg03b555e2011-01-04 15:40:05 +02003331 conn->remote_cap = ev->capability;
Johan Hedberg03b555e2011-01-04 15:40:05 +02003332 conn->remote_auth = ev->authentication;
Johan Hedberg58a681e2012-01-16 06:47:28 +02003333 if (ev->oob_data)
3334 set_bit(HCI_CONN_REMOTE_OOB, &conn->flags);
Johan Hedberg03b555e2011-01-04 15:40:05 +02003335
3336unlock:
Marcel Holtmann04936842008-07-14 20:13:48 +02003337 hci_dev_unlock(hdev);
3338}
3339
Gustavo Padovan6039aa72012-05-23 04:04:18 -03003340static void hci_user_confirm_request_evt(struct hci_dev *hdev,
3341 struct sk_buff *skb)
Johan Hedberga5c29682011-02-19 12:05:57 -03003342{
3343 struct hci_ev_user_confirm_req *ev = (void *) skb->data;
Johan Hedberg55bc1a32011-04-28 11:28:56 -07003344 int loc_mitm, rem_mitm, confirm_hint = 0;
Johan Hedberg7a828902011-04-28 11:28:53 -07003345 struct hci_conn *conn;
Johan Hedberga5c29682011-02-19 12:05:57 -03003346
3347 BT_DBG("%s", hdev->name);
3348
3349 hci_dev_lock(hdev);
3350
Johan Hedberga8b2d5c2012-01-08 23:11:15 +02003351 if (!test_bit(HCI_MGMT, &hdev->dev_flags))
Johan Hedberg7a828902011-04-28 11:28:53 -07003352 goto unlock;
Johan Hedberga5c29682011-02-19 12:05:57 -03003353
Johan Hedberg7a828902011-04-28 11:28:53 -07003354 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
3355 if (!conn)
3356 goto unlock;
3357
3358 loc_mitm = (conn->auth_type & 0x01);
3359 rem_mitm = (conn->remote_auth & 0x01);
3360
3361 /* If we require MITM but the remote device can't provide that
3362 * (it has NoInputNoOutput) then reject the confirmation
3363 * request. The only exception is when we're dedicated bonding
3364 * initiators (connect_cfm_cb set) since then we always have the MITM
3365 * bit set. */
3366 if (!conn->connect_cfm_cb && loc_mitm && conn->remote_cap == 0x03) {
3367 BT_DBG("Rejecting request: remote device can't provide MITM");
3368 hci_send_cmd(hdev, HCI_OP_USER_CONFIRM_NEG_REPLY,
Gustavo Padovan807deac2012-05-17 00:36:24 -03003369 sizeof(ev->bdaddr), &ev->bdaddr);
Johan Hedberg7a828902011-04-28 11:28:53 -07003370 goto unlock;
3371 }
3372
3373 /* If no side requires MITM protection; auto-accept */
3374 if ((!loc_mitm || conn->remote_cap == 0x03) &&
Gustavo Padovan807deac2012-05-17 00:36:24 -03003375 (!rem_mitm || conn->io_capability == 0x03)) {
Johan Hedberg55bc1a32011-04-28 11:28:56 -07003376
3377 /* If we're not the initiators request authorization to
3378 * proceed from user space (mgmt_user_confirm with
3379 * confirm_hint set to 1). */
Johan Hedberg51a8efd2012-01-16 06:10:31 +02003380 if (!test_bit(HCI_CONN_AUTH_PEND, &conn->flags)) {
Johan Hedberg55bc1a32011-04-28 11:28:56 -07003381 BT_DBG("Confirming auto-accept as acceptor");
3382 confirm_hint = 1;
3383 goto confirm;
3384 }
3385
Johan Hedberg9f616562011-04-28 11:28:54 -07003386 BT_DBG("Auto-accept of user confirmation with %ums delay",
Gustavo Padovan807deac2012-05-17 00:36:24 -03003387 hdev->auto_accept_delay);
Johan Hedberg9f616562011-04-28 11:28:54 -07003388
3389 if (hdev->auto_accept_delay > 0) {
3390 int delay = msecs_to_jiffies(hdev->auto_accept_delay);
3391 mod_timer(&conn->auto_accept_timer, jiffies + delay);
3392 goto unlock;
3393 }
3394
Johan Hedberg7a828902011-04-28 11:28:53 -07003395 hci_send_cmd(hdev, HCI_OP_USER_CONFIRM_REPLY,
Gustavo Padovan807deac2012-05-17 00:36:24 -03003396 sizeof(ev->bdaddr), &ev->bdaddr);
Johan Hedberg7a828902011-04-28 11:28:53 -07003397 goto unlock;
3398 }
3399
Johan Hedberg55bc1a32011-04-28 11:28:56 -07003400confirm:
Johan Hedberg272d90d2012-02-09 15:26:12 +02003401 mgmt_user_confirm_request(hdev, &ev->bdaddr, ACL_LINK, 0, ev->passkey,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003402 confirm_hint);
Johan Hedberg7a828902011-04-28 11:28:53 -07003403
3404unlock:
Johan Hedberga5c29682011-02-19 12:05:57 -03003405 hci_dev_unlock(hdev);
3406}
3407
Gustavo Padovan6039aa72012-05-23 04:04:18 -03003408static void hci_user_passkey_request_evt(struct hci_dev *hdev,
3409 struct sk_buff *skb)
Brian Gix1143d452011-11-23 08:28:34 -08003410{
3411 struct hci_ev_user_passkey_req *ev = (void *) skb->data;
3412
3413 BT_DBG("%s", hdev->name);
3414
Johan Hedberga8b2d5c2012-01-08 23:11:15 +02003415 if (test_bit(HCI_MGMT, &hdev->dev_flags))
Johan Hedberg272d90d2012-02-09 15:26:12 +02003416 mgmt_user_passkey_request(hdev, &ev->bdaddr, ACL_LINK, 0);
Brian Gix1143d452011-11-23 08:28:34 -08003417}
3418
Johan Hedberg92a25252012-09-06 18:39:26 +03003419static void hci_user_passkey_notify_evt(struct hci_dev *hdev,
3420 struct sk_buff *skb)
3421{
3422 struct hci_ev_user_passkey_notify *ev = (void *) skb->data;
3423 struct hci_conn *conn;
3424
3425 BT_DBG("%s", hdev->name);
3426
3427 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
3428 if (!conn)
3429 return;
3430
3431 conn->passkey_notify = __le32_to_cpu(ev->passkey);
3432 conn->passkey_entered = 0;
3433
3434 if (test_bit(HCI_MGMT, &hdev->dev_flags))
3435 mgmt_user_passkey_notify(hdev, &conn->dst, conn->type,
3436 conn->dst_type, conn->passkey_notify,
3437 conn->passkey_entered);
3438}
3439
3440static void hci_keypress_notify_evt(struct hci_dev *hdev, struct sk_buff *skb)
3441{
3442 struct hci_ev_keypress_notify *ev = (void *) skb->data;
3443 struct hci_conn *conn;
3444
3445 BT_DBG("%s", hdev->name);
3446
3447 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
3448 if (!conn)
3449 return;
3450
3451 switch (ev->type) {
3452 case HCI_KEYPRESS_STARTED:
3453 conn->passkey_entered = 0;
3454 return;
3455
3456 case HCI_KEYPRESS_ENTERED:
3457 conn->passkey_entered++;
3458 break;
3459
3460 case HCI_KEYPRESS_ERASED:
3461 conn->passkey_entered--;
3462 break;
3463
3464 case HCI_KEYPRESS_CLEARED:
3465 conn->passkey_entered = 0;
3466 break;
3467
3468 case HCI_KEYPRESS_COMPLETED:
3469 return;
3470 }
3471
3472 if (test_bit(HCI_MGMT, &hdev->dev_flags))
3473 mgmt_user_passkey_notify(hdev, &conn->dst, conn->type,
3474 conn->dst_type, conn->passkey_notify,
3475 conn->passkey_entered);
3476}
3477
Gustavo Padovan6039aa72012-05-23 04:04:18 -03003478static void hci_simple_pair_complete_evt(struct hci_dev *hdev,
3479 struct sk_buff *skb)
Marcel Holtmann04936842008-07-14 20:13:48 +02003480{
3481 struct hci_ev_simple_pair_complete *ev = (void *) skb->data;
3482 struct hci_conn *conn;
3483
3484 BT_DBG("%s", hdev->name);
3485
3486 hci_dev_lock(hdev);
3487
3488 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
Johan Hedberg2a611692011-02-19 12:06:00 -03003489 if (!conn)
3490 goto unlock;
Marcel Holtmann04936842008-07-14 20:13:48 +02003491
Johan Hedberg2a611692011-02-19 12:06:00 -03003492 /* To avoid duplicate auth_failed events to user space we check
3493 * the HCI_CONN_AUTH_PEND flag which will be set if we
3494 * initiated the authentication. A traditional auth_complete
3495 * event gets always produced as initiator and is also mapped to
3496 * the mgmt_auth_failed event */
Mikel Astizfa1bd912012-08-09 09:52:29 +02003497 if (!test_bit(HCI_CONN_AUTH_PEND, &conn->flags) && ev->status)
Johan Hedbergbab73cb2012-02-09 16:07:29 +02003498 mgmt_auth_failed(hdev, &conn->dst, conn->type, conn->dst_type,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003499 ev->status);
Johan Hedberg2a611692011-02-19 12:06:00 -03003500
3501 hci_conn_put(conn);
3502
3503unlock:
Marcel Holtmann04936842008-07-14 20:13:48 +02003504 hci_dev_unlock(hdev);
3505}
3506
Gustavo Padovan6039aa72012-05-23 04:04:18 -03003507static void hci_remote_host_features_evt(struct hci_dev *hdev,
3508 struct sk_buff *skb)
Marcel Holtmann41a96212008-07-14 20:13:48 +02003509{
3510 struct hci_ev_remote_host_features *ev = (void *) skb->data;
3511 struct inquiry_entry *ie;
3512
3513 BT_DBG("%s", hdev->name);
3514
3515 hci_dev_lock(hdev);
3516
Andrei Emeltchenkocc11b9c2010-11-22 13:21:37 +02003517 ie = hci_inquiry_cache_lookup(hdev, &ev->bdaddr);
3518 if (ie)
Johan Hedberg02b7cc62012-02-28 02:28:43 +02003519 ie->data.ssp_mode = (ev->features[0] & LMP_HOST_SSP);
Marcel Holtmann41a96212008-07-14 20:13:48 +02003520
3521 hci_dev_unlock(hdev);
3522}
3523
Gustavo Padovan6039aa72012-05-23 04:04:18 -03003524static void hci_remote_oob_data_request_evt(struct hci_dev *hdev,
3525 struct sk_buff *skb)
Szymon Janc2763eda2011-03-22 13:12:22 +01003526{
3527 struct hci_ev_remote_oob_data_request *ev = (void *) skb->data;
3528 struct oob_data *data;
3529
3530 BT_DBG("%s", hdev->name);
3531
3532 hci_dev_lock(hdev);
3533
Johan Hedberga8b2d5c2012-01-08 23:11:15 +02003534 if (!test_bit(HCI_MGMT, &hdev->dev_flags))
Szymon Jance1ba1f12011-04-06 13:01:59 +02003535 goto unlock;
3536
Szymon Janc2763eda2011-03-22 13:12:22 +01003537 data = hci_find_remote_oob_data(hdev, &ev->bdaddr);
3538 if (data) {
3539 struct hci_cp_remote_oob_data_reply cp;
3540
3541 bacpy(&cp.bdaddr, &ev->bdaddr);
3542 memcpy(cp.hash, data->hash, sizeof(cp.hash));
3543 memcpy(cp.randomizer, data->randomizer, sizeof(cp.randomizer));
3544
3545 hci_send_cmd(hdev, HCI_OP_REMOTE_OOB_DATA_REPLY, sizeof(cp),
Gustavo Padovan807deac2012-05-17 00:36:24 -03003546 &cp);
Szymon Janc2763eda2011-03-22 13:12:22 +01003547 } else {
3548 struct hci_cp_remote_oob_data_neg_reply cp;
3549
3550 bacpy(&cp.bdaddr, &ev->bdaddr);
3551 hci_send_cmd(hdev, HCI_OP_REMOTE_OOB_DATA_NEG_REPLY, sizeof(cp),
Gustavo Padovan807deac2012-05-17 00:36:24 -03003552 &cp);
Szymon Janc2763eda2011-03-22 13:12:22 +01003553 }
3554
Szymon Jance1ba1f12011-04-06 13:01:59 +02003555unlock:
Szymon Janc2763eda2011-03-22 13:12:22 +01003556 hci_dev_unlock(hdev);
3557}
3558
Andrei Emeltchenkod5e91192012-10-25 15:20:44 +03003559static void hci_phy_link_complete_evt(struct hci_dev *hdev,
3560 struct sk_buff *skb)
3561{
3562 struct hci_ev_phy_link_complete *ev = (void *) skb->data;
3563 struct hci_conn *hcon, *bredr_hcon;
3564
3565 BT_DBG("%s handle 0x%2.2x status 0x%2.2x", hdev->name, ev->phy_handle,
3566 ev->status);
3567
3568 hci_dev_lock(hdev);
3569
3570 hcon = hci_conn_hash_lookup_handle(hdev, ev->phy_handle);
3571 if (!hcon) {
3572 hci_dev_unlock(hdev);
3573 return;
3574 }
3575
3576 if (ev->status) {
3577 hci_conn_del(hcon);
3578 hci_dev_unlock(hdev);
3579 return;
3580 }
3581
3582 bredr_hcon = hcon->amp_mgr->l2cap_conn->hcon;
3583
3584 hcon->state = BT_CONNECTED;
3585 bacpy(&hcon->dst, &bredr_hcon->dst);
3586
3587 hci_conn_hold(hcon);
3588 hcon->disc_timeout = HCI_DISCONN_TIMEOUT;
3589 hci_conn_put(hcon);
3590
3591 hci_conn_hold_device(hcon);
3592 hci_conn_add_sysfs(hcon);
3593
Andrei Emeltchenkocf70ff22012-10-31 15:46:36 +02003594 amp_physical_cfm(bredr_hcon, hcon);
3595
Andrei Emeltchenkod5e91192012-10-25 15:20:44 +03003596 hci_dev_unlock(hdev);
Andrei Emeltchenkod5e91192012-10-25 15:20:44 +03003597}
3598
Andrei Emeltchenko27695fb2012-10-25 15:20:45 +03003599static void hci_loglink_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
3600{
3601 struct hci_ev_logical_link_complete *ev = (void *) skb->data;
3602 struct hci_conn *hcon;
3603 struct hci_chan *hchan;
3604 struct amp_mgr *mgr;
3605
3606 BT_DBG("%s log_handle 0x%4.4x phy_handle 0x%2.2x status 0x%2.2x",
3607 hdev->name, le16_to_cpu(ev->handle), ev->phy_handle,
3608 ev->status);
3609
3610 hcon = hci_conn_hash_lookup_handle(hdev, ev->phy_handle);
3611 if (!hcon)
3612 return;
3613
3614 /* Create AMP hchan */
3615 hchan = hci_chan_create(hcon);
3616 if (!hchan)
3617 return;
3618
3619 hchan->handle = le16_to_cpu(ev->handle);
3620
3621 BT_DBG("hcon %p mgr %p hchan %p", hcon, hcon->amp_mgr, hchan);
3622
3623 mgr = hcon->amp_mgr;
3624 if (mgr && mgr->bredr_chan) {
3625 struct l2cap_chan *bredr_chan = mgr->bredr_chan;
3626
3627 l2cap_chan_lock(bredr_chan);
3628
3629 bredr_chan->conn->mtu = hdev->block_mtu;
3630 l2cap_logical_cfm(bredr_chan, hchan, 0);
3631 hci_conn_hold(hcon);
3632
3633 l2cap_chan_unlock(bredr_chan);
3634 }
3635}
3636
Andrei Emeltchenko606e2a12012-10-31 15:46:31 +02003637static void hci_disconn_loglink_complete_evt(struct hci_dev *hdev,
3638 struct sk_buff *skb)
3639{
3640 struct hci_ev_disconn_logical_link_complete *ev = (void *) skb->data;
3641 struct hci_chan *hchan;
3642
3643 BT_DBG("%s log handle 0x%4.4x status 0x%2.2x", hdev->name,
3644 le16_to_cpu(ev->handle), ev->status);
3645
3646 if (ev->status)
3647 return;
3648
3649 hci_dev_lock(hdev);
3650
3651 hchan = hci_chan_lookup_handle(hdev, le16_to_cpu(ev->handle));
3652 if (!hchan)
3653 goto unlock;
3654
3655 amp_destroy_logical_link(hchan, ev->reason);
3656
3657unlock:
3658 hci_dev_unlock(hdev);
3659}
3660
Andrei Emeltchenko9eef6b32012-10-31 15:46:32 +02003661static void hci_disconn_phylink_complete_evt(struct hci_dev *hdev,
3662 struct sk_buff *skb)
3663{
3664 struct hci_ev_disconn_phy_link_complete *ev = (void *) skb->data;
3665 struct hci_conn *hcon;
3666
3667 BT_DBG("%s status 0x%2.2x", hdev->name, ev->status);
3668
3669 if (ev->status)
3670 return;
3671
3672 hci_dev_lock(hdev);
3673
3674 hcon = hci_conn_hash_lookup_handle(hdev, ev->phy_handle);
3675 if (hcon) {
3676 hcon->state = BT_CLOSED;
3677 hci_conn_del(hcon);
3678 }
3679
3680 hci_dev_unlock(hdev);
3681}
3682
Gustavo Padovan6039aa72012-05-23 04:04:18 -03003683static void hci_le_conn_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
Ville Tervofcd89c02011-02-10 22:38:47 -03003684{
3685 struct hci_ev_le_conn_complete *ev = (void *) skb->data;
3686 struct hci_conn *conn;
3687
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +03003688 BT_DBG("%s status 0x%2.2x", hdev->name, ev->status);
Ville Tervofcd89c02011-02-10 22:38:47 -03003689
3690 hci_dev_lock(hdev);
3691
Andre Guedesb47a09b2012-07-27 15:10:15 -03003692 conn = hci_conn_hash_lookup_state(hdev, LE_LINK, BT_CONNECT);
Ville Tervob62f3282011-02-10 22:38:50 -03003693 if (!conn) {
3694 conn = hci_conn_add(hdev, LE_LINK, &ev->bdaddr);
3695 if (!conn) {
3696 BT_ERR("No memory for new connection");
Andre Guedes230fd162012-07-27 15:10:10 -03003697 goto unlock;
Ville Tervob62f3282011-02-10 22:38:50 -03003698 }
Andre Guedes29b79882011-05-31 14:20:54 -03003699
3700 conn->dst_type = ev->bdaddr_type;
Andre Guedesb9b343d2012-07-27 15:10:11 -03003701
3702 if (ev->role == LE_CONN_ROLE_MASTER) {
3703 conn->out = true;
3704 conn->link_mode |= HCI_LM_MASTER;
3705 }
Ville Tervob62f3282011-02-10 22:38:50 -03003706 }
Ville Tervofcd89c02011-02-10 22:38:47 -03003707
Andre Guedescd17dec2012-07-27 15:10:16 -03003708 if (ev->status) {
3709 mgmt_connect_failed(hdev, &conn->dst, conn->type,
3710 conn->dst_type, ev->status);
3711 hci_proto_connect_cfm(conn, ev->status);
3712 conn->state = BT_CLOSED;
3713 hci_conn_del(conn);
3714 goto unlock;
3715 }
3716
Johan Hedbergb644ba32012-01-17 21:48:47 +02003717 if (!test_and_set_bit(HCI_CONN_MGMT_CONNECTED, &conn->flags))
3718 mgmt_device_connected(hdev, &ev->bdaddr, conn->type,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003719 conn->dst_type, 0, NULL, 0, NULL);
Vinicius Costa Gomes83bc71b2011-05-06 18:41:43 -03003720
Vinicius Costa Gomes7b5c0d52011-06-09 18:50:50 -03003721 conn->sec_level = BT_SECURITY_LOW;
Ville Tervofcd89c02011-02-10 22:38:47 -03003722 conn->handle = __le16_to_cpu(ev->handle);
3723 conn->state = BT_CONNECTED;
3724
3725 hci_conn_hold_device(conn);
3726 hci_conn_add_sysfs(conn);
3727
3728 hci_proto_connect_cfm(conn, ev->status);
3729
3730unlock:
3731 hci_dev_unlock(hdev);
3732}
3733
Gustavo Padovan6039aa72012-05-23 04:04:18 -03003734static void hci_le_adv_report_evt(struct hci_dev *hdev, struct sk_buff *skb)
Andre Guedes9aa04c92011-05-26 16:23:51 -03003735{
Andre Guedese95beb42011-09-26 20:48:35 -03003736 u8 num_reports = skb->data[0];
3737 void *ptr = &skb->data[1];
Andre Guedes3c9e9192012-01-10 18:20:50 -03003738 s8 rssi;
Andre Guedes9aa04c92011-05-26 16:23:51 -03003739
Andre Guedese95beb42011-09-26 20:48:35 -03003740 while (num_reports--) {
3741 struct hci_ev_le_advertising_info *ev = ptr;
Andre Guedes9aa04c92011-05-26 16:23:51 -03003742
Andre Guedes3c9e9192012-01-10 18:20:50 -03003743 rssi = ev->data[ev->length];
3744 mgmt_device_found(hdev, &ev->bdaddr, LE_LINK, ev->bdaddr_type,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003745 NULL, rssi, 0, 1, ev->data, ev->length);
Andre Guedes3c9e9192012-01-10 18:20:50 -03003746
Andre Guedese95beb42011-09-26 20:48:35 -03003747 ptr += sizeof(*ev) + ev->length + 1;
Andre Guedes9aa04c92011-05-26 16:23:51 -03003748 }
Andre Guedes9aa04c92011-05-26 16:23:51 -03003749}
3750
Gustavo Padovan6039aa72012-05-23 04:04:18 -03003751static void hci_le_ltk_request_evt(struct hci_dev *hdev, struct sk_buff *skb)
Vinicius Costa Gomesa7a595f2011-06-09 18:50:47 -03003752{
3753 struct hci_ev_le_ltk_req *ev = (void *) skb->data;
3754 struct hci_cp_le_ltk_reply cp;
Vinicius Costa Gomesbea710f2011-07-07 18:59:37 -03003755 struct hci_cp_le_ltk_neg_reply neg;
Vinicius Costa Gomesa7a595f2011-06-09 18:50:47 -03003756 struct hci_conn *conn;
Vinicius Costa Gomesc9839a12012-02-02 21:08:01 -03003757 struct smp_ltk *ltk;
Vinicius Costa Gomesa7a595f2011-06-09 18:50:47 -03003758
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +03003759 BT_DBG("%s handle 0x%4.4x", hdev->name, __le16_to_cpu(ev->handle));
Vinicius Costa Gomesa7a595f2011-06-09 18:50:47 -03003760
3761 hci_dev_lock(hdev);
3762
3763 conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
Vinicius Costa Gomesbea710f2011-07-07 18:59:37 -03003764 if (conn == NULL)
3765 goto not_found;
Vinicius Costa Gomesa7a595f2011-06-09 18:50:47 -03003766
Vinicius Costa Gomesbea710f2011-07-07 18:59:37 -03003767 ltk = hci_find_ltk(hdev, ev->ediv, ev->random);
3768 if (ltk == NULL)
3769 goto not_found;
3770
3771 memcpy(cp.ltk, ltk->val, sizeof(ltk->val));
Vinicius Costa Gomesa7a595f2011-06-09 18:50:47 -03003772 cp.handle = cpu_to_le16(conn->handle);
Vinicius Costa Gomesc9839a12012-02-02 21:08:01 -03003773
3774 if (ltk->authenticated)
3775 conn->sec_level = BT_SECURITY_HIGH;
Vinicius Costa Gomesa7a595f2011-06-09 18:50:47 -03003776
3777 hci_send_cmd(hdev, HCI_OP_LE_LTK_REPLY, sizeof(cp), &cp);
3778
Vinicius Costa Gomesc9839a12012-02-02 21:08:01 -03003779 if (ltk->type & HCI_SMP_STK) {
3780 list_del(&ltk->list);
3781 kfree(ltk);
3782 }
3783
Vinicius Costa Gomesa7a595f2011-06-09 18:50:47 -03003784 hci_dev_unlock(hdev);
Vinicius Costa Gomesbea710f2011-07-07 18:59:37 -03003785
3786 return;
3787
3788not_found:
3789 neg.handle = ev->handle;
3790 hci_send_cmd(hdev, HCI_OP_LE_LTK_NEG_REPLY, sizeof(neg), &neg);
3791 hci_dev_unlock(hdev);
Vinicius Costa Gomesa7a595f2011-06-09 18:50:47 -03003792}
3793
Gustavo Padovan6039aa72012-05-23 04:04:18 -03003794static void hci_le_meta_evt(struct hci_dev *hdev, struct sk_buff *skb)
Ville Tervofcd89c02011-02-10 22:38:47 -03003795{
3796 struct hci_ev_le_meta *le_ev = (void *) skb->data;
3797
3798 skb_pull(skb, sizeof(*le_ev));
3799
3800 switch (le_ev->subevent) {
3801 case HCI_EV_LE_CONN_COMPLETE:
3802 hci_le_conn_complete_evt(hdev, skb);
3803 break;
3804
Andre Guedes9aa04c92011-05-26 16:23:51 -03003805 case HCI_EV_LE_ADVERTISING_REPORT:
3806 hci_le_adv_report_evt(hdev, skb);
3807 break;
3808
Vinicius Costa Gomesa7a595f2011-06-09 18:50:47 -03003809 case HCI_EV_LE_LTK_REQ:
3810 hci_le_ltk_request_evt(hdev, skb);
3811 break;
3812
Ville Tervofcd89c02011-02-10 22:38:47 -03003813 default:
3814 break;
3815 }
3816}
3817
Andrei Emeltchenko9495b2e2012-09-27 17:26:22 +03003818static void hci_chan_selected_evt(struct hci_dev *hdev, struct sk_buff *skb)
3819{
3820 struct hci_ev_channel_selected *ev = (void *) skb->data;
3821 struct hci_conn *hcon;
3822
3823 BT_DBG("%s handle 0x%2.2x", hdev->name, ev->phy_handle);
3824
3825 skb_pull(skb, sizeof(*ev));
3826
3827 hcon = hci_conn_hash_lookup_handle(hdev, ev->phy_handle);
3828 if (!hcon)
3829 return;
3830
3831 amp_read_loc_assoc_final_data(hdev, hcon);
3832}
3833
Linus Torvalds1da177e2005-04-16 15:20:36 -07003834void hci_event_packet(struct hci_dev *hdev, struct sk_buff *skb)
3835{
Marcel Holtmanna9de9242007-10-20 13:33:56 +02003836 struct hci_event_hdr *hdr = (void *) skb->data;
3837 __u8 event = hdr->evt;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003838
3839 skb_pull(skb, HCI_EVENT_HDR_SIZE);
3840
Marcel Holtmanna9de9242007-10-20 13:33:56 +02003841 switch (event) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003842 case HCI_EV_INQUIRY_COMPLETE:
3843 hci_inquiry_complete_evt(hdev, skb);
3844 break;
3845
3846 case HCI_EV_INQUIRY_RESULT:
3847 hci_inquiry_result_evt(hdev, skb);
3848 break;
3849
Marcel Holtmanna9de9242007-10-20 13:33:56 +02003850 case HCI_EV_CONN_COMPLETE:
3851 hci_conn_complete_evt(hdev, skb);
Marcel Holtmann21d9e302005-09-13 01:32:25 +02003852 break;
3853
Linus Torvalds1da177e2005-04-16 15:20:36 -07003854 case HCI_EV_CONN_REQUEST:
3855 hci_conn_request_evt(hdev, skb);
3856 break;
3857
Linus Torvalds1da177e2005-04-16 15:20:36 -07003858 case HCI_EV_DISCONN_COMPLETE:
3859 hci_disconn_complete_evt(hdev, skb);
3860 break;
3861
Linus Torvalds1da177e2005-04-16 15:20:36 -07003862 case HCI_EV_AUTH_COMPLETE:
3863 hci_auth_complete_evt(hdev, skb);
3864 break;
3865
Marcel Holtmanna9de9242007-10-20 13:33:56 +02003866 case HCI_EV_REMOTE_NAME:
3867 hci_remote_name_evt(hdev, skb);
3868 break;
3869
Linus Torvalds1da177e2005-04-16 15:20:36 -07003870 case HCI_EV_ENCRYPT_CHANGE:
3871 hci_encrypt_change_evt(hdev, skb);
3872 break;
3873
Marcel Holtmanna9de9242007-10-20 13:33:56 +02003874 case HCI_EV_CHANGE_LINK_KEY_COMPLETE:
3875 hci_change_link_key_complete_evt(hdev, skb);
3876 break;
3877
3878 case HCI_EV_REMOTE_FEATURES:
3879 hci_remote_features_evt(hdev, skb);
3880 break;
3881
3882 case HCI_EV_REMOTE_VERSION:
3883 hci_remote_version_evt(hdev, skb);
3884 break;
3885
3886 case HCI_EV_QOS_SETUP_COMPLETE:
3887 hci_qos_setup_complete_evt(hdev, skb);
3888 break;
3889
3890 case HCI_EV_CMD_COMPLETE:
3891 hci_cmd_complete_evt(hdev, skb);
3892 break;
3893
3894 case HCI_EV_CMD_STATUS:
3895 hci_cmd_status_evt(hdev, skb);
3896 break;
3897
3898 case HCI_EV_ROLE_CHANGE:
3899 hci_role_change_evt(hdev, skb);
3900 break;
3901
3902 case HCI_EV_NUM_COMP_PKTS:
3903 hci_num_comp_pkts_evt(hdev, skb);
3904 break;
3905
3906 case HCI_EV_MODE_CHANGE:
3907 hci_mode_change_evt(hdev, skb);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003908 break;
3909
3910 case HCI_EV_PIN_CODE_REQ:
3911 hci_pin_code_request_evt(hdev, skb);
3912 break;
3913
3914 case HCI_EV_LINK_KEY_REQ:
3915 hci_link_key_request_evt(hdev, skb);
3916 break;
3917
3918 case HCI_EV_LINK_KEY_NOTIFY:
3919 hci_link_key_notify_evt(hdev, skb);
3920 break;
3921
3922 case HCI_EV_CLOCK_OFFSET:
3923 hci_clock_offset_evt(hdev, skb);
3924 break;
3925
Marcel Holtmanna8746412008-07-14 20:13:46 +02003926 case HCI_EV_PKT_TYPE_CHANGE:
3927 hci_pkt_type_change_evt(hdev, skb);
3928 break;
3929
Marcel Holtmann85a1e932005-08-09 20:28:02 -07003930 case HCI_EV_PSCAN_REP_MODE:
3931 hci_pscan_rep_mode_evt(hdev, skb);
3932 break;
3933
Marcel Holtmanna9de9242007-10-20 13:33:56 +02003934 case HCI_EV_INQUIRY_RESULT_WITH_RSSI:
3935 hci_inquiry_result_with_rssi_evt(hdev, skb);
3936 break;
3937
3938 case HCI_EV_REMOTE_EXT_FEATURES:
3939 hci_remote_ext_features_evt(hdev, skb);
3940 break;
3941
3942 case HCI_EV_SYNC_CONN_COMPLETE:
3943 hci_sync_conn_complete_evt(hdev, skb);
3944 break;
3945
3946 case HCI_EV_SYNC_CONN_CHANGED:
3947 hci_sync_conn_changed_evt(hdev, skb);
3948 break;
3949
Marcel Holtmann04837f62006-07-03 10:02:33 +02003950 case HCI_EV_SNIFF_SUBRATE:
3951 hci_sniff_subrate_evt(hdev, skb);
3952 break;
3953
Marcel Holtmanna9de9242007-10-20 13:33:56 +02003954 case HCI_EV_EXTENDED_INQUIRY_RESULT:
3955 hci_extended_inquiry_result_evt(hdev, skb);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003956 break;
3957
Johan Hedberg1c2e0042012-06-08 23:31:13 +08003958 case HCI_EV_KEY_REFRESH_COMPLETE:
3959 hci_key_refresh_complete_evt(hdev, skb);
3960 break;
3961
Marcel Holtmann04936842008-07-14 20:13:48 +02003962 case HCI_EV_IO_CAPA_REQUEST:
3963 hci_io_capa_request_evt(hdev, skb);
3964 break;
3965
Johan Hedberg03b555e2011-01-04 15:40:05 +02003966 case HCI_EV_IO_CAPA_REPLY:
3967 hci_io_capa_reply_evt(hdev, skb);
3968 break;
3969
Johan Hedberga5c29682011-02-19 12:05:57 -03003970 case HCI_EV_USER_CONFIRM_REQUEST:
3971 hci_user_confirm_request_evt(hdev, skb);
3972 break;
3973
Brian Gix1143d452011-11-23 08:28:34 -08003974 case HCI_EV_USER_PASSKEY_REQUEST:
3975 hci_user_passkey_request_evt(hdev, skb);
3976 break;
3977
Johan Hedberg92a25252012-09-06 18:39:26 +03003978 case HCI_EV_USER_PASSKEY_NOTIFY:
3979 hci_user_passkey_notify_evt(hdev, skb);
3980 break;
3981
3982 case HCI_EV_KEYPRESS_NOTIFY:
3983 hci_keypress_notify_evt(hdev, skb);
3984 break;
3985
Marcel Holtmann04936842008-07-14 20:13:48 +02003986 case HCI_EV_SIMPLE_PAIR_COMPLETE:
3987 hci_simple_pair_complete_evt(hdev, skb);
3988 break;
3989
Marcel Holtmann41a96212008-07-14 20:13:48 +02003990 case HCI_EV_REMOTE_HOST_FEATURES:
3991 hci_remote_host_features_evt(hdev, skb);
3992 break;
3993
Ville Tervofcd89c02011-02-10 22:38:47 -03003994 case HCI_EV_LE_META:
3995 hci_le_meta_evt(hdev, skb);
3996 break;
3997
Andrei Emeltchenko9495b2e2012-09-27 17:26:22 +03003998 case HCI_EV_CHANNEL_SELECTED:
3999 hci_chan_selected_evt(hdev, skb);
4000 break;
4001
Szymon Janc2763eda2011-03-22 13:12:22 +01004002 case HCI_EV_REMOTE_OOB_DATA_REQUEST:
4003 hci_remote_oob_data_request_evt(hdev, skb);
4004 break;
4005
Andrei Emeltchenkod5e91192012-10-25 15:20:44 +03004006 case HCI_EV_PHY_LINK_COMPLETE:
4007 hci_phy_link_complete_evt(hdev, skb);
4008 break;
4009
Andrei Emeltchenko27695fb2012-10-25 15:20:45 +03004010 case HCI_EV_LOGICAL_LINK_COMPLETE:
4011 hci_loglink_complete_evt(hdev, skb);
4012 break;
4013
Andrei Emeltchenko606e2a12012-10-31 15:46:31 +02004014 case HCI_EV_DISCONN_LOGICAL_LINK_COMPLETE:
4015 hci_disconn_loglink_complete_evt(hdev, skb);
4016 break;
4017
Andrei Emeltchenko9eef6b32012-10-31 15:46:32 +02004018 case HCI_EV_DISCONN_PHY_LINK_COMPLETE:
4019 hci_disconn_phylink_complete_evt(hdev, skb);
4020 break;
4021
Andrei Emeltchenko25e89e92012-01-04 12:41:58 +02004022 case HCI_EV_NUM_COMP_BLOCKS:
4023 hci_num_comp_blocks_evt(hdev, skb);
4024 break;
4025
Marcel Holtmanna9de9242007-10-20 13:33:56 +02004026 default:
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +03004027 BT_DBG("%s event 0x%2.2x", hdev->name, event);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004028 break;
4029 }
4030
4031 kfree_skb(skb);
4032 hdev->stat.evt_rx++;
4033}