blob: 7caea1af557b4a602ee41fb04f288312fbfac03b [file] [log] [blame]
YOSHIFUJI Hideaki8e87d142007-02-09 23:24:33 +09001/*
Linus Torvalds1da177e2005-04-16 15:20:36 -07002 BlueZ - Bluetooth protocol stack for Linux
Ron Shaffer2d0a0342010-05-28 11:53:46 -04003 Copyright (c) 2000-2001, 2010, Code Aurora Forum. All rights reserved.
Linus Torvalds1da177e2005-04-16 15:20:36 -07004
5 Written 2000,2001 by Maxim Krasnyansky <maxk@qualcomm.com>
6
7 This program is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License version 2 as
9 published by the Free Software Foundation;
10
11 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
12 OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
13 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF THIRD PARTY RIGHTS.
14 IN NO EVENT SHALL THE COPYRIGHT HOLDER(S) AND AUTHOR(S) BE LIABLE FOR ANY
YOSHIFUJI Hideaki8e87d142007-02-09 23:24:33 +090015 CLAIM, OR ANY SPECIAL INDIRECT OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES
16 WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
17 ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
Linus Torvalds1da177e2005-04-16 15:20:36 -070018 OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
19
YOSHIFUJI Hideaki8e87d142007-02-09 23:24:33 +090020 ALL LIABILITY, INCLUDING LIABILITY FOR INFRINGEMENT OF ANY PATENTS,
21 COPYRIGHTS, TRADEMARKS OR OTHER RIGHTS, RELATING TO USE OF THIS
Linus Torvalds1da177e2005-04-16 15:20:36 -070022 SOFTWARE IS DISCLAIMED.
23*/
24
25/* Bluetooth HCI event handling. */
26
Linus Torvalds1da177e2005-04-16 15:20:36 -070027#include <asm/unaligned.h>
28
29#include <net/bluetooth/bluetooth.h>
30#include <net/bluetooth/hci_core.h>
Mikel Astizf0d6a0e2012-08-09 09:52:30 +020031#include <net/bluetooth/mgmt.h>
Andrei Emeltchenko8e2a0d92012-09-27 17:26:08 +030032#include <net/bluetooth/a2mp.h>
Andrei Emeltchenko903e4542012-09-27 17:26:09 +030033#include <net/bluetooth/amp.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070034
Linus Torvalds1da177e2005-04-16 15:20:36 -070035/* Handle HCI Event packets */
36
Marcel Holtmanna9de9242007-10-20 13:33:56 +020037static void hci_cc_inquiry_cancel(struct hci_dev *hdev, struct sk_buff *skb)
Linus Torvalds1da177e2005-04-16 15:20:36 -070038{
Marcel Holtmanna9de9242007-10-20 13:33:56 +020039 __u8 status = *((__u8 *) skb->data);
Linus Torvalds1da177e2005-04-16 15:20:36 -070040
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +030041 BT_DBG("%s status 0x%2.2x", hdev->name, status);
Linus Torvalds1da177e2005-04-16 15:20:36 -070042
Andre Guedese6d465c2011-11-09 17:14:26 -030043 if (status) {
44 hci_dev_lock(hdev);
45 mgmt_stop_discovery_failed(hdev, status);
46 hci_dev_unlock(hdev);
Marcel Holtmanna9de9242007-10-20 13:33:56 +020047 return;
Andre Guedese6d465c2011-11-09 17:14:26 -030048 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070049
Andre Guedes89352e72011-11-04 14:16:53 -030050 clear_bit(HCI_INQUIRY, &hdev->flags);
51
Johan Hedberg56e5cb82011-11-08 20:40:16 +020052 hci_dev_lock(hdev);
Johan Hedbergff9ef572012-01-04 14:23:45 +020053 hci_discovery_set_state(hdev, DISCOVERY_STOPPED);
Johan Hedberg56e5cb82011-11-08 20:40:16 +020054 hci_dev_unlock(hdev);
Marcel Holtmann6bd57412006-11-18 22:14:22 +010055
Johan Hedberg23bb5762010-12-21 23:01:27 +020056 hci_req_complete(hdev, HCI_OP_INQUIRY_CANCEL, status);
Marcel Holtmann6bd57412006-11-18 22:14:22 +010057
Marcel Holtmanna9de9242007-10-20 13:33:56 +020058 hci_conn_check_pending(hdev);
Linus Torvalds1da177e2005-04-16 15:20:36 -070059}
60
Andre Guedes4d934832012-03-21 00:03:35 -030061static void hci_cc_periodic_inq(struct hci_dev *hdev, struct sk_buff *skb)
62{
63 __u8 status = *((__u8 *) skb->data);
64
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +030065 BT_DBG("%s status 0x%2.2x", hdev->name, status);
Andre Guedesae854a72012-03-21 00:03:36 -030066
67 if (status)
68 return;
69
70 set_bit(HCI_PERIODIC_INQ, &hdev->dev_flags);
Andre Guedes4d934832012-03-21 00:03:35 -030071}
72
Marcel Holtmanna9de9242007-10-20 13:33:56 +020073static void hci_cc_exit_periodic_inq(struct hci_dev *hdev, struct sk_buff *skb)
Linus Torvalds1da177e2005-04-16 15:20:36 -070074{
Marcel Holtmanna9de9242007-10-20 13:33:56 +020075 __u8 status = *((__u8 *) skb->data);
76
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +030077 BT_DBG("%s status 0x%2.2x", hdev->name, status);
Marcel Holtmanna9de9242007-10-20 13:33:56 +020078
79 if (status)
80 return;
81
Andre Guedesae854a72012-03-21 00:03:36 -030082 clear_bit(HCI_PERIODIC_INQ, &hdev->dev_flags);
83
Marcel Holtmanna9de9242007-10-20 13:33:56 +020084 hci_conn_check_pending(hdev);
85}
86
Gustavo Padovan807deac2012-05-17 00:36:24 -030087static void hci_cc_remote_name_req_cancel(struct hci_dev *hdev,
88 struct sk_buff *skb)
Marcel Holtmanna9de9242007-10-20 13:33:56 +020089{
90 BT_DBG("%s", hdev->name);
91}
92
93static void hci_cc_role_discovery(struct hci_dev *hdev, struct sk_buff *skb)
94{
95 struct hci_rp_role_discovery *rp = (void *) skb->data;
Linus Torvalds1da177e2005-04-16 15:20:36 -070096 struct hci_conn *conn;
Linus Torvalds1da177e2005-04-16 15:20:36 -070097
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +030098 BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
Linus Torvalds1da177e2005-04-16 15:20:36 -070099
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200100 if (rp->status)
101 return;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700102
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200103 hci_dev_lock(hdev);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700104
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200105 conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(rp->handle));
106 if (conn) {
107 if (rp->role)
108 conn->link_mode &= ~HCI_LM_MASTER;
109 else
110 conn->link_mode |= HCI_LM_MASTER;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700111 }
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200112
113 hci_dev_unlock(hdev);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700114}
115
Marcel Holtmanne4e8e372008-07-14 20:13:47 +0200116static void hci_cc_read_link_policy(struct hci_dev *hdev, struct sk_buff *skb)
117{
118 struct hci_rp_read_link_policy *rp = (void *) skb->data;
119 struct hci_conn *conn;
120
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +0300121 BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
Marcel Holtmanne4e8e372008-07-14 20:13:47 +0200122
123 if (rp->status)
124 return;
125
126 hci_dev_lock(hdev);
127
128 conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(rp->handle));
129 if (conn)
130 conn->link_policy = __le16_to_cpu(rp->policy);
131
132 hci_dev_unlock(hdev);
133}
134
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200135static void hci_cc_write_link_policy(struct hci_dev *hdev, struct sk_buff *skb)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700136{
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200137 struct hci_rp_write_link_policy *rp = (void *) skb->data;
138 struct hci_conn *conn;
139 void *sent;
140
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +0300141 BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200142
143 if (rp->status)
144 return;
145
146 sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_LINK_POLICY);
147 if (!sent)
148 return;
149
150 hci_dev_lock(hdev);
151
152 conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(rp->handle));
Marcel Holtmanne4e8e372008-07-14 20:13:47 +0200153 if (conn)
Harvey Harrison83985312008-05-02 16:25:46 -0700154 conn->link_policy = get_unaligned_le16(sent + 2);
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200155
156 hci_dev_unlock(hdev);
157}
158
Gustavo Padovan807deac2012-05-17 00:36:24 -0300159static void hci_cc_read_def_link_policy(struct hci_dev *hdev,
160 struct sk_buff *skb)
Marcel Holtmanne4e8e372008-07-14 20:13:47 +0200161{
162 struct hci_rp_read_def_link_policy *rp = (void *) skb->data;
163
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +0300164 BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
Marcel Holtmanne4e8e372008-07-14 20:13:47 +0200165
166 if (rp->status)
167 return;
168
169 hdev->link_policy = __le16_to_cpu(rp->policy);
170}
171
Gustavo Padovan807deac2012-05-17 00:36:24 -0300172static void hci_cc_write_def_link_policy(struct hci_dev *hdev,
173 struct sk_buff *skb)
Marcel Holtmanne4e8e372008-07-14 20:13:47 +0200174{
175 __u8 status = *((__u8 *) skb->data);
176 void *sent;
177
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +0300178 BT_DBG("%s status 0x%2.2x", hdev->name, status);
Marcel Holtmanne4e8e372008-07-14 20:13:47 +0200179
180 sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_DEF_LINK_POLICY);
181 if (!sent)
182 return;
183
184 if (!status)
185 hdev->link_policy = get_unaligned_le16(sent);
186
Johan Hedberg23bb5762010-12-21 23:01:27 +0200187 hci_req_complete(hdev, HCI_OP_WRITE_DEF_LINK_POLICY, status);
Marcel Holtmanne4e8e372008-07-14 20:13:47 +0200188}
189
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200190static void hci_cc_reset(struct hci_dev *hdev, struct sk_buff *skb)
191{
192 __u8 status = *((__u8 *) skb->data);
193
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +0300194 BT_DBG("%s status 0x%2.2x", hdev->name, status);
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200195
Gustavo F. Padovan10572132011-03-16 15:36:29 -0300196 clear_bit(HCI_RESET, &hdev->flags);
197
Johan Hedberg23bb5762010-12-21 23:01:27 +0200198 hci_req_complete(hdev, HCI_OP_RESET, status);
Andre Guedesd23264a2011-11-25 20:53:38 -0300199
Johan Hedberga297e972012-02-21 17:55:47 +0200200 /* Reset all non-persistent flags */
Andre Guedesae854a72012-03-21 00:03:36 -0300201 hdev->dev_flags &= ~(BIT(HCI_LE_SCAN) | BIT(HCI_PENDING_CLASS) |
202 BIT(HCI_PERIODIC_INQ));
Andre Guedes69775ff2012-02-23 16:50:05 +0200203
204 hdev->discovery.state = DISCOVERY_STOPPED;
Johan Hedbergbbaf4442012-11-08 01:22:59 +0100205 hdev->inq_tx_power = HCI_TX_POWER_INVALID;
206 hdev->adv_tx_power = HCI_TX_POWER_INVALID;
Johan Hedberg3f0f5242012-11-08 01:23:00 +0100207
208 memset(hdev->adv_data, 0, sizeof(hdev->adv_data));
209 hdev->adv_data_len = 0;
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200210}
211
212static void hci_cc_write_local_name(struct hci_dev *hdev, struct sk_buff *skb)
213{
214 __u8 status = *((__u8 *) skb->data);
215 void *sent;
216
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +0300217 BT_DBG("%s status 0x%2.2x", hdev->name, status);
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200218
219 sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_LOCAL_NAME);
220 if (!sent)
221 return;
222
Johan Hedberg56e5cb82011-11-08 20:40:16 +0200223 hci_dev_lock(hdev);
224
Johan Hedbergf51d5b22012-02-22 18:17:32 +0200225 if (test_bit(HCI_MGMT, &hdev->dev_flags))
226 mgmt_set_local_name_complete(hdev, sent, status);
Johan Hedberg28cc7bd2012-02-22 21:06:55 +0200227 else if (!status)
228 memcpy(hdev->dev_name, sent, HCI_MAX_NAME_LENGTH);
Johan Hedbergf51d5b22012-02-22 18:17:32 +0200229
Johan Hedberg56e5cb82011-11-08 20:40:16 +0200230 hci_dev_unlock(hdev);
Johan Hedberg3159d382012-02-24 13:47:56 +0200231
Johan Hedberg3f0f5242012-11-08 01:23:00 +0100232 if (!status && !test_bit(HCI_INIT, &hdev->flags))
233 hci_update_ad(hdev);
234
Johan Hedberg3159d382012-02-24 13:47:56 +0200235 hci_req_complete(hdev, HCI_OP_WRITE_LOCAL_NAME, status);
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200236}
237
238static void hci_cc_read_local_name(struct hci_dev *hdev, struct sk_buff *skb)
239{
240 struct hci_rp_read_local_name *rp = (void *) skb->data;
241
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +0300242 BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200243
244 if (rp->status)
245 return;
246
Johan Hedbergdb99b5f2012-02-22 20:14:22 +0200247 if (test_bit(HCI_SETUP, &hdev->dev_flags))
248 memcpy(hdev->dev_name, rp->name, HCI_MAX_NAME_LENGTH);
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200249}
250
251static void hci_cc_write_auth_enable(struct hci_dev *hdev, struct sk_buff *skb)
252{
253 __u8 status = *((__u8 *) skb->data);
254 void *sent;
255
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +0300256 BT_DBG("%s status 0x%2.2x", hdev->name, status);
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200257
258 sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_AUTH_ENABLE);
259 if (!sent)
260 return;
261
262 if (!status) {
263 __u8 param = *((__u8 *) sent);
264
265 if (param == AUTH_ENABLED)
266 set_bit(HCI_AUTH, &hdev->flags);
267 else
268 clear_bit(HCI_AUTH, &hdev->flags);
269 }
270
Johan Hedberg33ef95e2012-02-16 23:56:27 +0200271 if (test_bit(HCI_MGMT, &hdev->dev_flags))
272 mgmt_auth_enable_complete(hdev, status);
273
Johan Hedberg23bb5762010-12-21 23:01:27 +0200274 hci_req_complete(hdev, HCI_OP_WRITE_AUTH_ENABLE, status);
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200275}
276
277static void hci_cc_write_encrypt_mode(struct hci_dev *hdev, struct sk_buff *skb)
278{
279 __u8 status = *((__u8 *) skb->data);
280 void *sent;
281
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +0300282 BT_DBG("%s status 0x%2.2x", hdev->name, status);
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200283
284 sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_ENCRYPT_MODE);
285 if (!sent)
286 return;
287
288 if (!status) {
289 __u8 param = *((__u8 *) sent);
290
291 if (param)
292 set_bit(HCI_ENCRYPT, &hdev->flags);
293 else
294 clear_bit(HCI_ENCRYPT, &hdev->flags);
295 }
296
Johan Hedberg23bb5762010-12-21 23:01:27 +0200297 hci_req_complete(hdev, HCI_OP_WRITE_ENCRYPT_MODE, status);
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200298}
299
300static void hci_cc_write_scan_enable(struct hci_dev *hdev, struct sk_buff *skb)
301{
Johan Hedberg36f7fc72011-11-04 00:17:45 +0200302 __u8 param, status = *((__u8 *) skb->data);
303 int old_pscan, old_iscan;
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200304 void *sent;
305
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +0300306 BT_DBG("%s status 0x%2.2x", hdev->name, status);
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200307
308 sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_SCAN_ENABLE);
309 if (!sent)
310 return;
311
Johan Hedberg36f7fc72011-11-04 00:17:45 +0200312 param = *((__u8 *) sent);
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200313
Johan Hedberg56e5cb82011-11-08 20:40:16 +0200314 hci_dev_lock(hdev);
315
Mikel Astizfa1bd912012-08-09 09:52:29 +0200316 if (status) {
Johan Hedberg744cf192011-11-08 20:40:14 +0200317 mgmt_write_scan_failed(hdev, param, status);
Johan Hedberg2d7cee52011-11-07 22:16:03 +0200318 hdev->discov_timeout = 0;
319 goto done;
320 }
321
Johan Hedberg36f7fc72011-11-04 00:17:45 +0200322 old_pscan = test_and_clear_bit(HCI_PSCAN, &hdev->flags);
323 old_iscan = test_and_clear_bit(HCI_ISCAN, &hdev->flags);
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200324
Johan Hedberg36f7fc72011-11-04 00:17:45 +0200325 if (param & SCAN_INQUIRY) {
326 set_bit(HCI_ISCAN, &hdev->flags);
327 if (!old_iscan)
Johan Hedberg744cf192011-11-08 20:40:14 +0200328 mgmt_discoverable(hdev, 1);
Johan Hedberg16ab91a2011-11-07 22:16:02 +0200329 if (hdev->discov_timeout > 0) {
330 int to = msecs_to_jiffies(hdev->discov_timeout * 1000);
331 queue_delayed_work(hdev->workqueue, &hdev->discov_off,
Gustavo Padovan807deac2012-05-17 00:36:24 -0300332 to);
Johan Hedberg16ab91a2011-11-07 22:16:02 +0200333 }
Johan Hedberg36f7fc72011-11-04 00:17:45 +0200334 } else if (old_iscan)
Johan Hedberg744cf192011-11-08 20:40:14 +0200335 mgmt_discoverable(hdev, 0);
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200336
Johan Hedberg36f7fc72011-11-04 00:17:45 +0200337 if (param & SCAN_PAGE) {
338 set_bit(HCI_PSCAN, &hdev->flags);
339 if (!old_pscan)
Johan Hedberg744cf192011-11-08 20:40:14 +0200340 mgmt_connectable(hdev, 1);
Johan Hedberg36f7fc72011-11-04 00:17:45 +0200341 } else if (old_pscan)
Johan Hedberg744cf192011-11-08 20:40:14 +0200342 mgmt_connectable(hdev, 0);
Johan Hedberg36f7fc72011-11-04 00:17:45 +0200343
344done:
Johan Hedberg56e5cb82011-11-08 20:40:16 +0200345 hci_dev_unlock(hdev);
Johan Hedberg23bb5762010-12-21 23:01:27 +0200346 hci_req_complete(hdev, HCI_OP_WRITE_SCAN_ENABLE, status);
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200347}
348
349static void hci_cc_read_class_of_dev(struct hci_dev *hdev, struct sk_buff *skb)
350{
351 struct hci_rp_read_class_of_dev *rp = (void *) skb->data;
352
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +0300353 BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200354
355 if (rp->status)
356 return;
357
358 memcpy(hdev->dev_class, rp->dev_class, 3);
359
360 BT_DBG("%s class 0x%.2x%.2x%.2x", hdev->name,
Gustavo Padovan807deac2012-05-17 00:36:24 -0300361 hdev->dev_class[2], hdev->dev_class[1], hdev->dev_class[0]);
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200362}
363
364static void hci_cc_write_class_of_dev(struct hci_dev *hdev, struct sk_buff *skb)
365{
366 __u8 status = *((__u8 *) skb->data);
367 void *sent;
368
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +0300369 BT_DBG("%s status 0x%2.2x", hdev->name, status);
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200370
371 sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_CLASS_OF_DEV);
372 if (!sent)
373 return;
374
Marcel Holtmann7f9a9032012-02-22 18:38:01 +0100375 hci_dev_lock(hdev);
376
377 if (status == 0)
378 memcpy(hdev->dev_class, sent, 3);
379
380 if (test_bit(HCI_MGMT, &hdev->dev_flags))
381 mgmt_set_class_of_dev_complete(hdev, sent, status);
382
383 hci_dev_unlock(hdev);
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200384}
385
386static void hci_cc_read_voice_setting(struct hci_dev *hdev, struct sk_buff *skb)
387{
388 struct hci_rp_read_voice_setting *rp = (void *) skb->data;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700389 __u16 setting;
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200390
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +0300391 BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200392
393 if (rp->status)
394 return;
395
396 setting = __le16_to_cpu(rp->voice_setting);
397
Marcel Holtmannf383f272008-07-14 20:13:47 +0200398 if (hdev->voice_setting == setting)
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200399 return;
400
401 hdev->voice_setting = setting;
402
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +0300403 BT_DBG("%s voice setting 0x%4.4x", hdev->name, setting);
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200404
Gustavo F. Padovan3c547112011-12-14 22:58:44 -0200405 if (hdev->notify)
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200406 hdev->notify(hdev, HCI_NOTIFY_VOICE_SETTING);
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200407}
408
Gustavo Padovan8fc9ced2012-05-23 04:04:21 -0300409static void hci_cc_write_voice_setting(struct hci_dev *hdev,
410 struct sk_buff *skb)
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200411{
412 __u8 status = *((__u8 *) skb->data);
Marcel Holtmannf383f272008-07-14 20:13:47 +0200413 __u16 setting;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700414 void *sent;
415
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +0300416 BT_DBG("%s status 0x%2.2x", hdev->name, status);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700417
Marcel Holtmannf383f272008-07-14 20:13:47 +0200418 if (status)
419 return;
420
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200421 sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_VOICE_SETTING);
422 if (!sent)
423 return;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700424
Marcel Holtmannf383f272008-07-14 20:13:47 +0200425 setting = get_unaligned_le16(sent);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700426
Marcel Holtmannf383f272008-07-14 20:13:47 +0200427 if (hdev->voice_setting == setting)
428 return;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700429
Marcel Holtmannf383f272008-07-14 20:13:47 +0200430 hdev->voice_setting = setting;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700431
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +0300432 BT_DBG("%s voice setting 0x%4.4x", hdev->name, setting);
Marcel Holtmannf383f272008-07-14 20:13:47 +0200433
Gustavo F. Padovan3c547112011-12-14 22:58:44 -0200434 if (hdev->notify)
Marcel Holtmannf383f272008-07-14 20:13:47 +0200435 hdev->notify(hdev, HCI_NOTIFY_VOICE_SETTING);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700436}
437
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200438static void hci_cc_host_buffer_size(struct hci_dev *hdev, struct sk_buff *skb)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700439{
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200440 __u8 status = *((__u8 *) skb->data);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700441
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +0300442 BT_DBG("%s status 0x%2.2x", hdev->name, status);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700443
Johan Hedberg23bb5762010-12-21 23:01:27 +0200444 hci_req_complete(hdev, HCI_OP_HOST_BUFFER_SIZE, status);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700445}
446
Marcel Holtmann333140b2008-07-14 20:13:48 +0200447static void hci_cc_write_ssp_mode(struct hci_dev *hdev, struct sk_buff *skb)
448{
449 __u8 status = *((__u8 *) skb->data);
Johan Hedberg5ed8eb22012-10-25 00:09:51 +0300450 struct hci_cp_write_ssp_mode *sent;
Marcel Holtmann333140b2008-07-14 20:13:48 +0200451
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +0300452 BT_DBG("%s status 0x%2.2x", hdev->name, status);
Marcel Holtmann333140b2008-07-14 20:13:48 +0200453
Marcel Holtmann333140b2008-07-14 20:13:48 +0200454 sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_SSP_MODE);
455 if (!sent)
456 return;
457
Johan Hedberg5ed8eb22012-10-25 00:09:51 +0300458 if (!status) {
459 if (sent->mode)
460 hdev->host_features[0] |= LMP_HOST_SSP;
461 else
462 hdev->host_features[0] &= ~LMP_HOST_SSP;
463 }
464
Johan Hedberged2c4ee2012-02-17 00:56:28 +0200465 if (test_bit(HCI_MGMT, &hdev->dev_flags))
Johan Hedberg5ed8eb22012-10-25 00:09:51 +0300466 mgmt_ssp_enable_complete(hdev, sent->mode, status);
Johan Hedbergc0ecddc2012-02-22 12:38:31 +0200467 else if (!status) {
Johan Hedberg5ed8eb22012-10-25 00:09:51 +0300468 if (sent->mode)
Johan Hedbergc0ecddc2012-02-22 12:38:31 +0200469 set_bit(HCI_SSP_ENABLED, &hdev->dev_flags);
470 else
471 clear_bit(HCI_SSP_ENABLED, &hdev->dev_flags);
472 }
Marcel Holtmann333140b2008-07-14 20:13:48 +0200473}
474
Johan Hedbergd5859e22011-01-25 01:19:58 +0200475static u8 hci_get_inquiry_mode(struct hci_dev *hdev)
476{
Johan Hedberg976eb202012-10-24 21:12:01 +0300477 if (lmp_ext_inq_capable(hdev))
Johan Hedbergd5859e22011-01-25 01:19:58 +0200478 return 2;
479
Johan Hedberg976eb202012-10-24 21:12:01 +0300480 if (lmp_inq_rssi_capable(hdev))
Johan Hedbergd5859e22011-01-25 01:19:58 +0200481 return 1;
482
483 if (hdev->manufacturer == 11 && hdev->hci_rev == 0x00 &&
Gustavo Padovan807deac2012-05-17 00:36:24 -0300484 hdev->lmp_subver == 0x0757)
Johan Hedbergd5859e22011-01-25 01:19:58 +0200485 return 1;
486
487 if (hdev->manufacturer == 15) {
488 if (hdev->hci_rev == 0x03 && hdev->lmp_subver == 0x6963)
489 return 1;
490 if (hdev->hci_rev == 0x09 && hdev->lmp_subver == 0x6963)
491 return 1;
492 if (hdev->hci_rev == 0x00 && hdev->lmp_subver == 0x6965)
493 return 1;
494 }
495
496 if (hdev->manufacturer == 31 && hdev->hci_rev == 0x2005 &&
Gustavo Padovan807deac2012-05-17 00:36:24 -0300497 hdev->lmp_subver == 0x1805)
Johan Hedbergd5859e22011-01-25 01:19:58 +0200498 return 1;
499
500 return 0;
501}
502
503static void hci_setup_inquiry_mode(struct hci_dev *hdev)
504{
505 u8 mode;
506
507 mode = hci_get_inquiry_mode(hdev);
508
509 hci_send_cmd(hdev, HCI_OP_WRITE_INQUIRY_MODE, 1, &mode);
510}
511
512static void hci_setup_event_mask(struct hci_dev *hdev)
513{
514 /* The second byte is 0xff instead of 0x9f (two reserved bits
515 * disabled) since a Broadcom 1.2 dongle doesn't respond to the
516 * command otherwise */
517 u8 events[8] = { 0xff, 0xff, 0xfb, 0xff, 0x00, 0x00, 0x00, 0x00 };
518
Ville Tervo6de6c182011-05-27 11:16:21 +0300519 /* CSR 1.1 dongles does not accept any bitfield so don't try to set
520 * any event mask for pre 1.2 devices */
Andrei Emeltchenko5a13b092011-12-01 14:33:28 +0200521 if (hdev->hci_ver < BLUETOOTH_VER_1_2)
Ville Tervo6de6c182011-05-27 11:16:21 +0300522 return;
523
Johan Hedberge1171e82012-10-19 20:57:45 +0300524 if (lmp_bredr_capable(hdev)) {
525 events[4] |= 0x01; /* Flow Specification Complete */
526 events[4] |= 0x02; /* Inquiry Result with RSSI */
527 events[4] |= 0x04; /* Read Remote Extended Features Complete */
528 events[5] |= 0x08; /* Synchronous Connection Complete */
529 events[5] |= 0x10; /* Synchronous Connection Changed */
530 }
Johan Hedbergd5859e22011-01-25 01:19:58 +0200531
Johan Hedberg976eb202012-10-24 21:12:01 +0300532 if (lmp_inq_rssi_capable(hdev))
Johan Hedberga24299e2012-04-26 09:47:46 +0300533 events[4] |= 0x02; /* Inquiry Result with RSSI */
Johan Hedbergd5859e22011-01-25 01:19:58 +0200534
Andre Guedes999dcd12012-07-24 15:03:52 -0300535 if (lmp_sniffsubr_capable(hdev))
Johan Hedbergd5859e22011-01-25 01:19:58 +0200536 events[5] |= 0x20; /* Sniff Subrating */
537
Johan Hedberg976eb202012-10-24 21:12:01 +0300538 if (lmp_pause_enc_capable(hdev))
Johan Hedbergd5859e22011-01-25 01:19:58 +0200539 events[5] |= 0x80; /* Encryption Key Refresh Complete */
540
Johan Hedberg976eb202012-10-24 21:12:01 +0300541 if (lmp_ext_inq_capable(hdev))
Johan Hedbergd5859e22011-01-25 01:19:58 +0200542 events[5] |= 0x40; /* Extended Inquiry Result */
543
Andre Guedesc58e8102012-07-24 15:03:53 -0300544 if (lmp_no_flush_capable(hdev))
Johan Hedbergd5859e22011-01-25 01:19:58 +0200545 events[7] |= 0x01; /* Enhanced Flush Complete */
546
Johan Hedberg976eb202012-10-24 21:12:01 +0300547 if (lmp_lsto_capable(hdev))
Johan Hedbergd5859e22011-01-25 01:19:58 +0200548 events[6] |= 0x80; /* Link Supervision Timeout Changed */
549
Andre Guedes9a1a1992012-07-24 15:03:48 -0300550 if (lmp_ssp_capable(hdev)) {
Johan Hedbergd5859e22011-01-25 01:19:58 +0200551 events[6] |= 0x01; /* IO Capability Request */
552 events[6] |= 0x02; /* IO Capability Response */
553 events[6] |= 0x04; /* User Confirmation Request */
554 events[6] |= 0x08; /* User Passkey Request */
555 events[6] |= 0x10; /* Remote OOB Data Request */
556 events[6] |= 0x20; /* Simple Pairing Complete */
557 events[7] |= 0x04; /* User Passkey Notification */
558 events[7] |= 0x08; /* Keypress Notification */
559 events[7] |= 0x10; /* Remote Host Supported
560 * Features Notification */
561 }
562
Andre Guedesc383ddc2012-07-24 15:03:47 -0300563 if (lmp_le_capable(hdev))
Johan Hedbergd5859e22011-01-25 01:19:58 +0200564 events[7] |= 0x20; /* LE Meta-Event */
565
566 hci_send_cmd(hdev, HCI_OP_SET_EVENT_MASK, sizeof(events), events);
Johan Hedberge36b04c2012-10-19 20:57:47 +0300567
568 if (lmp_le_capable(hdev)) {
569 memset(events, 0, sizeof(events));
570 events[0] = 0x1f;
571 hci_send_cmd(hdev, HCI_OP_LE_SET_EVENT_MASK,
572 sizeof(events), events);
573 }
Johan Hedbergd5859e22011-01-25 01:19:58 +0200574}
575
Gustavo Padovan4611dfa2012-10-24 11:18:41 -0200576static void bredr_setup(struct hci_dev *hdev)
Johan Hedberge1171e82012-10-19 20:57:45 +0300577{
578 struct hci_cp_delete_stored_link_key cp;
579 __le16 param;
580 __u8 flt_type;
581
582 /* Read Buffer Size (ACL mtu, max pkt, etc.) */
583 hci_send_cmd(hdev, HCI_OP_READ_BUFFER_SIZE, 0, NULL);
584
585 /* Read Class of Device */
586 hci_send_cmd(hdev, HCI_OP_READ_CLASS_OF_DEV, 0, NULL);
587
588 /* Read Local Name */
589 hci_send_cmd(hdev, HCI_OP_READ_LOCAL_NAME, 0, NULL);
590
591 /* Read Voice Setting */
592 hci_send_cmd(hdev, HCI_OP_READ_VOICE_SETTING, 0, NULL);
593
594 /* Clear Event Filters */
595 flt_type = HCI_FLT_CLEAR_ALL;
596 hci_send_cmd(hdev, HCI_OP_SET_EVENT_FLT, 1, &flt_type);
597
598 /* Connection accept timeout ~20 secs */
599 param = __constant_cpu_to_le16(0x7d00);
600 hci_send_cmd(hdev, HCI_OP_WRITE_CA_TIMEOUT, 2, &param);
601
602 bacpy(&cp.bdaddr, BDADDR_ANY);
603 cp.delete_all = 1;
604 hci_send_cmd(hdev, HCI_OP_DELETE_STORED_LINK_KEY, sizeof(cp), &cp);
605}
606
Gustavo Padovan4611dfa2012-10-24 11:18:41 -0200607static void le_setup(struct hci_dev *hdev)
Johan Hedberge1171e82012-10-19 20:57:45 +0300608{
609 /* Read LE Buffer Size */
610 hci_send_cmd(hdev, HCI_OP_LE_READ_BUFFER_SIZE, 0, NULL);
Johan Hedberg8fa19092012-10-19 20:57:49 +0300611
612 /* Read LE Advertising Channel TX Power */
613 hci_send_cmd(hdev, HCI_OP_LE_READ_ADV_TX_POWER, 0, NULL);
Johan Hedberge1171e82012-10-19 20:57:45 +0300614}
615
Johan Hedbergd5859e22011-01-25 01:19:58 +0200616static void hci_setup(struct hci_dev *hdev)
617{
Andrei Emeltchenkoe61ef4992011-12-19 16:31:27 +0200618 if (hdev->dev_type != HCI_BREDR)
619 return;
620
Johan Hedberge1171e82012-10-19 20:57:45 +0300621 /* Read BD Address */
622 hci_send_cmd(hdev, HCI_OP_READ_BD_ADDR, 0, NULL);
623
624 if (lmp_bredr_capable(hdev))
Gustavo Padovan4611dfa2012-10-24 11:18:41 -0200625 bredr_setup(hdev);
Johan Hedberge1171e82012-10-19 20:57:45 +0300626
627 if (lmp_le_capable(hdev))
Gustavo Padovan4611dfa2012-10-24 11:18:41 -0200628 le_setup(hdev);
Johan Hedberge1171e82012-10-19 20:57:45 +0300629
Johan Hedbergd5859e22011-01-25 01:19:58 +0200630 hci_setup_event_mask(hdev);
631
Andrei Emeltchenkod095c1e2011-12-01 14:33:27 +0200632 if (hdev->hci_ver > BLUETOOTH_VER_1_1)
Johan Hedbergd5859e22011-01-25 01:19:58 +0200633 hci_send_cmd(hdev, HCI_OP_READ_LOCAL_COMMANDS, 0, NULL);
634
Gustavo Padovan6d3c7302012-05-24 03:36:37 -0300635 if (lmp_ssp_capable(hdev)) {
Johan Hedberg54d04db2012-02-22 15:47:48 +0200636 if (test_bit(HCI_SSP_ENABLED, &hdev->dev_flags)) {
637 u8 mode = 0x01;
638 hci_send_cmd(hdev, HCI_OP_WRITE_SSP_MODE,
Gustavo F. Padovan04124682012-03-08 01:25:00 -0300639 sizeof(mode), &mode);
Johan Hedberg54d04db2012-02-22 15:47:48 +0200640 } else {
641 struct hci_cp_write_eir cp;
642
643 memset(hdev->eir, 0, sizeof(hdev->eir));
644 memset(&cp, 0, sizeof(cp));
645
646 hci_send_cmd(hdev, HCI_OP_WRITE_EIR, sizeof(cp), &cp);
647 }
Johan Hedbergd5859e22011-01-25 01:19:58 +0200648 }
649
Johan Hedberg976eb202012-10-24 21:12:01 +0300650 if (lmp_inq_rssi_capable(hdev))
Johan Hedbergd5859e22011-01-25 01:19:58 +0200651 hci_setup_inquiry_mode(hdev);
652
Johan Hedberg976eb202012-10-24 21:12:01 +0300653 if (lmp_inq_tx_pwr_capable(hdev))
Johan Hedbergd5859e22011-01-25 01:19:58 +0200654 hci_send_cmd(hdev, HCI_OP_READ_INQ_RSP_TX_POWER, 0, NULL);
Andre Guedes971e3a42011-06-30 19:20:52 -0300655
Johan Hedberg976eb202012-10-24 21:12:01 +0300656 if (lmp_ext_feat_capable(hdev)) {
Andre Guedes971e3a42011-06-30 19:20:52 -0300657 struct hci_cp_read_local_ext_features cp;
658
659 cp.page = 0x01;
Gustavo F. Padovan04124682012-03-08 01:25:00 -0300660 hci_send_cmd(hdev, HCI_OP_READ_LOCAL_EXT_FEATURES, sizeof(cp),
661 &cp);
Andre Guedes971e3a42011-06-30 19:20:52 -0300662 }
Andre Guedese6100a22011-06-30 19:20:54 -0300663
Johan Hedberg47990ea2012-02-22 11:58:37 +0200664 if (test_bit(HCI_LINK_SECURITY, &hdev->dev_flags)) {
665 u8 enable = 1;
Gustavo F. Padovan04124682012-03-08 01:25:00 -0300666 hci_send_cmd(hdev, HCI_OP_WRITE_AUTH_ENABLE, sizeof(enable),
667 &enable);
Johan Hedberg47990ea2012-02-22 11:58:37 +0200668 }
Johan Hedbergd5859e22011-01-25 01:19:58 +0200669}
670
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200671static void hci_cc_read_local_version(struct hci_dev *hdev, struct sk_buff *skb)
672{
673 struct hci_rp_read_local_version *rp = (void *) skb->data;
674
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +0300675 BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200676
677 if (rp->status)
Andrei Emeltchenko28b8df72012-02-24 12:45:44 +0200678 goto done;
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200679
680 hdev->hci_ver = rp->hci_ver;
Marcel Holtmanne4e8e372008-07-14 20:13:47 +0200681 hdev->hci_rev = __le16_to_cpu(rp->hci_rev);
Johan Hedbergd5859e22011-01-25 01:19:58 +0200682 hdev->lmp_ver = rp->lmp_ver;
Marcel Holtmanne4e8e372008-07-14 20:13:47 +0200683 hdev->manufacturer = __le16_to_cpu(rp->manufacturer);
Johan Hedbergd5859e22011-01-25 01:19:58 +0200684 hdev->lmp_subver = __le16_to_cpu(rp->lmp_subver);
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200685
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +0300686 BT_DBG("%s manufacturer 0x%4.4x hci ver %d:%d", hdev->name,
Gustavo Padovan807deac2012-05-17 00:36:24 -0300687 hdev->manufacturer, hdev->hci_ver, hdev->hci_rev);
Johan Hedbergd5859e22011-01-25 01:19:58 +0200688
689 if (test_bit(HCI_INIT, &hdev->flags))
690 hci_setup(hdev);
Andrei Emeltchenko28b8df72012-02-24 12:45:44 +0200691
692done:
693 hci_req_complete(hdev, HCI_OP_READ_LOCAL_VERSION, rp->status);
Johan Hedbergd5859e22011-01-25 01:19:58 +0200694}
695
696static void hci_setup_link_policy(struct hci_dev *hdev)
697{
Andrei Emeltchenko035100c2012-03-12 15:59:32 +0200698 struct hci_cp_write_def_link_policy cp;
Johan Hedbergd5859e22011-01-25 01:19:58 +0200699 u16 link_policy = 0;
700
Andre Guedes9f92ebf2012-07-24 15:03:50 -0300701 if (lmp_rswitch_capable(hdev))
Johan Hedbergd5859e22011-01-25 01:19:58 +0200702 link_policy |= HCI_LP_RSWITCH;
Johan Hedberg976eb202012-10-24 21:12:01 +0300703 if (lmp_hold_capable(hdev))
Johan Hedbergd5859e22011-01-25 01:19:58 +0200704 link_policy |= HCI_LP_HOLD;
Andre Guedes6eded102012-07-24 15:03:51 -0300705 if (lmp_sniff_capable(hdev))
Johan Hedbergd5859e22011-01-25 01:19:58 +0200706 link_policy |= HCI_LP_SNIFF;
Johan Hedberg976eb202012-10-24 21:12:01 +0300707 if (lmp_park_capable(hdev))
Johan Hedbergd5859e22011-01-25 01:19:58 +0200708 link_policy |= HCI_LP_PARK;
709
Andrei Emeltchenko035100c2012-03-12 15:59:32 +0200710 cp.policy = cpu_to_le16(link_policy);
711 hci_send_cmd(hdev, HCI_OP_WRITE_DEF_LINK_POLICY, sizeof(cp), &cp);
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200712}
713
Gustavo Padovan8fc9ced2012-05-23 04:04:21 -0300714static void hci_cc_read_local_commands(struct hci_dev *hdev,
715 struct sk_buff *skb)
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200716{
717 struct hci_rp_read_local_commands *rp = (void *) skb->data;
718
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +0300719 BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200720
721 if (rp->status)
Johan Hedbergd5859e22011-01-25 01:19:58 +0200722 goto done;
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200723
724 memcpy(hdev->commands, rp->commands, sizeof(hdev->commands));
Johan Hedbergd5859e22011-01-25 01:19:58 +0200725
726 if (test_bit(HCI_INIT, &hdev->flags) && (hdev->commands[5] & 0x10))
727 hci_setup_link_policy(hdev);
728
729done:
730 hci_req_complete(hdev, HCI_OP_READ_LOCAL_COMMANDS, rp->status);
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200731}
732
Gustavo Padovan8fc9ced2012-05-23 04:04:21 -0300733static void hci_cc_read_local_features(struct hci_dev *hdev,
734 struct sk_buff *skb)
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200735{
736 struct hci_rp_read_local_features *rp = (void *) skb->data;
737
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +0300738 BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200739
740 if (rp->status)
741 return;
742
743 memcpy(hdev->features, rp->features, 8);
744
745 /* Adjust default settings according to features
746 * supported by device. */
747
748 if (hdev->features[0] & LMP_3SLOT)
749 hdev->pkt_type |= (HCI_DM3 | HCI_DH3);
750
751 if (hdev->features[0] & LMP_5SLOT)
752 hdev->pkt_type |= (HCI_DM5 | HCI_DH5);
753
754 if (hdev->features[1] & LMP_HV2) {
755 hdev->pkt_type |= (HCI_HV2);
756 hdev->esco_type |= (ESCO_HV2);
757 }
758
759 if (hdev->features[1] & LMP_HV3) {
760 hdev->pkt_type |= (HCI_HV3);
761 hdev->esco_type |= (ESCO_HV3);
762 }
763
Andre Guedes45db810f2012-07-24 15:03:49 -0300764 if (lmp_esco_capable(hdev))
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200765 hdev->esco_type |= (ESCO_EV3);
766
767 if (hdev->features[4] & LMP_EV4)
768 hdev->esco_type |= (ESCO_EV4);
769
770 if (hdev->features[4] & LMP_EV5)
771 hdev->esco_type |= (ESCO_EV5);
772
Marcel Holtmannefc76882009-02-06 09:13:37 +0100773 if (hdev->features[5] & LMP_EDR_ESCO_2M)
774 hdev->esco_type |= (ESCO_2EV3);
775
776 if (hdev->features[5] & LMP_EDR_ESCO_3M)
777 hdev->esco_type |= (ESCO_3EV3);
778
779 if (hdev->features[5] & LMP_EDR_3S_ESCO)
780 hdev->esco_type |= (ESCO_2EV5 | ESCO_3EV5);
781
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200782 BT_DBG("%s features 0x%.2x%.2x%.2x%.2x%.2x%.2x%.2x%.2x", hdev->name,
Gustavo Padovan807deac2012-05-17 00:36:24 -0300783 hdev->features[0], hdev->features[1],
784 hdev->features[2], hdev->features[3],
785 hdev->features[4], hdev->features[5],
786 hdev->features[6], hdev->features[7]);
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200787}
788
Johan Hedberg8f984df2012-02-28 01:07:22 +0200789static void hci_set_le_support(struct hci_dev *hdev)
790{
791 struct hci_cp_write_le_host_supported cp;
792
793 memset(&cp, 0, sizeof(cp));
794
Marcel Holtmann9d428202012-05-03 07:12:31 +0200795 if (test_bit(HCI_LE_ENABLED, &hdev->dev_flags)) {
Johan Hedberg8f984df2012-02-28 01:07:22 +0200796 cp.le = 1;
Johan Hedberg976eb202012-10-24 21:12:01 +0300797 cp.simul = !!lmp_le_br_capable(hdev);
Johan Hedberg8f984df2012-02-28 01:07:22 +0200798 }
799
Johan Hedberg976eb202012-10-24 21:12:01 +0300800 if (cp.le != !!lmp_host_le_capable(hdev))
Gustavo F. Padovan04124682012-03-08 01:25:00 -0300801 hci_send_cmd(hdev, HCI_OP_WRITE_LE_HOST_SUPPORTED, sizeof(cp),
802 &cp);
Johan Hedberg8f984df2012-02-28 01:07:22 +0200803}
804
Andre Guedes971e3a42011-06-30 19:20:52 -0300805static void hci_cc_read_local_ext_features(struct hci_dev *hdev,
Gustavo Padovan807deac2012-05-17 00:36:24 -0300806 struct sk_buff *skb)
Andre Guedes971e3a42011-06-30 19:20:52 -0300807{
808 struct hci_rp_read_local_ext_features *rp = (void *) skb->data;
809
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +0300810 BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
Andre Guedes971e3a42011-06-30 19:20:52 -0300811
812 if (rp->status)
Johan Hedberg8f984df2012-02-28 01:07:22 +0200813 goto done;
Andre Guedes971e3a42011-06-30 19:20:52 -0300814
Andre Guedesb5b32b62011-12-30 10:34:04 -0300815 switch (rp->page) {
816 case 0:
817 memcpy(hdev->features, rp->features, 8);
818 break;
819 case 1:
820 memcpy(hdev->host_features, rp->features, 8);
821 break;
822 }
Andre Guedes971e3a42011-06-30 19:20:52 -0300823
Andre Guedesc383ddc2012-07-24 15:03:47 -0300824 if (test_bit(HCI_INIT, &hdev->flags) && lmp_le_capable(hdev))
Johan Hedberg8f984df2012-02-28 01:07:22 +0200825 hci_set_le_support(hdev);
826
827done:
Andre Guedes971e3a42011-06-30 19:20:52 -0300828 hci_req_complete(hdev, HCI_OP_READ_LOCAL_EXT_FEATURES, rp->status);
829}
830
Andrei Emeltchenko1e89cff2011-11-24 14:52:02 +0200831static void hci_cc_read_flow_control_mode(struct hci_dev *hdev,
Gustavo Padovan807deac2012-05-17 00:36:24 -0300832 struct sk_buff *skb)
Andrei Emeltchenko1e89cff2011-11-24 14:52:02 +0200833{
834 struct hci_rp_read_flow_control_mode *rp = (void *) skb->data;
835
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +0300836 BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
Andrei Emeltchenko1e89cff2011-11-24 14:52:02 +0200837
838 if (rp->status)
839 return;
840
841 hdev->flow_ctl_mode = rp->mode;
842
843 hci_req_complete(hdev, HCI_OP_READ_FLOW_CONTROL_MODE, rp->status);
844}
845
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200846static void hci_cc_read_buffer_size(struct hci_dev *hdev, struct sk_buff *skb)
847{
848 struct hci_rp_read_buffer_size *rp = (void *) skb->data;
849
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +0300850 BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200851
852 if (rp->status)
853 return;
854
855 hdev->acl_mtu = __le16_to_cpu(rp->acl_mtu);
856 hdev->sco_mtu = rp->sco_mtu;
857 hdev->acl_pkts = __le16_to_cpu(rp->acl_max_pkt);
858 hdev->sco_pkts = __le16_to_cpu(rp->sco_max_pkt);
859
860 if (test_bit(HCI_QUIRK_FIXUP_BUFFER_SIZE, &hdev->quirks)) {
861 hdev->sco_mtu = 64;
862 hdev->sco_pkts = 8;
863 }
864
865 hdev->acl_cnt = hdev->acl_pkts;
866 hdev->sco_cnt = hdev->sco_pkts;
867
Gustavo Padovan807deac2012-05-17 00:36:24 -0300868 BT_DBG("%s acl mtu %d:%d sco mtu %d:%d", hdev->name, hdev->acl_mtu,
869 hdev->acl_pkts, hdev->sco_mtu, hdev->sco_pkts);
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200870}
871
872static void hci_cc_read_bd_addr(struct hci_dev *hdev, struct sk_buff *skb)
873{
874 struct hci_rp_read_bd_addr *rp = (void *) skb->data;
875
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +0300876 BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200877
878 if (!rp->status)
879 bacpy(&hdev->bdaddr, &rp->bdaddr);
880
Johan Hedberg23bb5762010-12-21 23:01:27 +0200881 hci_req_complete(hdev, HCI_OP_READ_BD_ADDR, rp->status);
882}
883
Andrei Emeltchenko350ee4c2011-12-07 15:56:51 +0200884static void hci_cc_read_data_block_size(struct hci_dev *hdev,
Gustavo Padovan807deac2012-05-17 00:36:24 -0300885 struct sk_buff *skb)
Andrei Emeltchenko350ee4c2011-12-07 15:56:51 +0200886{
887 struct hci_rp_read_data_block_size *rp = (void *) skb->data;
888
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +0300889 BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
Andrei Emeltchenko350ee4c2011-12-07 15:56:51 +0200890
891 if (rp->status)
892 return;
893
894 hdev->block_mtu = __le16_to_cpu(rp->max_acl_len);
895 hdev->block_len = __le16_to_cpu(rp->block_len);
896 hdev->num_blocks = __le16_to_cpu(rp->num_blocks);
897
898 hdev->block_cnt = hdev->num_blocks;
899
900 BT_DBG("%s blk mtu %d cnt %d len %d", hdev->name, hdev->block_mtu,
Gustavo Padovan807deac2012-05-17 00:36:24 -0300901 hdev->block_cnt, hdev->block_len);
Andrei Emeltchenko350ee4c2011-12-07 15:56:51 +0200902
903 hci_req_complete(hdev, HCI_OP_READ_DATA_BLOCK_SIZE, rp->status);
904}
905
Johan Hedberg23bb5762010-12-21 23:01:27 +0200906static void hci_cc_write_ca_timeout(struct hci_dev *hdev, struct sk_buff *skb)
907{
908 __u8 status = *((__u8 *) skb->data);
909
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +0300910 BT_DBG("%s status 0x%2.2x", hdev->name, status);
Johan Hedberg23bb5762010-12-21 23:01:27 +0200911
912 hci_req_complete(hdev, HCI_OP_WRITE_CA_TIMEOUT, status);
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200913}
914
Andrei Emeltchenko928abaa2011-10-12 10:53:57 +0300915static void hci_cc_read_local_amp_info(struct hci_dev *hdev,
Gustavo Padovan807deac2012-05-17 00:36:24 -0300916 struct sk_buff *skb)
Andrei Emeltchenko928abaa2011-10-12 10:53:57 +0300917{
918 struct hci_rp_read_local_amp_info *rp = (void *) skb->data;
919
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +0300920 BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
Andrei Emeltchenko928abaa2011-10-12 10:53:57 +0300921
922 if (rp->status)
Andrei Emeltchenko8e2a0d92012-09-27 17:26:08 +0300923 goto a2mp_rsp;
Andrei Emeltchenko928abaa2011-10-12 10:53:57 +0300924
925 hdev->amp_status = rp->amp_status;
926 hdev->amp_total_bw = __le32_to_cpu(rp->total_bw);
927 hdev->amp_max_bw = __le32_to_cpu(rp->max_bw);
928 hdev->amp_min_latency = __le32_to_cpu(rp->min_latency);
929 hdev->amp_max_pdu = __le32_to_cpu(rp->max_pdu);
930 hdev->amp_type = rp->amp_type;
931 hdev->amp_pal_cap = __le16_to_cpu(rp->pal_cap);
932 hdev->amp_assoc_size = __le16_to_cpu(rp->max_assoc_size);
933 hdev->amp_be_flush_to = __le32_to_cpu(rp->be_flush_to);
934 hdev->amp_max_flush_to = __le32_to_cpu(rp->max_flush_to);
935
936 hci_req_complete(hdev, HCI_OP_READ_LOCAL_AMP_INFO, rp->status);
Andrei Emeltchenko8e2a0d92012-09-27 17:26:08 +0300937
938a2mp_rsp:
939 a2mp_send_getinfo_rsp(hdev);
Andrei Emeltchenko928abaa2011-10-12 10:53:57 +0300940}
941
Andrei Emeltchenko903e4542012-09-27 17:26:09 +0300942static void hci_cc_read_local_amp_assoc(struct hci_dev *hdev,
943 struct sk_buff *skb)
944{
945 struct hci_rp_read_local_amp_assoc *rp = (void *) skb->data;
946 struct amp_assoc *assoc = &hdev->loc_assoc;
947 size_t rem_len, frag_len;
948
949 BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
950
951 if (rp->status)
952 goto a2mp_rsp;
953
954 frag_len = skb->len - sizeof(*rp);
955 rem_len = __le16_to_cpu(rp->rem_len);
956
957 if (rem_len > frag_len) {
Andrei Emeltchenko2e430be32012-09-28 14:44:23 +0300958 BT_DBG("frag_len %zu rem_len %zu", frag_len, rem_len);
Andrei Emeltchenko903e4542012-09-27 17:26:09 +0300959
960 memcpy(assoc->data + assoc->offset, rp->frag, frag_len);
961 assoc->offset += frag_len;
962
963 /* Read other fragments */
964 amp_read_loc_assoc_frag(hdev, rp->phy_handle);
965
966 return;
967 }
968
969 memcpy(assoc->data + assoc->offset, rp->frag, rem_len);
970 assoc->len = assoc->offset + rem_len;
971 assoc->offset = 0;
972
973a2mp_rsp:
974 /* Send A2MP Rsp when all fragments are received */
975 a2mp_send_getampassoc_rsp(hdev, rp->status);
Andrei Emeltchenko9495b2e2012-09-27 17:26:22 +0300976 a2mp_send_create_phy_link_req(hdev, rp->status);
Andrei Emeltchenko903e4542012-09-27 17:26:09 +0300977}
978
Johan Hedbergb0916ea2011-01-10 13:44:55 +0200979static void hci_cc_delete_stored_link_key(struct hci_dev *hdev,
Gustavo Padovan807deac2012-05-17 00:36:24 -0300980 struct sk_buff *skb)
Johan Hedbergb0916ea2011-01-10 13:44:55 +0200981{
982 __u8 status = *((__u8 *) skb->data);
983
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +0300984 BT_DBG("%s status 0x%2.2x", hdev->name, status);
Johan Hedbergb0916ea2011-01-10 13:44:55 +0200985
986 hci_req_complete(hdev, HCI_OP_DELETE_STORED_LINK_KEY, status);
987}
988
Johan Hedbergd5859e22011-01-25 01:19:58 +0200989static void hci_cc_set_event_mask(struct hci_dev *hdev, struct sk_buff *skb)
990{
991 __u8 status = *((__u8 *) skb->data);
992
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +0300993 BT_DBG("%s status 0x%2.2x", hdev->name, status);
Johan Hedbergd5859e22011-01-25 01:19:58 +0200994
995 hci_req_complete(hdev, HCI_OP_SET_EVENT_MASK, status);
996}
997
998static void hci_cc_write_inquiry_mode(struct hci_dev *hdev,
Gustavo Padovan807deac2012-05-17 00:36:24 -0300999 struct sk_buff *skb)
Johan Hedbergd5859e22011-01-25 01:19:58 +02001000{
1001 __u8 status = *((__u8 *) skb->data);
1002
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +03001003 BT_DBG("%s status 0x%2.2x", hdev->name, status);
Johan Hedbergd5859e22011-01-25 01:19:58 +02001004
1005 hci_req_complete(hdev, HCI_OP_WRITE_INQUIRY_MODE, status);
1006}
1007
1008static void hci_cc_read_inq_rsp_tx_power(struct hci_dev *hdev,
Gustavo Padovan807deac2012-05-17 00:36:24 -03001009 struct sk_buff *skb)
Johan Hedbergd5859e22011-01-25 01:19:58 +02001010{
Marcel Holtmann91c4e9b2012-03-11 19:27:21 -07001011 struct hci_rp_read_inq_rsp_tx_power *rp = (void *) skb->data;
Johan Hedbergd5859e22011-01-25 01:19:58 +02001012
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +03001013 BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
Johan Hedbergd5859e22011-01-25 01:19:58 +02001014
Marcel Holtmann91c4e9b2012-03-11 19:27:21 -07001015 if (!rp->status)
1016 hdev->inq_tx_power = rp->tx_power;
1017
1018 hci_req_complete(hdev, HCI_OP_READ_INQ_RSP_TX_POWER, rp->status);
Johan Hedbergd5859e22011-01-25 01:19:58 +02001019}
1020
1021static void hci_cc_set_event_flt(struct hci_dev *hdev, struct sk_buff *skb)
1022{
1023 __u8 status = *((__u8 *) skb->data);
1024
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +03001025 BT_DBG("%s status 0x%2.2x", hdev->name, status);
Johan Hedbergd5859e22011-01-25 01:19:58 +02001026
1027 hci_req_complete(hdev, HCI_OP_SET_EVENT_FLT, status);
1028}
1029
Johan Hedberg980e1a52011-01-22 06:10:07 +02001030static void hci_cc_pin_code_reply(struct hci_dev *hdev, struct sk_buff *skb)
1031{
1032 struct hci_rp_pin_code_reply *rp = (void *) skb->data;
1033 struct hci_cp_pin_code_reply *cp;
1034 struct hci_conn *conn;
1035
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +03001036 BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
Johan Hedberg980e1a52011-01-22 06:10:07 +02001037
Johan Hedberg56e5cb82011-11-08 20:40:16 +02001038 hci_dev_lock(hdev);
1039
Johan Hedberga8b2d5c2012-01-08 23:11:15 +02001040 if (test_bit(HCI_MGMT, &hdev->dev_flags))
Johan Hedberg744cf192011-11-08 20:40:14 +02001041 mgmt_pin_code_reply_complete(hdev, &rp->bdaddr, rp->status);
Johan Hedberg980e1a52011-01-22 06:10:07 +02001042
Mikel Astizfa1bd912012-08-09 09:52:29 +02001043 if (rp->status)
Johan Hedberg56e5cb82011-11-08 20:40:16 +02001044 goto unlock;
Johan Hedberg980e1a52011-01-22 06:10:07 +02001045
1046 cp = hci_sent_cmd_data(hdev, HCI_OP_PIN_CODE_REPLY);
1047 if (!cp)
Johan Hedberg56e5cb82011-11-08 20:40:16 +02001048 goto unlock;
Johan Hedberg980e1a52011-01-22 06:10:07 +02001049
1050 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &cp->bdaddr);
1051 if (conn)
1052 conn->pin_length = cp->pin_len;
Johan Hedberg56e5cb82011-11-08 20:40:16 +02001053
1054unlock:
1055 hci_dev_unlock(hdev);
Johan Hedberg980e1a52011-01-22 06:10:07 +02001056}
1057
1058static void hci_cc_pin_code_neg_reply(struct hci_dev *hdev, struct sk_buff *skb)
1059{
1060 struct hci_rp_pin_code_neg_reply *rp = (void *) skb->data;
1061
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +03001062 BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
Johan Hedberg980e1a52011-01-22 06:10:07 +02001063
Johan Hedberg56e5cb82011-11-08 20:40:16 +02001064 hci_dev_lock(hdev);
1065
Johan Hedberga8b2d5c2012-01-08 23:11:15 +02001066 if (test_bit(HCI_MGMT, &hdev->dev_flags))
Johan Hedberg744cf192011-11-08 20:40:14 +02001067 mgmt_pin_code_neg_reply_complete(hdev, &rp->bdaddr,
Gustavo Padovan807deac2012-05-17 00:36:24 -03001068 rp->status);
Johan Hedberg56e5cb82011-11-08 20:40:16 +02001069
1070 hci_dev_unlock(hdev);
Johan Hedberg980e1a52011-01-22 06:10:07 +02001071}
Johan Hedberg56e5cb82011-11-08 20:40:16 +02001072
Ville Tervo6ed58ec2011-02-10 22:38:48 -03001073static void hci_cc_le_read_buffer_size(struct hci_dev *hdev,
1074 struct sk_buff *skb)
1075{
1076 struct hci_rp_le_read_buffer_size *rp = (void *) skb->data;
1077
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +03001078 BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
Ville Tervo6ed58ec2011-02-10 22:38:48 -03001079
1080 if (rp->status)
1081 return;
1082
1083 hdev->le_mtu = __le16_to_cpu(rp->le_mtu);
1084 hdev->le_pkts = rp->le_max_pkt;
1085
1086 hdev->le_cnt = hdev->le_pkts;
1087
1088 BT_DBG("%s le mtu %d:%d", hdev->name, hdev->le_mtu, hdev->le_pkts);
1089
1090 hci_req_complete(hdev, HCI_OP_LE_READ_BUFFER_SIZE, rp->status);
1091}
Johan Hedberg980e1a52011-01-22 06:10:07 +02001092
Johan Hedberg8fa19092012-10-19 20:57:49 +03001093static void hci_cc_le_read_adv_tx_power(struct hci_dev *hdev,
1094 struct sk_buff *skb)
1095{
1096 struct hci_rp_le_read_adv_tx_power *rp = (void *) skb->data;
1097
1098 BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
1099
Johan Hedberg3f0f5242012-11-08 01:23:00 +01001100 if (!rp->status) {
Johan Hedberg8fa19092012-10-19 20:57:49 +03001101 hdev->adv_tx_power = rp->tx_power;
Johan Hedberg3f0f5242012-11-08 01:23:00 +01001102 if (!test_bit(HCI_INIT, &hdev->flags))
1103 hci_update_ad(hdev);
1104 }
Johan Hedberg8fa19092012-10-19 20:57:49 +03001105
1106 hci_req_complete(hdev, HCI_OP_LE_READ_ADV_TX_POWER, rp->status);
1107}
1108
Johan Hedberge36b04c2012-10-19 20:57:47 +03001109static void hci_cc_le_set_event_mask(struct hci_dev *hdev, struct sk_buff *skb)
1110{
1111 __u8 status = *((__u8 *) skb->data);
1112
1113 BT_DBG("%s status 0x%2.2x", hdev->name, status);
1114
1115 hci_req_complete(hdev, HCI_OP_LE_SET_EVENT_MASK, status);
1116}
1117
Johan Hedberga5c29682011-02-19 12:05:57 -03001118static void hci_cc_user_confirm_reply(struct hci_dev *hdev, struct sk_buff *skb)
1119{
1120 struct hci_rp_user_confirm_reply *rp = (void *) skb->data;
1121
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +03001122 BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
Johan Hedberga5c29682011-02-19 12:05:57 -03001123
Johan Hedberg56e5cb82011-11-08 20:40:16 +02001124 hci_dev_lock(hdev);
1125
Johan Hedberga8b2d5c2012-01-08 23:11:15 +02001126 if (test_bit(HCI_MGMT, &hdev->dev_flags))
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001127 mgmt_user_confirm_reply_complete(hdev, &rp->bdaddr, ACL_LINK, 0,
1128 rp->status);
Johan Hedberg56e5cb82011-11-08 20:40:16 +02001129
1130 hci_dev_unlock(hdev);
Johan Hedberga5c29682011-02-19 12:05:57 -03001131}
1132
1133static void hci_cc_user_confirm_neg_reply(struct hci_dev *hdev,
Gustavo Padovan807deac2012-05-17 00:36:24 -03001134 struct sk_buff *skb)
Johan Hedberga5c29682011-02-19 12:05:57 -03001135{
1136 struct hci_rp_user_confirm_reply *rp = (void *) skb->data;
1137
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +03001138 BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
Johan Hedberga5c29682011-02-19 12:05:57 -03001139
Johan Hedberg56e5cb82011-11-08 20:40:16 +02001140 hci_dev_lock(hdev);
1141
Johan Hedberga8b2d5c2012-01-08 23:11:15 +02001142 if (test_bit(HCI_MGMT, &hdev->dev_flags))
Johan Hedberg744cf192011-11-08 20:40:14 +02001143 mgmt_user_confirm_neg_reply_complete(hdev, &rp->bdaddr,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001144 ACL_LINK, 0, rp->status);
Johan Hedberg56e5cb82011-11-08 20:40:16 +02001145
1146 hci_dev_unlock(hdev);
Johan Hedberga5c29682011-02-19 12:05:57 -03001147}
1148
Brian Gix1143d452011-11-23 08:28:34 -08001149static void hci_cc_user_passkey_reply(struct hci_dev *hdev, struct sk_buff *skb)
1150{
1151 struct hci_rp_user_confirm_reply *rp = (void *) skb->data;
1152
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +03001153 BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
Brian Gix1143d452011-11-23 08:28:34 -08001154
1155 hci_dev_lock(hdev);
1156
Johan Hedberga8b2d5c2012-01-08 23:11:15 +02001157 if (test_bit(HCI_MGMT, &hdev->dev_flags))
Johan Hedberg272d90d2012-02-09 15:26:12 +02001158 mgmt_user_passkey_reply_complete(hdev, &rp->bdaddr, ACL_LINK,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001159 0, rp->status);
Brian Gix1143d452011-11-23 08:28:34 -08001160
1161 hci_dev_unlock(hdev);
1162}
1163
1164static void hci_cc_user_passkey_neg_reply(struct hci_dev *hdev,
Gustavo Padovan807deac2012-05-17 00:36:24 -03001165 struct sk_buff *skb)
Brian Gix1143d452011-11-23 08:28:34 -08001166{
1167 struct hci_rp_user_confirm_reply *rp = (void *) skb->data;
1168
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +03001169 BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
Brian Gix1143d452011-11-23 08:28:34 -08001170
1171 hci_dev_lock(hdev);
1172
Johan Hedberga8b2d5c2012-01-08 23:11:15 +02001173 if (test_bit(HCI_MGMT, &hdev->dev_flags))
Brian Gix1143d452011-11-23 08:28:34 -08001174 mgmt_user_passkey_neg_reply_complete(hdev, &rp->bdaddr,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001175 ACL_LINK, 0, rp->status);
Brian Gix1143d452011-11-23 08:28:34 -08001176
1177 hci_dev_unlock(hdev);
1178}
1179
Szymon Jancc35938b2011-03-22 13:12:21 +01001180static void hci_cc_read_local_oob_data_reply(struct hci_dev *hdev,
Gustavo Padovan807deac2012-05-17 00:36:24 -03001181 struct sk_buff *skb)
Szymon Jancc35938b2011-03-22 13:12:21 +01001182{
1183 struct hci_rp_read_local_oob_data *rp = (void *) skb->data;
1184
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +03001185 BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
Szymon Jancc35938b2011-03-22 13:12:21 +01001186
Johan Hedberg56e5cb82011-11-08 20:40:16 +02001187 hci_dev_lock(hdev);
Johan Hedberg744cf192011-11-08 20:40:14 +02001188 mgmt_read_local_oob_data_reply_complete(hdev, rp->hash,
Szymon Jancc35938b2011-03-22 13:12:21 +01001189 rp->randomizer, rp->status);
Johan Hedberg56e5cb82011-11-08 20:40:16 +02001190 hci_dev_unlock(hdev);
Szymon Jancc35938b2011-03-22 13:12:21 +01001191}
1192
Andre Guedes07f7fa52011-12-02 21:13:31 +09001193static void hci_cc_le_set_scan_param(struct hci_dev *hdev, struct sk_buff *skb)
1194{
1195 __u8 status = *((__u8 *) skb->data);
1196
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +03001197 BT_DBG("%s status 0x%2.2x", hdev->name, status);
Andre Guedes7ba8b4b2012-02-03 17:47:59 -03001198
1199 hci_req_complete(hdev, HCI_OP_LE_SET_SCAN_PARAM, status);
Andre Guedes3fd24152012-02-03 17:48:01 -03001200
1201 if (status) {
1202 hci_dev_lock(hdev);
1203 mgmt_start_discovery_failed(hdev, status);
1204 hci_dev_unlock(hdev);
1205 return;
1206 }
Andre Guedes07f7fa52011-12-02 21:13:31 +09001207}
1208
Andre Guedeseb9d91f2011-05-26 16:23:52 -03001209static void hci_cc_le_set_scan_enable(struct hci_dev *hdev,
Gustavo Padovan807deac2012-05-17 00:36:24 -03001210 struct sk_buff *skb)
Andre Guedeseb9d91f2011-05-26 16:23:52 -03001211{
1212 struct hci_cp_le_set_scan_enable *cp;
1213 __u8 status = *((__u8 *) skb->data);
1214
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +03001215 BT_DBG("%s status 0x%2.2x", hdev->name, status);
Andre Guedeseb9d91f2011-05-26 16:23:52 -03001216
Andre Guedeseb9d91f2011-05-26 16:23:52 -03001217 cp = hci_sent_cmd_data(hdev, HCI_OP_LE_SET_SCAN_ENABLE);
1218 if (!cp)
1219 return;
1220
Andrei Emeltchenko68a8aea2011-12-19 16:14:18 +02001221 switch (cp->enable) {
1222 case LE_SCANNING_ENABLED:
Andre Guedes7ba8b4b2012-02-03 17:47:59 -03001223 hci_req_complete(hdev, HCI_OP_LE_SET_SCAN_ENABLE, status);
1224
Andre Guedes3fd24152012-02-03 17:48:01 -03001225 if (status) {
1226 hci_dev_lock(hdev);
1227 mgmt_start_discovery_failed(hdev, status);
1228 hci_dev_unlock(hdev);
Andre Guedes7ba8b4b2012-02-03 17:47:59 -03001229 return;
Andre Guedes3fd24152012-02-03 17:48:01 -03001230 }
Andre Guedes7ba8b4b2012-02-03 17:47:59 -03001231
Andre Guedesd23264a2011-11-25 20:53:38 -03001232 set_bit(HCI_LE_SCAN, &hdev->dev_flags);
1233
Andre Guedesa8f13c82011-09-09 18:56:24 -03001234 hci_dev_lock(hdev);
Andre Guedes343f9352012-02-17 20:39:37 -03001235 hci_discovery_set_state(hdev, DISCOVERY_FINDING);
Andre Guedesa8f13c82011-09-09 18:56:24 -03001236 hci_dev_unlock(hdev);
Andrei Emeltchenko68a8aea2011-12-19 16:14:18 +02001237 break;
1238
1239 case LE_SCANNING_DISABLED:
Andre Guedesc9ecc482012-03-15 16:52:08 -03001240 if (status) {
1241 hci_dev_lock(hdev);
1242 mgmt_stop_discovery_failed(hdev, status);
1243 hci_dev_unlock(hdev);
Andre Guedes7ba8b4b2012-02-03 17:47:59 -03001244 return;
Andre Guedesc9ecc482012-03-15 16:52:08 -03001245 }
Andre Guedes7ba8b4b2012-02-03 17:47:59 -03001246
Andre Guedesd23264a2011-11-25 20:53:38 -03001247 clear_bit(HCI_LE_SCAN, &hdev->dev_flags);
1248
Andre Guedesbc3dd332012-03-06 19:37:06 -03001249 if (hdev->discovery.type == DISCOV_TYPE_INTERLEAVED &&
1250 hdev->discovery.state == DISCOVERY_FINDING) {
Andre Guedes5e0452c2012-02-17 20:39:38 -03001251 mgmt_interleaved_discovery(hdev);
1252 } else {
1253 hci_dev_lock(hdev);
1254 hci_discovery_set_state(hdev, DISCOVERY_STOPPED);
1255 hci_dev_unlock(hdev);
1256 }
1257
Andrei Emeltchenko68a8aea2011-12-19 16:14:18 +02001258 break;
1259
1260 default:
1261 BT_ERR("Used reserved LE_Scan_Enable param %d", cp->enable);
1262 break;
Andre Guedes35815082011-05-26 16:23:53 -03001263 }
Andre Guedeseb9d91f2011-05-26 16:23:52 -03001264}
1265
Vinicius Costa Gomesa7a595f2011-06-09 18:50:47 -03001266static void hci_cc_le_ltk_reply(struct hci_dev *hdev, struct sk_buff *skb)
1267{
1268 struct hci_rp_le_ltk_reply *rp = (void *) skb->data;
1269
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +03001270 BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
Vinicius Costa Gomesa7a595f2011-06-09 18:50:47 -03001271
1272 if (rp->status)
1273 return;
1274
1275 hci_req_complete(hdev, HCI_OP_LE_LTK_REPLY, rp->status);
1276}
1277
1278static void hci_cc_le_ltk_neg_reply(struct hci_dev *hdev, struct sk_buff *skb)
1279{
1280 struct hci_rp_le_ltk_neg_reply *rp = (void *) skb->data;
1281
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +03001282 BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
Vinicius Costa Gomesa7a595f2011-06-09 18:50:47 -03001283
1284 if (rp->status)
1285 return;
1286
1287 hci_req_complete(hdev, HCI_OP_LE_LTK_NEG_REPLY, rp->status);
1288}
1289
Gustavo Padovan6039aa732012-05-23 04:04:18 -03001290static void hci_cc_write_le_host_supported(struct hci_dev *hdev,
1291 struct sk_buff *skb)
Andre Guedesf9b49302011-06-30 19:20:53 -03001292{
Johan Hedberg06199cf2012-02-22 16:37:11 +02001293 struct hci_cp_write_le_host_supported *sent;
Andre Guedesf9b49302011-06-30 19:20:53 -03001294 __u8 status = *((__u8 *) skb->data);
1295
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +03001296 BT_DBG("%s status 0x%2.2x", hdev->name, status);
Andre Guedesf9b49302011-06-30 19:20:53 -03001297
Johan Hedberg06199cf2012-02-22 16:37:11 +02001298 sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_LE_HOST_SUPPORTED);
Johan Hedberg8f984df2012-02-28 01:07:22 +02001299 if (!sent)
Andre Guedesf9b49302011-06-30 19:20:53 -03001300 return;
1301
Johan Hedberg8f984df2012-02-28 01:07:22 +02001302 if (!status) {
1303 if (sent->le)
1304 hdev->host_features[0] |= LMP_HOST_LE;
1305 else
1306 hdev->host_features[0] &= ~LMP_HOST_LE;
Johan Hedberg53b2caa2012-10-24 21:11:59 +03001307
1308 if (sent->simul)
1309 hdev->host_features[0] |= LMP_HOST_LE_BREDR;
1310 else
1311 hdev->host_features[0] &= ~LMP_HOST_LE_BREDR;
Johan Hedberg8f984df2012-02-28 01:07:22 +02001312 }
1313
1314 if (test_bit(HCI_MGMT, &hdev->dev_flags) &&
Gustavo Padovan807deac2012-05-17 00:36:24 -03001315 !test_bit(HCI_INIT, &hdev->flags))
Johan Hedberg8f984df2012-02-28 01:07:22 +02001316 mgmt_le_enable_complete(hdev, sent->le, status);
1317
1318 hci_req_complete(hdev, HCI_OP_WRITE_LE_HOST_SUPPORTED, status);
Andre Guedesf9b49302011-06-30 19:20:53 -03001319}
1320
Andrei Emeltchenko93c284e2012-09-27 17:26:20 +03001321static void hci_cc_write_remote_amp_assoc(struct hci_dev *hdev,
1322 struct sk_buff *skb)
1323{
1324 struct hci_rp_write_remote_amp_assoc *rp = (void *) skb->data;
1325
1326 BT_DBG("%s status 0x%2.2x phy_handle 0x%2.2x",
1327 hdev->name, rp->status, rp->phy_handle);
1328
1329 if (rp->status)
1330 return;
1331
1332 amp_write_rem_assoc_continue(hdev, rp->phy_handle);
1333}
1334
Gustavo Padovan6039aa732012-05-23 04:04:18 -03001335static void hci_cs_inquiry(struct hci_dev *hdev, __u8 status)
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001336{
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +03001337 BT_DBG("%s status 0x%2.2x", hdev->name, status);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001338
1339 if (status) {
Johan Hedberg23bb5762010-12-21 23:01:27 +02001340 hci_req_complete(hdev, HCI_OP_INQUIRY, status);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001341 hci_conn_check_pending(hdev);
Johan Hedberg56e5cb82011-11-08 20:40:16 +02001342 hci_dev_lock(hdev);
Johan Hedberga8b2d5c2012-01-08 23:11:15 +02001343 if (test_bit(HCI_MGMT, &hdev->dev_flags))
Andre Guedes7a135102011-11-09 17:14:25 -03001344 mgmt_start_discovery_failed(hdev, status);
Johan Hedberg56e5cb82011-11-08 20:40:16 +02001345 hci_dev_unlock(hdev);
Johan Hedberg314b2382011-04-27 10:29:57 -04001346 return;
1347 }
1348
Andre Guedes89352e72011-11-04 14:16:53 -03001349 set_bit(HCI_INQUIRY, &hdev->flags);
1350
Johan Hedberg56e5cb82011-11-08 20:40:16 +02001351 hci_dev_lock(hdev);
Andre Guedes343f9352012-02-17 20:39:37 -03001352 hci_discovery_set_state(hdev, DISCOVERY_FINDING);
Johan Hedberg56e5cb82011-11-08 20:40:16 +02001353 hci_dev_unlock(hdev);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001354}
1355
Gustavo Padovan6039aa732012-05-23 04:04:18 -03001356static void hci_cs_create_conn(struct hci_dev *hdev, __u8 status)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001357{
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001358 struct hci_cp_create_conn *cp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001359 struct hci_conn *conn;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001360
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +03001361 BT_DBG("%s status 0x%2.2x", hdev->name, status);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001362
1363 cp = hci_sent_cmd_data(hdev, HCI_OP_CREATE_CONN);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001364 if (!cp)
1365 return;
1366
1367 hci_dev_lock(hdev);
1368
1369 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &cp->bdaddr);
1370
Andrei Emeltchenko6ed93dc2012-09-25 12:49:43 +03001371 BT_DBG("%s bdaddr %pMR hcon %p", hdev->name, &cp->bdaddr, conn);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001372
1373 if (status) {
1374 if (conn && conn->state == BT_CONNECT) {
Marcel Holtmann4c67bc72006-10-15 17:30:56 +02001375 if (status != 0x0c || conn->attempt > 2) {
1376 conn->state = BT_CLOSED;
1377 hci_proto_connect_cfm(conn, status);
1378 hci_conn_del(conn);
1379 } else
1380 conn->state = BT_CONNECT2;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001381 }
1382 } else {
1383 if (!conn) {
1384 conn = hci_conn_add(hdev, ACL_LINK, &cp->bdaddr);
1385 if (conn) {
Johan Hedberga0c808b2012-01-16 09:49:58 +02001386 conn->out = true;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001387 conn->link_mode |= HCI_LM_MASTER;
1388 } else
Gustavo F. Padovan893ef972010-07-18 15:13:37 -03001389 BT_ERR("No memory for new connection");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001390 }
1391 }
1392
1393 hci_dev_unlock(hdev);
1394}
1395
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001396static void hci_cs_add_sco(struct hci_dev *hdev, __u8 status)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001397{
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001398 struct hci_cp_add_sco *cp;
1399 struct hci_conn *acl, *sco;
1400 __u16 handle;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001401
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +03001402 BT_DBG("%s status 0x%2.2x", hdev->name, status);
Marcel Holtmannb6a0dc82007-10-20 14:55:10 +02001403
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001404 if (!status)
1405 return;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001406
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001407 cp = hci_sent_cmd_data(hdev, HCI_OP_ADD_SCO);
1408 if (!cp)
1409 return;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001410
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001411 handle = __le16_to_cpu(cp->handle);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001412
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +03001413 BT_DBG("%s handle 0x%4.4x", hdev->name, handle);
Marcel Holtmann6bd57412006-11-18 22:14:22 +01001414
1415 hci_dev_lock(hdev);
1416
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001417 acl = hci_conn_hash_lookup_handle(hdev, handle);
Andrei Emeltchenko5a08ecc2011-01-11 17:20:20 +02001418 if (acl) {
1419 sco = acl->link;
1420 if (sco) {
1421 sco->state = BT_CLOSED;
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001422
Andrei Emeltchenko5a08ecc2011-01-11 17:20:20 +02001423 hci_proto_connect_cfm(sco, status);
1424 hci_conn_del(sco);
1425 }
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001426 }
Marcel Holtmann6bd57412006-11-18 22:14:22 +01001427
1428 hci_dev_unlock(hdev);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001429}
1430
Marcel Holtmannf8558552008-07-14 20:13:49 +02001431static void hci_cs_auth_requested(struct hci_dev *hdev, __u8 status)
1432{
1433 struct hci_cp_auth_requested *cp;
1434 struct hci_conn *conn;
1435
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +03001436 BT_DBG("%s status 0x%2.2x", hdev->name, status);
Marcel Holtmannf8558552008-07-14 20:13:49 +02001437
1438 if (!status)
1439 return;
1440
1441 cp = hci_sent_cmd_data(hdev, HCI_OP_AUTH_REQUESTED);
1442 if (!cp)
1443 return;
1444
1445 hci_dev_lock(hdev);
1446
1447 conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(cp->handle));
1448 if (conn) {
1449 if (conn->state == BT_CONFIG) {
1450 hci_proto_connect_cfm(conn, status);
1451 hci_conn_put(conn);
1452 }
1453 }
1454
1455 hci_dev_unlock(hdev);
1456}
1457
1458static void hci_cs_set_conn_encrypt(struct hci_dev *hdev, __u8 status)
1459{
1460 struct hci_cp_set_conn_encrypt *cp;
1461 struct hci_conn *conn;
1462
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +03001463 BT_DBG("%s status 0x%2.2x", hdev->name, status);
Marcel Holtmannf8558552008-07-14 20:13:49 +02001464
1465 if (!status)
1466 return;
1467
1468 cp = hci_sent_cmd_data(hdev, HCI_OP_SET_CONN_ENCRYPT);
1469 if (!cp)
1470 return;
1471
1472 hci_dev_lock(hdev);
1473
1474 conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(cp->handle));
1475 if (conn) {
1476 if (conn->state == BT_CONFIG) {
1477 hci_proto_connect_cfm(conn, status);
1478 hci_conn_put(conn);
1479 }
1480 }
1481
1482 hci_dev_unlock(hdev);
1483}
1484
Johan Hedberg127178d2010-11-18 22:22:29 +02001485static int hci_outgoing_auth_needed(struct hci_dev *hdev,
Gustavo Padovan807deac2012-05-17 00:36:24 -03001486 struct hci_conn *conn)
Johan Hedberg392599b2010-11-18 22:22:28 +02001487{
Johan Hedberg392599b2010-11-18 22:22:28 +02001488 if (conn->state != BT_CONFIG || !conn->out)
1489 return 0;
1490
Johan Hedberg765c2a92011-01-19 12:06:52 +05301491 if (conn->pending_sec_level == BT_SECURITY_SDP)
Johan Hedberg392599b2010-11-18 22:22:28 +02001492 return 0;
1493
1494 /* Only request authentication for SSP connections or non-SSP
Vinicius Costa Gomese9bf2bf2011-09-02 14:51:20 -03001495 * devices with sec_level HIGH or if MITM protection is requested */
Gustavo Padovan807deac2012-05-17 00:36:24 -03001496 if (!hci_conn_ssp_enabled(conn) && !(conn->auth_type & 0x01) &&
1497 conn->pending_sec_level != BT_SECURITY_HIGH)
Johan Hedberg392599b2010-11-18 22:22:28 +02001498 return 0;
1499
Johan Hedberg392599b2010-11-18 22:22:28 +02001500 return 1;
1501}
1502
Gustavo Padovan6039aa732012-05-23 04:04:18 -03001503static int hci_resolve_name(struct hci_dev *hdev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001504 struct inquiry_entry *e)
Johan Hedberg30dc78e2012-01-04 15:44:20 +02001505{
1506 struct hci_cp_remote_name_req cp;
1507
1508 memset(&cp, 0, sizeof(cp));
1509
1510 bacpy(&cp.bdaddr, &e->data.bdaddr);
1511 cp.pscan_rep_mode = e->data.pscan_rep_mode;
1512 cp.pscan_mode = e->data.pscan_mode;
1513 cp.clock_offset = e->data.clock_offset;
1514
1515 return hci_send_cmd(hdev, HCI_OP_REMOTE_NAME_REQ, sizeof(cp), &cp);
1516}
1517
Johan Hedbergb644ba32012-01-17 21:48:47 +02001518static bool hci_resolve_next_name(struct hci_dev *hdev)
Johan Hedberg30dc78e2012-01-04 15:44:20 +02001519{
1520 struct discovery_state *discov = &hdev->discovery;
1521 struct inquiry_entry *e;
1522
Johan Hedbergb644ba32012-01-17 21:48:47 +02001523 if (list_empty(&discov->resolve))
1524 return false;
1525
1526 e = hci_inquiry_cache_lookup_resolve(hdev, BDADDR_ANY, NAME_NEEDED);
Ram Malovanyc8100892012-07-19 10:26:09 +03001527 if (!e)
1528 return false;
1529
Johan Hedbergb644ba32012-01-17 21:48:47 +02001530 if (hci_resolve_name(hdev, e) == 0) {
1531 e->name_state = NAME_PENDING;
1532 return true;
1533 }
1534
1535 return false;
1536}
1537
1538static void hci_check_pending_name(struct hci_dev *hdev, struct hci_conn *conn,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001539 bdaddr_t *bdaddr, u8 *name, u8 name_len)
Johan Hedbergb644ba32012-01-17 21:48:47 +02001540{
1541 struct discovery_state *discov = &hdev->discovery;
1542 struct inquiry_entry *e;
1543
1544 if (conn && !test_and_set_bit(HCI_CONN_MGMT_CONNECTED, &conn->flags))
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001545 mgmt_device_connected(hdev, bdaddr, ACL_LINK, 0x00, 0, name,
1546 name_len, conn->dev_class);
Johan Hedbergb644ba32012-01-17 21:48:47 +02001547
1548 if (discov->state == DISCOVERY_STOPPED)
1549 return;
1550
Johan Hedberg30dc78e2012-01-04 15:44:20 +02001551 if (discov->state == DISCOVERY_STOPPING)
1552 goto discov_complete;
1553
1554 if (discov->state != DISCOVERY_RESOLVING)
1555 return;
1556
1557 e = hci_inquiry_cache_lookup_resolve(hdev, bdaddr, NAME_PENDING);
Ram Malovany7cc83802012-07-19 10:26:10 +03001558 /* If the device was not found in a list of found devices names of which
1559 * are pending. there is no need to continue resolving a next name as it
1560 * will be done upon receiving another Remote Name Request Complete
1561 * Event */
1562 if (!e)
1563 return;
1564
1565 list_del(&e->list);
1566 if (name) {
Johan Hedberg30dc78e2012-01-04 15:44:20 +02001567 e->name_state = NAME_KNOWN;
Ram Malovany7cc83802012-07-19 10:26:10 +03001568 mgmt_remote_name(hdev, bdaddr, ACL_LINK, 0x00,
1569 e->data.rssi, name, name_len);
Ram Malovanyc3e7c0d2012-07-19 10:26:11 +03001570 } else {
1571 e->name_state = NAME_NOT_KNOWN;
Johan Hedberg30dc78e2012-01-04 15:44:20 +02001572 }
1573
Johan Hedbergb644ba32012-01-17 21:48:47 +02001574 if (hci_resolve_next_name(hdev))
Johan Hedberg30dc78e2012-01-04 15:44:20 +02001575 return;
Johan Hedberg30dc78e2012-01-04 15:44:20 +02001576
1577discov_complete:
1578 hci_discovery_set_state(hdev, DISCOVERY_STOPPED);
1579}
1580
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001581static void hci_cs_remote_name_req(struct hci_dev *hdev, __u8 status)
1582{
Johan Hedberg127178d2010-11-18 22:22:29 +02001583 struct hci_cp_remote_name_req *cp;
1584 struct hci_conn *conn;
1585
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +03001586 BT_DBG("%s status 0x%2.2x", hdev->name, status);
Johan Hedberg127178d2010-11-18 22:22:29 +02001587
1588 /* If successful wait for the name req complete event before
1589 * checking for the need to do authentication */
1590 if (!status)
1591 return;
1592
1593 cp = hci_sent_cmd_data(hdev, HCI_OP_REMOTE_NAME_REQ);
1594 if (!cp)
1595 return;
1596
1597 hci_dev_lock(hdev);
1598
1599 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &cp->bdaddr);
Johan Hedbergb644ba32012-01-17 21:48:47 +02001600
1601 if (test_bit(HCI_MGMT, &hdev->dev_flags))
1602 hci_check_pending_name(hdev, conn, &cp->bdaddr, NULL, 0);
1603
Johan Hedberg79c6c702011-04-28 11:28:55 -07001604 if (!conn)
1605 goto unlock;
1606
1607 if (!hci_outgoing_auth_needed(hdev, conn))
1608 goto unlock;
1609
Johan Hedberg51a8efd2012-01-16 06:10:31 +02001610 if (!test_and_set_bit(HCI_CONN_AUTH_PEND, &conn->flags)) {
Johan Hedberg127178d2010-11-18 22:22:29 +02001611 struct hci_cp_auth_requested cp;
1612 cp.handle = __cpu_to_le16(conn->handle);
1613 hci_send_cmd(hdev, HCI_OP_AUTH_REQUESTED, sizeof(cp), &cp);
1614 }
1615
Johan Hedberg79c6c702011-04-28 11:28:55 -07001616unlock:
Johan Hedberg127178d2010-11-18 22:22:29 +02001617 hci_dev_unlock(hdev);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001618}
1619
Marcel Holtmann769be972008-07-14 20:13:49 +02001620static void hci_cs_read_remote_features(struct hci_dev *hdev, __u8 status)
1621{
1622 struct hci_cp_read_remote_features *cp;
1623 struct hci_conn *conn;
1624
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +03001625 BT_DBG("%s status 0x%2.2x", hdev->name, status);
Marcel Holtmann769be972008-07-14 20:13:49 +02001626
1627 if (!status)
1628 return;
1629
1630 cp = hci_sent_cmd_data(hdev, HCI_OP_READ_REMOTE_FEATURES);
1631 if (!cp)
1632 return;
1633
1634 hci_dev_lock(hdev);
1635
1636 conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(cp->handle));
1637 if (conn) {
1638 if (conn->state == BT_CONFIG) {
Marcel Holtmann769be972008-07-14 20:13:49 +02001639 hci_proto_connect_cfm(conn, status);
1640 hci_conn_put(conn);
1641 }
1642 }
1643
1644 hci_dev_unlock(hdev);
1645}
1646
1647static void hci_cs_read_remote_ext_features(struct hci_dev *hdev, __u8 status)
1648{
1649 struct hci_cp_read_remote_ext_features *cp;
1650 struct hci_conn *conn;
1651
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +03001652 BT_DBG("%s status 0x%2.2x", hdev->name, status);
Marcel Holtmann769be972008-07-14 20:13:49 +02001653
1654 if (!status)
1655 return;
1656
1657 cp = hci_sent_cmd_data(hdev, HCI_OP_READ_REMOTE_EXT_FEATURES);
1658 if (!cp)
1659 return;
1660
1661 hci_dev_lock(hdev);
1662
1663 conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(cp->handle));
1664 if (conn) {
1665 if (conn->state == BT_CONFIG) {
Marcel Holtmann769be972008-07-14 20:13:49 +02001666 hci_proto_connect_cfm(conn, status);
1667 hci_conn_put(conn);
1668 }
1669 }
1670
1671 hci_dev_unlock(hdev);
1672}
1673
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001674static void hci_cs_setup_sync_conn(struct hci_dev *hdev, __u8 status)
1675{
Marcel Holtmannb6a0dc82007-10-20 14:55:10 +02001676 struct hci_cp_setup_sync_conn *cp;
1677 struct hci_conn *acl, *sco;
1678 __u16 handle;
1679
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +03001680 BT_DBG("%s status 0x%2.2x", hdev->name, status);
Marcel Holtmannb6a0dc82007-10-20 14:55:10 +02001681
1682 if (!status)
1683 return;
1684
1685 cp = hci_sent_cmd_data(hdev, HCI_OP_SETUP_SYNC_CONN);
1686 if (!cp)
1687 return;
1688
1689 handle = __le16_to_cpu(cp->handle);
1690
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +03001691 BT_DBG("%s handle 0x%4.4x", hdev->name, handle);
Marcel Holtmannb6a0dc82007-10-20 14:55:10 +02001692
1693 hci_dev_lock(hdev);
1694
1695 acl = hci_conn_hash_lookup_handle(hdev, handle);
Andrei Emeltchenko5a08ecc2011-01-11 17:20:20 +02001696 if (acl) {
1697 sco = acl->link;
1698 if (sco) {
1699 sco->state = BT_CLOSED;
Marcel Holtmannb6a0dc82007-10-20 14:55:10 +02001700
Andrei Emeltchenko5a08ecc2011-01-11 17:20:20 +02001701 hci_proto_connect_cfm(sco, status);
1702 hci_conn_del(sco);
1703 }
Marcel Holtmannb6a0dc82007-10-20 14:55:10 +02001704 }
1705
1706 hci_dev_unlock(hdev);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001707}
1708
1709static void hci_cs_sniff_mode(struct hci_dev *hdev, __u8 status)
1710{
1711 struct hci_cp_sniff_mode *cp;
1712 struct hci_conn *conn;
1713
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +03001714 BT_DBG("%s status 0x%2.2x", hdev->name, status);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001715
1716 if (!status)
1717 return;
1718
1719 cp = hci_sent_cmd_data(hdev, HCI_OP_SNIFF_MODE);
1720 if (!cp)
1721 return;
1722
1723 hci_dev_lock(hdev);
1724
1725 conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(cp->handle));
Marcel Holtmanne73439d2010-07-26 10:06:00 -04001726 if (conn) {
Johan Hedberg51a8efd2012-01-16 06:10:31 +02001727 clear_bit(HCI_CONN_MODE_CHANGE_PEND, &conn->flags);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001728
Johan Hedberg51a8efd2012-01-16 06:10:31 +02001729 if (test_and_clear_bit(HCI_CONN_SCO_SETUP_PEND, &conn->flags))
Marcel Holtmanne73439d2010-07-26 10:06:00 -04001730 hci_sco_setup(conn, status);
1731 }
1732
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001733 hci_dev_unlock(hdev);
1734}
1735
1736static void hci_cs_exit_sniff_mode(struct hci_dev *hdev, __u8 status)
1737{
1738 struct hci_cp_exit_sniff_mode *cp;
1739 struct hci_conn *conn;
1740
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +03001741 BT_DBG("%s status 0x%2.2x", hdev->name, status);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001742
1743 if (!status)
1744 return;
1745
1746 cp = hci_sent_cmd_data(hdev, HCI_OP_EXIT_SNIFF_MODE);
1747 if (!cp)
1748 return;
1749
1750 hci_dev_lock(hdev);
1751
1752 conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(cp->handle));
Marcel Holtmanne73439d2010-07-26 10:06:00 -04001753 if (conn) {
Johan Hedberg51a8efd2012-01-16 06:10:31 +02001754 clear_bit(HCI_CONN_MODE_CHANGE_PEND, &conn->flags);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001755
Johan Hedberg51a8efd2012-01-16 06:10:31 +02001756 if (test_and_clear_bit(HCI_CONN_SCO_SETUP_PEND, &conn->flags))
Marcel Holtmanne73439d2010-07-26 10:06:00 -04001757 hci_sco_setup(conn, status);
1758 }
1759
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001760 hci_dev_unlock(hdev);
1761}
1762
Johan Hedberg88c3df12012-02-09 14:27:38 +02001763static void hci_cs_disconnect(struct hci_dev *hdev, u8 status)
1764{
1765 struct hci_cp_disconnect *cp;
1766 struct hci_conn *conn;
1767
1768 if (!status)
1769 return;
1770
1771 cp = hci_sent_cmd_data(hdev, HCI_OP_DISCONNECT);
1772 if (!cp)
1773 return;
1774
1775 hci_dev_lock(hdev);
1776
1777 conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(cp->handle));
1778 if (conn)
1779 mgmt_disconnect_failed(hdev, &conn->dst, conn->type,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001780 conn->dst_type, status);
Johan Hedberg88c3df12012-02-09 14:27:38 +02001781
1782 hci_dev_unlock(hdev);
1783}
1784
Ville Tervofcd89c02011-02-10 22:38:47 -03001785static void hci_cs_le_create_conn(struct hci_dev *hdev, __u8 status)
1786{
Ville Tervofcd89c02011-02-10 22:38:47 -03001787 struct hci_conn *conn;
1788
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +03001789 BT_DBG("%s status 0x%2.2x", hdev->name, status);
Ville Tervofcd89c02011-02-10 22:38:47 -03001790
Ville Tervofcd89c02011-02-10 22:38:47 -03001791 if (status) {
Andre Guedesf00a06a2012-07-27 15:10:13 -03001792 hci_dev_lock(hdev);
Ville Tervofcd89c02011-02-10 22:38:47 -03001793
Andre Guedes0c95ab72012-07-27 15:10:14 -03001794 conn = hci_conn_hash_lookup_state(hdev, LE_LINK, BT_CONNECT);
Andre Guedesf00a06a2012-07-27 15:10:13 -03001795 if (!conn) {
1796 hci_dev_unlock(hdev);
1797 return;
1798 }
1799
Andrei Emeltchenko6ed93dc2012-09-25 12:49:43 +03001800 BT_DBG("%s bdaddr %pMR conn %p", hdev->name, &conn->dst, conn);
Andre Guedesf00a06a2012-07-27 15:10:13 -03001801
1802 conn->state = BT_CLOSED;
Andre Guedes0c95ab72012-07-27 15:10:14 -03001803 mgmt_connect_failed(hdev, &conn->dst, conn->type,
Andre Guedesf00a06a2012-07-27 15:10:13 -03001804 conn->dst_type, status);
1805 hci_proto_connect_cfm(conn, status);
1806 hci_conn_del(conn);
1807
1808 hci_dev_unlock(hdev);
1809 }
Ville Tervofcd89c02011-02-10 22:38:47 -03001810}
1811
Vinicius Costa Gomesa7a595f2011-06-09 18:50:47 -03001812static void hci_cs_le_start_enc(struct hci_dev *hdev, u8 status)
1813{
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +03001814 BT_DBG("%s status 0x%2.2x", hdev->name, status);
Vinicius Costa Gomesa7a595f2011-06-09 18:50:47 -03001815}
1816
Andrei Emeltchenkoa02226d2012-09-27 17:26:19 +03001817static void hci_cs_create_phylink(struct hci_dev *hdev, u8 status)
1818{
Andrei Emeltchenko93c284e2012-09-27 17:26:20 +03001819 struct hci_cp_create_phy_link *cp;
1820
Andrei Emeltchenkoa02226d2012-09-27 17:26:19 +03001821 BT_DBG("%s status 0x%2.2x", hdev->name, status);
Andrei Emeltchenko93c284e2012-09-27 17:26:20 +03001822
Andrei Emeltchenko93c284e2012-09-27 17:26:20 +03001823 cp = hci_sent_cmd_data(hdev, HCI_OP_CREATE_PHY_LINK);
1824 if (!cp)
1825 return;
1826
Andrei Emeltchenkoe58917b2012-10-31 15:46:33 +02001827 hci_dev_lock(hdev);
1828
1829 if (status) {
1830 struct hci_conn *hcon;
1831
1832 hcon = hci_conn_hash_lookup_handle(hdev, cp->phy_handle);
1833 if (hcon)
1834 hci_conn_del(hcon);
1835 } else {
1836 amp_write_remote_assoc(hdev, cp->phy_handle);
1837 }
1838
1839 hci_dev_unlock(hdev);
Andrei Emeltchenkoa02226d2012-09-27 17:26:19 +03001840}
1841
Andrei Emeltchenko0b26ab92012-09-27 17:26:24 +03001842static void hci_cs_accept_phylink(struct hci_dev *hdev, u8 status)
1843{
1844 struct hci_cp_accept_phy_link *cp;
1845
1846 BT_DBG("%s status 0x%2.2x", hdev->name, status);
1847
1848 if (status)
1849 return;
1850
1851 cp = hci_sent_cmd_data(hdev, HCI_OP_ACCEPT_PHY_LINK);
1852 if (!cp)
1853 return;
1854
1855 amp_write_remote_assoc(hdev, cp->phy_handle);
1856}
1857
Andrei Emeltchenko5ce66b52012-10-31 15:46:30 +02001858static void hci_cs_create_logical_link(struct hci_dev *hdev, u8 status)
1859{
1860 BT_DBG("%s status 0x%2.2x", hdev->name, status);
1861}
1862
Gustavo Padovan6039aa732012-05-23 04:04:18 -03001863static void hci_inquiry_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001864{
1865 __u8 status = *((__u8 *) skb->data);
Johan Hedberg30dc78e2012-01-04 15:44:20 +02001866 struct discovery_state *discov = &hdev->discovery;
1867 struct inquiry_entry *e;
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001868
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +03001869 BT_DBG("%s status 0x%2.2x", hdev->name, status);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001870
Johan Hedberg23bb5762010-12-21 23:01:27 +02001871 hci_req_complete(hdev, HCI_OP_INQUIRY, status);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001872
1873 hci_conn_check_pending(hdev);
Andre Guedes89352e72011-11-04 14:16:53 -03001874
1875 if (!test_and_clear_bit(HCI_INQUIRY, &hdev->flags))
1876 return;
1877
Johan Hedberga8b2d5c2012-01-08 23:11:15 +02001878 if (!test_bit(HCI_MGMT, &hdev->dev_flags))
Johan Hedberg30dc78e2012-01-04 15:44:20 +02001879 return;
1880
Johan Hedberg56e5cb82011-11-08 20:40:16 +02001881 hci_dev_lock(hdev);
Johan Hedberg30dc78e2012-01-04 15:44:20 +02001882
Andre Guedes343f9352012-02-17 20:39:37 -03001883 if (discov->state != DISCOVERY_FINDING)
Johan Hedberg30dc78e2012-01-04 15:44:20 +02001884 goto unlock;
1885
1886 if (list_empty(&discov->resolve)) {
1887 hci_discovery_set_state(hdev, DISCOVERY_STOPPED);
1888 goto unlock;
1889 }
1890
1891 e = hci_inquiry_cache_lookup_resolve(hdev, BDADDR_ANY, NAME_NEEDED);
1892 if (e && hci_resolve_name(hdev, e) == 0) {
1893 e->name_state = NAME_PENDING;
1894 hci_discovery_set_state(hdev, DISCOVERY_RESOLVING);
1895 } else {
1896 hci_discovery_set_state(hdev, DISCOVERY_STOPPED);
1897 }
1898
1899unlock:
Johan Hedberg56e5cb82011-11-08 20:40:16 +02001900 hci_dev_unlock(hdev);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001901}
1902
Gustavo Padovan6039aa732012-05-23 04:04:18 -03001903static void hci_inquiry_result_evt(struct hci_dev *hdev, struct sk_buff *skb)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001904{
Marcel Holtmann45bb4bf2005-08-09 20:27:49 -07001905 struct inquiry_data data;
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001906 struct inquiry_info *info = (void *) (skb->data + 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001907 int num_rsp = *((__u8 *) skb->data);
1908
1909 BT_DBG("%s num_rsp %d", hdev->name, num_rsp);
1910
Marcel Holtmann45bb4bf2005-08-09 20:27:49 -07001911 if (!num_rsp)
1912 return;
1913
Andre Guedes1519cc12012-03-21 00:03:38 -03001914 if (test_bit(HCI_PERIODIC_INQ, &hdev->dev_flags))
1915 return;
1916
Linus Torvalds1da177e2005-04-16 15:20:36 -07001917 hci_dev_lock(hdev);
Marcel Holtmann45bb4bf2005-08-09 20:27:49 -07001918
Johan Hedberge17acd42011-03-30 23:57:16 +03001919 for (; num_rsp; num_rsp--, info++) {
Johan Hedberg388fc8f2012-02-23 00:38:59 +02001920 bool name_known, ssp;
Johan Hedberg31754052012-01-04 13:39:52 +02001921
Linus Torvalds1da177e2005-04-16 15:20:36 -07001922 bacpy(&data.bdaddr, &info->bdaddr);
1923 data.pscan_rep_mode = info->pscan_rep_mode;
1924 data.pscan_period_mode = info->pscan_period_mode;
1925 data.pscan_mode = info->pscan_mode;
1926 memcpy(data.dev_class, info->dev_class, 3);
1927 data.clock_offset = info->clock_offset;
1928 data.rssi = 0x00;
Marcel Holtmann41a96212008-07-14 20:13:48 +02001929 data.ssp_mode = 0x00;
Johan Hedberg31754052012-01-04 13:39:52 +02001930
Johan Hedberg388fc8f2012-02-23 00:38:59 +02001931 name_known = hci_inquiry_cache_update(hdev, &data, false, &ssp);
Johan Hedberg48264f02011-11-09 13:58:58 +02001932 mgmt_device_found(hdev, &info->bdaddr, ACL_LINK, 0x00,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001933 info->dev_class, 0, !name_known, ssp, NULL,
1934 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001935 }
Marcel Holtmann45bb4bf2005-08-09 20:27:49 -07001936
Linus Torvalds1da177e2005-04-16 15:20:36 -07001937 hci_dev_unlock(hdev);
1938}
1939
Gustavo Padovan6039aa732012-05-23 04:04:18 -03001940static void hci_conn_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001941{
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001942 struct hci_ev_conn_complete *ev = (void *) skb->data;
1943 struct hci_conn *conn;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001944
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001945 BT_DBG("%s", hdev->name);
Marcel Holtmann45bb4bf2005-08-09 20:27:49 -07001946
Linus Torvalds1da177e2005-04-16 15:20:36 -07001947 hci_dev_lock(hdev);
Marcel Holtmann45bb4bf2005-08-09 20:27:49 -07001948
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001949 conn = hci_conn_hash_lookup_ba(hdev, ev->link_type, &ev->bdaddr);
Marcel Holtmann94992372009-04-19 19:30:03 +02001950 if (!conn) {
1951 if (ev->link_type != SCO_LINK)
1952 goto unlock;
1953
1954 conn = hci_conn_hash_lookup_ba(hdev, ESCO_LINK, &ev->bdaddr);
1955 if (!conn)
1956 goto unlock;
1957
1958 conn->type = SCO_LINK;
1959 }
Marcel Holtmann45bb4bf2005-08-09 20:27:49 -07001960
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001961 if (!ev->status) {
1962 conn->handle = __le16_to_cpu(ev->handle);
Marcel Holtmann769be972008-07-14 20:13:49 +02001963
1964 if (conn->type == ACL_LINK) {
1965 conn->state = BT_CONFIG;
1966 hci_conn_hold(conn);
Szymon Janca9ea3ed2012-07-19 14:46:08 +02001967
1968 if (!conn->out && !hci_conn_ssp_enabled(conn) &&
1969 !hci_find_link_key(hdev, &ev->bdaddr))
1970 conn->disc_timeout = HCI_PAIRING_TIMEOUT;
1971 else
1972 conn->disc_timeout = HCI_DISCONN_TIMEOUT;
Marcel Holtmann769be972008-07-14 20:13:49 +02001973 } else
1974 conn->state = BT_CONNECTED;
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001975
Marcel Holtmann9eba32b2009-08-22 14:19:26 -07001976 hci_conn_hold_device(conn);
Marcel Holtmann7d0db0a2008-07-14 20:13:51 +02001977 hci_conn_add_sysfs(conn);
1978
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001979 if (test_bit(HCI_AUTH, &hdev->flags))
1980 conn->link_mode |= HCI_LM_AUTH;
1981
1982 if (test_bit(HCI_ENCRYPT, &hdev->flags))
1983 conn->link_mode |= HCI_LM_ENCRYPT;
1984
1985 /* Get remote features */
1986 if (conn->type == ACL_LINK) {
1987 struct hci_cp_read_remote_features cp;
1988 cp.handle = ev->handle;
Marcel Holtmann769be972008-07-14 20:13:49 +02001989 hci_send_cmd(hdev, HCI_OP_READ_REMOTE_FEATURES,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001990 sizeof(cp), &cp);
Marcel Holtmann45bb4bf2005-08-09 20:27:49 -07001991 }
Marcel Holtmann45bb4bf2005-08-09 20:27:49 -07001992
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001993 /* Set packet type for incoming connection */
Andrei Emeltchenkod095c1e2011-12-01 14:33:27 +02001994 if (!conn->out && hdev->hci_ver < BLUETOOTH_VER_2_0) {
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001995 struct hci_cp_change_conn_ptype cp;
1996 cp.handle = ev->handle;
Marcel Holtmanna8746412008-07-14 20:13:46 +02001997 cp.pkt_type = cpu_to_le16(conn->pkt_type);
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001998 hci_send_cmd(hdev, HCI_OP_CHANGE_CONN_PTYPE, sizeof(cp),
1999 &cp);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002000 }
Johan Hedberg17d5c042011-01-22 06:09:08 +02002001 } else {
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002002 conn->state = BT_CLOSED;
Johan Hedberg17d5c042011-01-22 06:09:08 +02002003 if (conn->type == ACL_LINK)
Johan Hedberg744cf192011-11-08 20:40:14 +02002004 mgmt_connect_failed(hdev, &ev->bdaddr, conn->type,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002005 conn->dst_type, ev->status);
Johan Hedberg17d5c042011-01-22 06:09:08 +02002006 }
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002007
Marcel Holtmanne73439d2010-07-26 10:06:00 -04002008 if (conn->type == ACL_LINK)
2009 hci_sco_setup(conn, ev->status);
Marcel Holtmann45bb4bf2005-08-09 20:27:49 -07002010
Marcel Holtmann769be972008-07-14 20:13:49 +02002011 if (ev->status) {
2012 hci_proto_connect_cfm(conn, ev->status);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002013 hci_conn_del(conn);
Marcel Holtmannc89b6e62009-01-15 21:57:03 +01002014 } else if (ev->link_type != ACL_LINK)
2015 hci_proto_connect_cfm(conn, ev->status);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002016
2017unlock:
Linus Torvalds1da177e2005-04-16 15:20:36 -07002018 hci_dev_unlock(hdev);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002019
2020 hci_conn_check_pending(hdev);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002021}
2022
Gustavo Padovan6039aa732012-05-23 04:04:18 -03002023static void hci_conn_request_evt(struct hci_dev *hdev, struct sk_buff *skb)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002024{
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002025 struct hci_ev_conn_request *ev = (void *) skb->data;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002026 int mask = hdev->link_mode;
2027
Andrei Emeltchenko6ed93dc2012-09-25 12:49:43 +03002028 BT_DBG("%s bdaddr %pMR type 0x%x", hdev->name, &ev->bdaddr,
Gustavo Padovan807deac2012-05-17 00:36:24 -03002029 ev->link_type);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002030
2031 mask |= hci_proto_connect_ind(hdev, &ev->bdaddr, ev->link_type);
2032
Szymon Janc138d22e2011-02-17 16:44:23 +01002033 if ((mask & HCI_LM_ACCEPT) &&
Gustavo Padovan807deac2012-05-17 00:36:24 -03002034 !hci_blacklist_lookup(hdev, &ev->bdaddr)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002035 /* Connection accepted */
Marcel Holtmannc7bdd502008-07-14 20:13:47 +02002036 struct inquiry_entry *ie;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002037 struct hci_conn *conn;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002038
2039 hci_dev_lock(hdev);
Marcel Holtmannb6a0dc82007-10-20 14:55:10 +02002040
Andrei Emeltchenkocc11b9c2010-11-22 13:21:37 +02002041 ie = hci_inquiry_cache_lookup(hdev, &ev->bdaddr);
2042 if (ie)
Marcel Holtmannc7bdd502008-07-14 20:13:47 +02002043 memcpy(ie->data.dev_class, ev->dev_class, 3);
2044
Gustavo Padovan8fc9ced2012-05-23 04:04:21 -03002045 conn = hci_conn_hash_lookup_ba(hdev, ev->link_type,
2046 &ev->bdaddr);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002047 if (!conn) {
Andrei Emeltchenkocc11b9c2010-11-22 13:21:37 +02002048 conn = hci_conn_add(hdev, ev->link_type, &ev->bdaddr);
2049 if (!conn) {
Gustavo F. Padovan893ef972010-07-18 15:13:37 -03002050 BT_ERR("No memory for new connection");
Linus Torvalds1da177e2005-04-16 15:20:36 -07002051 hci_dev_unlock(hdev);
2052 return;
2053 }
2054 }
Marcel Holtmannb6a0dc82007-10-20 14:55:10 +02002055
Linus Torvalds1da177e2005-04-16 15:20:36 -07002056 memcpy(conn->dev_class, ev->dev_class, 3);
2057 conn->state = BT_CONNECT;
Marcel Holtmannb6a0dc82007-10-20 14:55:10 +02002058
Linus Torvalds1da177e2005-04-16 15:20:36 -07002059 hci_dev_unlock(hdev);
2060
Marcel Holtmannb6a0dc82007-10-20 14:55:10 +02002061 if (ev->link_type == ACL_LINK || !lmp_esco_capable(hdev)) {
2062 struct hci_cp_accept_conn_req cp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002063
Marcel Holtmannb6a0dc82007-10-20 14:55:10 +02002064 bacpy(&cp.bdaddr, &ev->bdaddr);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002065
Marcel Holtmannb6a0dc82007-10-20 14:55:10 +02002066 if (lmp_rswitch_capable(hdev) && (mask & HCI_LM_MASTER))
2067 cp.role = 0x00; /* Become master */
2068 else
2069 cp.role = 0x01; /* Remain slave */
2070
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002071 hci_send_cmd(hdev, HCI_OP_ACCEPT_CONN_REQ, sizeof(cp),
2072 &cp);
Marcel Holtmannb6a0dc82007-10-20 14:55:10 +02002073 } else {
2074 struct hci_cp_accept_sync_conn_req cp;
2075
2076 bacpy(&cp.bdaddr, &ev->bdaddr);
Marcel Holtmanna8746412008-07-14 20:13:46 +02002077 cp.pkt_type = cpu_to_le16(conn->pkt_type);
Marcel Holtmannb6a0dc82007-10-20 14:55:10 +02002078
Andrei Emeltchenko82781e62012-05-25 11:38:27 +03002079 cp.tx_bandwidth = __constant_cpu_to_le32(0x00001f40);
2080 cp.rx_bandwidth = __constant_cpu_to_le32(0x00001f40);
2081 cp.max_latency = __constant_cpu_to_le16(0xffff);
Marcel Holtmannb6a0dc82007-10-20 14:55:10 +02002082 cp.content_format = cpu_to_le16(hdev->voice_setting);
2083 cp.retrans_effort = 0xff;
2084
2085 hci_send_cmd(hdev, HCI_OP_ACCEPT_SYNC_CONN_REQ,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002086 sizeof(cp), &cp);
Marcel Holtmannb6a0dc82007-10-20 14:55:10 +02002087 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002088 } else {
2089 /* Connection rejected */
2090 struct hci_cp_reject_conn_req cp;
2091
2092 bacpy(&cp.bdaddr, &ev->bdaddr);
Andrei Emeltchenko9f5a0d72011-11-07 14:20:25 +02002093 cp.reason = HCI_ERROR_REJ_BAD_ADDR;
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002094 hci_send_cmd(hdev, HCI_OP_REJECT_CONN_REQ, sizeof(cp), &cp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002095 }
2096}
2097
Mikel Astizf0d6a0e2012-08-09 09:52:30 +02002098static u8 hci_to_mgmt_reason(u8 err)
2099{
2100 switch (err) {
2101 case HCI_ERROR_CONNECTION_TIMEOUT:
2102 return MGMT_DEV_DISCONN_TIMEOUT;
2103 case HCI_ERROR_REMOTE_USER_TERM:
2104 case HCI_ERROR_REMOTE_LOW_RESOURCES:
2105 case HCI_ERROR_REMOTE_POWER_OFF:
2106 return MGMT_DEV_DISCONN_REMOTE;
2107 case HCI_ERROR_LOCAL_HOST_TERM:
2108 return MGMT_DEV_DISCONN_LOCAL_HOST;
2109 default:
2110 return MGMT_DEV_DISCONN_UNKNOWN;
2111 }
2112}
2113
Gustavo Padovan6039aa732012-05-23 04:04:18 -03002114static void hci_disconn_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002115{
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002116 struct hci_ev_disconn_complete *ev = (void *) skb->data;
Marcel Holtmann04837f62006-07-03 10:02:33 +02002117 struct hci_conn *conn;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002118
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +03002119 BT_DBG("%s status 0x%2.2x", hdev->name, ev->status);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002120
Linus Torvalds1da177e2005-04-16 15:20:36 -07002121 hci_dev_lock(hdev);
2122
Marcel Holtmann04837f62006-07-03 10:02:33 +02002123 conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
Johan Hedbergf7520542011-01-20 12:34:39 +02002124 if (!conn)
2125 goto unlock;
Marcel Holtmann7d0db0a2008-07-14 20:13:51 +02002126
Johan Hedberg37d9ef72011-11-10 15:54:39 +02002127 if (ev->status == 0)
2128 conn->state = BT_CLOSED;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002129
Johan Hedbergb644ba32012-01-17 21:48:47 +02002130 if (test_and_clear_bit(HCI_CONN_MGMT_CONNECTED, &conn->flags) &&
Gustavo Padovan807deac2012-05-17 00:36:24 -03002131 (conn->type == ACL_LINK || conn->type == LE_LINK)) {
Mikel Astizf0d6a0e2012-08-09 09:52:30 +02002132 if (ev->status) {
Johan Hedberg88c3df12012-02-09 14:27:38 +02002133 mgmt_disconnect_failed(hdev, &conn->dst, conn->type,
Gustavo Padovan807deac2012-05-17 00:36:24 -03002134 conn->dst_type, ev->status);
Mikel Astizf0d6a0e2012-08-09 09:52:30 +02002135 } else {
2136 u8 reason = hci_to_mgmt_reason(ev->reason);
2137
Johan Hedbergafc747a2012-01-15 18:11:07 +02002138 mgmt_device_disconnected(hdev, &conn->dst, conn->type,
Mikel Astizf0d6a0e2012-08-09 09:52:30 +02002139 conn->dst_type, reason);
2140 }
Johan Hedberg37d9ef72011-11-10 15:54:39 +02002141 }
Johan Hedbergf7520542011-01-20 12:34:39 +02002142
Johan Hedberg37d9ef72011-11-10 15:54:39 +02002143 if (ev->status == 0) {
Vishal Agarwal6ec5bca2012-04-16 14:44:44 +05302144 if (conn->type == ACL_LINK && conn->flush_key)
2145 hci_remove_link_key(hdev, &conn->dst);
Johan Hedberg37d9ef72011-11-10 15:54:39 +02002146 hci_proto_disconn_cfm(conn, ev->reason);
2147 hci_conn_del(conn);
2148 }
Johan Hedbergf7520542011-01-20 12:34:39 +02002149
2150unlock:
Linus Torvalds1da177e2005-04-16 15:20:36 -07002151 hci_dev_unlock(hdev);
2152}
2153
Gustavo Padovan6039aa732012-05-23 04:04:18 -03002154static void hci_auth_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002155{
2156 struct hci_ev_auth_complete *ev = (void *) skb->data;
2157 struct hci_conn *conn;
2158
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +03002159 BT_DBG("%s status 0x%2.2x", hdev->name, ev->status);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002160
2161 hci_dev_lock(hdev);
2162
2163 conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
Waldemar Rymarkiewiczd7556e22011-05-31 15:49:26 +02002164 if (!conn)
2165 goto unlock;
2166
2167 if (!ev->status) {
Johan Hedbergaa64a8b2012-01-18 21:33:12 +02002168 if (!hci_conn_ssp_enabled(conn) &&
Gustavo Padovan807deac2012-05-17 00:36:24 -03002169 test_bit(HCI_CONN_REAUTH_PEND, &conn->flags)) {
Waldemar Rymarkiewiczd7556e22011-05-31 15:49:26 +02002170 BT_INFO("re-auth of legacy device is not possible.");
Johan Hedberg2a611692011-02-19 12:06:00 -03002171 } else {
Waldemar Rymarkiewiczd7556e22011-05-31 15:49:26 +02002172 conn->link_mode |= HCI_LM_AUTH;
2173 conn->sec_level = conn->pending_sec_level;
Johan Hedberg2a611692011-02-19 12:06:00 -03002174 }
Waldemar Rymarkiewiczd7556e22011-05-31 15:49:26 +02002175 } else {
Johan Hedbergbab73cb2012-02-09 16:07:29 +02002176 mgmt_auth_failed(hdev, &conn->dst, conn->type, conn->dst_type,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002177 ev->status);
Waldemar Rymarkiewiczd7556e22011-05-31 15:49:26 +02002178 }
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002179
Johan Hedberg51a8efd2012-01-16 06:10:31 +02002180 clear_bit(HCI_CONN_AUTH_PEND, &conn->flags);
2181 clear_bit(HCI_CONN_REAUTH_PEND, &conn->flags);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002182
Waldemar Rymarkiewiczd7556e22011-05-31 15:49:26 +02002183 if (conn->state == BT_CONFIG) {
Johan Hedbergaa64a8b2012-01-18 21:33:12 +02002184 if (!ev->status && hci_conn_ssp_enabled(conn)) {
Waldemar Rymarkiewiczd7556e22011-05-31 15:49:26 +02002185 struct hci_cp_set_conn_encrypt cp;
2186 cp.handle = ev->handle;
2187 cp.encrypt = 0x01;
2188 hci_send_cmd(hdev, HCI_OP_SET_CONN_ENCRYPT, sizeof(cp),
Gustavo Padovan807deac2012-05-17 00:36:24 -03002189 &cp);
Marcel Holtmann052b30b2009-04-26 20:01:22 +02002190 } else {
Waldemar Rymarkiewiczd7556e22011-05-31 15:49:26 +02002191 conn->state = BT_CONNECTED;
2192 hci_proto_connect_cfm(conn, ev->status);
Marcel Holtmann052b30b2009-04-26 20:01:22 +02002193 hci_conn_put(conn);
2194 }
Waldemar Rymarkiewiczd7556e22011-05-31 15:49:26 +02002195 } else {
2196 hci_auth_cfm(conn, ev->status);
Marcel Holtmann052b30b2009-04-26 20:01:22 +02002197
Waldemar Rymarkiewiczd7556e22011-05-31 15:49:26 +02002198 hci_conn_hold(conn);
2199 conn->disc_timeout = HCI_DISCONN_TIMEOUT;
2200 hci_conn_put(conn);
2201 }
2202
Johan Hedberg51a8efd2012-01-16 06:10:31 +02002203 if (test_bit(HCI_CONN_ENCRYPT_PEND, &conn->flags)) {
Waldemar Rymarkiewiczd7556e22011-05-31 15:49:26 +02002204 if (!ev->status) {
2205 struct hci_cp_set_conn_encrypt cp;
2206 cp.handle = ev->handle;
2207 cp.encrypt = 0x01;
2208 hci_send_cmd(hdev, HCI_OP_SET_CONN_ENCRYPT, sizeof(cp),
Gustavo Padovan807deac2012-05-17 00:36:24 -03002209 &cp);
Waldemar Rymarkiewiczd7556e22011-05-31 15:49:26 +02002210 } else {
Johan Hedberg51a8efd2012-01-16 06:10:31 +02002211 clear_bit(HCI_CONN_ENCRYPT_PEND, &conn->flags);
Waldemar Rymarkiewiczd7556e22011-05-31 15:49:26 +02002212 hci_encrypt_cfm(conn, ev->status, 0x00);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002213 }
2214 }
2215
Waldemar Rymarkiewiczd7556e22011-05-31 15:49:26 +02002216unlock:
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002217 hci_dev_unlock(hdev);
2218}
2219
Gustavo Padovan6039aa732012-05-23 04:04:18 -03002220static void hci_remote_name_evt(struct hci_dev *hdev, struct sk_buff *skb)
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002221{
Johan Hedberg127178d2010-11-18 22:22:29 +02002222 struct hci_ev_remote_name *ev = (void *) skb->data;
2223 struct hci_conn *conn;
2224
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002225 BT_DBG("%s", hdev->name);
2226
2227 hci_conn_check_pending(hdev);
Johan Hedberg127178d2010-11-18 22:22:29 +02002228
2229 hci_dev_lock(hdev);
2230
2231 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
Johan Hedbergb644ba32012-01-17 21:48:47 +02002232
2233 if (!test_bit(HCI_MGMT, &hdev->dev_flags))
2234 goto check_auth;
2235
2236 if (ev->status == 0)
2237 hci_check_pending_name(hdev, conn, &ev->bdaddr, ev->name,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002238 strnlen(ev->name, HCI_MAX_NAME_LENGTH));
Johan Hedbergb644ba32012-01-17 21:48:47 +02002239 else
2240 hci_check_pending_name(hdev, conn, &ev->bdaddr, NULL, 0);
2241
2242check_auth:
Johan Hedberg79c6c702011-04-28 11:28:55 -07002243 if (!conn)
2244 goto unlock;
2245
2246 if (!hci_outgoing_auth_needed(hdev, conn))
2247 goto unlock;
2248
Johan Hedberg51a8efd2012-01-16 06:10:31 +02002249 if (!test_and_set_bit(HCI_CONN_AUTH_PEND, &conn->flags)) {
Johan Hedberg127178d2010-11-18 22:22:29 +02002250 struct hci_cp_auth_requested cp;
2251 cp.handle = __cpu_to_le16(conn->handle);
2252 hci_send_cmd(hdev, HCI_OP_AUTH_REQUESTED, sizeof(cp), &cp);
2253 }
2254
Johan Hedberg79c6c702011-04-28 11:28:55 -07002255unlock:
Johan Hedberg127178d2010-11-18 22:22:29 +02002256 hci_dev_unlock(hdev);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002257}
2258
Gustavo Padovan6039aa732012-05-23 04:04:18 -03002259static void hci_encrypt_change_evt(struct hci_dev *hdev, struct sk_buff *skb)
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002260{
2261 struct hci_ev_encrypt_change *ev = (void *) skb->data;
2262 struct hci_conn *conn;
2263
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +03002264 BT_DBG("%s status 0x%2.2x", hdev->name, ev->status);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002265
2266 hci_dev_lock(hdev);
2267
2268 conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
2269 if (conn) {
2270 if (!ev->status) {
Marcel Holtmannae293192008-07-14 20:13:45 +02002271 if (ev->encrypt) {
2272 /* Encryption implies authentication */
2273 conn->link_mode |= HCI_LM_AUTH;
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002274 conn->link_mode |= HCI_LM_ENCRYPT;
Vinicius Costa Gomesda85e5e2011-06-09 18:50:53 -03002275 conn->sec_level = conn->pending_sec_level;
Marcel Holtmannae293192008-07-14 20:13:45 +02002276 } else
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002277 conn->link_mode &= ~HCI_LM_ENCRYPT;
2278 }
2279
Johan Hedberg51a8efd2012-01-16 06:10:31 +02002280 clear_bit(HCI_CONN_ENCRYPT_PEND, &conn->flags);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002281
Gustavo Padovana7d77232012-05-13 03:20:07 -03002282 if (ev->status && conn->state == BT_CONNECTED) {
Gustavo Padovand839c812012-05-16 12:17:12 -03002283 hci_acl_disconn(conn, HCI_ERROR_AUTH_FAILURE);
Gustavo Padovana7d77232012-05-13 03:20:07 -03002284 hci_conn_put(conn);
2285 goto unlock;
2286 }
2287
Marcel Holtmannf8558552008-07-14 20:13:49 +02002288 if (conn->state == BT_CONFIG) {
2289 if (!ev->status)
2290 conn->state = BT_CONNECTED;
2291
2292 hci_proto_connect_cfm(conn, ev->status);
2293 hci_conn_put(conn);
2294 } else
2295 hci_encrypt_cfm(conn, ev->status, ev->encrypt);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002296 }
2297
Gustavo Padovana7d77232012-05-13 03:20:07 -03002298unlock:
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002299 hci_dev_unlock(hdev);
2300}
2301
Gustavo Padovan6039aa732012-05-23 04:04:18 -03002302static void hci_change_link_key_complete_evt(struct hci_dev *hdev,
2303 struct sk_buff *skb)
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002304{
2305 struct hci_ev_change_link_key_complete *ev = (void *) skb->data;
2306 struct hci_conn *conn;
2307
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +03002308 BT_DBG("%s status 0x%2.2x", hdev->name, ev->status);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002309
2310 hci_dev_lock(hdev);
2311
2312 conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
2313 if (conn) {
2314 if (!ev->status)
2315 conn->link_mode |= HCI_LM_SECURE;
2316
Johan Hedberg51a8efd2012-01-16 06:10:31 +02002317 clear_bit(HCI_CONN_AUTH_PEND, &conn->flags);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002318
2319 hci_key_change_cfm(conn, ev->status);
2320 }
2321
2322 hci_dev_unlock(hdev);
2323}
2324
Gustavo Padovan6039aa732012-05-23 04:04:18 -03002325static void hci_remote_features_evt(struct hci_dev *hdev,
2326 struct sk_buff *skb)
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002327{
2328 struct hci_ev_remote_features *ev = (void *) skb->data;
2329 struct hci_conn *conn;
2330
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +03002331 BT_DBG("%s status 0x%2.2x", hdev->name, ev->status);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002332
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002333 hci_dev_lock(hdev);
2334
2335 conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
Johan Hedbergccd556f2010-11-10 17:11:51 +02002336 if (!conn)
2337 goto unlock;
Marcel Holtmann769be972008-07-14 20:13:49 +02002338
Johan Hedbergccd556f2010-11-10 17:11:51 +02002339 if (!ev->status)
2340 memcpy(conn->features, ev->features, 8);
2341
2342 if (conn->state != BT_CONFIG)
2343 goto unlock;
2344
2345 if (!ev->status && lmp_ssp_capable(hdev) && lmp_ssp_capable(conn)) {
2346 struct hci_cp_read_remote_ext_features cp;
2347 cp.handle = ev->handle;
2348 cp.page = 0x01;
2349 hci_send_cmd(hdev, HCI_OP_READ_REMOTE_EXT_FEATURES,
Gustavo Padovan807deac2012-05-17 00:36:24 -03002350 sizeof(cp), &cp);
Johan Hedberg392599b2010-11-18 22:22:28 +02002351 goto unlock;
2352 }
2353
Johan Hedberg671267b2012-05-12 16:11:50 -03002354 if (!ev->status && !test_bit(HCI_CONN_MGMT_CONNECTED, &conn->flags)) {
Johan Hedberg127178d2010-11-18 22:22:29 +02002355 struct hci_cp_remote_name_req cp;
2356 memset(&cp, 0, sizeof(cp));
2357 bacpy(&cp.bdaddr, &conn->dst);
2358 cp.pscan_rep_mode = 0x02;
2359 hci_send_cmd(hdev, HCI_OP_REMOTE_NAME_REQ, sizeof(cp), &cp);
Johan Hedbergb644ba32012-01-17 21:48:47 +02002360 } else if (!test_and_set_bit(HCI_CONN_MGMT_CONNECTED, &conn->flags))
2361 mgmt_device_connected(hdev, &conn->dst, conn->type,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002362 conn->dst_type, 0, NULL, 0,
2363 conn->dev_class);
Johan Hedberg392599b2010-11-18 22:22:28 +02002364
Johan Hedberg127178d2010-11-18 22:22:29 +02002365 if (!hci_outgoing_auth_needed(hdev, conn)) {
Johan Hedbergccd556f2010-11-10 17:11:51 +02002366 conn->state = BT_CONNECTED;
2367 hci_proto_connect_cfm(conn, ev->status);
2368 hci_conn_put(conn);
Marcel Holtmann769be972008-07-14 20:13:49 +02002369 }
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002370
Johan Hedbergccd556f2010-11-10 17:11:51 +02002371unlock:
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002372 hci_dev_unlock(hdev);
2373}
2374
Gustavo Padovan6039aa732012-05-23 04:04:18 -03002375static void hci_remote_version_evt(struct hci_dev *hdev, struct sk_buff *skb)
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002376{
2377 BT_DBG("%s", hdev->name);
2378}
2379
Gustavo Padovan6039aa732012-05-23 04:04:18 -03002380static void hci_qos_setup_complete_evt(struct hci_dev *hdev,
2381 struct sk_buff *skb)
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002382{
2383 BT_DBG("%s", hdev->name);
2384}
2385
Gustavo Padovan6039aa732012-05-23 04:04:18 -03002386static void hci_cmd_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002387{
2388 struct hci_ev_cmd_complete *ev = (void *) skb->data;
2389 __u16 opcode;
2390
2391 skb_pull(skb, sizeof(*ev));
2392
2393 opcode = __le16_to_cpu(ev->opcode);
2394
2395 switch (opcode) {
2396 case HCI_OP_INQUIRY_CANCEL:
2397 hci_cc_inquiry_cancel(hdev, skb);
2398 break;
2399
Andre Guedes4d934832012-03-21 00:03:35 -03002400 case HCI_OP_PERIODIC_INQ:
2401 hci_cc_periodic_inq(hdev, skb);
2402 break;
2403
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002404 case HCI_OP_EXIT_PERIODIC_INQ:
2405 hci_cc_exit_periodic_inq(hdev, skb);
2406 break;
2407
2408 case HCI_OP_REMOTE_NAME_REQ_CANCEL:
2409 hci_cc_remote_name_req_cancel(hdev, skb);
2410 break;
2411
2412 case HCI_OP_ROLE_DISCOVERY:
2413 hci_cc_role_discovery(hdev, skb);
2414 break;
2415
Marcel Holtmanne4e8e372008-07-14 20:13:47 +02002416 case HCI_OP_READ_LINK_POLICY:
2417 hci_cc_read_link_policy(hdev, skb);
2418 break;
2419
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002420 case HCI_OP_WRITE_LINK_POLICY:
2421 hci_cc_write_link_policy(hdev, skb);
2422 break;
2423
Marcel Holtmanne4e8e372008-07-14 20:13:47 +02002424 case HCI_OP_READ_DEF_LINK_POLICY:
2425 hci_cc_read_def_link_policy(hdev, skb);
2426 break;
2427
2428 case HCI_OP_WRITE_DEF_LINK_POLICY:
2429 hci_cc_write_def_link_policy(hdev, skb);
2430 break;
2431
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002432 case HCI_OP_RESET:
2433 hci_cc_reset(hdev, skb);
2434 break;
2435
2436 case HCI_OP_WRITE_LOCAL_NAME:
2437 hci_cc_write_local_name(hdev, skb);
2438 break;
2439
2440 case HCI_OP_READ_LOCAL_NAME:
2441 hci_cc_read_local_name(hdev, skb);
2442 break;
2443
2444 case HCI_OP_WRITE_AUTH_ENABLE:
2445 hci_cc_write_auth_enable(hdev, skb);
2446 break;
2447
2448 case HCI_OP_WRITE_ENCRYPT_MODE:
2449 hci_cc_write_encrypt_mode(hdev, skb);
2450 break;
2451
2452 case HCI_OP_WRITE_SCAN_ENABLE:
2453 hci_cc_write_scan_enable(hdev, skb);
2454 break;
2455
2456 case HCI_OP_READ_CLASS_OF_DEV:
2457 hci_cc_read_class_of_dev(hdev, skb);
2458 break;
2459
2460 case HCI_OP_WRITE_CLASS_OF_DEV:
2461 hci_cc_write_class_of_dev(hdev, skb);
2462 break;
2463
2464 case HCI_OP_READ_VOICE_SETTING:
2465 hci_cc_read_voice_setting(hdev, skb);
2466 break;
2467
2468 case HCI_OP_WRITE_VOICE_SETTING:
2469 hci_cc_write_voice_setting(hdev, skb);
2470 break;
2471
2472 case HCI_OP_HOST_BUFFER_SIZE:
2473 hci_cc_host_buffer_size(hdev, skb);
2474 break;
2475
Marcel Holtmann333140b2008-07-14 20:13:48 +02002476 case HCI_OP_WRITE_SSP_MODE:
2477 hci_cc_write_ssp_mode(hdev, skb);
2478 break;
2479
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002480 case HCI_OP_READ_LOCAL_VERSION:
2481 hci_cc_read_local_version(hdev, skb);
2482 break;
2483
2484 case HCI_OP_READ_LOCAL_COMMANDS:
2485 hci_cc_read_local_commands(hdev, skb);
2486 break;
2487
2488 case HCI_OP_READ_LOCAL_FEATURES:
2489 hci_cc_read_local_features(hdev, skb);
2490 break;
2491
Andre Guedes971e3a42011-06-30 19:20:52 -03002492 case HCI_OP_READ_LOCAL_EXT_FEATURES:
2493 hci_cc_read_local_ext_features(hdev, skb);
2494 break;
2495
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002496 case HCI_OP_READ_BUFFER_SIZE:
2497 hci_cc_read_buffer_size(hdev, skb);
2498 break;
2499
2500 case HCI_OP_READ_BD_ADDR:
2501 hci_cc_read_bd_addr(hdev, skb);
2502 break;
2503
Andrei Emeltchenko350ee4c2011-12-07 15:56:51 +02002504 case HCI_OP_READ_DATA_BLOCK_SIZE:
2505 hci_cc_read_data_block_size(hdev, skb);
2506 break;
2507
Johan Hedberg23bb5762010-12-21 23:01:27 +02002508 case HCI_OP_WRITE_CA_TIMEOUT:
2509 hci_cc_write_ca_timeout(hdev, skb);
2510 break;
2511
Andrei Emeltchenko1e89cff2011-11-24 14:52:02 +02002512 case HCI_OP_READ_FLOW_CONTROL_MODE:
2513 hci_cc_read_flow_control_mode(hdev, skb);
2514 break;
2515
Andrei Emeltchenko928abaa2011-10-12 10:53:57 +03002516 case HCI_OP_READ_LOCAL_AMP_INFO:
2517 hci_cc_read_local_amp_info(hdev, skb);
2518 break;
2519
Andrei Emeltchenko903e4542012-09-27 17:26:09 +03002520 case HCI_OP_READ_LOCAL_AMP_ASSOC:
2521 hci_cc_read_local_amp_assoc(hdev, skb);
2522 break;
2523
Johan Hedbergb0916ea2011-01-10 13:44:55 +02002524 case HCI_OP_DELETE_STORED_LINK_KEY:
2525 hci_cc_delete_stored_link_key(hdev, skb);
2526 break;
2527
Johan Hedbergd5859e22011-01-25 01:19:58 +02002528 case HCI_OP_SET_EVENT_MASK:
2529 hci_cc_set_event_mask(hdev, skb);
2530 break;
2531
2532 case HCI_OP_WRITE_INQUIRY_MODE:
2533 hci_cc_write_inquiry_mode(hdev, skb);
2534 break;
2535
2536 case HCI_OP_READ_INQ_RSP_TX_POWER:
2537 hci_cc_read_inq_rsp_tx_power(hdev, skb);
2538 break;
2539
2540 case HCI_OP_SET_EVENT_FLT:
2541 hci_cc_set_event_flt(hdev, skb);
2542 break;
2543
Johan Hedberg980e1a52011-01-22 06:10:07 +02002544 case HCI_OP_PIN_CODE_REPLY:
2545 hci_cc_pin_code_reply(hdev, skb);
2546 break;
2547
2548 case HCI_OP_PIN_CODE_NEG_REPLY:
2549 hci_cc_pin_code_neg_reply(hdev, skb);
2550 break;
2551
Szymon Jancc35938b2011-03-22 13:12:21 +01002552 case HCI_OP_READ_LOCAL_OOB_DATA:
2553 hci_cc_read_local_oob_data_reply(hdev, skb);
2554 break;
2555
Ville Tervo6ed58ec2011-02-10 22:38:48 -03002556 case HCI_OP_LE_READ_BUFFER_SIZE:
2557 hci_cc_le_read_buffer_size(hdev, skb);
2558 break;
2559
Johan Hedberg8fa19092012-10-19 20:57:49 +03002560 case HCI_OP_LE_READ_ADV_TX_POWER:
2561 hci_cc_le_read_adv_tx_power(hdev, skb);
2562 break;
2563
Johan Hedberge36b04c2012-10-19 20:57:47 +03002564 case HCI_OP_LE_SET_EVENT_MASK:
2565 hci_cc_le_set_event_mask(hdev, skb);
2566 break;
2567
Johan Hedberga5c29682011-02-19 12:05:57 -03002568 case HCI_OP_USER_CONFIRM_REPLY:
2569 hci_cc_user_confirm_reply(hdev, skb);
2570 break;
2571
2572 case HCI_OP_USER_CONFIRM_NEG_REPLY:
2573 hci_cc_user_confirm_neg_reply(hdev, skb);
2574 break;
2575
Brian Gix1143d452011-11-23 08:28:34 -08002576 case HCI_OP_USER_PASSKEY_REPLY:
2577 hci_cc_user_passkey_reply(hdev, skb);
2578 break;
2579
2580 case HCI_OP_USER_PASSKEY_NEG_REPLY:
2581 hci_cc_user_passkey_neg_reply(hdev, skb);
Szymon Janc16cde992012-04-13 12:32:42 +02002582 break;
Andre Guedes07f7fa52011-12-02 21:13:31 +09002583
2584 case HCI_OP_LE_SET_SCAN_PARAM:
2585 hci_cc_le_set_scan_param(hdev, skb);
Brian Gix1143d452011-11-23 08:28:34 -08002586 break;
2587
Andre Guedeseb9d91f2011-05-26 16:23:52 -03002588 case HCI_OP_LE_SET_SCAN_ENABLE:
2589 hci_cc_le_set_scan_enable(hdev, skb);
2590 break;
2591
Vinicius Costa Gomesa7a595f2011-06-09 18:50:47 -03002592 case HCI_OP_LE_LTK_REPLY:
2593 hci_cc_le_ltk_reply(hdev, skb);
2594 break;
2595
2596 case HCI_OP_LE_LTK_NEG_REPLY:
2597 hci_cc_le_ltk_neg_reply(hdev, skb);
2598 break;
2599
Andre Guedesf9b49302011-06-30 19:20:53 -03002600 case HCI_OP_WRITE_LE_HOST_SUPPORTED:
2601 hci_cc_write_le_host_supported(hdev, skb);
2602 break;
2603
Andrei Emeltchenko93c284e2012-09-27 17:26:20 +03002604 case HCI_OP_WRITE_REMOTE_AMP_ASSOC:
2605 hci_cc_write_remote_amp_assoc(hdev, skb);
2606 break;
2607
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002608 default:
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +03002609 BT_DBG("%s opcode 0x%4.4x", hdev->name, opcode);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002610 break;
2611 }
2612
Ville Tervo6bd32322011-02-16 16:32:41 +02002613 if (ev->opcode != HCI_OP_NOP)
2614 del_timer(&hdev->cmd_timer);
2615
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002616 if (ev->ncmd) {
2617 atomic_set(&hdev->cmd_cnt, 1);
2618 if (!skb_queue_empty(&hdev->cmd_q))
Gustavo F. Padovanc347b762011-12-14 23:53:47 -02002619 queue_work(hdev->workqueue, &hdev->cmd_work);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002620 }
2621}
2622
Gustavo Padovan6039aa732012-05-23 04:04:18 -03002623static void hci_cmd_status_evt(struct hci_dev *hdev, struct sk_buff *skb)
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002624{
2625 struct hci_ev_cmd_status *ev = (void *) skb->data;
2626 __u16 opcode;
2627
2628 skb_pull(skb, sizeof(*ev));
2629
2630 opcode = __le16_to_cpu(ev->opcode);
2631
2632 switch (opcode) {
2633 case HCI_OP_INQUIRY:
2634 hci_cs_inquiry(hdev, ev->status);
2635 break;
2636
2637 case HCI_OP_CREATE_CONN:
2638 hci_cs_create_conn(hdev, ev->status);
2639 break;
2640
2641 case HCI_OP_ADD_SCO:
2642 hci_cs_add_sco(hdev, ev->status);
2643 break;
2644
Marcel Holtmannf8558552008-07-14 20:13:49 +02002645 case HCI_OP_AUTH_REQUESTED:
2646 hci_cs_auth_requested(hdev, ev->status);
2647 break;
2648
2649 case HCI_OP_SET_CONN_ENCRYPT:
2650 hci_cs_set_conn_encrypt(hdev, ev->status);
2651 break;
2652
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002653 case HCI_OP_REMOTE_NAME_REQ:
2654 hci_cs_remote_name_req(hdev, ev->status);
2655 break;
2656
Marcel Holtmann769be972008-07-14 20:13:49 +02002657 case HCI_OP_READ_REMOTE_FEATURES:
2658 hci_cs_read_remote_features(hdev, ev->status);
2659 break;
2660
2661 case HCI_OP_READ_REMOTE_EXT_FEATURES:
2662 hci_cs_read_remote_ext_features(hdev, ev->status);
2663 break;
2664
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002665 case HCI_OP_SETUP_SYNC_CONN:
2666 hci_cs_setup_sync_conn(hdev, ev->status);
2667 break;
2668
2669 case HCI_OP_SNIFF_MODE:
2670 hci_cs_sniff_mode(hdev, ev->status);
2671 break;
2672
2673 case HCI_OP_EXIT_SNIFF_MODE:
2674 hci_cs_exit_sniff_mode(hdev, ev->status);
2675 break;
2676
Johan Hedberg8962ee72011-01-20 12:40:27 +02002677 case HCI_OP_DISCONNECT:
Johan Hedberg88c3df12012-02-09 14:27:38 +02002678 hci_cs_disconnect(hdev, ev->status);
Johan Hedberg8962ee72011-01-20 12:40:27 +02002679 break;
2680
Ville Tervofcd89c02011-02-10 22:38:47 -03002681 case HCI_OP_LE_CREATE_CONN:
2682 hci_cs_le_create_conn(hdev, ev->status);
2683 break;
2684
Vinicius Costa Gomesa7a595f2011-06-09 18:50:47 -03002685 case HCI_OP_LE_START_ENC:
2686 hci_cs_le_start_enc(hdev, ev->status);
2687 break;
2688
Andrei Emeltchenkoa02226d2012-09-27 17:26:19 +03002689 case HCI_OP_CREATE_PHY_LINK:
2690 hci_cs_create_phylink(hdev, ev->status);
2691 break;
2692
Andrei Emeltchenko0b26ab92012-09-27 17:26:24 +03002693 case HCI_OP_ACCEPT_PHY_LINK:
2694 hci_cs_accept_phylink(hdev, ev->status);
2695 break;
2696
Andrei Emeltchenko5ce66b52012-10-31 15:46:30 +02002697 case HCI_OP_CREATE_LOGICAL_LINK:
2698 hci_cs_create_logical_link(hdev, ev->status);
2699 break;
2700
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002701 default:
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +03002702 BT_DBG("%s opcode 0x%4.4x", hdev->name, opcode);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002703 break;
2704 }
2705
Ville Tervo6bd32322011-02-16 16:32:41 +02002706 if (ev->opcode != HCI_OP_NOP)
2707 del_timer(&hdev->cmd_timer);
2708
Gustavo F. Padovan10572132011-03-16 15:36:29 -03002709 if (ev->ncmd && !test_bit(HCI_RESET, &hdev->flags)) {
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002710 atomic_set(&hdev->cmd_cnt, 1);
2711 if (!skb_queue_empty(&hdev->cmd_q))
Gustavo F. Padovanc347b762011-12-14 23:53:47 -02002712 queue_work(hdev->workqueue, &hdev->cmd_work);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002713 }
2714}
2715
Gustavo Padovan6039aa732012-05-23 04:04:18 -03002716static void hci_role_change_evt(struct hci_dev *hdev, struct sk_buff *skb)
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002717{
2718 struct hci_ev_role_change *ev = (void *) skb->data;
2719 struct hci_conn *conn;
2720
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +03002721 BT_DBG("%s status 0x%2.2x", hdev->name, ev->status);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002722
2723 hci_dev_lock(hdev);
2724
2725 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
2726 if (conn) {
2727 if (!ev->status) {
2728 if (ev->role)
2729 conn->link_mode &= ~HCI_LM_MASTER;
2730 else
2731 conn->link_mode |= HCI_LM_MASTER;
2732 }
2733
Johan Hedberg51a8efd2012-01-16 06:10:31 +02002734 clear_bit(HCI_CONN_RSWITCH_PEND, &conn->flags);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002735
2736 hci_role_switch_cfm(conn, ev->status, ev->role);
2737 }
2738
2739 hci_dev_unlock(hdev);
2740}
2741
Gustavo Padovan6039aa732012-05-23 04:04:18 -03002742static void hci_num_comp_pkts_evt(struct hci_dev *hdev, struct sk_buff *skb)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002743{
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002744 struct hci_ev_num_comp_pkts *ev = (void *) skb->data;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002745 int i;
2746
Andrei Emeltchenko32ac5b92011-12-19 16:31:29 +02002747 if (hdev->flow_ctl_mode != HCI_FLOW_CTL_MODE_PACKET_BASED) {
2748 BT_ERR("Wrong event for mode %d", hdev->flow_ctl_mode);
2749 return;
2750 }
2751
Andrei Emeltchenkoc5993de2011-12-30 12:07:47 +02002752 if (skb->len < sizeof(*ev) || skb->len < sizeof(*ev) +
Gustavo Padovan807deac2012-05-17 00:36:24 -03002753 ev->num_hndl * sizeof(struct hci_comp_pkts_info)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002754 BT_DBG("%s bad parameters", hdev->name);
2755 return;
2756 }
2757
Andrei Emeltchenkoc5993de2011-12-30 12:07:47 +02002758 BT_DBG("%s num_hndl %d", hdev->name, ev->num_hndl);
2759
Andrei Emeltchenko613a1c02011-12-19 16:31:30 +02002760 for (i = 0; i < ev->num_hndl; i++) {
2761 struct hci_comp_pkts_info *info = &ev->handles[i];
Linus Torvalds1da177e2005-04-16 15:20:36 -07002762 struct hci_conn *conn;
2763 __u16 handle, count;
2764
Andrei Emeltchenko613a1c02011-12-19 16:31:30 +02002765 handle = __le16_to_cpu(info->handle);
2766 count = __le16_to_cpu(info->count);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002767
2768 conn = hci_conn_hash_lookup_handle(hdev, handle);
Andrei Emeltchenkof4280912011-12-07 15:56:52 +02002769 if (!conn)
2770 continue;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002771
Andrei Emeltchenkof4280912011-12-07 15:56:52 +02002772 conn->sent -= count;
2773
2774 switch (conn->type) {
2775 case ACL_LINK:
2776 hdev->acl_cnt += count;
2777 if (hdev->acl_cnt > hdev->acl_pkts)
2778 hdev->acl_cnt = hdev->acl_pkts;
2779 break;
2780
2781 case LE_LINK:
2782 if (hdev->le_pkts) {
2783 hdev->le_cnt += count;
2784 if (hdev->le_cnt > hdev->le_pkts)
2785 hdev->le_cnt = hdev->le_pkts;
2786 } else {
Andrei Emeltchenko70f230202010-12-01 16:58:25 +02002787 hdev->acl_cnt += count;
2788 if (hdev->acl_cnt > hdev->acl_pkts)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002789 hdev->acl_cnt = hdev->acl_pkts;
2790 }
Andrei Emeltchenkof4280912011-12-07 15:56:52 +02002791 break;
2792
2793 case SCO_LINK:
2794 hdev->sco_cnt += count;
2795 if (hdev->sco_cnt > hdev->sco_pkts)
2796 hdev->sco_cnt = hdev->sco_pkts;
2797 break;
2798
2799 default:
2800 BT_ERR("Unknown type %d conn %p", conn->type, conn);
2801 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002802 }
2803 }
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002804
Gustavo F. Padovan3eff45e2011-12-15 00:50:02 -02002805 queue_work(hdev->workqueue, &hdev->tx_work);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002806}
2807
Andrei Emeltchenko76ef7cf2012-10-10 17:38:29 +03002808static struct hci_conn *__hci_conn_lookup_handle(struct hci_dev *hdev,
2809 __u16 handle)
2810{
2811 struct hci_chan *chan;
2812
2813 switch (hdev->dev_type) {
2814 case HCI_BREDR:
2815 return hci_conn_hash_lookup_handle(hdev, handle);
2816 case HCI_AMP:
2817 chan = hci_chan_lookup_handle(hdev, handle);
2818 if (chan)
2819 return chan->conn;
2820 break;
2821 default:
2822 BT_ERR("%s unknown dev_type %d", hdev->name, hdev->dev_type);
2823 break;
2824 }
2825
2826 return NULL;
2827}
2828
Gustavo Padovan6039aa732012-05-23 04:04:18 -03002829static void hci_num_comp_blocks_evt(struct hci_dev *hdev, struct sk_buff *skb)
Andrei Emeltchenko25e89e92012-01-04 12:41:58 +02002830{
2831 struct hci_ev_num_comp_blocks *ev = (void *) skb->data;
2832 int i;
2833
2834 if (hdev->flow_ctl_mode != HCI_FLOW_CTL_MODE_BLOCK_BASED) {
2835 BT_ERR("Wrong event for mode %d", hdev->flow_ctl_mode);
2836 return;
2837 }
2838
2839 if (skb->len < sizeof(*ev) || skb->len < sizeof(*ev) +
Gustavo Padovan807deac2012-05-17 00:36:24 -03002840 ev->num_hndl * sizeof(struct hci_comp_blocks_info)) {
Andrei Emeltchenko25e89e92012-01-04 12:41:58 +02002841 BT_DBG("%s bad parameters", hdev->name);
2842 return;
2843 }
2844
2845 BT_DBG("%s num_blocks %d num_hndl %d", hdev->name, ev->num_blocks,
Gustavo Padovan807deac2012-05-17 00:36:24 -03002846 ev->num_hndl);
Andrei Emeltchenko25e89e92012-01-04 12:41:58 +02002847
2848 for (i = 0; i < ev->num_hndl; i++) {
2849 struct hci_comp_blocks_info *info = &ev->handles[i];
Andrei Emeltchenko76ef7cf2012-10-10 17:38:29 +03002850 struct hci_conn *conn = NULL;
Andrei Emeltchenko25e89e92012-01-04 12:41:58 +02002851 __u16 handle, block_count;
2852
2853 handle = __le16_to_cpu(info->handle);
2854 block_count = __le16_to_cpu(info->blocks);
2855
Andrei Emeltchenko76ef7cf2012-10-10 17:38:29 +03002856 conn = __hci_conn_lookup_handle(hdev, handle);
Andrei Emeltchenko25e89e92012-01-04 12:41:58 +02002857 if (!conn)
2858 continue;
2859
2860 conn->sent -= block_count;
2861
2862 switch (conn->type) {
2863 case ACL_LINK:
Andrei Emeltchenkobd1eb662012-10-10 17:38:30 +03002864 case AMP_LINK:
Andrei Emeltchenko25e89e92012-01-04 12:41:58 +02002865 hdev->block_cnt += block_count;
2866 if (hdev->block_cnt > hdev->num_blocks)
2867 hdev->block_cnt = hdev->num_blocks;
2868 break;
2869
2870 default:
2871 BT_ERR("Unknown type %d conn %p", conn->type, conn);
2872 break;
2873 }
2874 }
2875
2876 queue_work(hdev->workqueue, &hdev->tx_work);
2877}
2878
Gustavo Padovan6039aa732012-05-23 04:04:18 -03002879static void hci_mode_change_evt(struct hci_dev *hdev, struct sk_buff *skb)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002880{
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002881 struct hci_ev_mode_change *ev = (void *) skb->data;
Marcel Holtmann04837f62006-07-03 10:02:33 +02002882 struct hci_conn *conn;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002883
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +03002884 BT_DBG("%s status 0x%2.2x", hdev->name, ev->status);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002885
2886 hci_dev_lock(hdev);
2887
Marcel Holtmann04837f62006-07-03 10:02:33 +02002888 conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
2889 if (conn) {
2890 conn->mode = ev->mode;
2891 conn->interval = __le16_to_cpu(ev->interval);
2892
Gustavo Padovan8fc9ced2012-05-23 04:04:21 -03002893 if (!test_and_clear_bit(HCI_CONN_MODE_CHANGE_PEND,
2894 &conn->flags)) {
Marcel Holtmann04837f62006-07-03 10:02:33 +02002895 if (conn->mode == HCI_CM_ACTIVE)
Johan Hedberg58a681e2012-01-16 06:47:28 +02002896 set_bit(HCI_CONN_POWER_SAVE, &conn->flags);
Marcel Holtmann04837f62006-07-03 10:02:33 +02002897 else
Johan Hedberg58a681e2012-01-16 06:47:28 +02002898 clear_bit(HCI_CONN_POWER_SAVE, &conn->flags);
Marcel Holtmann04837f62006-07-03 10:02:33 +02002899 }
Marcel Holtmanne73439d2010-07-26 10:06:00 -04002900
Johan Hedberg51a8efd2012-01-16 06:10:31 +02002901 if (test_and_clear_bit(HCI_CONN_SCO_SETUP_PEND, &conn->flags))
Marcel Holtmanne73439d2010-07-26 10:06:00 -04002902 hci_sco_setup(conn, ev->status);
Marcel Holtmann04837f62006-07-03 10:02:33 +02002903 }
2904
2905 hci_dev_unlock(hdev);
2906}
2907
Gustavo Padovan6039aa732012-05-23 04:04:18 -03002908static void hci_pin_code_request_evt(struct hci_dev *hdev, struct sk_buff *skb)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002909{
Marcel Holtmann052b30b2009-04-26 20:01:22 +02002910 struct hci_ev_pin_code_req *ev = (void *) skb->data;
2911 struct hci_conn *conn;
2912
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002913 BT_DBG("%s", hdev->name);
Marcel Holtmann052b30b2009-04-26 20:01:22 +02002914
2915 hci_dev_lock(hdev);
2916
2917 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
Waldemar Rymarkiewiczb6f98042011-09-23 10:01:30 +02002918 if (!conn)
2919 goto unlock;
2920
2921 if (conn->state == BT_CONNECTED) {
Marcel Holtmann052b30b2009-04-26 20:01:22 +02002922 hci_conn_hold(conn);
2923 conn->disc_timeout = HCI_PAIRING_TIMEOUT;
2924 hci_conn_put(conn);
2925 }
2926
Johan Hedberga8b2d5c2012-01-08 23:11:15 +02002927 if (!test_bit(HCI_PAIRABLE, &hdev->dev_flags))
Johan Hedberg03b555e2011-01-04 15:40:05 +02002928 hci_send_cmd(hdev, HCI_OP_PIN_CODE_NEG_REPLY,
Gustavo Padovan807deac2012-05-17 00:36:24 -03002929 sizeof(ev->bdaddr), &ev->bdaddr);
Johan Hedberga8b2d5c2012-01-08 23:11:15 +02002930 else if (test_bit(HCI_MGMT, &hdev->dev_flags)) {
Waldemar Rymarkiewicza770bb52011-04-28 12:07:59 +02002931 u8 secure;
2932
2933 if (conn->pending_sec_level == BT_SECURITY_HIGH)
2934 secure = 1;
2935 else
2936 secure = 0;
2937
Johan Hedberg744cf192011-11-08 20:40:14 +02002938 mgmt_pin_code_request(hdev, &ev->bdaddr, secure);
Waldemar Rymarkiewicza770bb52011-04-28 12:07:59 +02002939 }
Johan Hedberg980e1a52011-01-22 06:10:07 +02002940
Waldemar Rymarkiewiczb6f98042011-09-23 10:01:30 +02002941unlock:
Marcel Holtmann052b30b2009-04-26 20:01:22 +02002942 hci_dev_unlock(hdev);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002943}
2944
Gustavo Padovan6039aa732012-05-23 04:04:18 -03002945static void hci_link_key_request_evt(struct hci_dev *hdev, struct sk_buff *skb)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002946{
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002947 struct hci_ev_link_key_req *ev = (void *) skb->data;
2948 struct hci_cp_link_key_reply cp;
2949 struct hci_conn *conn;
2950 struct link_key *key;
2951
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002952 BT_DBG("%s", hdev->name);
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002953
Johan Hedberga8b2d5c2012-01-08 23:11:15 +02002954 if (!test_bit(HCI_LINK_KEYS, &hdev->dev_flags))
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002955 return;
2956
2957 hci_dev_lock(hdev);
2958
2959 key = hci_find_link_key(hdev, &ev->bdaddr);
2960 if (!key) {
Andrei Emeltchenko6ed93dc2012-09-25 12:49:43 +03002961 BT_DBG("%s link key not found for %pMR", hdev->name,
2962 &ev->bdaddr);
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002963 goto not_found;
2964 }
2965
Andrei Emeltchenko6ed93dc2012-09-25 12:49:43 +03002966 BT_DBG("%s found key type %u for %pMR", hdev->name, key->type,
2967 &ev->bdaddr);
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002968
Johan Hedberga8b2d5c2012-01-08 23:11:15 +02002969 if (!test_bit(HCI_DEBUG_KEYS, &hdev->dev_flags) &&
Gustavo Padovan807deac2012-05-17 00:36:24 -03002970 key->type == HCI_LK_DEBUG_COMBINATION) {
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002971 BT_DBG("%s ignoring debug key", hdev->name);
2972 goto not_found;
2973 }
2974
2975 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
Waldemar Rymarkiewicz60b83f52011-04-28 12:07:56 +02002976 if (conn) {
2977 if (key->type == HCI_LK_UNAUTH_COMBINATION &&
Gustavo Padovan807deac2012-05-17 00:36:24 -03002978 conn->auth_type != 0xff && (conn->auth_type & 0x01)) {
Waldemar Rymarkiewicz60b83f52011-04-28 12:07:56 +02002979 BT_DBG("%s ignoring unauthenticated key", hdev->name);
2980 goto not_found;
2981 }
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002982
Waldemar Rymarkiewicz60b83f52011-04-28 12:07:56 +02002983 if (key->type == HCI_LK_COMBINATION && key->pin_len < 16 &&
Gustavo Padovan807deac2012-05-17 00:36:24 -03002984 conn->pending_sec_level == BT_SECURITY_HIGH) {
Gustavo Padovan8fc9ced2012-05-23 04:04:21 -03002985 BT_DBG("%s ignoring key unauthenticated for high security",
2986 hdev->name);
Waldemar Rymarkiewicz60b83f52011-04-28 12:07:56 +02002987 goto not_found;
2988 }
2989
2990 conn->key_type = key->type;
2991 conn->pin_length = key->pin_len;
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002992 }
2993
2994 bacpy(&cp.bdaddr, &ev->bdaddr);
Andrei Emeltchenko9b3b4462012-05-23 11:31:20 +03002995 memcpy(cp.link_key, key->val, HCI_LINK_KEY_SIZE);
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002996
2997 hci_send_cmd(hdev, HCI_OP_LINK_KEY_REPLY, sizeof(cp), &cp);
2998
2999 hci_dev_unlock(hdev);
3000
3001 return;
3002
3003not_found:
3004 hci_send_cmd(hdev, HCI_OP_LINK_KEY_NEG_REPLY, 6, &ev->bdaddr);
3005 hci_dev_unlock(hdev);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003006}
3007
Gustavo Padovan6039aa732012-05-23 04:04:18 -03003008static void hci_link_key_notify_evt(struct hci_dev *hdev, struct sk_buff *skb)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003009{
Marcel Holtmann052b30b2009-04-26 20:01:22 +02003010 struct hci_ev_link_key_notify *ev = (void *) skb->data;
3011 struct hci_conn *conn;
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02003012 u8 pin_len = 0;
Marcel Holtmann052b30b2009-04-26 20:01:22 +02003013
Marcel Holtmanna9de9242007-10-20 13:33:56 +02003014 BT_DBG("%s", hdev->name);
Marcel Holtmann052b30b2009-04-26 20:01:22 +02003015
3016 hci_dev_lock(hdev);
3017
3018 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
3019 if (conn) {
3020 hci_conn_hold(conn);
3021 conn->disc_timeout = HCI_DISCONN_TIMEOUT;
Johan Hedberg980e1a52011-01-22 06:10:07 +02003022 pin_len = conn->pin_length;
Waldemar Rymarkiewicz13d39312011-04-28 12:07:55 +02003023
3024 if (ev->key_type != HCI_LK_CHANGED_COMBINATION)
3025 conn->key_type = ev->key_type;
3026
Marcel Holtmann052b30b2009-04-26 20:01:22 +02003027 hci_conn_put(conn);
3028 }
3029
Johan Hedberga8b2d5c2012-01-08 23:11:15 +02003030 if (test_bit(HCI_LINK_KEYS, &hdev->dev_flags))
Johan Hedbergd25e28a2011-04-28 11:28:59 -07003031 hci_add_link_key(hdev, conn, 1, &ev->bdaddr, ev->link_key,
Gustavo Padovan807deac2012-05-17 00:36:24 -03003032 ev->key_type, pin_len);
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02003033
Marcel Holtmann052b30b2009-04-26 20:01:22 +02003034 hci_dev_unlock(hdev);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003035}
3036
Gustavo Padovan6039aa732012-05-23 04:04:18 -03003037static void hci_clock_offset_evt(struct hci_dev *hdev, struct sk_buff *skb)
Marcel Holtmann04837f62006-07-03 10:02:33 +02003038{
Marcel Holtmanna9de9242007-10-20 13:33:56 +02003039 struct hci_ev_clock_offset *ev = (void *) skb->data;
Marcel Holtmann04837f62006-07-03 10:02:33 +02003040 struct hci_conn *conn;
3041
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +03003042 BT_DBG("%s status 0x%2.2x", hdev->name, ev->status);
Marcel Holtmann04837f62006-07-03 10:02:33 +02003043
3044 hci_dev_lock(hdev);
3045
3046 conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
Linus Torvalds1da177e2005-04-16 15:20:36 -07003047 if (conn && !ev->status) {
3048 struct inquiry_entry *ie;
3049
Andrei Emeltchenkocc11b9c2010-11-22 13:21:37 +02003050 ie = hci_inquiry_cache_lookup(hdev, &conn->dst);
3051 if (ie) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003052 ie->data.clock_offset = ev->clock_offset;
3053 ie->timestamp = jiffies;
3054 }
3055 }
3056
3057 hci_dev_unlock(hdev);
3058}
3059
Gustavo Padovan6039aa732012-05-23 04:04:18 -03003060static void hci_pkt_type_change_evt(struct hci_dev *hdev, struct sk_buff *skb)
Marcel Holtmanna8746412008-07-14 20:13:46 +02003061{
3062 struct hci_ev_pkt_type_change *ev = (void *) skb->data;
3063 struct hci_conn *conn;
3064
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +03003065 BT_DBG("%s status 0x%2.2x", hdev->name, ev->status);
Marcel Holtmanna8746412008-07-14 20:13:46 +02003066
3067 hci_dev_lock(hdev);
3068
3069 conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
3070 if (conn && !ev->status)
3071 conn->pkt_type = __le16_to_cpu(ev->pkt_type);
3072
3073 hci_dev_unlock(hdev);
3074}
3075
Gustavo Padovan6039aa732012-05-23 04:04:18 -03003076static void hci_pscan_rep_mode_evt(struct hci_dev *hdev, struct sk_buff *skb)
Marcel Holtmann85a1e932005-08-09 20:28:02 -07003077{
Marcel Holtmanna9de9242007-10-20 13:33:56 +02003078 struct hci_ev_pscan_rep_mode *ev = (void *) skb->data;
Marcel Holtmann85a1e932005-08-09 20:28:02 -07003079 struct inquiry_entry *ie;
3080
3081 BT_DBG("%s", hdev->name);
3082
3083 hci_dev_lock(hdev);
3084
Andrei Emeltchenkocc11b9c2010-11-22 13:21:37 +02003085 ie = hci_inquiry_cache_lookup(hdev, &ev->bdaddr);
3086 if (ie) {
Marcel Holtmann85a1e932005-08-09 20:28:02 -07003087 ie->data.pscan_rep_mode = ev->pscan_rep_mode;
3088 ie->timestamp = jiffies;
3089 }
3090
3091 hci_dev_unlock(hdev);
3092}
3093
Gustavo Padovan6039aa732012-05-23 04:04:18 -03003094static void hci_inquiry_result_with_rssi_evt(struct hci_dev *hdev,
3095 struct sk_buff *skb)
Marcel Holtmanna9de9242007-10-20 13:33:56 +02003096{
3097 struct inquiry_data data;
3098 int num_rsp = *((__u8 *) skb->data);
Johan Hedberg388fc8f2012-02-23 00:38:59 +02003099 bool name_known, ssp;
Marcel Holtmanna9de9242007-10-20 13:33:56 +02003100
3101 BT_DBG("%s num_rsp %d", hdev->name, num_rsp);
3102
3103 if (!num_rsp)
3104 return;
3105
Andre Guedes1519cc12012-03-21 00:03:38 -03003106 if (test_bit(HCI_PERIODIC_INQ, &hdev->dev_flags))
3107 return;
3108
Marcel Holtmanna9de9242007-10-20 13:33:56 +02003109 hci_dev_lock(hdev);
3110
3111 if ((skb->len - 1) / num_rsp != sizeof(struct inquiry_info_with_rssi)) {
Szymon Janc138d22e2011-02-17 16:44:23 +01003112 struct inquiry_info_with_rssi_and_pscan_mode *info;
3113 info = (void *) (skb->data + 1);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02003114
Johan Hedberge17acd42011-03-30 23:57:16 +03003115 for (; num_rsp; num_rsp--, info++) {
Marcel Holtmanna9de9242007-10-20 13:33:56 +02003116 bacpy(&data.bdaddr, &info->bdaddr);
3117 data.pscan_rep_mode = info->pscan_rep_mode;
3118 data.pscan_period_mode = info->pscan_period_mode;
3119 data.pscan_mode = info->pscan_mode;
3120 memcpy(data.dev_class, info->dev_class, 3);
3121 data.clock_offset = info->clock_offset;
3122 data.rssi = info->rssi;
Marcel Holtmann41a96212008-07-14 20:13:48 +02003123 data.ssp_mode = 0x00;
Johan Hedberg31754052012-01-04 13:39:52 +02003124
3125 name_known = hci_inquiry_cache_update(hdev, &data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003126 false, &ssp);
Johan Hedberg48264f02011-11-09 13:58:58 +02003127 mgmt_device_found(hdev, &info->bdaddr, ACL_LINK, 0x00,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003128 info->dev_class, info->rssi,
3129 !name_known, ssp, NULL, 0);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02003130 }
3131 } else {
3132 struct inquiry_info_with_rssi *info = (void *) (skb->data + 1);
3133
Johan Hedberge17acd42011-03-30 23:57:16 +03003134 for (; num_rsp; num_rsp--, info++) {
Marcel Holtmanna9de9242007-10-20 13:33:56 +02003135 bacpy(&data.bdaddr, &info->bdaddr);
3136 data.pscan_rep_mode = info->pscan_rep_mode;
3137 data.pscan_period_mode = info->pscan_period_mode;
3138 data.pscan_mode = 0x00;
3139 memcpy(data.dev_class, info->dev_class, 3);
3140 data.clock_offset = info->clock_offset;
3141 data.rssi = info->rssi;
Marcel Holtmann41a96212008-07-14 20:13:48 +02003142 data.ssp_mode = 0x00;
Johan Hedberg31754052012-01-04 13:39:52 +02003143 name_known = hci_inquiry_cache_update(hdev, &data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003144 false, &ssp);
Johan Hedberg48264f02011-11-09 13:58:58 +02003145 mgmt_device_found(hdev, &info->bdaddr, ACL_LINK, 0x00,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003146 info->dev_class, info->rssi,
3147 !name_known, ssp, NULL, 0);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02003148 }
3149 }
3150
3151 hci_dev_unlock(hdev);
3152}
3153
Gustavo Padovan6039aa732012-05-23 04:04:18 -03003154static void hci_remote_ext_features_evt(struct hci_dev *hdev,
3155 struct sk_buff *skb)
Marcel Holtmanna9de9242007-10-20 13:33:56 +02003156{
Marcel Holtmann41a96212008-07-14 20:13:48 +02003157 struct hci_ev_remote_ext_features *ev = (void *) skb->data;
3158 struct hci_conn *conn;
3159
Marcel Holtmanna9de9242007-10-20 13:33:56 +02003160 BT_DBG("%s", hdev->name);
Marcel Holtmann41a96212008-07-14 20:13:48 +02003161
Marcel Holtmann41a96212008-07-14 20:13:48 +02003162 hci_dev_lock(hdev);
3163
3164 conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
Johan Hedbergccd556f2010-11-10 17:11:51 +02003165 if (!conn)
3166 goto unlock;
Marcel Holtmann41a96212008-07-14 20:13:48 +02003167
Johan Hedbergccd556f2010-11-10 17:11:51 +02003168 if (!ev->status && ev->page == 0x01) {
3169 struct inquiry_entry *ie;
Marcel Holtmann41a96212008-07-14 20:13:48 +02003170
Andrei Emeltchenkocc11b9c2010-11-22 13:21:37 +02003171 ie = hci_inquiry_cache_lookup(hdev, &conn->dst);
3172 if (ie)
Johan Hedberg02b7cc62012-02-28 02:28:43 +02003173 ie->data.ssp_mode = (ev->features[0] & LMP_HOST_SSP);
Marcel Holtmann769be972008-07-14 20:13:49 +02003174
Johan Hedberg02b7cc62012-02-28 02:28:43 +02003175 if (ev->features[0] & LMP_HOST_SSP)
Johan Hedberg58a681e2012-01-16 06:47:28 +02003176 set_bit(HCI_CONN_SSP_ENABLED, &conn->flags);
Marcel Holtmann41a96212008-07-14 20:13:48 +02003177 }
3178
Johan Hedbergccd556f2010-11-10 17:11:51 +02003179 if (conn->state != BT_CONFIG)
3180 goto unlock;
3181
Johan Hedberg671267b2012-05-12 16:11:50 -03003182 if (!ev->status && !test_bit(HCI_CONN_MGMT_CONNECTED, &conn->flags)) {
Johan Hedberg127178d2010-11-18 22:22:29 +02003183 struct hci_cp_remote_name_req cp;
3184 memset(&cp, 0, sizeof(cp));
3185 bacpy(&cp.bdaddr, &conn->dst);
3186 cp.pscan_rep_mode = 0x02;
3187 hci_send_cmd(hdev, HCI_OP_REMOTE_NAME_REQ, sizeof(cp), &cp);
Johan Hedbergb644ba32012-01-17 21:48:47 +02003188 } else if (!test_and_set_bit(HCI_CONN_MGMT_CONNECTED, &conn->flags))
3189 mgmt_device_connected(hdev, &conn->dst, conn->type,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003190 conn->dst_type, 0, NULL, 0,
3191 conn->dev_class);
Johan Hedberg392599b2010-11-18 22:22:28 +02003192
Johan Hedberg127178d2010-11-18 22:22:29 +02003193 if (!hci_outgoing_auth_needed(hdev, conn)) {
Johan Hedbergccd556f2010-11-10 17:11:51 +02003194 conn->state = BT_CONNECTED;
3195 hci_proto_connect_cfm(conn, ev->status);
3196 hci_conn_put(conn);
3197 }
3198
3199unlock:
Marcel Holtmann41a96212008-07-14 20:13:48 +02003200 hci_dev_unlock(hdev);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02003201}
3202
Gustavo Padovan6039aa732012-05-23 04:04:18 -03003203static void hci_sync_conn_complete_evt(struct hci_dev *hdev,
3204 struct sk_buff *skb)
Marcel Holtmanna9de9242007-10-20 13:33:56 +02003205{
Marcel Holtmannb6a0dc82007-10-20 14:55:10 +02003206 struct hci_ev_sync_conn_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", hdev->name, ev->status);
Marcel Holtmannb6a0dc82007-10-20 14:55:10 +02003210
3211 hci_dev_lock(hdev);
3212
3213 conn = hci_conn_hash_lookup_ba(hdev, ev->link_type, &ev->bdaddr);
Marcel Holtmann9dc0a3a2008-07-14 20:13:46 +02003214 if (!conn) {
3215 if (ev->link_type == ESCO_LINK)
3216 goto unlock;
3217
3218 conn = hci_conn_hash_lookup_ba(hdev, ESCO_LINK, &ev->bdaddr);
3219 if (!conn)
3220 goto unlock;
3221
3222 conn->type = SCO_LINK;
3223 }
Marcel Holtmannb6a0dc82007-10-20 14:55:10 +02003224
Marcel Holtmann732547f2009-04-19 19:14:14 +02003225 switch (ev->status) {
3226 case 0x00:
Marcel Holtmannb6a0dc82007-10-20 14:55:10 +02003227 conn->handle = __le16_to_cpu(ev->handle);
3228 conn->state = BT_CONNECTED;
Marcel Holtmann7d0db0a2008-07-14 20:13:51 +02003229
Marcel Holtmann9eba32b2009-08-22 14:19:26 -07003230 hci_conn_hold_device(conn);
Marcel Holtmann7d0db0a2008-07-14 20:13:51 +02003231 hci_conn_add_sysfs(conn);
Marcel Holtmann732547f2009-04-19 19:14:14 +02003232 break;
3233
Stephen Coe705e5712010-02-16 11:29:44 -05003234 case 0x11: /* Unsupported Feature or Parameter Value */
Marcel Holtmann732547f2009-04-19 19:14:14 +02003235 case 0x1c: /* SCO interval rejected */
Nick Pelly1038a002010-02-03 11:42:26 -08003236 case 0x1a: /* Unsupported Remote Feature */
Marcel Holtmann732547f2009-04-19 19:14:14 +02003237 case 0x1f: /* Unspecified error */
3238 if (conn->out && conn->attempt < 2) {
3239 conn->pkt_type = (hdev->esco_type & SCO_ESCO_MASK) |
3240 (hdev->esco_type & EDR_ESCO_MASK);
3241 hci_setup_sync(conn, conn->link->handle);
3242 goto unlock;
3243 }
3244 /* fall through */
3245
3246 default:
Marcel Holtmannb6a0dc82007-10-20 14:55:10 +02003247 conn->state = BT_CLOSED;
Marcel Holtmann732547f2009-04-19 19:14:14 +02003248 break;
3249 }
Marcel Holtmannb6a0dc82007-10-20 14:55:10 +02003250
3251 hci_proto_connect_cfm(conn, ev->status);
3252 if (ev->status)
3253 hci_conn_del(conn);
3254
3255unlock:
3256 hci_dev_unlock(hdev);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02003257}
3258
Gustavo Padovan6039aa732012-05-23 04:04:18 -03003259static void hci_sync_conn_changed_evt(struct hci_dev *hdev, struct sk_buff *skb)
Marcel Holtmanna9de9242007-10-20 13:33:56 +02003260{
3261 BT_DBG("%s", hdev->name);
3262}
3263
Gustavo Padovan6039aa732012-05-23 04:04:18 -03003264static void hci_sniff_subrate_evt(struct hci_dev *hdev, struct sk_buff *skb)
Marcel Holtmann04837f62006-07-03 10:02:33 +02003265{
Marcel Holtmanna9de9242007-10-20 13:33:56 +02003266 struct hci_ev_sniff_subrate *ev = (void *) skb->data;
Marcel Holtmann04837f62006-07-03 10:02:33 +02003267
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +03003268 BT_DBG("%s status 0x%2.2x", hdev->name, ev->status);
Marcel Holtmann04837f62006-07-03 10:02:33 +02003269}
3270
Gustavo Padovan6039aa732012-05-23 04:04:18 -03003271static void hci_extended_inquiry_result_evt(struct hci_dev *hdev,
3272 struct sk_buff *skb)
Marcel Holtmanna9de9242007-10-20 13:33:56 +02003273{
3274 struct inquiry_data data;
3275 struct extended_inquiry_info *info = (void *) (skb->data + 1);
3276 int num_rsp = *((__u8 *) skb->data);
Vishal Agarwal9d939d92012-04-26 19:19:56 +05303277 size_t eir_len;
Marcel Holtmanna9de9242007-10-20 13:33:56 +02003278
3279 BT_DBG("%s num_rsp %d", hdev->name, num_rsp);
3280
3281 if (!num_rsp)
3282 return;
3283
Andre Guedes1519cc12012-03-21 00:03:38 -03003284 if (test_bit(HCI_PERIODIC_INQ, &hdev->dev_flags))
3285 return;
3286
Marcel Holtmanna9de9242007-10-20 13:33:56 +02003287 hci_dev_lock(hdev);
3288
Johan Hedberge17acd42011-03-30 23:57:16 +03003289 for (; num_rsp; num_rsp--, info++) {
Johan Hedberg388fc8f2012-02-23 00:38:59 +02003290 bool name_known, ssp;
Johan Hedberg561aafb2012-01-04 13:31:59 +02003291
Marcel Holtmanna9de9242007-10-20 13:33:56 +02003292 bacpy(&data.bdaddr, &info->bdaddr);
Szymon Janc138d22e2011-02-17 16:44:23 +01003293 data.pscan_rep_mode = info->pscan_rep_mode;
3294 data.pscan_period_mode = info->pscan_period_mode;
3295 data.pscan_mode = 0x00;
Marcel Holtmanna9de9242007-10-20 13:33:56 +02003296 memcpy(data.dev_class, info->dev_class, 3);
Szymon Janc138d22e2011-02-17 16:44:23 +01003297 data.clock_offset = info->clock_offset;
3298 data.rssi = info->rssi;
Marcel Holtmann41a96212008-07-14 20:13:48 +02003299 data.ssp_mode = 0x01;
Johan Hedberg561aafb2012-01-04 13:31:59 +02003300
Johan Hedberga8b2d5c2012-01-08 23:11:15 +02003301 if (test_bit(HCI_MGMT, &hdev->dev_flags))
Johan Hedberg4ddb1932012-01-15 20:04:43 +02003302 name_known = eir_has_data_type(info->data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003303 sizeof(info->data),
3304 EIR_NAME_COMPLETE);
Johan Hedberg561aafb2012-01-04 13:31:59 +02003305 else
3306 name_known = true;
3307
Johan Hedberg388fc8f2012-02-23 00:38:59 +02003308 name_known = hci_inquiry_cache_update(hdev, &data, name_known,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003309 &ssp);
Vishal Agarwal9d939d92012-04-26 19:19:56 +05303310 eir_len = eir_get_length(info->data, sizeof(info->data));
Johan Hedberg48264f02011-11-09 13:58:58 +02003311 mgmt_device_found(hdev, &info->bdaddr, ACL_LINK, 0x00,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003312 info->dev_class, info->rssi, !name_known,
Vishal Agarwal9d939d92012-04-26 19:19:56 +05303313 ssp, info->data, eir_len);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02003314 }
3315
3316 hci_dev_unlock(hdev);
3317}
3318
Johan Hedberg1c2e0042012-06-08 23:31:13 +08003319static void hci_key_refresh_complete_evt(struct hci_dev *hdev,
3320 struct sk_buff *skb)
3321{
3322 struct hci_ev_key_refresh_complete *ev = (void *) skb->data;
3323 struct hci_conn *conn;
3324
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +03003325 BT_DBG("%s status 0x%2.2x handle 0x%4.4x", hdev->name, ev->status,
Johan Hedberg1c2e0042012-06-08 23:31:13 +08003326 __le16_to_cpu(ev->handle));
3327
3328 hci_dev_lock(hdev);
3329
3330 conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
3331 if (!conn)
3332 goto unlock;
3333
3334 if (!ev->status)
3335 conn->sec_level = conn->pending_sec_level;
3336
3337 clear_bit(HCI_CONN_ENCRYPT_PEND, &conn->flags);
3338
3339 if (ev->status && conn->state == BT_CONNECTED) {
3340 hci_acl_disconn(conn, HCI_ERROR_AUTH_FAILURE);
3341 hci_conn_put(conn);
3342 goto unlock;
3343 }
3344
3345 if (conn->state == BT_CONFIG) {
3346 if (!ev->status)
3347 conn->state = BT_CONNECTED;
3348
3349 hci_proto_connect_cfm(conn, ev->status);
3350 hci_conn_put(conn);
3351 } else {
3352 hci_auth_cfm(conn, ev->status);
3353
3354 hci_conn_hold(conn);
3355 conn->disc_timeout = HCI_DISCONN_TIMEOUT;
3356 hci_conn_put(conn);
3357 }
3358
3359unlock:
3360 hci_dev_unlock(hdev);
3361}
3362
Gustavo Padovan6039aa732012-05-23 04:04:18 -03003363static u8 hci_get_auth_req(struct hci_conn *conn)
Johan Hedberg17fa4b92011-01-25 13:28:33 +02003364{
3365 /* If remote requests dedicated bonding follow that lead */
3366 if (conn->remote_auth == 0x02 || conn->remote_auth == 0x03) {
3367 /* If both remote and local IO capabilities allow MITM
3368 * protection then require it, otherwise don't */
3369 if (conn->remote_cap == 0x03 || conn->io_capability == 0x03)
3370 return 0x02;
3371 else
3372 return 0x03;
3373 }
3374
3375 /* If remote requests no-bonding follow that lead */
3376 if (conn->remote_auth == 0x00 || conn->remote_auth == 0x01)
Waldemar Rymarkiewicz58797bf2011-04-28 12:07:58 +02003377 return conn->remote_auth | (conn->auth_type & 0x01);
Johan Hedberg17fa4b92011-01-25 13:28:33 +02003378
3379 return conn->auth_type;
3380}
3381
Gustavo Padovan6039aa732012-05-23 04:04:18 -03003382static void hci_io_capa_request_evt(struct hci_dev *hdev, struct sk_buff *skb)
Marcel Holtmann04936842008-07-14 20:13:48 +02003383{
3384 struct hci_ev_io_capa_request *ev = (void *) skb->data;
3385 struct hci_conn *conn;
3386
3387 BT_DBG("%s", hdev->name);
3388
3389 hci_dev_lock(hdev);
3390
3391 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
Johan Hedberg03b555e2011-01-04 15:40:05 +02003392 if (!conn)
3393 goto unlock;
Marcel Holtmann04936842008-07-14 20:13:48 +02003394
Johan Hedberg03b555e2011-01-04 15:40:05 +02003395 hci_conn_hold(conn);
3396
Johan Hedberga8b2d5c2012-01-08 23:11:15 +02003397 if (!test_bit(HCI_MGMT, &hdev->dev_flags))
Johan Hedberg03b555e2011-01-04 15:40:05 +02003398 goto unlock;
3399
Johan Hedberga8b2d5c2012-01-08 23:11:15 +02003400 if (test_bit(HCI_PAIRABLE, &hdev->dev_flags) ||
Gustavo Padovan807deac2012-05-17 00:36:24 -03003401 (conn->remote_auth & ~0x01) == HCI_AT_NO_BONDING) {
Johan Hedberg17fa4b92011-01-25 13:28:33 +02003402 struct hci_cp_io_capability_reply cp;
3403
3404 bacpy(&cp.bdaddr, &ev->bdaddr);
Hemant Gupta7a7f1e72012-01-16 13:34:29 +05303405 /* Change the IO capability from KeyboardDisplay
3406 * to DisplayYesNo as it is not supported by BT spec. */
3407 cp.capability = (conn->io_capability == 0x04) ?
3408 0x01 : conn->io_capability;
Johan Hedberg7cbc9bd2011-04-28 11:29:04 -07003409 conn->auth_type = hci_get_auth_req(conn);
3410 cp.authentication = conn->auth_type;
Johan Hedberg17fa4b92011-01-25 13:28:33 +02003411
Gustavo Padovan8fc9ced2012-05-23 04:04:21 -03003412 if (hci_find_remote_oob_data(hdev, &conn->dst) &&
3413 (conn->out || test_bit(HCI_CONN_REMOTE_OOB, &conn->flags)))
Szymon Jancce85ee12011-03-22 13:12:23 +01003414 cp.oob_data = 0x01;
3415 else
3416 cp.oob_data = 0x00;
3417
Johan Hedberg17fa4b92011-01-25 13:28:33 +02003418 hci_send_cmd(hdev, HCI_OP_IO_CAPABILITY_REPLY,
Gustavo Padovan807deac2012-05-17 00:36:24 -03003419 sizeof(cp), &cp);
Johan Hedberg03b555e2011-01-04 15:40:05 +02003420 } else {
3421 struct hci_cp_io_capability_neg_reply cp;
3422
3423 bacpy(&cp.bdaddr, &ev->bdaddr);
Andrei Emeltchenko9f5a0d72011-11-07 14:20:25 +02003424 cp.reason = HCI_ERROR_PAIRING_NOT_ALLOWED;
Johan Hedberg03b555e2011-01-04 15:40:05 +02003425
3426 hci_send_cmd(hdev, HCI_OP_IO_CAPABILITY_NEG_REPLY,
Gustavo Padovan807deac2012-05-17 00:36:24 -03003427 sizeof(cp), &cp);
Johan Hedberg03b555e2011-01-04 15:40:05 +02003428 }
3429
3430unlock:
3431 hci_dev_unlock(hdev);
3432}
3433
Gustavo Padovan6039aa732012-05-23 04:04:18 -03003434static void hci_io_capa_reply_evt(struct hci_dev *hdev, struct sk_buff *skb)
Johan Hedberg03b555e2011-01-04 15:40:05 +02003435{
3436 struct hci_ev_io_capa_reply *ev = (void *) skb->data;
3437 struct hci_conn *conn;
3438
3439 BT_DBG("%s", hdev->name);
3440
3441 hci_dev_lock(hdev);
3442
3443 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
3444 if (!conn)
3445 goto unlock;
3446
Johan Hedberg03b555e2011-01-04 15:40:05 +02003447 conn->remote_cap = ev->capability;
Johan Hedberg03b555e2011-01-04 15:40:05 +02003448 conn->remote_auth = ev->authentication;
Johan Hedberg58a681e2012-01-16 06:47:28 +02003449 if (ev->oob_data)
3450 set_bit(HCI_CONN_REMOTE_OOB, &conn->flags);
Johan Hedberg03b555e2011-01-04 15:40:05 +02003451
3452unlock:
Marcel Holtmann04936842008-07-14 20:13:48 +02003453 hci_dev_unlock(hdev);
3454}
3455
Gustavo Padovan6039aa732012-05-23 04:04:18 -03003456static void hci_user_confirm_request_evt(struct hci_dev *hdev,
3457 struct sk_buff *skb)
Johan Hedberga5c29682011-02-19 12:05:57 -03003458{
3459 struct hci_ev_user_confirm_req *ev = (void *) skb->data;
Johan Hedberg55bc1a32011-04-28 11:28:56 -07003460 int loc_mitm, rem_mitm, confirm_hint = 0;
Johan Hedberg7a828902011-04-28 11:28:53 -07003461 struct hci_conn *conn;
Johan Hedberga5c29682011-02-19 12:05:57 -03003462
3463 BT_DBG("%s", hdev->name);
3464
3465 hci_dev_lock(hdev);
3466
Johan Hedberga8b2d5c2012-01-08 23:11:15 +02003467 if (!test_bit(HCI_MGMT, &hdev->dev_flags))
Johan Hedberg7a828902011-04-28 11:28:53 -07003468 goto unlock;
Johan Hedberga5c29682011-02-19 12:05:57 -03003469
Johan Hedberg7a828902011-04-28 11:28:53 -07003470 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
3471 if (!conn)
3472 goto unlock;
3473
3474 loc_mitm = (conn->auth_type & 0x01);
3475 rem_mitm = (conn->remote_auth & 0x01);
3476
3477 /* If we require MITM but the remote device can't provide that
3478 * (it has NoInputNoOutput) then reject the confirmation
3479 * request. The only exception is when we're dedicated bonding
3480 * initiators (connect_cfm_cb set) since then we always have the MITM
3481 * bit set. */
3482 if (!conn->connect_cfm_cb && loc_mitm && conn->remote_cap == 0x03) {
3483 BT_DBG("Rejecting request: remote device can't provide MITM");
3484 hci_send_cmd(hdev, HCI_OP_USER_CONFIRM_NEG_REPLY,
Gustavo Padovan807deac2012-05-17 00:36:24 -03003485 sizeof(ev->bdaddr), &ev->bdaddr);
Johan Hedberg7a828902011-04-28 11:28:53 -07003486 goto unlock;
3487 }
3488
3489 /* If no side requires MITM protection; auto-accept */
3490 if ((!loc_mitm || conn->remote_cap == 0x03) &&
Gustavo Padovan807deac2012-05-17 00:36:24 -03003491 (!rem_mitm || conn->io_capability == 0x03)) {
Johan Hedberg55bc1a32011-04-28 11:28:56 -07003492
3493 /* If we're not the initiators request authorization to
3494 * proceed from user space (mgmt_user_confirm with
3495 * confirm_hint set to 1). */
Johan Hedberg51a8efd2012-01-16 06:10:31 +02003496 if (!test_bit(HCI_CONN_AUTH_PEND, &conn->flags)) {
Johan Hedberg55bc1a32011-04-28 11:28:56 -07003497 BT_DBG("Confirming auto-accept as acceptor");
3498 confirm_hint = 1;
3499 goto confirm;
3500 }
3501
Johan Hedberg9f616562011-04-28 11:28:54 -07003502 BT_DBG("Auto-accept of user confirmation with %ums delay",
Gustavo Padovan807deac2012-05-17 00:36:24 -03003503 hdev->auto_accept_delay);
Johan Hedberg9f616562011-04-28 11:28:54 -07003504
3505 if (hdev->auto_accept_delay > 0) {
3506 int delay = msecs_to_jiffies(hdev->auto_accept_delay);
3507 mod_timer(&conn->auto_accept_timer, jiffies + delay);
3508 goto unlock;
3509 }
3510
Johan Hedberg7a828902011-04-28 11:28:53 -07003511 hci_send_cmd(hdev, HCI_OP_USER_CONFIRM_REPLY,
Gustavo Padovan807deac2012-05-17 00:36:24 -03003512 sizeof(ev->bdaddr), &ev->bdaddr);
Johan Hedberg7a828902011-04-28 11:28:53 -07003513 goto unlock;
3514 }
3515
Johan Hedberg55bc1a32011-04-28 11:28:56 -07003516confirm:
Johan Hedberg272d90d2012-02-09 15:26:12 +02003517 mgmt_user_confirm_request(hdev, &ev->bdaddr, ACL_LINK, 0, ev->passkey,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003518 confirm_hint);
Johan Hedberg7a828902011-04-28 11:28:53 -07003519
3520unlock:
Johan Hedberga5c29682011-02-19 12:05:57 -03003521 hci_dev_unlock(hdev);
3522}
3523
Gustavo Padovan6039aa732012-05-23 04:04:18 -03003524static void hci_user_passkey_request_evt(struct hci_dev *hdev,
3525 struct sk_buff *skb)
Brian Gix1143d452011-11-23 08:28:34 -08003526{
3527 struct hci_ev_user_passkey_req *ev = (void *) skb->data;
3528
3529 BT_DBG("%s", hdev->name);
3530
Johan Hedberga8b2d5c2012-01-08 23:11:15 +02003531 if (test_bit(HCI_MGMT, &hdev->dev_flags))
Johan Hedberg272d90d2012-02-09 15:26:12 +02003532 mgmt_user_passkey_request(hdev, &ev->bdaddr, ACL_LINK, 0);
Brian Gix1143d452011-11-23 08:28:34 -08003533}
3534
Johan Hedberg92a25252012-09-06 18:39:26 +03003535static void hci_user_passkey_notify_evt(struct hci_dev *hdev,
3536 struct sk_buff *skb)
3537{
3538 struct hci_ev_user_passkey_notify *ev = (void *) skb->data;
3539 struct hci_conn *conn;
3540
3541 BT_DBG("%s", hdev->name);
3542
3543 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
3544 if (!conn)
3545 return;
3546
3547 conn->passkey_notify = __le32_to_cpu(ev->passkey);
3548 conn->passkey_entered = 0;
3549
3550 if (test_bit(HCI_MGMT, &hdev->dev_flags))
3551 mgmt_user_passkey_notify(hdev, &conn->dst, conn->type,
3552 conn->dst_type, conn->passkey_notify,
3553 conn->passkey_entered);
3554}
3555
3556static void hci_keypress_notify_evt(struct hci_dev *hdev, struct sk_buff *skb)
3557{
3558 struct hci_ev_keypress_notify *ev = (void *) skb->data;
3559 struct hci_conn *conn;
3560
3561 BT_DBG("%s", hdev->name);
3562
3563 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
3564 if (!conn)
3565 return;
3566
3567 switch (ev->type) {
3568 case HCI_KEYPRESS_STARTED:
3569 conn->passkey_entered = 0;
3570 return;
3571
3572 case HCI_KEYPRESS_ENTERED:
3573 conn->passkey_entered++;
3574 break;
3575
3576 case HCI_KEYPRESS_ERASED:
3577 conn->passkey_entered--;
3578 break;
3579
3580 case HCI_KEYPRESS_CLEARED:
3581 conn->passkey_entered = 0;
3582 break;
3583
3584 case HCI_KEYPRESS_COMPLETED:
3585 return;
3586 }
3587
3588 if (test_bit(HCI_MGMT, &hdev->dev_flags))
3589 mgmt_user_passkey_notify(hdev, &conn->dst, conn->type,
3590 conn->dst_type, conn->passkey_notify,
3591 conn->passkey_entered);
3592}
3593
Gustavo Padovan6039aa732012-05-23 04:04:18 -03003594static void hci_simple_pair_complete_evt(struct hci_dev *hdev,
3595 struct sk_buff *skb)
Marcel Holtmann04936842008-07-14 20:13:48 +02003596{
3597 struct hci_ev_simple_pair_complete *ev = (void *) skb->data;
3598 struct hci_conn *conn;
3599
3600 BT_DBG("%s", hdev->name);
3601
3602 hci_dev_lock(hdev);
3603
3604 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
Johan Hedberg2a611692011-02-19 12:06:00 -03003605 if (!conn)
3606 goto unlock;
Marcel Holtmann04936842008-07-14 20:13:48 +02003607
Johan Hedberg2a611692011-02-19 12:06:00 -03003608 /* To avoid duplicate auth_failed events to user space we check
3609 * the HCI_CONN_AUTH_PEND flag which will be set if we
3610 * initiated the authentication. A traditional auth_complete
3611 * event gets always produced as initiator and is also mapped to
3612 * the mgmt_auth_failed event */
Mikel Astizfa1bd912012-08-09 09:52:29 +02003613 if (!test_bit(HCI_CONN_AUTH_PEND, &conn->flags) && ev->status)
Johan Hedbergbab73cb2012-02-09 16:07:29 +02003614 mgmt_auth_failed(hdev, &conn->dst, conn->type, conn->dst_type,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003615 ev->status);
Johan Hedberg2a611692011-02-19 12:06:00 -03003616
3617 hci_conn_put(conn);
3618
3619unlock:
Marcel Holtmann04936842008-07-14 20:13:48 +02003620 hci_dev_unlock(hdev);
3621}
3622
Gustavo Padovan6039aa732012-05-23 04:04:18 -03003623static void hci_remote_host_features_evt(struct hci_dev *hdev,
3624 struct sk_buff *skb)
Marcel Holtmann41a96212008-07-14 20:13:48 +02003625{
3626 struct hci_ev_remote_host_features *ev = (void *) skb->data;
3627 struct inquiry_entry *ie;
3628
3629 BT_DBG("%s", hdev->name);
3630
3631 hci_dev_lock(hdev);
3632
Andrei Emeltchenkocc11b9c2010-11-22 13:21:37 +02003633 ie = hci_inquiry_cache_lookup(hdev, &ev->bdaddr);
3634 if (ie)
Johan Hedberg02b7cc62012-02-28 02:28:43 +02003635 ie->data.ssp_mode = (ev->features[0] & LMP_HOST_SSP);
Marcel Holtmann41a96212008-07-14 20:13:48 +02003636
3637 hci_dev_unlock(hdev);
3638}
3639
Gustavo Padovan6039aa732012-05-23 04:04:18 -03003640static void hci_remote_oob_data_request_evt(struct hci_dev *hdev,
3641 struct sk_buff *skb)
Szymon Janc2763eda2011-03-22 13:12:22 +01003642{
3643 struct hci_ev_remote_oob_data_request *ev = (void *) skb->data;
3644 struct oob_data *data;
3645
3646 BT_DBG("%s", hdev->name);
3647
3648 hci_dev_lock(hdev);
3649
Johan Hedberga8b2d5c2012-01-08 23:11:15 +02003650 if (!test_bit(HCI_MGMT, &hdev->dev_flags))
Szymon Jance1ba1f12011-04-06 13:01:59 +02003651 goto unlock;
3652
Szymon Janc2763eda2011-03-22 13:12:22 +01003653 data = hci_find_remote_oob_data(hdev, &ev->bdaddr);
3654 if (data) {
3655 struct hci_cp_remote_oob_data_reply cp;
3656
3657 bacpy(&cp.bdaddr, &ev->bdaddr);
3658 memcpy(cp.hash, data->hash, sizeof(cp.hash));
3659 memcpy(cp.randomizer, data->randomizer, sizeof(cp.randomizer));
3660
3661 hci_send_cmd(hdev, HCI_OP_REMOTE_OOB_DATA_REPLY, sizeof(cp),
Gustavo Padovan807deac2012-05-17 00:36:24 -03003662 &cp);
Szymon Janc2763eda2011-03-22 13:12:22 +01003663 } else {
3664 struct hci_cp_remote_oob_data_neg_reply cp;
3665
3666 bacpy(&cp.bdaddr, &ev->bdaddr);
3667 hci_send_cmd(hdev, HCI_OP_REMOTE_OOB_DATA_NEG_REPLY, sizeof(cp),
Gustavo Padovan807deac2012-05-17 00:36:24 -03003668 &cp);
Szymon Janc2763eda2011-03-22 13:12:22 +01003669 }
3670
Szymon Jance1ba1f12011-04-06 13:01:59 +02003671unlock:
Szymon Janc2763eda2011-03-22 13:12:22 +01003672 hci_dev_unlock(hdev);
3673}
3674
Andrei Emeltchenkod5e91192012-10-25 15:20:44 +03003675static void hci_phy_link_complete_evt(struct hci_dev *hdev,
3676 struct sk_buff *skb)
3677{
3678 struct hci_ev_phy_link_complete *ev = (void *) skb->data;
3679 struct hci_conn *hcon, *bredr_hcon;
3680
3681 BT_DBG("%s handle 0x%2.2x status 0x%2.2x", hdev->name, ev->phy_handle,
3682 ev->status);
3683
3684 hci_dev_lock(hdev);
3685
3686 hcon = hci_conn_hash_lookup_handle(hdev, ev->phy_handle);
3687 if (!hcon) {
3688 hci_dev_unlock(hdev);
3689 return;
3690 }
3691
3692 if (ev->status) {
3693 hci_conn_del(hcon);
3694 hci_dev_unlock(hdev);
3695 return;
3696 }
3697
3698 bredr_hcon = hcon->amp_mgr->l2cap_conn->hcon;
3699
3700 hcon->state = BT_CONNECTED;
3701 bacpy(&hcon->dst, &bredr_hcon->dst);
3702
3703 hci_conn_hold(hcon);
3704 hcon->disc_timeout = HCI_DISCONN_TIMEOUT;
3705 hci_conn_put(hcon);
3706
3707 hci_conn_hold_device(hcon);
3708 hci_conn_add_sysfs(hcon);
3709
Andrei Emeltchenkocf70ff22012-10-31 15:46:36 +02003710 amp_physical_cfm(bredr_hcon, hcon);
3711
Andrei Emeltchenkod5e91192012-10-25 15:20:44 +03003712 hci_dev_unlock(hdev);
Andrei Emeltchenkod5e91192012-10-25 15:20:44 +03003713}
3714
Andrei Emeltchenko27695fb2012-10-25 15:20:45 +03003715static void hci_loglink_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
3716{
3717 struct hci_ev_logical_link_complete *ev = (void *) skb->data;
3718 struct hci_conn *hcon;
3719 struct hci_chan *hchan;
3720 struct amp_mgr *mgr;
3721
3722 BT_DBG("%s log_handle 0x%4.4x phy_handle 0x%2.2x status 0x%2.2x",
3723 hdev->name, le16_to_cpu(ev->handle), ev->phy_handle,
3724 ev->status);
3725
3726 hcon = hci_conn_hash_lookup_handle(hdev, ev->phy_handle);
3727 if (!hcon)
3728 return;
3729
3730 /* Create AMP hchan */
3731 hchan = hci_chan_create(hcon);
3732 if (!hchan)
3733 return;
3734
3735 hchan->handle = le16_to_cpu(ev->handle);
3736
3737 BT_DBG("hcon %p mgr %p hchan %p", hcon, hcon->amp_mgr, hchan);
3738
3739 mgr = hcon->amp_mgr;
3740 if (mgr && mgr->bredr_chan) {
3741 struct l2cap_chan *bredr_chan = mgr->bredr_chan;
3742
3743 l2cap_chan_lock(bredr_chan);
3744
3745 bredr_chan->conn->mtu = hdev->block_mtu;
3746 l2cap_logical_cfm(bredr_chan, hchan, 0);
3747 hci_conn_hold(hcon);
3748
3749 l2cap_chan_unlock(bredr_chan);
3750 }
3751}
3752
Andrei Emeltchenko606e2a12012-10-31 15:46:31 +02003753static void hci_disconn_loglink_complete_evt(struct hci_dev *hdev,
3754 struct sk_buff *skb)
3755{
3756 struct hci_ev_disconn_logical_link_complete *ev = (void *) skb->data;
3757 struct hci_chan *hchan;
3758
3759 BT_DBG("%s log handle 0x%4.4x status 0x%2.2x", hdev->name,
3760 le16_to_cpu(ev->handle), ev->status);
3761
3762 if (ev->status)
3763 return;
3764
3765 hci_dev_lock(hdev);
3766
3767 hchan = hci_chan_lookup_handle(hdev, le16_to_cpu(ev->handle));
3768 if (!hchan)
3769 goto unlock;
3770
3771 amp_destroy_logical_link(hchan, ev->reason);
3772
3773unlock:
3774 hci_dev_unlock(hdev);
3775}
3776
Andrei Emeltchenko9eef6b32012-10-31 15:46:32 +02003777static void hci_disconn_phylink_complete_evt(struct hci_dev *hdev,
3778 struct sk_buff *skb)
3779{
3780 struct hci_ev_disconn_phy_link_complete *ev = (void *) skb->data;
3781 struct hci_conn *hcon;
3782
3783 BT_DBG("%s status 0x%2.2x", hdev->name, ev->status);
3784
3785 if (ev->status)
3786 return;
3787
3788 hci_dev_lock(hdev);
3789
3790 hcon = hci_conn_hash_lookup_handle(hdev, ev->phy_handle);
3791 if (hcon) {
3792 hcon->state = BT_CLOSED;
3793 hci_conn_del(hcon);
3794 }
3795
3796 hci_dev_unlock(hdev);
3797}
3798
Gustavo Padovan6039aa732012-05-23 04:04:18 -03003799static void hci_le_conn_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
Ville Tervofcd89c02011-02-10 22:38:47 -03003800{
3801 struct hci_ev_le_conn_complete *ev = (void *) skb->data;
3802 struct hci_conn *conn;
3803
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +03003804 BT_DBG("%s status 0x%2.2x", hdev->name, ev->status);
Ville Tervofcd89c02011-02-10 22:38:47 -03003805
3806 hci_dev_lock(hdev);
3807
Andre Guedesb47a09b2012-07-27 15:10:15 -03003808 conn = hci_conn_hash_lookup_state(hdev, LE_LINK, BT_CONNECT);
Ville Tervob62f3282011-02-10 22:38:50 -03003809 if (!conn) {
3810 conn = hci_conn_add(hdev, LE_LINK, &ev->bdaddr);
3811 if (!conn) {
3812 BT_ERR("No memory for new connection");
Andre Guedes230fd162012-07-27 15:10:10 -03003813 goto unlock;
Ville Tervob62f3282011-02-10 22:38:50 -03003814 }
Andre Guedes29b79882011-05-31 14:20:54 -03003815
3816 conn->dst_type = ev->bdaddr_type;
Andre Guedesb9b343d2012-07-27 15:10:11 -03003817
3818 if (ev->role == LE_CONN_ROLE_MASTER) {
3819 conn->out = true;
3820 conn->link_mode |= HCI_LM_MASTER;
3821 }
Ville Tervob62f3282011-02-10 22:38:50 -03003822 }
Ville Tervofcd89c02011-02-10 22:38:47 -03003823
Andre Guedescd17dec2012-07-27 15:10:16 -03003824 if (ev->status) {
3825 mgmt_connect_failed(hdev, &conn->dst, conn->type,
3826 conn->dst_type, ev->status);
3827 hci_proto_connect_cfm(conn, ev->status);
3828 conn->state = BT_CLOSED;
3829 hci_conn_del(conn);
3830 goto unlock;
3831 }
3832
Johan Hedbergb644ba32012-01-17 21:48:47 +02003833 if (!test_and_set_bit(HCI_CONN_MGMT_CONNECTED, &conn->flags))
3834 mgmt_device_connected(hdev, &ev->bdaddr, conn->type,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003835 conn->dst_type, 0, NULL, 0, NULL);
Vinicius Costa Gomes83bc71b2011-05-06 18:41:43 -03003836
Vinicius Costa Gomes7b5c0d52011-06-09 18:50:50 -03003837 conn->sec_level = BT_SECURITY_LOW;
Ville Tervofcd89c02011-02-10 22:38:47 -03003838 conn->handle = __le16_to_cpu(ev->handle);
3839 conn->state = BT_CONNECTED;
3840
3841 hci_conn_hold_device(conn);
3842 hci_conn_add_sysfs(conn);
3843
3844 hci_proto_connect_cfm(conn, ev->status);
3845
3846unlock:
3847 hci_dev_unlock(hdev);
3848}
3849
Gustavo Padovan6039aa732012-05-23 04:04:18 -03003850static void hci_le_adv_report_evt(struct hci_dev *hdev, struct sk_buff *skb)
Andre Guedes9aa04c92011-05-26 16:23:51 -03003851{
Andre Guedese95beb42011-09-26 20:48:35 -03003852 u8 num_reports = skb->data[0];
3853 void *ptr = &skb->data[1];
Andre Guedes3c9e9192012-01-10 18:20:50 -03003854 s8 rssi;
Andre Guedes9aa04c92011-05-26 16:23:51 -03003855
3856 hci_dev_lock(hdev);
3857
Andre Guedese95beb42011-09-26 20:48:35 -03003858 while (num_reports--) {
3859 struct hci_ev_le_advertising_info *ev = ptr;
Andre Guedes9aa04c92011-05-26 16:23:51 -03003860
Andre Guedes3c9e9192012-01-10 18:20:50 -03003861 rssi = ev->data[ev->length];
3862 mgmt_device_found(hdev, &ev->bdaddr, LE_LINK, ev->bdaddr_type,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003863 NULL, rssi, 0, 1, ev->data, ev->length);
Andre Guedes3c9e9192012-01-10 18:20:50 -03003864
Andre Guedese95beb42011-09-26 20:48:35 -03003865 ptr += sizeof(*ev) + ev->length + 1;
Andre Guedes9aa04c92011-05-26 16:23:51 -03003866 }
3867
3868 hci_dev_unlock(hdev);
3869}
3870
Gustavo Padovan6039aa732012-05-23 04:04:18 -03003871static void hci_le_ltk_request_evt(struct hci_dev *hdev, struct sk_buff *skb)
Vinicius Costa Gomesa7a595f2011-06-09 18:50:47 -03003872{
3873 struct hci_ev_le_ltk_req *ev = (void *) skb->data;
3874 struct hci_cp_le_ltk_reply cp;
Vinicius Costa Gomesbea710f2011-07-07 18:59:37 -03003875 struct hci_cp_le_ltk_neg_reply neg;
Vinicius Costa Gomesa7a595f2011-06-09 18:50:47 -03003876 struct hci_conn *conn;
Vinicius Costa Gomesc9839a12012-02-02 21:08:01 -03003877 struct smp_ltk *ltk;
Vinicius Costa Gomesa7a595f2011-06-09 18:50:47 -03003878
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +03003879 BT_DBG("%s handle 0x%4.4x", hdev->name, __le16_to_cpu(ev->handle));
Vinicius Costa Gomesa7a595f2011-06-09 18:50:47 -03003880
3881 hci_dev_lock(hdev);
3882
3883 conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
Vinicius Costa Gomesbea710f2011-07-07 18:59:37 -03003884 if (conn == NULL)
3885 goto not_found;
Vinicius Costa Gomesa7a595f2011-06-09 18:50:47 -03003886
Vinicius Costa Gomesbea710f2011-07-07 18:59:37 -03003887 ltk = hci_find_ltk(hdev, ev->ediv, ev->random);
3888 if (ltk == NULL)
3889 goto not_found;
3890
3891 memcpy(cp.ltk, ltk->val, sizeof(ltk->val));
Vinicius Costa Gomesa7a595f2011-06-09 18:50:47 -03003892 cp.handle = cpu_to_le16(conn->handle);
Vinicius Costa Gomesc9839a12012-02-02 21:08:01 -03003893
3894 if (ltk->authenticated)
3895 conn->sec_level = BT_SECURITY_HIGH;
Vinicius Costa Gomesa7a595f2011-06-09 18:50:47 -03003896
3897 hci_send_cmd(hdev, HCI_OP_LE_LTK_REPLY, sizeof(cp), &cp);
3898
Vinicius Costa Gomesc9839a12012-02-02 21:08:01 -03003899 if (ltk->type & HCI_SMP_STK) {
3900 list_del(&ltk->list);
3901 kfree(ltk);
3902 }
3903
Vinicius Costa Gomesa7a595f2011-06-09 18:50:47 -03003904 hci_dev_unlock(hdev);
Vinicius Costa Gomesbea710f2011-07-07 18:59:37 -03003905
3906 return;
3907
3908not_found:
3909 neg.handle = ev->handle;
3910 hci_send_cmd(hdev, HCI_OP_LE_LTK_NEG_REPLY, sizeof(neg), &neg);
3911 hci_dev_unlock(hdev);
Vinicius Costa Gomesa7a595f2011-06-09 18:50:47 -03003912}
3913
Gustavo Padovan6039aa732012-05-23 04:04:18 -03003914static void hci_le_meta_evt(struct hci_dev *hdev, struct sk_buff *skb)
Ville Tervofcd89c02011-02-10 22:38:47 -03003915{
3916 struct hci_ev_le_meta *le_ev = (void *) skb->data;
3917
3918 skb_pull(skb, sizeof(*le_ev));
3919
3920 switch (le_ev->subevent) {
3921 case HCI_EV_LE_CONN_COMPLETE:
3922 hci_le_conn_complete_evt(hdev, skb);
3923 break;
3924
Andre Guedes9aa04c92011-05-26 16:23:51 -03003925 case HCI_EV_LE_ADVERTISING_REPORT:
3926 hci_le_adv_report_evt(hdev, skb);
3927 break;
3928
Vinicius Costa Gomesa7a595f2011-06-09 18:50:47 -03003929 case HCI_EV_LE_LTK_REQ:
3930 hci_le_ltk_request_evt(hdev, skb);
3931 break;
3932
Ville Tervofcd89c02011-02-10 22:38:47 -03003933 default:
3934 break;
3935 }
3936}
3937
Andrei Emeltchenko9495b2e2012-09-27 17:26:22 +03003938static void hci_chan_selected_evt(struct hci_dev *hdev, struct sk_buff *skb)
3939{
3940 struct hci_ev_channel_selected *ev = (void *) skb->data;
3941 struct hci_conn *hcon;
3942
3943 BT_DBG("%s handle 0x%2.2x", hdev->name, ev->phy_handle);
3944
3945 skb_pull(skb, sizeof(*ev));
3946
3947 hcon = hci_conn_hash_lookup_handle(hdev, ev->phy_handle);
3948 if (!hcon)
3949 return;
3950
3951 amp_read_loc_assoc_final_data(hdev, hcon);
3952}
3953
Linus Torvalds1da177e2005-04-16 15:20:36 -07003954void hci_event_packet(struct hci_dev *hdev, struct sk_buff *skb)
3955{
Marcel Holtmanna9de9242007-10-20 13:33:56 +02003956 struct hci_event_hdr *hdr = (void *) skb->data;
3957 __u8 event = hdr->evt;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003958
3959 skb_pull(skb, HCI_EVENT_HDR_SIZE);
3960
Marcel Holtmanna9de9242007-10-20 13:33:56 +02003961 switch (event) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003962 case HCI_EV_INQUIRY_COMPLETE:
3963 hci_inquiry_complete_evt(hdev, skb);
3964 break;
3965
3966 case HCI_EV_INQUIRY_RESULT:
3967 hci_inquiry_result_evt(hdev, skb);
3968 break;
3969
Marcel Holtmanna9de9242007-10-20 13:33:56 +02003970 case HCI_EV_CONN_COMPLETE:
3971 hci_conn_complete_evt(hdev, skb);
Marcel Holtmann21d9e302005-09-13 01:32:25 +02003972 break;
3973
Linus Torvalds1da177e2005-04-16 15:20:36 -07003974 case HCI_EV_CONN_REQUEST:
3975 hci_conn_request_evt(hdev, skb);
3976 break;
3977
Linus Torvalds1da177e2005-04-16 15:20:36 -07003978 case HCI_EV_DISCONN_COMPLETE:
3979 hci_disconn_complete_evt(hdev, skb);
3980 break;
3981
Linus Torvalds1da177e2005-04-16 15:20:36 -07003982 case HCI_EV_AUTH_COMPLETE:
3983 hci_auth_complete_evt(hdev, skb);
3984 break;
3985
Marcel Holtmanna9de9242007-10-20 13:33:56 +02003986 case HCI_EV_REMOTE_NAME:
3987 hci_remote_name_evt(hdev, skb);
3988 break;
3989
Linus Torvalds1da177e2005-04-16 15:20:36 -07003990 case HCI_EV_ENCRYPT_CHANGE:
3991 hci_encrypt_change_evt(hdev, skb);
3992 break;
3993
Marcel Holtmanna9de9242007-10-20 13:33:56 +02003994 case HCI_EV_CHANGE_LINK_KEY_COMPLETE:
3995 hci_change_link_key_complete_evt(hdev, skb);
3996 break;
3997
3998 case HCI_EV_REMOTE_FEATURES:
3999 hci_remote_features_evt(hdev, skb);
4000 break;
4001
4002 case HCI_EV_REMOTE_VERSION:
4003 hci_remote_version_evt(hdev, skb);
4004 break;
4005
4006 case HCI_EV_QOS_SETUP_COMPLETE:
4007 hci_qos_setup_complete_evt(hdev, skb);
4008 break;
4009
4010 case HCI_EV_CMD_COMPLETE:
4011 hci_cmd_complete_evt(hdev, skb);
4012 break;
4013
4014 case HCI_EV_CMD_STATUS:
4015 hci_cmd_status_evt(hdev, skb);
4016 break;
4017
4018 case HCI_EV_ROLE_CHANGE:
4019 hci_role_change_evt(hdev, skb);
4020 break;
4021
4022 case HCI_EV_NUM_COMP_PKTS:
4023 hci_num_comp_pkts_evt(hdev, skb);
4024 break;
4025
4026 case HCI_EV_MODE_CHANGE:
4027 hci_mode_change_evt(hdev, skb);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004028 break;
4029
4030 case HCI_EV_PIN_CODE_REQ:
4031 hci_pin_code_request_evt(hdev, skb);
4032 break;
4033
4034 case HCI_EV_LINK_KEY_REQ:
4035 hci_link_key_request_evt(hdev, skb);
4036 break;
4037
4038 case HCI_EV_LINK_KEY_NOTIFY:
4039 hci_link_key_notify_evt(hdev, skb);
4040 break;
4041
4042 case HCI_EV_CLOCK_OFFSET:
4043 hci_clock_offset_evt(hdev, skb);
4044 break;
4045
Marcel Holtmanna8746412008-07-14 20:13:46 +02004046 case HCI_EV_PKT_TYPE_CHANGE:
4047 hci_pkt_type_change_evt(hdev, skb);
4048 break;
4049
Marcel Holtmann85a1e932005-08-09 20:28:02 -07004050 case HCI_EV_PSCAN_REP_MODE:
4051 hci_pscan_rep_mode_evt(hdev, skb);
4052 break;
4053
Marcel Holtmanna9de9242007-10-20 13:33:56 +02004054 case HCI_EV_INQUIRY_RESULT_WITH_RSSI:
4055 hci_inquiry_result_with_rssi_evt(hdev, skb);
4056 break;
4057
4058 case HCI_EV_REMOTE_EXT_FEATURES:
4059 hci_remote_ext_features_evt(hdev, skb);
4060 break;
4061
4062 case HCI_EV_SYNC_CONN_COMPLETE:
4063 hci_sync_conn_complete_evt(hdev, skb);
4064 break;
4065
4066 case HCI_EV_SYNC_CONN_CHANGED:
4067 hci_sync_conn_changed_evt(hdev, skb);
4068 break;
4069
Marcel Holtmann04837f62006-07-03 10:02:33 +02004070 case HCI_EV_SNIFF_SUBRATE:
4071 hci_sniff_subrate_evt(hdev, skb);
4072 break;
4073
Marcel Holtmanna9de9242007-10-20 13:33:56 +02004074 case HCI_EV_EXTENDED_INQUIRY_RESULT:
4075 hci_extended_inquiry_result_evt(hdev, skb);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004076 break;
4077
Johan Hedberg1c2e0042012-06-08 23:31:13 +08004078 case HCI_EV_KEY_REFRESH_COMPLETE:
4079 hci_key_refresh_complete_evt(hdev, skb);
4080 break;
4081
Marcel Holtmann04936842008-07-14 20:13:48 +02004082 case HCI_EV_IO_CAPA_REQUEST:
4083 hci_io_capa_request_evt(hdev, skb);
4084 break;
4085
Johan Hedberg03b555e2011-01-04 15:40:05 +02004086 case HCI_EV_IO_CAPA_REPLY:
4087 hci_io_capa_reply_evt(hdev, skb);
4088 break;
4089
Johan Hedberga5c29682011-02-19 12:05:57 -03004090 case HCI_EV_USER_CONFIRM_REQUEST:
4091 hci_user_confirm_request_evt(hdev, skb);
4092 break;
4093
Brian Gix1143d452011-11-23 08:28:34 -08004094 case HCI_EV_USER_PASSKEY_REQUEST:
4095 hci_user_passkey_request_evt(hdev, skb);
4096 break;
4097
Johan Hedberg92a25252012-09-06 18:39:26 +03004098 case HCI_EV_USER_PASSKEY_NOTIFY:
4099 hci_user_passkey_notify_evt(hdev, skb);
4100 break;
4101
4102 case HCI_EV_KEYPRESS_NOTIFY:
4103 hci_keypress_notify_evt(hdev, skb);
4104 break;
4105
Marcel Holtmann04936842008-07-14 20:13:48 +02004106 case HCI_EV_SIMPLE_PAIR_COMPLETE:
4107 hci_simple_pair_complete_evt(hdev, skb);
4108 break;
4109
Marcel Holtmann41a96212008-07-14 20:13:48 +02004110 case HCI_EV_REMOTE_HOST_FEATURES:
4111 hci_remote_host_features_evt(hdev, skb);
4112 break;
4113
Ville Tervofcd89c02011-02-10 22:38:47 -03004114 case HCI_EV_LE_META:
4115 hci_le_meta_evt(hdev, skb);
4116 break;
4117
Andrei Emeltchenko9495b2e2012-09-27 17:26:22 +03004118 case HCI_EV_CHANNEL_SELECTED:
4119 hci_chan_selected_evt(hdev, skb);
4120 break;
4121
Szymon Janc2763eda2011-03-22 13:12:22 +01004122 case HCI_EV_REMOTE_OOB_DATA_REQUEST:
4123 hci_remote_oob_data_request_evt(hdev, skb);
4124 break;
4125
Andrei Emeltchenkod5e91192012-10-25 15:20:44 +03004126 case HCI_EV_PHY_LINK_COMPLETE:
4127 hci_phy_link_complete_evt(hdev, skb);
4128 break;
4129
Andrei Emeltchenko27695fb2012-10-25 15:20:45 +03004130 case HCI_EV_LOGICAL_LINK_COMPLETE:
4131 hci_loglink_complete_evt(hdev, skb);
4132 break;
4133
Andrei Emeltchenko606e2a12012-10-31 15:46:31 +02004134 case HCI_EV_DISCONN_LOGICAL_LINK_COMPLETE:
4135 hci_disconn_loglink_complete_evt(hdev, skb);
4136 break;
4137
Andrei Emeltchenko9eef6b32012-10-31 15:46:32 +02004138 case HCI_EV_DISCONN_PHY_LINK_COMPLETE:
4139 hci_disconn_phylink_complete_evt(hdev, skb);
4140 break;
4141
Andrei Emeltchenko25e89e92012-01-04 12:41:58 +02004142 case HCI_EV_NUM_COMP_BLOCKS:
4143 hci_num_comp_blocks_evt(hdev, skb);
4144 break;
4145
Marcel Holtmanna9de9242007-10-20 13:33:56 +02004146 default:
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +03004147 BT_DBG("%s event 0x%2.2x", hdev->name, event);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004148 break;
4149 }
4150
4151 kfree_skb(skb);
4152 hdev->stat.evt_rx++;
4153}